0

I have a code like this:

for(i=0;i<somevalue;i++){
   $(".elem[order='"+i+"']").delay(i*duration).animate({opacity:0},duration);
}

and at when the last item animation completes, I want to execute

$(".elem").remove();

I'm currently doing this with

$(".elem[order='"+i+"']").animate({opacity:0},duration,
function(){
    if(i==somevalue-1){
        $(".elem").remove();
    }
});

But how can I do this with $.Deferred? I'm learning jQuery Deferred's and I couldn't solve this.

Taha Paksu
  • 15,371
  • 2
  • 44
  • 78

2 Answers2

1

UPDATE 2:

Here is a working example using $.Deferred:

<html>
    <head>
        <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
        <script type="text/javascript">
            $(document).ready(function () {
                $.Deferred(function (defer) {
                    var i;
                    var duration = 1000;

                    var pipe = function(defer, index, duration) {
                        return defer.pipe(function () {
                            return $(".elem[order='" + index + "']").animate({opacity: 0}, duration);
                        });
                    };

                    defer.resolve();

                    for (i = 0; i < 5; i++) {
                        defer = pipe(defer, i, duration);
                    }

                    defer.done(function () {
                        console.log("Done, removing all .elem");
                        $(".elem").remove();
                    });
                });
            });
        </script>
        <style type="text/css">
            body { padding: 20px; }
            .elem { border: 1px solid #000; padding: 10px; opacity: 1.0; }
        </style>
    </head>
    <body>
        <div class="elem" order="0">elem 0</div>
        <div class="elem" order="1">elem 1</div>
        <div class="elem" order="2">elem 2</div>
        <div class="elem" order="3">elem 3</div>
        <div class="elem" order="4">elem 4</div>
    </body>
</html>

UPDATE 1, BASED ON NEWLY INTRODUCED DELAY

To answer your comment below, I think your best bet is to simply fire off the callback on the animation that fires last. Since you're in full control of deciding duration (i.e. it's not a randomly generated duration), then you could compute what the last duration will be and use that to decide if it will be the correct iteration in which to fire the callback:

var i, callback, delay;
var onComplete = function () {
    console.log("Animations complete!");
};
for (i = 0; i < somevalue; i++) {
    delay = i * duration;
    callback = delay === ((somevalue - 1) * duration) ? onComplete : $.noop;
    //callback = i === somevalue - 1 ? onComplete : $.noop; //this can work too but doesn't check duration
    $(".elem[order='" + i + "']").delay(delay).animate({opacity:0}, duration, callback);
}

ORIGINAL ANSWER

It looks like you want all of these elements to start animating at the same time, and have the same duration. Based on this, I would suggest doing a single animate call, and modifying your approach to gathering the collection of elements.

Example:

var i, elements, selector;

for (i = 0; i < somevalue; i++) {
    selector = ".elem[order='" + i + "']";
    if (i === 0) {
        // Start the collection up with the first element
        elements = $(selector);
    } else {
        // Append element to the collection
        elements.add(selector);
    }
}

// Fire up the animation on all elements
elements.animate({opacity:0}, duration, function () {
    console.log("Animation complete!");
});

I haven't actually ran this code, but I'm pretty confident it should work.

matb33
  • 2,820
  • 1
  • 19
  • 28
  • I added a .delay() to the first code in the question while you were writing this I guess. The animations may vary btw. – Taha Paksu May 17 '12 at 14:15
  • sorry for the late answer, but I'm currently doing this with `if(i==somevalue-1) oncomplete();` in the callback function without questioning the delay. (and assuming the last loop's element is animating at last and it is the last one to execute the callback). I was asking how to use jQuery Deferred's in situations like this. Thank you for your effort though. – Taha Paksu May 24 '12 at 04:49
  • Ah yes, I see I pretty much looped back to your own solution... Stay tuned for an attempt at solving it with $.Deferred – matb33 May 24 '12 at 13:10
  • In the definition of `.pipe()` function, they wrote `.pipe([donefilter],[failfilter],[progressfilter])` and it's kinda misleading I think. Or I couldn't understand what it's used for. I thought it was something like `.done(method).fail(method).progress(method)`. Thanks for your effort. – Taha Paksu Jun 02 '12 at 20:36
0

you have to declare variable datatype like var i.

for(var i=0;i<somevalue;i++){
   $(".elem[order='"+i+"']).animate({opacity:0},duration);
}
mohana rao
  • 433
  • 3
  • 13
  • No, the code is a prototype of my current code, and my current code is working. This answer is not related to the question. – Taha Paksu May 17 '12 at 14:03