jQuery.each() is pretty sweet but earlier today I wanted to run some animations across a set of three elements and since the animate() calls are non-blocking everything was happening at the same time. What I wanted to do was have the functions execute in a serial fashion (1 after the other).

I poked around and it doesn’t look like there’s a native way to do this. After a bit I decided to just whip something up and see how it works. Here’s what I had originally:

$("#splashStream .snippetbox").each( function(index){
	$(this).animate( {opacity: 0}, 1000, function(){
		$(this).html( $("#hiddenSplashDiv .snippetbox:eq(" + index + ")").html() );
		$(this).animate( {opacity: 1}, 2000 );
	});
});

That ran fine but everything happened at the same time. The modified serial code looks like:

                  var hasCallbackCompleted = [ true ];
                  $("#splashStream .snippetbox").each( function(index){
                      
                      var f = arguments.callee;
                      var args = arguments;
                      var t = this;
                      
                      if( !hasCallbackCompleted[ index ] ){
                        window.setTimeout( function(){ f.apply(t, args); }, 5 );
                        return true; 
                      }
                      
                      hasCallbackCompleted[ index + 1 ] = false;
                      $(this).animate( {opacity: 0}, 1000, function(){
                          $(this).html( $("#hiddenSplashDiv .snippetbox:eq(" + index + ")").html() );
                          $(this).animate( {opacity: 1}, 2000, function(){
                            hasCallbackCompleted[ index + 1 ] = true;
                          });
                      });
                     
                  });

Basically, what it does is after the first element, the code will delay execution of the each() function until the hasCallbackCompleted flag is set for the correct element.