Search code examples
jquerycallbackdelay

jQuery function callbacks and animation timing


I'd like to have a DIV fade in after fading another out. Because the one DIV is inside of the other, I need the parent DIV to fade out completely (clearing any other content that might be showing) before the child DIV then fades in. I tried using the jQuery callback function in my code below to no avail.

$('#viewer a').click(function(e) {
    e.preventDefault();
    $('#content > *').fadeOut(500, function(){
        $('#kiosk').fadeIn(250);
    });
});

The DIVs are jumpy, and it's obvious that the script is not waiting for the animation to complete before beginning the fading in of the other DIV. Why is this?

Nota bene: I know I could probably chain a .delay() or something of the sort, but I'd rather not tack on half of a second when the callback function is there for this exact purpose!


Solution

  • I'm guessing that part of the choppiness is from the fact that you are fading elements whose ancestors are currently being faded.

    When you fade something, it automatically fades its descendants as well, so you should probably do this instead.

    $('#content').children().fadeOut(500, function(){
        $('#kiosk').fadeIn(250);
    });
    

    Now keep in mind that the callback with the .fadeIn() will be called once for each element that is faded out. This could be an issue as well.

    Since (presumably) #kiosk is a direct descendant of #content, you could just directly chain the fadeIn() on the end. No .delay() is needed.

    Try it out: http://jsfiddle.net/rrM28/

    $('#content').children().fadeOut(500).filter('#kiosk').fadeIn(250);
    

    EDIT: From your updated example in the comment, the fadeIn() is running immediately because the #kiosk is initially hidden, therefore the animation is immediately complete for that one, and the chain continues.

    A solution is to place the .fadeIn() in an animation .queue() so that it will run only after the fadeOut() is complete.

    Try it out: http://jsfiddle.net/rrM28/4

    $('#viewer a').click(function(e) {
        e.preventDefault();
               // Don't fadeOut the #kiosk
        $('#content').children(':not(#kiosk)').fadeOut(500)
               // Place the fadeIn of #kiosk in the next step of the animation queue
            .queue(function() {
                $(this).siblings('#kiosk').fadeIn(250).dequeue();
            });
    });