views:

384

answers:

3

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.addClass('msg_confirm');
            break;

        case 'error':
            elem.addClass('msg_error');
            break;
    }

    elem.html(message);
    elem.show().delay(5000).fadeOut(1000);
}

thanks in advance...

A: 

Try this.

elem.stop().show().delay(5000).fadeOut(1000);
bobthabuilda
thıs does not work. tried it before. the new message is displayed but for a period of whatever left from that 5 seconds of the first message.
Emin
A: 

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.

mVChr
@mhr nope! this also doesn't seem to work. the more I delve into this, the more I come accross more people having problems with the delay function. read the comments here http://api.jquery.com/delay/
Emin
Ah, interesting, I only tested certain cases but it doesn't work for all. Will keep fiddling.
mVChr
+1  A: 

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

Nick Craver
perfect answer! thank you very much!
Emin