Question

I'm trying to do the following:

I have two sets of DOM elements on a page. All elements in the first set carry the class display-element, and the second set of elements carry the class edit-element.

Now I have a button (id=edit-button). When I click this button, I want all the display-elements to fade out, and all the edit-elements to appear.

I naturally did:

$('#edit-button').click(function(){
    $('.display-element').fadeOut(300, function() {
        $('.edit-element').fadeIn(300);
    });
});

I found to my surprise that this did not work as expected. This is what happened: as soon as the first element with class display-element faded out, all the edit-elements started fading in.

Now is there any easy way (perhaps something in the documentation I missed) using which I can have all the edit-elements start fading in only after all display-elements have faded out?

Thanks
jrh

Was it helpful?

Solution

Why would this happen, really? I mean, it appears, that you are starting the animations at the same time (there is only one call to .fadeOut after all, right?). I guess, this is because $() yields an array and when you call .fadeOut, jQuery iterates through the array and performs whatever it performs for each of its elements. Starting from the first. Since the callback gets "attached" to every animation, you see the visible effect of the first callback.

I guess, you could sidestep this by iterating through the array of the returned elements yourself and making sure, that you attach the callback only to the last one.

$('#edit-button').click(function(){
    var display_elements = $('.display-element');
    var len = display_elements.length;
    for (var i = 0; i < len-1; i++) {
        $(display_elements[i]).fadeOut(300); // no callback
    }
    $(display_elements[len-1]).fadeOut(300, function() {
        $('.edit-element').fadeIn(300);
    }); // last element - attach callback
});

I am sorry if the code is off, I must admit, that my javascript-fu is not very strong :)

OTHER TIPS

Well, having not found any 'nifty API method', I resolved to this:

$('#edit-button').click(function() {
    var displays = $('.display-element');
    var counter = 0;
    var max = displays.length;
    displays.fadeOut(300, function() {
        counter++;
        if( counter>=max ) $('.input-element').fadeIn(300);
    }
});

This is essentially @shylent's answer, with more 'javascript-fu' :)

The solution is to use a setTimeout on the fading in function

$('#edit-button').click(function(){
    $('.display-element').fadeOut(300);
setTimeout("$('.edit-element').fadeIn(300);", 300);
});

That javascript function will delay the trigger of the the fading in function for 300 miliseconds

I just ran a similar issue and found the "step" callback option yielded the desired behavior.

step: A function to be called after each step of the animation.

^ http://api.jquery.com/animate/

Scroll down to the demo for step usage and you'll see how it will enable you to call animate on a single object then use step to update the rest your set at each step of the animation. This way you only have one callback fired when the animation completes.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top