Run jQuery each() serially
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.