Effect Delay Trick

Here is a quick trick for getting an effect to delay without using setTimeout.

Let's say, for example, that I want to show an alert message on the page every time a user clicks on a certain button. But I don't want it to stay there forever; I want it to go away a few seconds later. You know, like the way they do in all of those crazy Web 2.0 sites.

The HTML

Well, first I'll need a message, along with a container for it:

HTML:
  1. <div class="quick-alert">Alert! Watch me before it's too late!</div>

Oh, I should also put my button into the HTML—something like this: <input type="submit" id="show-alert" value="Show Alert" />

The CSS

Now I could also use some stylin' for that quick-alert class:

CSS:
  1. .quick-alert {
  2.    width: 50%;
  3.    margin: 1em 0;
  4.    padding: .5em;
  5.    background: #ffa;
  6.    border: 1px solid #a00;
  7.    color: #a00;
  8.    font-weight: bold;
  9.    display: none;
  10.  }

I'll stick that in my stylesheet so that it's ready to be applied to our new, button-generated DIV.

Inserting the Content

On to the code! First, we'll get our message to be inserted when someone clicks on the "Show Alert" button. Let's put the message right after the button, like so:

JavaScript:
  1. $(document).ready(function() {
  2.   $('#show-alert').click(function() {
  3.     $('<div class="quick-alert">Alert! Watch me before it\'s too late!</div>')
  4.     .insertAfter( $(this) );
  5.   });
  6. });


So, basically, what I'm saying here is, upon clicking the <input id="show-alert" /> button, create this div with the class and all the text inside of it, and place it right after the button. Notice the backslash in "it\'s." That keeps jQuery from getting confused That escapes the single quote, which is necessary because otherwise — as Dave Cardwell explains in his comment — "the JavaScript parser would interpret that as the close of the string."

Adding the Effects

So far, so good. Now I'm going to add my .fadeIn() and .fadeOut() effects. And after those are done, I'll remove the div that I just created. No sense keeping it around:

JavaScript:
  1. $(document).ready(function() {
  2.   $('#show-alert').click(function() {
  3.     $('<div class="quick-alert">Alert! Watch me before it\'s too late!</div>')
  4.     .insertAfter( $(this) )
  5.     .fadeIn('slow')
  6.     .fadeOut('slow', function() {
  7.       $(this).remove();
  8.     });
  9.   });
  10. });

Because I put $(this).remove() in the callback of the .fadeOut() method, it occurs after the the fading out is finished.

The Delay

So, here's the thing. The entry's title says that this is a trick, right? Well, I hope it's not a dirty trick, but here goes the full code:

JavaScript:
  1. $(document).ready(function() {
  2.   $('#show-alert').click(function() {
  3.     $('<div class="quick-alert">Alert! Watch me before it\'s too late!</div>')
  4.     .insertAfter( $(this) )
  5.     .fadeIn('slow')
  6.     .animate({opacity: 1.0}, 3000)
  7.     .fadeOut('slow', function() {
  8.       $(this).remove();
  9.     });
  10.   });
  11. });

Do you see that .animate() method there? I have it animating to a full opacity in 3 seconds. But the div is already at full opacity, so it just sits there looking like it's doing nothing for 3 seconds. Isn't that cute?

Here you go. Try it out for yourself:

I hope you enjoyed the message while it lasted!

42 Responses to “Effect Delay Trick”

  1. Dylan Says:

    omg. Thats just what I've been looking for, thank you!

  2. teemu Says:

    now that was cool and simple, thanks!

  3. Neil Says:

    Nice stuff Karl,

    As an added bonus, you can click the button several times and see mesages appearing and fading out one after the other !

    Neil

  4. Neil Says:

    Karl,

    Firefox 1.5.0.7 - brilliant!
    Firefox 2.0.01 - brilliant!
    IE 7 - brilliant!

    Just thought I'd let you know a couple of bugs I noticed:

    All on Win XP Pro

    IE 6 SP2 - message didn't fade in or out
    Firefox 1.0.8 - message flicker at end of fade in and beginning of fade out
    Opera 9.10 - slight "shift" in the text upon complete fade in
    Netscape 7.2 - message flicker at end of fade in and beginning of fade out
    Netscape 8.1.2 - message flicker at end of fade in and beginning of fade out

  5. Karl Says:

    Thanks for the browser testing, Neil! Oddly, I just tried it in IE 6 SP2, and the fades were working properly. I don't have the version of Firefox/Netscape that produced bugs, but I'll take your word for it. :) The Opera bug is a little disconcerting. It might have to do with the way jQuery calculates the height of the div before fading it in. I'll have to install Opera on my machine and give it a whirl. Thanks again!

  6. Dave Cardwell Says:

    Notice the backslash in "it\'s." That keeps jQuery from getting confused.

    The reason you need the backslash is because otherwise the JavaScript parser would interpret that as the close of the string, not for jQuery's sake.

    Nice tip and write up - Jonathan Howard's Pause plugin performs a similar function.

  7. Karl Says:

    Thanks, Dave, for the clarification. You're right, of course. It was late, and I was too tired to think about what I was writing at that point. Should have waited for the clear light of dawn, as they say. :) Thanks, too, for the link to the pause plugin. Cheers!

  8. Dan G. Switzer, II Says:

    @Karl:

    I would think Dave's recommendation of a pause() plug-in would be a more elegant and efficient method of doing this. The animate() method is going to be wasting some processing--as it will attempt to animate the layer (i.e. the flicker effect.)

    At least the pause plug-in does exactly what you want w/no extra overhead.

  9. Karl Says:

    @Dan,
    Yep, you're absolutely right. This entry was meant more as a quick (and dirty) trick, emphasis on the trick. :) (I've got to stop using these emoticons!) Certainly not a "best practice." A more elegant solution would use setTimeout, which Jonathan's does, and which I mention in the first paragraph. That said, I checked CPU usage while running this, and the impact — on my machine at least — was negligible. Still, I really appreciate the comment. It never hurts to reinforce these things.

  10. Erin Says:

    Help me understand: On line 4 'this' refers to the button being clicked but on line 8 'this' refers to the div. Why? and when did it change?

  11. Erin Says:

    Opera 9.10 (Mac) looks fine to me.

  12. choan Says:

    Erin,

    In line 4, we're inside the event handler for the click event of #showAlert. this points to that element.

    In line 8, we're inside a function that acts as a callback for the finished effect, so this refers to the element which has been animated.

    HTH.

  13. choan Says:

    Uh, that last comment was mine, not Erin's.

  14. Karl Says:

    Fixed! :)

    And thanks, Choan, for explaining this to Erin.

  15. Benjamin Says:

    I`ve changed it a bit to make this work with a text-link without getting moved to the top of the page.
    It works for me, but being totally new to Jquery I dont know if the code is correct, but hey...it works :)

    I really love your tutorials keep them coming :)


    $(document).ready(function() {

    $('#quick-alert').hide();

    $('a#show-alert').click(function() {
    $('#quick-alert').fadeIn('slow')

    .animate({opacity: 1.0}, 6000)
    .fadeOut('slow', function() {
    $(this).remove();

    });
    return false;
    });
    });

  16. Karl Says:

    Well done, Benjamin. That's exactly what you need to do — add return false to the .click() handler.

  17. Neil Merton Says:

    Hi Karl,

    Great website - it's been a tremdous help. I would like to incorporate this idea but instead of it being activated by a button I would like it to trigger when the page loads. I.e. when the page loads it displays the message for xx seconds and then the message disappears.

    Any ideas?

    Many thanks, and keep up the great tutorials!

  18. Karl Says:

    Hi Neil,

    So glad you like the tutorials! For triggering on page load, you might want to just use window.setTimeout(). Say you want to show <div id="temp">temporary message</div> for 3 seconds when the window loads. You could do something like this:

    var removeTemp = function() {
      $('#temp').remove();
    };
    window.setTimeout(removeTemp,3000);

    Hope that helps!

  19. Neil Merton Says:

    Hi Karl,

    Thanks for the reply - here's what I went with:

    var removeTemp = function() { $('#message').fadeOut('slow', function() { $(this).remove(); }); };
    window.setTimeout(removeTemp,3000);

  20. John A. Bilicki III Says:

    What about a delay before any effect takes place in order to take advantage of implementing this with other scripts and effects?

  21. Karl Says:

    Hi John, I'm not sure I'm understanding your question correctly, but I think it's just a matter of where you position the delay in your code, whether it's the "trick" or the setTimeout().

  22. Mike Miner Says:

    Hello I'm new to the jQuery world and new to JavaScript. I'm looking to use the "Delay Trick" for an in-page massage, but I only want the message to appear on the first click and not reoccur.

    Or better yet to display something different on an additional click.
    I was wondering if any one out there has tackled this one.

  23. Karl Says:

    Hi Mike,

    If you only want to trigger an event one time, you can take advantage of jQuery's .one('event', fn) method.

    If you want to display something different on additional clicks, try something like this:

    $(document).ready(function() {
      var $foo = $('<div id="foo"></div>')
        .hide()
        .prependTo('body');
      var warnings = 0;
      var warningMsg = 'Welcome to the click event!';
      $('#set-warning').click(function() {
        if (warnings) {
          warningMsg = 'you have clicked this link ' + (warnings + 1) + ' times!';
        };
        $foo.html(warningMsg).animate({opacity: 1}, 2000, function() {
          $foo.slideUp('fast');
        });
        warnings++;
        return false;
      });
    });

    This creates a div element with id="foo" when the DOM is ready, hides it, and inserts it at the beginning of the body. Then it sets a counter and changes the message based on whether the counter is at 0 or more than 0. As for the rest, well, it's pretty much the same as what I wrote about in the entry.

    Hope that helps.

  24. La Fuente » JQuery: Sistema de errores Says:

    [...] Otra forma de hacer esto mismo es utilizando el siguiente código (http://www.learningjquery.com/2007/01/effect-delay-trick): [...]

  25. Alex Says:

    Hi Karl,

    I'm trying to use your delay trick to reposition a background-image position, delay the animation for a split second, then return the background-image to it's original position -- but getting no love.

    $("#flip")
    .css("background-position", "top right")
    .animate({opacity:1.0}, 3000)
    .css("background-position", "top center");

    Is my thinking flawed here?

  26. Karl Says:

    Hi Alex,

    The problem is that this trick only works with jQuery's effects (slideUp, fadeIn, etc.), not with your standard css manipulation, because it takes advantage of jQuery's built-in queuing of effects. For delaying something like background position, I'd recommend using a setTimeout(), as I describe in comment 18 above. Let me know if that works for you.

  27. Alex Says:

    Thanks Karl,

    Yes, that's what I thought. Was hoping there might be a more jQuery-like method to pull it off.

    Do you imagine CSS manipulations ever being added to jQuery's animation queue (or have their own queue)? The ability to pause between chained CSS instructions would seem to open up a huge potential for animation without adding a massive overhead to the library (I'm guessing there).

  28. Luis Filipe Says:

    Seems like this effect delay trick is not working so well with jquery 1.2

  29. Karl Says:

    Hi Luis,

    I just put up a test page with the script from here, and it seems to be working fine.

    Please have a look and see if it causes any problems for you:
    effect delay test

    Thanks.

  30. Luis Filipe Says:

    Weird... It's working fine now.

  31. Poxline Says:

    Very nice alert effect !

  32. Nick Says:

    I've been playing around with it for a bit, but i'm new to javascript and am having no luck. I have a div with a text link in it, when someone clicks it, I want the alert to appear in another div right below that one, and push everything below it down. Right now, the alert appearing on top of the div with the link it it(as in, the alert hovers over the div), just a pixel or two below the link. How would I fix this? Is it possible to place the div somewhere on the page, and have the link that calls the alert somewhere else on the page? it's only appearing right below the link/button. Sorry, again I'm new.

  33. Nick Says:

    http://www.muttmansion.com/lightbox/fader/

    I found this page which displays a similar alert effect, but doesn't remove the div once it's been placed in the page, it just fades the opacity, leaving the space it occupied when visible. It uses ajax though, to fetch a seperate page for the alert box. and no matter where the button is at, in the page, it will always display the alert inside the same box.. whereas yours only displays it directly below the button.(if I did it right)

    I'm trying to find/make/get a script that will display the message(grabbed from another file(ajax)) in a div, and no matter where I have the button at, always have the messages displayed inside that div, not directly under the button. I want it to act like yours, in that it removes the space where the div occupied when it was visible, after it disappears.

    could you point me in the right direction?

  34. benant Says:

    That's a great trick and simple!! Thanks.

  35. benant Says:

    That's great trick and simple !! Thanks.

  36. Code4Gold Says:

    When I found this article, I was looking for a lightbox script with a fader but I'm glad I came across this because I wasn't familiar with JQuery library. Within 10 minutes of reading this article I was using JQuery library and the example here was a great start for somebody already familiar with JavaScript and coding to show the basic power of this great tool.

    Thanks for the article !!

  37. gtraxx Says:

    Great, I have adapted to perform some additional tasks :
    $('#dirConnect a#noframe').click(function (e) {
    e.preventDefault();
    var answer = $('#url_connex');
    if (answer.is(':visible')){
    answer.slideUp(400);
    //alert("La fenêtre de connexion est fermée");
    $('#connect_msg').html("La fenêtre de connexion est fermée").css({ border:"1px solid red" ,color:"red" }).insertAfter( $(this) ).fadeIn('slow').animate({opacity: 1.0}, 3000).fadeOut('slow');
    }else{answer.slideDown(400);
    //alert("La fenêtre de connexion est ouverte");
    $('#connect_msg').html("La fenêtre de connexion est ouverte").css({ border:"1px solid orange" ,color:"orange" }).insertAfter( $(this) ).fadeIn('slow').animate({opacity: 1.0}, 3000).fadeOut('slow');
    }
    return false;
    });

  38. ctraos Says:

    exelente plungin, muchas gracias, saludos desde Chile!!

  39. Florian Says:

    Cool Trick :)

    Do you have a tip for me how to modify this a little bit?

    I have a dropdown menu. Do open it I have to click a link which I defined:

    $("a.btn_options_bar").click(function () {
    $("div.menu_options").slideToggle("normal");
    $("a.btn_options_bar").toggleClass("btn_options_bar_act");
    });

    So, clicking on the button slides down the menu and sets the button to active
    status. Clicking again sets everything back. The menu consists of an div > .menu_options
    within this div there is a list (ul/li).
    To close the menu you have to click again. But I also want to hide the menu when I move
    out of the ul/li area after 1 sec. Hence I tried something with mouseout but the event starts at
    once. Any idea how to realize that kind of functionality?

    thanks indeed!

  40. Karl Says:

    Hi Florian,

    To get that to work, you'll need to use a standard JavaScript setTimeout() method. Or, you could take a look at the hoverIntent plugin:
    http://cherne.net/brian/resources/jquery.hoverIntent.html

  41. pig23 Says:

    that's great

  42. Danyal Says:

    Its perfect and cool... i like it :)

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <pre> <em> <i> <li> <ol> <strike> <strong> <ul>

IMPORTANT: If you wish to post code examples, please wrap them in <code> tags. Multi-line code should be wrapped in <pre><code> </code></pre> Also, use &lt; instead of < and &gt; instead of > in the examples themselves. Otherwise, you could lose part of the comment when it's submitted.