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.
Questions or comments about this? Email us at contact@setfive.com.