1

I am having some serious issues making the JQuery queue work. All the defined functions execute at once, so the class change occurs before the animation- we want it to fade out, then change class, THEN fade back in.

function animatePlusMinus(){
    if ($(this).hasClass("ui-icon-minus")) {
        $(this).queue("goPlus",function(next) {
                $(this).fadeOut(500);
                next();
            })
            .queue("goPlus", function (next) {
                $(this).removeClass("ui-icon-minus").addClass("ui-icon-plus").fadeIn(500);
            })
            .dequeue("goPlus");

    } else if ($(this).hasClass("ui-icon-plus")) {
        $(this)
            .queue("goMinus", function (next) {
                $(this).fadeOut(500);
                next();
            })
            .queue("goMinus", function (next) {
                $(this).removeClass("ui-icon-plus").addClass("ui-icon-minus").fadeIn(500);
            })
            .dequeue("goMinus");
    }
}

I could do this simple example with the callback function on fadeOut, however I'd like to expand this logic in a way which would need a proper queue. I also need to learn how to use .queue()!

UPDATE: Here is an JSFiddle

Jess
  • 345
  • 1
  • 3
  • 17

1 Answers1

1

Right now, you're calling next immediately after having started the fading.

A solution is to pass next as callback to fadeOut:

function animatePlusMinus(){
    if ($(this).hasClass("ui-icon-minus")) {
        $(this).queue("goPlus",function(next) {
                $(this).fadeOut(500, next);
            })
            .queue("goPlus", function (next) {
                $(this).removeClass("ui-icon-minus").addClass("ui-icon-plus").fadeIn(500);
            })
            .dequeue("goPlus");

    } else if ($(this).hasClass("ui-icon-plus")) {
        $(this)
            .queue("goMinus", function (next) {
                $(this).fadeOut(500, next);
            })
            .queue("goMinus", function (next) {
                $(this).removeClass("ui-icon-plus").addClass("ui-icon-minus").fadeIn(500);
            })
            .dequeue("goMinus");
    }
}

But if you're looking in a more generic solution, you'd probably better dive into promises rather than into queues. Here, with jQuery's implementation of promises, you could do

function animatePlusMinus(){
    if ($(this).hasClass("ui-icon-minus")) {
        $(this).fadeOut(500).promise().then(function(){
            $(this).removeClass("ui-icon-minus").addClass("ui-icon-plus").fadeIn(500);
        });
    } else if ($(this).hasClass("ui-icon-plus")) {
        $(this).fadeOut(500).promise().then(function(){
            $(this).removeClass("ui-icon-plus").addClass("ui-icon-minus").fadeIn(500);          
        });
    }
}
Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • Without`dequeue` the queue doesn't start at all though. Without `next`, it doesn't move to the next function. – Jess May 13 '15 at 15:44
  • Thank you! I knew it would be something silly. The promises interface looks promising* for the future but it seems like support isn't wide enough on browsers yet *(heh) – Jess May 14 '15 at 07:50
  • @Jess Right now I don't recommend using promises in the browser (I use it a lot on node/io.js) but using jQuery promises when available (for example here or on ajax queries) is a step in the right direction and immediately makes your code cleaner. – Denys Séguret May 14 '15 at 08:21
  • @Jess: FYI jQuery promises work on all browsers that jQuery works on (which is pretty much everything). Using queues is a lot messier as `dystroy` shows – iCollect.it Ltd May 14 '15 at 11:31
  • I assume JQuery has it's own mechanism then? Native javascript promises aren't well supported yet from what I can see – Jess May 14 '15 at 12:59
  • When you do `$(this).fadeOut(500).promise()` you're getting a jQuery promise, not a native one. That's what I meant with *"jQuery's implementation of promises"* in my answer. – Denys Séguret May 14 '15 at 13:00