views:

37

answers:

2

Consider this code...

$(function() {

  for (var i = 0; i < 10; i++) {
    $('body').append('<div style="width: 30px; height: 30px; background: red; margin: 10px;" />')

    }

      $('div').slideUp(1000, function() {

        $('body').append('done sliding');

      });

});

(see it on JSbin)

It creates 10 divs and then slides them up. The callback is called 10 times, when I would prefer it to be called once (after all have finished sliding).

I know I could do a Boolean or something, like hasCalledCallback, but is there any other more elegant way to make multiple elements animating call a completion callback only once?

+5  A: 

try this

if ($('div:animated').length == 1)
        $('body').append('done sliding');

demo

Reigel
+1..for elegant solution..but I think it should be ($('div:animated').length < 1) or ($('div:visible').length < 1).Otherwise, the statement will be executed after the one before the last has slid up.
Kai
@kai - trust me, that was my first thought... well, please try playing with the demo... :)
Reigel
ohh! yes..u r rite!
Kai
This still calls the callback for each div...just doesn't do anything most of the time.
sje397
@sje397 - yes it is... and if you have a better idea, we're open to it.. :)
Reigel
+1  A: 

One possibility is to use setTimeout:

$(function() {

  for (var i = 0; i < 10; i++) {
    $('body').append('<div style="width: 30px; height: 30px; background: red; margin: 10px;" />');
  }

  var timerid;
  $('div').slideUp(1000, function() {
    clearTimeout(timerid);
    timerid = setTimeout(function() {$('body').append('done sliding')}, 100);
  });
});

To actually avoid calling the callback multiple times, only add it to the last div:

$(function() {

  var lastDiv, otherDivs = [];
  for (var i = 0; i < 10; i++) {
    div = $('<div style="width: 30px; height: 30px; background: red; margin: 10px;" />');
    $('body').append(div);
    if(i == 9) lastDiv = div;
    else otherDivs.push(div);
  }

  $.each(otherDivs, function(index, val) {
    val.slideUp(1000);
  });
  lastDiv.slideUp(1000, function() {
    $('body').append('done sliding');
  });
});

You could do that last part without the lastDiv and otherDivs variables by adding classes to the divs and selecting on those.

sje397
+1 ............
Reigel