How to start/stop/restart jQuery animation
I have the following function that when I call displays a message to the user for a certain amount of time (5 secs in my case). During this "period" if I call the function again to display another message, practically it should hide, then re-appear with the new message for another 5 seconds.
What happens with my code below, I call the function to display the message. Then, lets say on the 4th second, I call it again to display another message, the new message is displayed for 1 second.
I need to somehow -reset- the time but can't figure out how. Tried stopping the animation, checking if the element was visible and hiding it if it was, and many other things. I believe the solution is a simple chaining issue but can't get it right. So any help would be appreciated!
function display_message(msgType, message) {
var elem = $('#ur_messagebox');
switch (msgType) {
case 'confirm':
elem.addC开发者_运维问答lass('msg_confirm');
break;
case 'error':
elem.addClass('msg_error');
break;
}
elem.html(message);
elem.show().delay(5000).fadeOut(1000);
}
thanks in advance...
In short, you can't use .delay()
for what you want. It's just a wrapper for setTimeout()
on the next queue item, you can see the source here, the important part:
return this.queue( type, function() {
var elem = this;
setTimeout(function() {
jQuery.dequeue( elem, type );
}, time );
});
So this is just queuing a setTimeout()
which when executed, dequeues the next item in the queue and executes it. So what is happening is you've added a delay, and even with .stop(true)
or .clearQueue()
, when you queue the .fadeOut()
afterwards you're adding that back to the same fx
queue, so when that setTimeout()
finishes in 5 seconds, it's grabbing the new fade you queued and executing it.
You'll need to setTimout()
and clear it manually, since jQuery core doesn't have this built-in, something like this:
function display_message(msgType, message) {
var mb = $('#ur_messagebox')
.addClass(msgType === 'confirm' ? 'msg_confirm' : 'msg_error')
.html(message)
.stop(true, true).fadeIn();
if(mb.data('delay')) clearTimeout(mb.data('delay'));
mb.data('delay', setTimeout(function() { mb.fadeOut(1000); }, 5000));
}
You can see a working demo here
As Nick pointed out:
In short, you can't use .delay() for what you want.
But there is a simple workaround: instead of using .delay(x)
just use .fadeTo(x,1)
.
Basically, this would fade to full opacity, but since the message box is already at full opacity, this does nothing except delaying the following animations for x
milliseconds. And the advantage is that .fadeTo()
can be stopped/aborted using .stop(true)
.
Try this.
elem.stop().show().delay(5000).fadeOut(1000);
I was getting CSS conflicts because you never remove the msg classes before adding the other, so I cleared those with elem.removeClass('msg_confirm msg_error');
in addition to fixing the problem:
function display_message(msgType, message) {
var elem = $('#ur_messagebox');
elem.removeClass('msg_confirm msg_error');
switch (msgType) {
case 'confirm':
elem.addClass('msg_confirm');
break;
case 'error':
elem.addClass('msg_error');
break;
}
elem.stop().css({opacity:1}).clearQueue();
elem.html(message);
elem.show().delay(5000).fadeOut(1000);
}
So with elem.stop().css({opacity:1}).clearQueue();
I stop the animation, reset the opacity in case it was in the middle of fading out and clear the queue before adding the message and restarting the queue. I tested this and it should work for you.
I restart animations this way: (not sure if it's entirely right, though)
$(element).stop().clearQueue();
$(element).delay(20).animate({ ... });
if using jQuery, just finish the current animation before restarting it again:
tooltip.finish();// set a defined start for animation
tooltip.show();
tooltip.delay(4000).fadeOut(1500);
精彩评论