Home > javascript, jquery > Sequentially chain your callbacks in jQuery – Three ways

Sequentially chain your callbacks in jQuery – Three ways

August 22nd, 2008

I had a challenge to get four divs to fade in sequentially.

Writing this out the long way is not really my favorite:

$("#vehicle1").fadeIn("slow", function(){
  $("#vehicle2").fadeIn("slow", function(){
    $("#vehicle3").fadeIn("slow", function(){
      $("#vehicle4").fadeIn("slow");
    });
  });
});

Ewwww. right?

After some conversation in the #jQuery IRC channel, I present twothree classier ways of accomplishing the same thing:

Self-executing callback chaining

(function showVehicle(elem){
  elem.fadeIn('slow',function(){
    $(this).next().length && showVehicle($(this).next()); 
  });
})( $("div.vehicle:first") );

Custom event triggering (via: ajpiano)

$('div.vehicle')
  .bind('showVehicle',function(e) {$(this).fadeIn('slow',function(){ 
    $(this).next().length && $(this).next().trigger("showVehicle"); 
  })})
  .eq(0)
    .trigger('showVehicle');
Update 2009.06.15: I'm incredibly impressed with temp01's solution in the comments. So that's my recommendation going forward:

Self-executing callback chain on an arbitrary jQuery object (via: temp01)

(function hidenext(jq){
    jq.eq(0).fadeOut("fast", function(){
        (jq=jq.slice(1)).length && hidenext(jq);
    });
})($('div#bodyContent a'))

Paul Irish javascript, jquery

  1. November 25th, 2008 at 17:57 #1

    I won't have you diss my way of doing it on IRC ;)

    Here it another way of doing a recursive call with jQuery:

     
    $(function(){
      recursiveFunction();
    });
     
     
    function recursiveFunction(){
      $('div:not(.recursiveRun):first').animate({width: '100px'},function(){
      $(this).addClass('recursiveRun');
        recursiveFunction();
      });
    }

    It might not be all that pretty and jQuery-like, but it still works.. :)

  2. temp01
    June 5th, 2009 at 13:42 #2

    Another way – works on any jquery object(not just on sibling elements):

    (function hidenext(jq){
        jq.eq(0).fadeOut("fast", function(){
            (jq=jq.slice(1)).length && hidenext(jq);
        });
    })($('div#bodyContent a'))
  3. June 5th, 2009 at 13:46 #3

    @temp01 That is very very nice, temp01. As far as flexibility is concerned, I think that's the nicest implementation here.

  4. July 29th, 2009 at 07:15 #4

    @Paul Irish
    I'm trying to develop a similar effect of the ted.com site where elements load sequentially over time. Can this solution work for that with times (500, 1000, 1200) instead of range settings (slow, medium, fast)?

  5. August 3rd, 2009 at 17:03 #5

    @Trey Yah totally. Just replace the 'fast' shorthand with a millisecond value.

    You could also do something like:

    jq.eq(0).fadeIn([500,1000,1200][Math.floor(Math.random()*3)], function(){

    for some randomness.

  6. September 14th, 2009 at 17:37 #6

    i have just achieved the effect by a simple computer science 101 recursive function:

    $(document).ready({
    //say you have a div id=text with say 10 paragraphs... first hide them:
    $("#text p").hide();
     
    //then call the recursive function on the first p tag
    fadeUpR($("#text p:first"));
     
     
    });
     
    function fadeUpR(e){
     
    	$(e).fadeIn(500, function(){
    		if($(e).next("p").length != 0){
    			fadeUpR($(e).next("p"));
    		}
    	});
     
    }
  7. September 14th, 2009 at 18:01 #7

    another prettier way to do it, rather than waiting for the callback to fire, is to start each element fading up at a certain increment, say 200ms apart each, but have each element take longer than the triggering increment to complete its fade up. this is a prettier look.

    $(document).ready({
       //say you have a div id=text with say 10 paragraphs... first hide them:
       $("#text p").hide();
     
       for(i=1;i<=$("#text p").length; i++){
          setTimeout("fadeUp($('#text p:nth-child("+i+")'))", 100*i);
       }
     
    });
     
    function fadeUp(e){
       //note that this function could perform whatever you want on element e
       $(e).fadeIn(2000);
    }
  8. adolfo
    October 20th, 2009 at 06:45 #8

    @temp01
    really neat huh?

  9. October 21st, 2009 at 04:33 #9

    Here is one that I've been using. It fades in items sequentially then after a brief pause slowly fades them out again.

    		$(function(){
     
    			var delay = 100;
    			$("#menu div").each(function(){
    				var fade = $(this);
    				showItem(fade,delay);
    				delay += 250;
    			});
     
    		});
     
    		function showItem($o,n) { 
    		  setTimeout(function() {
    		     $o.fadeIn(1000);
    		     setTimeout(function(){
    			     $o.fadeOut(3000);    
    		     }, 3000);
    		  }, n); 
    		}
  10. February 19th, 2010 at 15:44 #10

    This one comes from NetTuts (http://tinyurl.com/ycm4bap), slightly modified to use a named function instead of arguments.callee (depricated):

    var elems = $('div.vehicle'), i = 0;
     
    // If using jQuery 1.3 or lower, you need to do $(elems[i++] || []) to avoid an "undefined" error
    (function fadePlz(){
      $(elems[i++]).fadeOut('slow', fadePlz);
    })();
  11. March 19th, 2010 at 21:19 #11

    @temp01 Cool! Favorite script of the day

  12. carl
    April 21st, 2010 at 04:31 #12

    @temp01
    Is this executable code? (A function in brackets, etc.?) I would love a short explanation how this works.

  13. temp01
    April 21st, 2010 at 17:21 #13

    @carl
    Yes, it's executable. The '(function foo(){ })(…)' is just a self-invoking function, see Decoding Self-Invoking Anonymous Functions.

  14. July 15th, 2010 at 00:49 #14

    I've created a simple plugin that can fade in elements sequentially.

    http://www.thewebsqueeze.com/web-design-tutorials/sequential-fade-in-jquery-plug-in.html

    While the code is not nearly as elegant as the ones listed here, the function call is nice, simple, readable, and chain-able.

    An example function call with my plugin is:
    $(elem).children().fadeInSequence();

  15. August
    November 23rd, 2010 at 17:46 #15

    great code! temp01!!
    I have question though.. how to invoke the function again once it finished?
    Thank you..!

  16. j
    January 2nd, 2011 at 18:20 #16

    hi temp01;

    im new to this , is there a way to post a demo ? ( like displaying result from remote file )

    tks
    jeff

  17. April 12th, 2011 at 02:13 #17

    @j
    http://jsfiddle.net/AEPEP/ check the console

  18. John
    June 30th, 2011 at 20:50 #18

    I am using Temp01's method and was wondering how it would be possible to reverse the sequence to start from the last item or to even start from any item and fade in the remaining items.

    Thanks

  19. August 15th, 2011 at 11:08 #19

    @temp01
    Thanks for this awesome snippet, it works well and is helpful. I am having a hard time understanding how to run more than the fadeOut operation with this code, i would like to make a pulsing effect by fadein in then fading out for each item. Appreciate any response

  20. August 15th, 2011 at 11:23 #20

    @August
    I figured it out lol…. heres an example for my situation in which i wanted a pulsing effect for each item in the selector at the end, hopefully it helps

    (function hidenext(jq){
    jq.eq(0).fadeOut(100, function(){
    $(this).fadeIn(100, function() {

    });
    (jq=jq.slice(1)).length && hidenext(jq);
    });
    })($('.homeherowrap > div'))

  21. Alejandro
    December 5th, 2011 at 09:16 #21

    I don't like jQuery, but for me

    $("#vehicle1").fadeIn("slow", function(){
      $("#vehicle2").fadeIn("slow", function(){
        $("#vehicle3").fadeIn("slow", function(){
          $("#vehicle4").fadeIn("slow");
        });
      });
    });

    Is the easiest to read…

  1. June 11th, 2010 at 17:46 | #1
  2. May 27th, 2011 at 19:47 | #2
  3. November 27th, 2011 at 23:44 | #3

For code blocks, use <pre lang="javascript">. css and html4strict are also accepted.

i left this space here for you to play. <3