How do you pause before fading an element out using jQuery? - javascript

I would like to flash a success message on my page.
I am using the jQuery fadeOut method to fade and then remove the element. I can increase the duration to make it last longer, however this looks strange.
What I would like to happen is have the element be displayed for five seconds, then fade quickly, and finally be removed.
How can you animate this using jQuery?

The new delay() function in jQuery 1.4 should do the trick.
$('#foo').fadeIn(200).delay(5000).fadeOut(200).remove();

use setTimeout(function(){$elem.hide();}, 5000);
Where $elem is the element you wish to hide, and 5000 is the delay in milliseconds. You can actually use any function within the call to setTimeout(), that code just defines a small anonymous function for simplicity.

While #John Sheehan's approach works, you run into the jQuery fadeIn/fadeOut ClearType glitch in IE7. Personally, I'd opt for #John Millikin's setTimeout() approach, but if you're set on a pure jQuery approach, better to trigger an animation on a non-opacity property, such as a margin.
var left = parseInt($('#element').css('marginLeft'));
$('#element')
.animate({ marginLeft: left ? left : 0 }, 5000)
.fadeOut('fast');
You can be a bit cleaner if you know your margin to be a fixed value:
$('#element')
.animate({ marginLeft: 0 }, 5000)
.fadeOut('fast');
EDIT: It looks like the jQuery FxQueues plug-in does just what you need:
$('#element').fadeOut({
speed: 'fast',
preDelay: 5000
});

For a pure jQuery approach, you can do
$("#element").animate({opacity: 1.0}, 5000).fadeOut();
It's a hack, but it does the job

var $msg = $('#msg-container-id');
$msg.fadeIn(function(){
setTimeout(function(){
$msg.fadeOut(function(){
$msg.remove();
});
},5000);
});

Following on from dansays' comment, the following seems to work perfectly well:
$('#thing') .animate({dummy:1}, 2000)
.animate({ etc ... });

dansays's answer just doesn't work for me. For some reason, remove() runs immediately and the div disappears before any animations happen.
The following works, however (by omitting the remove() method):
$('#foo').fadeIn(500).delay(5000).fadeOut(500);
I don't mind if there are hidden DIVs on the page (there shouldn't be more than a few anyway).

Update for 1.6.2
Nathan Long's answer will cause the element to pop off without obeying delay or fadeOut.
This works:
$('#foo').delay(2000).fadeOut(2000);

Related

Javascript running tasks chronologically [duplicate]

I've the following JavaScript snippet:
$("#dashboard").addClass("standby").delay(3000).removeClass("standby");
$(".active").removeClass("active");
$("." + target).addClass("active");
$(".showDiv").removeClass("showDiv").addClass("hide");
$("#" + target).removeClass("hide").addClass("showDiv");
While #dashboard is in standby, it should handle all this CSS-Class changes. After this changes, it should display the #dashboard again. So I set delay() between the add and remove of the standby-class. To see if it works I added the too long duration of 3sek.
But it doesn't delay! Why it don't? I don't see it...
delay will only work on actions that go through the animation pipeline, and won't have an influence on the timing of instant atomic operations like that. In order to delay things such as adding or removing classes, then you can use setTimeout.
the .delay() method allows us to delay the execution of functions that follow it in the queue. It can be used with the standard effects queue or with a custom queue.
The .delay() method is best for delaying between queued jQuery effects. Because it is limited—it doesn't, for example, offer a way to cancel the delay—.delay() is not a replacement for JavaScript's native setTimeout function, which may be more appropriate for certain use cases.
.delay() will only delay animations in jQuery.
To set an actual delay, you might want to use setTimeout().
let cancelId;
// ...
cancelId = window.setTimeout(function() {
// ... do stuff ...
}, 3000);
// If you want to cancel prematurely, use `window.clearTimeout`
if (cancelId) {
window.clearTimeout(cancelId);
}
This will execute the code in ... do stuff ... in 3 seconds (3000 miliseconds)
As stated ... delay won't work the way you expect ...
Here is how it works:
$(document).ready(function(){
var audio = new Audio('sang3.mp3');
audio.play();
$("#image1")
.hide()
.attr("src", "https://placeholdit.imgix.net/~text?txtsize=63&bg=FF6347&txtclr=ffffff&txt=Image-1&w=350&h=250")
.fadeIn(1000)
.delay(3000)
.fadeOut(1000)
.queue(function(next) {
$(this).attr("src", "https://placeholdit.imgix.net/~text?txtsize=63&bg=FF6347&txtclr=ffffff&txt=Image-2&w=350&h=250")
next();
})
.fadeIn(1000);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<img src="" id="image1">
Delay won't work the way you expect it to on these line:
$("#image1").delay(9000).attr("src", "image/image1.jpg");
$("#image1").delay(9000).attr("src", "image/image2.jpg");
It will run the attribute change immediately. Why? Because the attribute change isn't part of the "animation". Delay can only be used with with animating functions.
If you only need two images, it might be easiest for you to have two images stacked together, and fade them in and out as needed.
If you want to expand this to many images, try using the more robust ".animate" function to fade in and out. "Animate" can be given a callback function that will be called when complete.
Try utilizing .queue()
$("#image1").delay(5000).fadeIn(3000, function() {
$(this).delay(9000, "task" ).queue("task", function() {
$(this).attr("src", "image/image1.jpg")
.delay(5000).fadeOut(3000, function() {
$(this).delay(9000, "task")
.queue("task", function() {
$(this).attr("src", "image/image2.jpg")
.delay(5000).fadeIn(3000, function() {
$(this).delay(5000).fadeOut(3000)
})
}).dequeue("task")
});
}).dequeue("task")
});
All your delays start on $(document).ready();
$("#image1").delay(5000).fadeIn(3000);
$("#image1").delay(9000).attr("src", "image/image1.jpg");
$("#image1").delay(5000).fadeOut(3000);
$("#image1").delay(9000).attr("src", "image/image2.jpg");
$("#image1").delay(5000).fadeIn(3000);
$("#image1").delay(5000).fadeOut(3000);
Think of it this way. When doc is ready, JS start executing whatever is inside that function, first delay it executes is this: $("#image1").delay(5000).fadeIn(3000);
That will START a delay of 5000 ms and then a fadeOut() with a duration of 3000 ms. That fadeOut is synchronus to the delay, but the next line of code is completely asynchronous to this one.
Then it procceeds to the next line. And so on. It won't wait to your delay to finish, it simply starts counting on the background.
.delay() DOES stack when applied to the same element: JSFiddle
I leave this just in case someone is confused as I was
Seems like for what you are trying to do, you might want to take a look at CSS transitions:
http://css-tricks.com/almanac/properties/t/transition/
You can still have .addClass(), except now your class will utilize these transition properties, and you won't need .delay().
Usually we need to do things before removing the standby state, so we remove the class in an ajax callback :
$("#dashboard").addClass("standby");
$.get('urltoget',function(data){
if(data)
$("#dashboard").removeClass("standby");
else
$("#dashboard").removeClass("standby").addClass('error');
})

jQuery.slideDown completing instantly

I'm trying to do a simple slide out effect, then add a class with display:none;
But for some reason, the jQuery animation is completing instantly, instead of using the duration as the docs say. I tried using different values, and 'slow' / 'fast'.
Looking at the source in Chrome's developer tools, the DOM is updated instantly. Removing the callback doesn't make the animation work either, it just does nothing in that case.
$('.type-panel').slideDown(500, function () {
$(this).addClass('panel-hidden')
});
<div class="ed-panel type-panel">
//bunch of stuff
</div>
What am I missing?
(I have jQuery and jQueryUI referenced)
I think you meant to use .slideUp() to hide it.
$('.type-panel').slideUp(500, function() {
$(this).addClass('panel-hidden');
});
Notice, .slideUp() will add automatically set the display to none.

Animate.CSS Replay?

I have an animation using Animate.CSS that I would like to have replay if the user would like but what I have attempted does not work. Here is the code:
HTML:
<div class="img-center">
<img src="path.jpg" class="feature-image animated rotateInDownRight" />
</div>
<p class="textcenter"> </p>
<div class="img-center">
Replay
</div>
JS:
var $j = jQuery.noConflict();
$j("#replay").click(function() {
$j('.feature-image').removeClass('animated rotateInDownRight').addClass('animated rotateInDownRight');
});
I do know the script itself works as I can see it happen in Firebug however that animation doesn't animate again. How do I achieve this with Animate.CSS?
This is just a guess but it appears that jQuery isn't "finished" removing the class before it adds it back in. I know this makes NO sense, but it's how JavaScript works. It can call the next function in the chain before all the stuff from the first one is finished. I poked around the code on Animate.CSS's site and saw that they use a timeout in their animation function. You might try the same. Here's their code:
function testAnim(x) {
$('#animateTest').removeClass().addClass(x);
var wait = window.setTimeout( function(){
$('#animateTest').removeClass()},
1300
);
}
What this is doing is exactly like what you are doing except that it waits for the animation to finish, then removes the classes. That way when the other class is added back in, it is truely "new" to the tag. Here is a slightly modified function:
function testAnim(elementId, animClasses) {
$(elementId).addClass(animClasses);
var wait = window.setTimeout( function(){
$(elementId).removeClass(animClasses)},
1300
);
}
Notice two things: First this code would allow you to change what element gets the animation. Second, you remove the classes you added after 1300 milliseconds. Still not 100% there, but it might get you further down the road.
It should be noted that if there is already some animation classes on the object it might break this JS.
found the right answer at animate.css issue#3
var $at = $('#animateTest').removeClass();
//timeout is important !!
setTimeout(function(){
$at.addClass('flash')
}, 10);
Actually a simpler version can avoid using JQuery too.
el.classList.remove('animated','flash');
//timeout is important !!
setTimeout(function(){
el.classList.add('animated','flash');
}, 10);
I believe the issue here is that when I remove the class it was adding the class to quickly. Here is how I solved this issue:
(HTML is same as above question).
JS:
var $j = jQuery.noConflict();
window.setTimeout( function(){
$j('.feature-image').removeClass('animated rotateInDownRight')},
1300);
$j("#replay").click(function() {
$j('.feature-image').addClass('animated rotateInDownRight');
});
What I believe is happening is the jQuery code is removing and adding the class to quickly. Regardless of the reason this code works.
If you wish you can also give a try to this javaScript side development that support animate.css animations. Here is an example of usage.
//Select the elements to animate and enjoy!
var elt = document.querySelector("#notification") ;
iJS.animate(elt, "shake") ;
//it return an AnimationPlayer object
//animation iteration and duration can also be indicated.
var vivifyElt = iJS.animate(elt, "bounce", 3, 500) ;
vivifyElt.onfinish = function(e) {
//doSomething ...;
}
// less than 1500ms later...changed mind!
vivifyElt.cancel();
Take a look here
My answer is a trick to add/remove the css class with a tint delay:
$('#Box').removeClass('animated').hide().delay(1).queue(function() {
$(this).addClass('animated').show().dequeue();
});
Also you can test it without hide/show methods:
$('#Box').removeClass('animated').delay(1).queue(function() {
$(this).addClass('animated').dequeue();
});
I fill it works smooth in chrome but it works with more unexpected delay in FF, so you can test this js timeout:
$('#Box').removeClass('animated');
setTimeout(function(){
$('#Box').addClass('animated');
}, 1);
This solution relies on React useEffect, and it's rather clean, as it avoids manipulating the class names directly.
It doesn't really answers the OP question (which seems to be using jQuery), but it might still be useful to many people using React and Animate CSS library.
const [repeatAnimation, setRepeatAnimation] = useState<boolean>(true);
/**
* When the displayedFrom changes, replay the animations of the component.
* It toggles the CSS classes injected in the component to force replaying the animations.
* Uses a short timeout that isn't noticeable to the human eye, but is necessary for the toggle to work properly.
*/
useEffect(() => {
setRepeatAnimation(false);
setTimeout(() => setRepeatAnimation(true), 100);
}, [displayedFrom]);
return (
<div
className={classnames('block-picker-menu', {
'animate__animated': repeatAnimation,
'animate__pulse': repeatAnimation,
})}
...
)

Simple jquery fader doesnt work in Chrome

I have built a really simple image fading gallery sorta thing, which works on firefox (and I'm sure worked on chrome before the holidays). However now Chrome just fades out the first image and never applies the .first class so subsequent animation is skipped.
JS
function doRotator(time){
$('.rotator3 .property.first').fadeOut(1500, function(){
$('.rotator3 .property.first').removeClass('first').next(".property").addClass('first').fadeIn(1500);
$(this).appendTo('.rotator3'); });
}
setInterval(function () { doRotator(3000);}, 3000);
JSFiddle: http://jsfiddle.net/pkyAS/1/
under each "property" div you have a div with "opacity:inherit" remove the "opacity:inherit" and it should work. let me know if there are more problems.
Here is my solution on fiddle.
I removed your interval, and made the "doRotator" run once - it was easier for me to debug
By the way - fadeIn(1500) is on your interval time.
If your interval is for 3000 millis, and you have fadeIn(1500) - then the div will be visible for 1.5 sec.
Consider triggering "setTimeout(doRotator,3000)" with 3000 when the fadeOut finishes.
EDIT : how to force removal of "opacity:inherit" - you can simply append some JS code to force that.
function doRotator(time){
$('.rotator3 .property.first').fadeOut(1500, function(){
$('.rotator3 .property.first').removeClass('first').next(".property")
.addClass('first').fadeIn(1500).find("div:first").css("opacity",null); $(this).appendTo('.rotator3'); });
}
setInterval(function () { doRotator(3000);}, 3000);

A sticky situation for jQuery slideshow

I'm required to develop a slideshow (not an existing one) with jQuery. I was able to change picture with a function that I created named changePic (takes an image link). It incorporates the fading animation from the jQuery library.
For the slideshow I'm trying to use a while loop. It kind of works, except that it doesn't wait for the animation to finish.
How do I, a) wait for the animation to finish, b) delay the changing picture so it display the picture for a couple of seconds?
Also tried Settimeout, and it doesn't work.
Edit:
Basically changing image is like this:
function changePic(imglink){
var imgnode = document.getElementById("galleryimg");
$(imgnode).fadeTo(500, 0, function(){
$(imgnode).attr("src", imglink);
$(imgnode).fadeTo(1000, 1);
})
}
and the slideshow code is like this, but obviously it shouldn't.
function slideshow(gallerylinks){
var i=0;
while (i<gallerylinks.length){
changePic(gallerylinks[i]);
i++;
}
}
You could always try ditching the while loop, and going with a perpetually recursive function...
on the .animate, you could add a timeout function (at whatever interval) that calls the changePic function. As I have no idea what your code looks like, I will provide a fantastically generic outline.
/* array of imgUrls */
var imgUrls = new Array(); //populate it however
changePic(slideToShowIndex, fadeOutSpeed, fadeInSpeed, slideDelay)
{
$('#slideHolder').animate({ opacity: 0}, fadeOutSpeed , function(){
$('#slideHolder').attr('src', imgUrls[slideToShowIndex]);
$('#slideHolder').animate({ opacity: 1 }, fadeInSpeed, function() {
setTimeout(function() { changePic(slideToShowIndex+1, fadeOutSpeed, fadeInSpeed, slideDelay);}, slideDelay});
});
}});
}
$(document).ready(function() {
changePic(0, 5000, 5000, 10000);
});
This should (in theory) fade the image out, swap it with the new one, and fade it in (both taking 5 seconds) and then adding a delay to call itself with the next slide index in 10 seconds.
This is in no way perfect, but does outline the general idea. Since we have no idea what your code looks like, I can only assume your setTimeout was in the wrong spot. Doing it like this will make sure that the animation has finished before the timeout is set. This guarantees that the slide wont change until after the animation has changed.
of course you could always use a combination of the ':not(:animated)' selector and a setInterval to achieve much the same effect.
EDIT: made a slight change to stack the animations properly. The thoery behind this still works even with the OPs addition of code.
You could have provided more details or example code but have a look at stop() and delay() functions.

Categories

Resources