Paul Irish

Making the www great

Sequentially Chain Your Callbacks in jQuery - Three Ways

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

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

1
2
3
4
5
6
7
$("#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

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

Custom event triggering (via: ajpiano)

1
2
3
4
5
6
$('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)

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

The Two CSS Selector Bugs in IE6

Internet Explorer 6’s CSS selector support is a far cry from every other A-Grade browser. It doesn’t handle attribute tags, adjacent or child selectors, or the :first-child psuedo-selector. And yes, it sucks. We deal with it.

But beyond selectors not being implemented, there are two BUGS when it comes to selectors in IE6:

The multiple class bug
When you define rules like:

1
p.disclosure.warning { text-align: center; color: red; }
Most browsers will apply this to any P tags with both the class disclosure and warning. IE6, however, will only apply this to P tags with the last class mentioned; in this case, P tags with the class warning. so IE6 pretends like you wrote:

1
p.warning { text-align: center; color: red; } /* no .disclosure */
Workarounds are typically not hard, but staying aware of this fact will save you time debugging.
The ID-class bug
When you define a block like:

1
2
#tooltip.red { background: white; color: red; }
#tooltip.yellow { background: black; color: red; }
IE will ignore the the second rule. So even if you have a

1
<div id="tooltip" class="yellow">I'm on a black background in yellow text!</div>
, IE will not apply the CSS styles you had defined for it. If you have laid our rules for the same ID but different classes, it will ignore all CSS rules defined after the first one. (Your red tooltip will be fine).

Solutions:

  • Don’t let the #id.class combo be the last selector: Multiple selectors of this type #tooltip.yellow div will be fine.
  • Move the class to a parent container: div.yellow #tooltip will not mess up anything.
  • Make your classes be superspecific and dont use an ID in your selector: div.yellowtooltip. You’ll have to repeat yourself with duplicate CSS definitions, but you can thank IE6 for making your day miserable, yet again. :)