Angular 14 Class binding transition is not triggering - javascript

I'm using class binding on an element which then should have its scaleY() change from 1 to 0. When I tried the transition with a :hover selector it worked perfectly but when I actually try it with class binding it just pops off without the desired transition.
I looked online and most of the already answered question were about the CSS that was incorrect such as this example (angular ng-class appending classes does not trigger css3 transition).
Here's the code :
filledPortionis an array containing 10 booleans if they're set to true then it adds the filled class, which it does ! I'm gonna repeat myself but Angular does add/remove the class as it should my only problem is that it skips my transition (which is working when I tried using it with an :hover selector)
component.html
<div class="bar" [class.end]="typeEnd">
<span *ngFor="let portion of filledPortion; let i = index" class="portion" [class.filled]="portion"></span>
</div>
component.scss
.bar {
.portion {
position: relative;
width: 2rem;
height: 1.5rem;
clip-path: polygon(100% 0, 0 0, 50% 100%);
&::before {
content: '';
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
transform-origin: bottom;
transform: scaleY(0);
background-color: var(--red);
transition: transform .250s cubic-bezier(0.4, 0.0, 0.2, 1);
z-index: 1;
}
&.filled::before {
transform: scaleY(1);
}
}
}
.end {
.portion {
&::before , &::after {
background-color: #fff;
}
}
}

Related

Image won't stay visible for hover effect

Hello and thank you in advance for reading my question.
GOAL: Set image so that once it's scrolled into view it transitions smoothly into a set position - but still reacts to :hover. Using #keyframes and a little JavaScript, I set the image to opacity: 0 and it's final opacity to opacity: .85. Then I added a hover effect in CSS to make it's opacity: 1
The issue is once it's finished with it's transition - it disappears - reverting to it's original opacity which is zero. I managed to make it freeze at .85 with animation-fill-mode: forwards, rather than animation-fill-mode: none, but then it won't respond to :hover
And here's a test snippet of the problem in action:
let observer_img = new IntersectionObserver(updates => {
updates.forEach(update => {
if (update.isIntersecting) {
update.target.classList.add('shift_frame_center_img');
} else {
update.target.classList.remove('shift_frame_center_img');
}
});
}, { threshold: 0 });
[...document.querySelectorAll('.features-img-wrapper img')].forEach(element => observer_img.observe(element));
body {
width: 100%;
height: 100vh;
background-color: lightgrey;
}
/* CHILD */
.features-img-wrapper img {
width: 10rem;
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 8rem;
opacity: 0;
transition: all .5s;
}
/* APPEND-CHILD */
.shift_frame_center_img {
animation: center_img 1s 0.5s none;
}
/* CHILD ON HOVER */
.features-img-wrapper img:hover {
opacity: 1;
transform: scale(1.035);
}
/* KEYFRAMES */
#keyframes center_img {
0% {
transform: translateY(20rem);
}
100% {
transform: translateY(0);
opacity: .85;
}
}
<body>
<div class="features-img-wrapper">
<img src="https://synapse.it/wp-content/uploads/2020/12/test.png">
</div>
</body>
If I could get a hand with this that would be wonderful, I'm a bit of a beginner and have already spent a few hours on this, all feedback welcome. Thank you very much.
Solution 1
To understand why the hover effect was not working with the animation-fill-mode: forwards, read this answer.
You can fix that by adding !important property to the hover styles:
.features-img-wrapper img:hover {
opacity: 1 !important;
transform: scale(1.035) !important;
}
The problem, in this case, is that the transition will not work for hover.
Solution 2
You could remove the animation entirely and add the final state styles to the shift_frame_center_img class.
But you would still need to use the !important property because of the CSS Specificity.
let observer_img = new IntersectionObserver(updates => {
updates.forEach(update => {
if (update.isIntersecting) {
update.target.classList.add('shift_frame_center_img');
} else {
update.target.classList.remove('shift_frame_center_img');
}
});
}, { threshold: 0 });
[...document.querySelectorAll('.features-img-wrapper img')].forEach(element => observer_img.observe(element));
body {
width: 100%;
height: 100vh;
background-color: lightgrey;
}
/* CHILD */
.features-img-wrapper img {
width: 10rem;
transform: translateY(20rem);
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 8rem;
opacity: 0;
transition: all .5s;
}
/* APPEND-CHILD */
.shift_frame_center_img {
transform: none !important;
opacity: .85 !important;
}
/* CHILD ON HOVER */
.features-img-wrapper img:hover {
opacity: 1 !important;
transform: scale(1.035) !important;
}
<body>
<div class="features-img-wrapper">
<img src="https://synapse.it/wp-content/uploads/2020/12/test.png">
</div>
</body>
This snippet removes the need for fill-mode forwards by setting the img to have opacity 1 as its initial state so it will revert to that at the end of the animation.
The animation itself is altered to take 1.5s rather than 1s with the first third simply setting the img opacity to 0 so it can't be seen. This gives the delay effect.
let observer_img = new IntersectionObserver(updates => {
updates.forEach(update => {
if (update.isIntersecting) {
update.target.classList.add('shift_frame_center_img');
} else {
update.target.classList.remove('shift_frame_center_img');
}
});
}, { threshold: 0 });
[...document.querySelectorAll('.features-img-wrapper img')].forEach(element => observer_img.observe(element));
body {
width: 100%;
height: 100vh;
background-color: lightgrey;
}
/* CHILD */
.features-img-wrapper img {
width: 10rem;
display: block;
margin-left: auto;
margin-right: auto;
margin-top: 8rem;
opacity: 0;
transition: all .5s;
opacity: 1;
}
/* APPEND-CHILD */
.features-img-wrapper img {
animation: center_img 1.5s 0s none;
}
/* CHILD ON HOVER */
.shift_frame_center_img:hover {
opacity: 1;
transform: translateY(0) scale(1.035);
}
/* KEYFRAMES */
#keyframes center_img {
0% {
transform: translateY(20rem) scale(1);
opacity: 0;
}
33.33% {
transform: translateY(20rem) scale(1);
opacity: 0;
}
100% {
transform: translateY(0) scale(1);
opacity: .85;
}
}
<body>
<div class="features-img-wrapper">
<img src="https://synapse.it/wp-content/uploads/2020/12/test.png">
</div>
</body>
Note: as each transform setting will reset anything that isn't included both tranlateY and scale are included in each setting.
Outside the SO snippet system it was possible to leave the animation settings untouched by chaining another animation to the front which ran for 0.5s and just set the img to opacity: 0. This did not work in the snippet system (it got into a loop of flashing on and off) hence the introduction of one but extended animation.

issue with line through animation

I want to create a simple line through animation and so far I'm here:
.strikethrough {
display: inline-block;
position: relative;
line-height: 1.5em;
}
.strikethrough:after {
content: '';
position: absolute;
display: block;
width: 100%;
height: 1px;
box-shadow: 0 1px rgba(252, 3, 3,0.7);
margin-top: -0.7em;
background: rgba(252, 3, 3,0.8);
transform-origin: center left;
animation: strikethrough 1s 0.5s cubic-bezier(.55, 0, .1, 1) 1;
}
#keyframes strikethrough {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
<span class="strikethrough">Favor packaging over toy</span>
As you see everything works fine except two things:
Now we can see the line at first then it hides and starts the animation, I want to see only the animated line.
I want to initiate the animation using javascript... but with this pseudo-element (after) it seems complicated!
You can fix your animation using animation-fill-mode:
animation-fill-mode: backwards;
To trigger your animation, just add the strikethrough class. The thing where I think this won't work is when you have a multiline text, as your ::after won't cover that.
document.querySelector( '.strikethrough' ).addEventListener( 'click', event => { event.target.classList.toggle( 'strikethrough' ); });
.strikethrough {
display: inline-block;
position: relative;
line-height: 1.5em;
}
.strikethrough:after {
content: '';
position: absolute;
display: block;
width: 100%;
height: 1px;
box-shadow: 0 1px rgba(252, 3, 3,0.7);
margin-top: -0.7em;
background: rgba(252, 3, 3,0.8);
transform-origin: center left;
animation: strikethrough 1s 0.5s cubic-bezier(.55, 0, .1, 1) 1;
animation-fill-mode: backwards;
}
#keyframes strikethrough {
from {
transform: scaleX(0);
}
to {
transform: scaleX(1);
}
}
<span class="strikethrough">Favor packaging over toy</span>
Personally, I would take this simpler tack to reduce the amount of actual objects on screen, and the amount of code, by using a background image to scale. If cleverly set up, you could even multi-line this (by making the background the line height and having a middle pixel in it - and with SVGs you could ensure it was only 1px regardless of the stretching etc...).
document.querySelector( 'p' ).addEventListener( 'click', event => {
event.target.classList.toggle( 'strikethrough' );
})
#keyframes stretch {
to { background-size: 100% var(--line-height); }
}
:root {
--line-height: 1.2em;
}
p {
line-height: var(--line-height);
}
.strikethrough {
line-height: 1.2em;
background: url('data:image/svg+xml;charset=utf8,<svg xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="none"><line x1="0" y1="50%" x2="100%" y2="50%" stroke="black" stroke-width="1px" /></svg>') repeat-y 0 0 / 0 var(--line-height);
animation: stretch 4s;
animation-fill-mode: forwards;
}
<p>Hello World!<br />Another line, does it work?</p>

problem on onclick() event for more than one clicks done on a div

i have an html page where,when hovered over the first image a second image fades in/is shown.The first image has an onclick() event which performs a transition of rotating the image and scaling it by some number.During the transition, the first image disappears and some text appears on the same place(area of the div tag of the first image).I perform the transition through javascript and the hovering animation using css. Now when i click on the text(or the area of the div tag) the transition must reverse back i.e., the div area must be as it was before clicking(even with the hovering working.). I would like to know the answer through pure javascript please.
Thank you in advance.
timesclicked = 0;
document.getElementById("hoverImage").addEventListener("click", function()
{
var x = document.getElementById('container');
timesclicked+=1;
if(timesclicked%2!=0)
{
//obj.style.opacity = '0.5';
x.style.transform = 'rotateZ(-360deg) scale(1.4)';
x.style.transition = 'all 1.5s ease-in-out';
setTimeout(() => {
x.innerHTML = '<div style="font-size:16px; font-family: monospace; font-weight:bold; text-align:center; "> My Hero Academia, abbreviated as HeroAca is a Japanese superhero manga series written and illustrated by Kōhei Horikoshi. It has been serialized in Weekly Shōnen Jump since July 2014, and, as of February 2019, 22 volumes have been collected in tankōbon format.</div>'},'1300');
}
else
{
x.style.transform = 'rotateZ(-45deg) scale(1)';
x.style.transition = 'all 1.5s ease-in-out';
setTimeout(() => {
x.innerHTML = '<img src="https://picsum.photos/300">'},'500');
}
});
img
{
width: 300px;
height: 300px;
}
#mainImage,#hoverImage
{
left: 0px;
position: absolute;
top: 0px;
}
#hoverImage
{
opacity: 0;
transition: opacity 0.4s 0.1s ;
}
#hoverImage:hover
{
opacity: 1;
}
#container
{
background: url(https://picsum.photos/300);
background-size: cover;
width: 300px;
height: 300px;
position: absolute;
top:20%;
left:40%;
transform: rotateZ(-45deg);
}
#container:before
{
content: "";
display: block;
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: -1;
background-color: rgba(255, 255, 255, 0.6);
}
<div id="container" >
<img id="mainImage" src="https://picsum.photos/300">
<img id="hoverImage" src="https://picsum.photos/300">
</div>
As much as i know, I think the second clicking event is not happening because the eventlistener is on the hoverImage. I need a way to run the else part of the code somehow.
It looks like there are a few problems with your code, and you're going to have some debugging to do. That said, try this for a strategy:
Put your on-click event on the #container.
Put all the styling and transitioning details in the css. Your javascript will just add and remove a class from the #container.
Don't track the number of clicks unless you need it for something else. Have your if statement check for the presence or absence of the class you're toggling. (Or use an explicit toggle instead of an if-else block.)
Don't add and remove the text and background in the javascript, put them both in the HTML and control their visibility using the CSS.
edit:
People asked for examples and clarification. I'm stealing some of this from other people's answers.
I'm not completely sure I've understood OP's intentions correctly, and there are some rough-around-the-edgues details (like the cursor when you hover before clicking), but I think this should serve as an example:
let container = document.getElementById("container");
container.addEventListener("click", function(){
container.classList.toggle("selected");
});
#mainImage, #hoverImage, #selectedText {
width: 300px;
height: 300px;
left: 0px;
position: absolute;
top: 0px;
}
#hoverImage {
opacity: 0;
transition: opacity 0.4s 0.1s;
}
#container:hover > #hoverImage {
opacity: 1;
}
#container {
width: 300px;
height: 300px;
position: absolute;
top:20%;
left:40%;
transform: rotateZ(-45deg);
transition: all 1.5s ease-in-out;
}
#container.selected {
transform: rotateZ(-360deg) scale(1.4);
}
#container:before {
content: "";
display: block;
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: -1;
background-color: rgba(255, 255, 255, 0.6);
}
#selectedText {
font-size:16px;
font-family: monospace;
font-weight:bold;
text-align:center;
background: url(https://picsum.photos/300?text);
background-size: cover;
opacity: 0;
transition: opacity 0.1s 0.5s;
}
#container.selected > #selectedText {
opacity: 1;
transition: opacity 0.1s 1.3s;
}
<div id="container">
<img id="mainImage" src="https://picsum.photos/300?main">
<img id="hoverImage" src="https://picsum.photos/300?hover">
<div id="selectedText">
My Hero Academia, abbreviated as HeroAca is a Japanese superhero
manga series written and illustrated by Kōhei Horikoshi. It has been
serialized in Weekly Shōnen Jump since July 2014, and, as of
February 2019, 22 volumes have been collected in tankōbon format.
</div>
</div>
you can add the click event listener on the container div.
timesclicked = 0;
document.getElementById("container").addEventListener("click", function()
{
var x = document.getElementById('container');
timesclicked+=1;
if(timesclicked%2!=0)
{
//obj.style.opacity = '0.5';
x.style.transform = 'rotateZ(-360deg) scale(1.4)';
x.style.transition = 'all 1.5s ease-in-out';
setTimeout(() => {
x.innerHTML = '<div style="font-size:16px; font-family: monospace; font-weight:bold; text-align:center; "> My Hero Academia, abbreviated as HeroAca is a Japanese superhero manga series written and illustrated by Kōhei Horikoshi. It has been serialized in Weekly Shōnen Jump since July 2014, and, as of February 2019, 22 volumes have been collected in tankōbon format.</div>'},'1300');
}
else
{
x.style.transform = 'rotateZ(-45deg) scale(1)';
x.style.transition = 'all 1.5s ease-in-out';
setTimeout(() => {
x.innerHTML = '<img src="https://picsum.photos/300">'},'500');
}
});
img
{
width: 300px;
height: 300px;
}
#mainImage,#hoverImage
{
left: 0px;
position: absolute;
top: 0px;
}
#hoverImage
{
opacity: 0;
transition: opacity 0.4s 0.1s ;
}
#hoverImage:hover
{
opacity: 1;
}
#container
{
background: url(https://picsum.photos/300);
background-size: cover;
width: 300px;
height: 300px;
position: absolute;
top:20%;
left:40%;
transform: rotateZ(-45deg);
}
#container:before
{
content: "";
display: block;
position: fixed;
width: 100%;
height: 100%;
left: 0;
top: 0;
z-index: -1;
background-color: rgba(255, 255, 255, 0.6);
}
<div id="container" >
<img id="mainImage" src="https://picsum.photos/300">
<img id="hoverImage" src="https://picsum.photos/300">
</div>
</style>
if I understand your problem correctly, I think you just need to move the transition styles into your CSS
x.style.transition = 'all 1.5s ease-in-out';

How to delay basic HTML tooltip?

I was wondering if there was any way to delay just the classic HTML tooltip (no jQuery plugins like qTip, please). It's just a button as:
<input type="button" title="Click" value="My Button">
I want to know if there is any way to delay the title using pure JavaScript or client-side scripting. From what I have researched, it doesn't seem possible as it is part of the actual OS' GUI programming, which is impossible to access via browser scripting, but if there is any way that I just haven't come across yet, I would love to know! Thanks!
The browser controls the tool tip. If you want to make any changes you will have to create your own. Maybe by using the plug ins your refered to.
I'm 7+ years late, but just stumbled across the same desire and wrote a simple solution to delay tooltips using CSS.
Simply use transition-delay or animation keyframes for opacity. While the transition-delay is easiest, it has the trouble of delaying both reactions in and out of hover, afaik. Animation bypasses that and will only delay the start, for example:
/* Tooltip container */
.tooltip {
position: relative;
display: inline-block;
}
/* Tooltip text */
.tooltip {
position: relative;
display: inline-block;
}
.tooltip .tooltiptext {
visibility: hidden;
width: 120px;
background-color: #444;
color: #fff;
text-align: center;
border-radius: 6px;
padding: 5px 0;
/* Position the tooltip */
position: absolute;
z-index: 1;
top: 0;
left: 105%;
opacity: 1;
transition: opacity 1s;
}
.tooltip .tooltiptext::after {
content: " ";
position: absolute;
top: 50%;
right: 100%;
/* To the left of the tooltip */
margin-top: -5px;
border-width: 5px;
border-style: solid;
border-color: transparent #545 transparent transparent;
}
/*this is the IMPORTANT bit: hover with animation*/
.tooltip:hover .tooltiptext {
visibility: visible;
animation: tooltipkeys 1s 1; //here just change the 1s to you desired delay time!
opacity: 1;
}
#-webkit-keyframes tooltipkeys {
0% {
opacity: 0;
}
75% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#-moz-keyframes tooltipkeys {
0% {
opacity: 0;
}
75% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#-o-keyframes tooltipkeys {
0% {
opacity: 0;
}
75% {
opacity: 0;
}
100% {
opacity: 1;
}
}
#keyframes tooltipkeys {
0% {
opacity: 0;
}
75% {
opacity: 0;
}
100% {
opacity: 1;
}
}
<div class="tooltip"><span class="tooltiptext">delayed tip</span>Example</div>
For more tips on tooltips you should check w3 schools for plenty of good advice.
This is a feature of the system which you cannot manipulate with HTML, CSS or JavaScript.
Keep in mind that different Operating Systems have different set of delays and styling to these tooltips, the best option to consider for better control (delay,styling,animation,etc) would be to implement your own tooltip.

How to show Page Loading div until the page has finished loading?

I have a section on our website that loads quite slowly as it's doing some intensive calls.
Any idea how I can get a div to say something similar to "loading" to show while the page prepares itself and then vanish when everything is ready?
Original Answer
I've needed this and after some research I came up with this (jQuery needed):
First, right after the <body> tag add this:
<div id="loading">
<img id="loading-image" src="path/to/ajax-loader.gif" alt="Loading..." />
</div>
Then add the style class for the div and image to your CSS:
#loading {
position: fixed;
display: block;
width: 100%;
height: 100%;
top: 0;
left: 0;
text-align: center;
opacity: 0.7;
background-color: #fff;
z-index: 99;
}
#loading-image {
position: absolute;
top: 100px;
left: 240px;
z-index: 100;
}
Then, add this javascript to your page (preferably at the end of your page, before your closing </body> tag, of course):
<script>
$(window).load(function() {
$('#loading').hide();
});
</script>
Finally, adjust the position of the loading image and the background-color of the loading div with the style class.
This is it, should work just fine. But of course you should have an ajax-loader.gif somewhere or use base64 url for image's src value. Freebies here. (Right-click > Save Image As...)
Update
For jQuery 3.0 and above you can use:
<script>
$(window).on('load', function () {
$('#loading').hide();
})
</script>
Update
The original answer is from jQuery and before flexbox era. You can use many view management libraries / frameworks now like Angular, React and Vue.js. And for CSS you have flexbox option. Below is CSS alternative:
#loading {
position: fixed;
display: flex;
justify-content: center;
align-items: center;
width: 100%;
height: 100%;
top: 0;
left: 0;
opacity: 0.7;
background-color: #fff;
z-index: 99;
}
#loading-image {
z-index: 100;
}
This script will add a div that covers the entire window as the page loads. It will show a CSS-only loading spinner automatically. It will wait until the window (not the document) finishes loading, then it will wait an optional extra few seconds.
Works with jQuery 3 (it has a new window load event)
No image needed but it's easy to add one
Change the delay for more branding or instructions
Only dependency is jQuery.
CSS loader code from https://projects.lukehaas.me/css-loaders
$('body').append('<div style="" id="loadingDiv"><div class="loader">Loading...</div></div>');
$(window).on('load', function(){
setTimeout(removeLoader, 2000); //wait for page load PLUS two seconds.
});
function removeLoader(){
$( "#loadingDiv" ).fadeOut(500, function() {
// fadeOut complete. Remove the loading div
$( "#loadingDiv" ).remove(); //makes page more lightweight
});
}
.loader,
.loader:after {
border-radius: 50%;
width: 10em;
height: 10em;
}
.loader {
margin: 60px auto;
font-size: 10px;
position: relative;
text-indent: -9999em;
border-top: 1.1em solid rgba(255, 255, 255, 0.2);
border-right: 1.1em solid rgba(255, 255, 255, 0.2);
border-bottom: 1.1em solid rgba(255, 255, 255, 0.2);
border-left: 1.1em solid #ffffff;
-webkit-transform: translateZ(0);
-ms-transform: translateZ(0);
transform: translateZ(0);
-webkit-animation: load8 1.1s infinite linear;
animation: load8 1.1s infinite linear;
}
#-webkit-keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
#keyframes load8 {
0% {
-webkit-transform: rotate(0deg);
transform: rotate(0deg);
}
100% {
-webkit-transform: rotate(360deg);
transform: rotate(360deg);
}
}
#loadingDiv {
position:absolute;;
top:0;
left:0;
width:100%;
height:100%;
background-color:#000;
}
This script will add a div that covers the entire window as the page loads. It will show a CSS-only loading spinner automatically. It will wait until the window (not the document) finishes loading.
<ul>
<li>Works with jQuery 3, which has a new window load event</li>
<li>No image needed but it's easy to add one</li>
<li>Change the delay for branding or instructions</li>
<li>Only dependency is jQuery.</li>
</ul>
Place the script below at the bottom of the body.
CSS loader code from https://projects.lukehaas.me/css-loaders
<!-- Place the script below at the bottom of the body -->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
window.onload = function(){ document.getElementById("loading").style.display = "none" }
#loading {width: 100%;height: 100%;top: 0px;left: 0px;position: fixed;display: block; z-index: 99}
#loading-image {position: absolute;top: 40%;left: 45%;z-index: 100}
<div id="loading">
<img id="loading-image" src="img/loading.gif" alt="Loading..." />
</div>
Page loading image with simplest fadeout effect created in JS:
I have another below simple solution for this which perfectly worked for me.
First of all, create a CSS with name Lockon class which is transparent overlay along with loading GIF as shown below
.LockOn {
display: block;
visibility: visible;
position: absolute;
z-index: 999;
top: 0px;
left: 0px;
width: 105%;
height: 105%;
background-color:white;
vertical-align:bottom;
padding-top: 20%;
filter: alpha(opacity=75);
opacity: 0.75;
font-size:large;
color:blue;
font-style:italic;
font-weight:400;
background-image: url("../Common/loadingGIF.gif");
background-repeat: no-repeat;
background-attachment: fixed;
background-position: center;
}
Now we need to create our div with this class which cover entire page as an overlay whenever the page is getting loaded
<div id="coverScreen" class="LockOn">
</div>
Now we need to hide this cover screen whenever the page is ready and so that we can restrict the user from clicking/firing any event until the page is ready
$(window).on('load', function () {
$("#coverScreen").hide();
});
Above solution will be fine whenever the page is loading.
Now the question is after the page is loaded, whenever we click a button or an event which will take a long time, we need to show this in the client click event as shown below
$("#ucNoteGrid_grdViewNotes_ctl01_btnPrint").click(function () {
$("#coverScreen").show();
});
That means when we click this print button (which will take a long time to give the report) it will show our cover screen with GIF which gives result and once the page is ready above windows on load function will fire and which hide the cover screen once the screen is fully loaded.
Default the contents to display:none and then have an event handler that sets it to display:block or similar after it's fully loaded. Then have a div that's set to display:block with "Loading" in it, and set it to display:none in the same event handler as before.
Here's the jQuery I ended up using, which monitors all ajax start/stop, so you don't need to add it to each ajax call:
$(document).ajaxStart(function(){
$("#loading").removeClass('hide');
}).ajaxStop(function(){
$("#loading").addClass('hide');
});
CSS for the loading container & content (mostly from mehyaa's answer), as well as a hide class:
#loading {
width: 100%;
height: 100%;
top: 0px;
left: 0px;
position: fixed;
display: block;
opacity: 0.7;
background-color: #fff;
z-index: 99;
text-align: center;
}
#loading-content {
position: absolute;
top: 50%;
left: 50%;
text-align: center;
z-index: 100;
}
.hide{
display: none;
}
HTML:
<div id="loading" class="hide">
<div id="loading-content">
Loading...
</div>
</div>
Well, this largely depends on how you're loading the elements needed in the 'intensive call', my initial thought is that you're doing those loads via ajax. If that's the case, then you could use the 'beforeSend' option and make an ajax call like this:
$.ajax({
type: 'GET',
url: "some.php",
data: "name=John&location=Boston",
beforeSend: function(xhr){ <---- use this option here
$('.select_element_you_want_to_load_into').html('Loading...');
},
success: function(msg){
$('.select_element_you_want_to_load_into').html(msg);
}
});
EDIT
I see, in that case, using one of the 'display:block'/'display:none' options above in conjunction with $(document).ready(...) from jQuery is probably the way to go. The $(document).ready() function waits for the entire document structure to be loaded before executing (but it doesn't wait for all media to load). You'd do something like this:
$(document).ready( function() {
$('table#with_slow_data').show();
$('div#loading image or text').hide();
});
My blog will work 100 percent.
function showLoader()
{
$(".loader").fadeIn("slow");
}
function hideLoader()
{
$(".loader").fadeOut("slow");
}
.loader {
position: fixed;
left: 0px;
top: 0px;
width: 100%;
height: 100%;
z-index: 9999;
background: url('pageLoader2.gif') 50% 50% no-repeat rgb(249,249,249);
opacity: .8;
}
<div class="loader"></div>
Create a <div> element that contains your loading message, give the <div> an ID, and then when your content has finished loading, hide the <div>:
$("#myElement").css("display", "none");
...or in plain JavaScript:
document.getElementById("myElement").style.display = "none";
This will be in synchronisation with an api call, When the api call is triggered, the loader is shown. When the api call is succesful, the loader is removed. This can be used for either page load or during an api call.
$.ajax({
type: 'GET',
url: url,
async: true,
dataType: 'json',
beforeSend: function (xhr) {
$( "<div class='loader' id='searching-loader'></div>").appendTo("#table-playlist-section");
$("html, body").animate( { scrollTop: $(document).height() }, 100);
},
success: function (jsonOptions) {
$('#searching-loader').remove();
.
.
}
});
CSS
.loader {
border: 2px solid #f3f3f3;
border-radius: 50%;
border-top: 2px solid #3498db;
width: 30px;
height: 30px;
margin: auto;
-webkit-animation: spin 2s linear infinite; /* Safari */
animation: spin 2s linear infinite;
margin-top: 35px;
margin-bottom: -35px;
}
/* Safari */
#-webkit-keyframes spin {
0% { -webkit-transform: rotate(0deg); }
100% { -webkit-transform: rotate(360deg); }
}
#keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
for drupal in your theme
custom_theme.theme file
function custom_theme_preprocess_html(&$variables) {
$variables['preloader'] = 1;
}
In html.html.twig file after skip main content link in body
{% if preloader %}
<div id="test-preloader" >
<div id="preloader-inner" class="cssload-container">
<div class="wait-text">{{ 'Please wait...'|t }} </div>
<div class="cssload-item cssload-moon"></div>
</div>
</div>
{% endif %}
in css file
#test-preloader {
position: fixed;
background: white;
width: 100%;
height: 100%;
top: 0;
left: 0;
z-index: 9999;
}
.cssload-container .wait-text {
text-align: center;
padding-bottom: 15px;
color: #000;
}
.cssload-container .cssload-item {
margin: auto;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: 131px;
height: 131px;
background-color: #fff;
box-sizing: border-box;
-o-box-sizing: border-box;
-ms-box-sizing: border-box;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-shadow: 0 0 21px 3px rgba(130, 130, 130, 0.26);
-o-box-shadow: 0 0 21px 3px rgba(130, 130, 130, 0.26);
-ms-box-shadow: 0 0 21px 3px rgba(130, 130, 130, 0.26);
-webkit-box-shadow: 0 0 21px 3px rgba(130, 130, 130, 0.26);
-moz-box-shadow: 0 0 21px 3px rgba(130, 130, 130, 0.26);
}
.cssload-container .cssload-moon {
border-bottom: 26px solid #008AFA;
border-radius: 50%;
-o-border-radius: 50%;
-ms-border-radius: 50%;
-webkit-border-radius: 50%;
-moz-border-radius: 50%;
animation: spin 1.45s ease infinite;
-o-animation: spin 1.45s ease infinite;
-ms-animation: spin 1.45s ease infinite;
-webkit-animation: spin 1.45s ease infinite;
-moz-animation: spin 1.45s ease infinite;
}
I needed a splash screen, which I implemented by reusing parts of the solutions listed here. It uses Vanilla JS for full backwards-compatibility.
Step 1: Add a background with a spinner gif on top of the page, then remove them when everything is loaded.
body.has-js::before {
content: '';
position: fixed;
left: 0;
right: 0;
top: 0;
bottom: 0;
z-index: 10;
height: 100vh;
width: 100vw;
pointer-events: none;
transition: all .2s;
background: white url('/img/spinner.gif') no-repeat center center / 50px;
}
body.loaded::before {
opacity: 0;
width: 0;
height: 0;
}
Step 2: Add a little script right after the opening body tag to start displaying the load/splash screen.
<body>
<script>
// Only show loader if JS is available
document.body.className += ' has-js';
// Option 1: Hide loader when 'load' event fires
window.onload = function() { document.body.className += ' loaded'; }
// Option 2: Hide loader after 2 seconds, in case the 'load' event never fires
setTimeout(function(){ document.body.className += ' loaded'; }, 1000 * 2);
</script>
<!-- Page content goes after this -->
</body>
Based on #mehyaa answer, but much shorter:
HTML (right after <body>):
<img id = "loading" src = "loading.gif" alt = "Loading indicator">
CSS:
#loading {
position: absolute;
top: 50%;
left: 50%;
width: 32px;
height: 32px;
/* 1/2 of the height and width of the actual gif */
margin: -16px 0 0 -16px;
z-index: 100;
}
Javascript (jQuery, since I'm already using it):
$(window).load(function() {
$('#loading').remove();
});

Categories

Resources