6

I'm trying to create an effect that works in a queue, so that each effect starts only after the previous one finished. I was successful, but I'm sure that there's a cleaner way.

This is what I have so far:

$("tr:last td:nth-child(1) div").slideUp(200, function() {
    $("tr:last td:nth-child(2) div").slideUp(200, function() {
        $("tr:last td:nth-child(3) div").slideUp(200, function() {
            $("tr:last td:nth-child(4) div").slideUp(200, function() {
                $("tr:last td:nth-child(5) div").slideUp(200, function() {
                    $("tr:last td:nth-child(6) div").slideUp(200, function() {
                        $("tr:last td:nth-child(7) div").slideUp(200, function() {
                            $("tr:last").remove();
                        });
                    });
                });
            });
        });
    });
});

There's gotta be a cleaner way, right?

Much obliged in advance.

Cesar
  • 3,519
  • 2
  • 29
  • 43
rpophessagr
  • 905
  • 3
  • 10
  • 17

3 Answers3

7

Just as you say in your question. Use .queue().

http://api.jquery.com/queue

and check:

What are queues in jQuery?

Community
  • 1
  • 1
Marnix
  • 6,384
  • 4
  • 43
  • 78
  • Does it queue effects on different elements? Reading the documentation I would say *no*, every element has its own queue. How would you use `queue` then? – Felix Kling Jan 12 '11 at 12:08
4

Ouch, that's horrid! I'd do it by using delay:

var divs = $("tr:last td div");
divs.each(function(idx, el) {
    $(this).delay(idx * 200).slideUp(200, function(){
        if (idx === divs.length - 1) { // 0-based index
            $("tr:last").remove()
        }
    });
});
lonesomeday
  • 233,373
  • 50
  • 316
  • 318
  • Wow! Beautiful! Thanks! Can I do this with an each loop? – rpophessagr Jan 12 '11 at 12:10
  • The new version looks even cleaner... nice :) +1 – Felix Kling Jan 12 '11 at 12:17
  • Would you mind please explaining what you did with the 'idx' and 'el', not quite following it. =) – rpophessagr Jan 12 '11 at 12:25
  • 1
    @user [See the documentation for `each`](http://api.jquery.com/each). `idx` is the position of the element in the selection; `el` is the element being processed and is identical to `this`. – lonesomeday Jan 12 '11 at 12:27
  • Thanks, one more thing. You took out the $("tr:last").remove(); which is crucial for me to be able to run this multiple times. I tried putting it back, but it just removed it without any delay. – rpophessagr Jan 12 '11 at 12:30
  • @rpophessagr I've put it back, inside a callback. Hopefully this will fix things for you. – lonesomeday Jan 12 '11 at 12:35
  • 1
    To make it more flexible, maybe better would be `if(($(this).closest('td').is(':last')) { /* remove */}`. Would be slower but not depend on the number of `td` s in the row. Or you count the `td` s beforehand. – Felix Kling Jan 12 '11 at 12:38
  • I would add len = $("tr:last td").length-2; at the beginning and replace 6 with len to keep the effect flexible if the author changes the number of tds – jackreichert Jan 12 '11 at 12:57
  • @jackreichert, Felix Changed. It seems safe to assume that there is one div per td. – lonesomeday Jan 12 '11 at 13:21
2

You could make a recursive function:

function slide(i) {
    if(i < 8) {
        $("tr:last td:nth-child(" + i + ") div").slideUp(200, function() {
            slide(i+1);
        });
    }
    else {
        $("tr:last").remove();
    }
}
slide(1);

But it is all very hardcoded....

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143