jquery animating multiple elements
-
19-09-2019 - |
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
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.