0

I am looking for some function that:

  • would be able to wait for all effects in the queue to finish
  • could be used in the classical jQuery call sequence

Example:

I want to do some animations and then some operations after they finish:

$('.obs_list')
.delay(500)
.animate({
        'background-color' : '#ffcc33'
}, 200)
.delay(1000)
.animate({
        'background-color' : 'transparent'
}, 2000)
.THE_FUNCTION_I_AM_LOOKING_FOR() 
.css({ 'color' : 'red' }) // this should come *after* the effects above are finished
...

I want to avoid the complete callback of the animate function since you have to call jquery again inside it, it is not very elegant and breaks the chain:

...
.animate({
        'background-color' : 'transparent'
}, 2000, function () {
        $(this)
        .css({ 'color' : 'red' })
        ...
});

I hate this solution.

I tried to use .promise() but this breaks the chain too as it apparently doesn't return the proper jQuery object. And please avoid writing new plugin :-)

Community
  • 1
  • 1
Tomas
  • 57,621
  • 49
  • 238
  • 373

2 Answers2

5

You have a few options:

queue:

.animate(...)
.queue(function (n) {
    $(this).css('color', 'red');
    n();
});

The queue callback will be called once per element in the collection when each of them have reached this function in the queue. This means that the queue callback will be called multiple times, and possibly at different times if the items have differing animations.

promise (with done):

.animate(...)
.promise()
.done(function () {
    $(this).css('color', 'red');
});

The done callback will be called once after all elements in the collection have emptied their queues completely. This is useful if you have a bunch of animations happening and you want to trigger something to happen when all of them have finished.

A custom jQuery plugin:

//I wrote this on the fly and it looks like it should work
//I haven't tested it, so let me know if there are any bugs
$.fn.queuedCSS = function () {
    var args = Array.prototype.slice.call(arguments);
    return this.queue(function (n) {
        $.fn.css.apply($(this), args);
        n();
    });
};

.animate(...)
.queuedCSS('color', 'red');

The complete callback of the animate call:

.animate(..., function () {
    $(this).css('color', 'red');
});

When the specific animation on this specific element has finished, the complete callback will run.

An animation that executes (almost) immediately:

.animate(...)
.animate({'color': 'red'}, 1);

As the animation is part of the fx queue and the duration is so short as to be immediate, the animation will complete and set the styles.


Now, I'm aware that you don't like any of these solutions, but that's too bad because they are the solutions. The css function does not interact with the fx queue, so if you want it to be part of the timed queue, you must use it within a callback in some way.

zzzzBov
  • 174,988
  • 54
  • 320
  • 367
  • +1 nice answer, you could add the `.animate()` trick mentioned by Jonathan. – Tomas Apr 17 '14 at 19:36
  • Great! I like the last animate trick most! The pitty is that I cannot use it when animating background color to transparent: `.animate({ 'background-color' : '' }, 1)` won't work. Would you know how to fix this? – Tomas Apr 17 '14 at 19:53
  • @TMS, `'background-color': 'transparent'` would be the correct value, but the reason why you can't animate to transparent is because it's ambiguous. If you want to animate from a color to a transparent color, you should use the `rgba` format. e.x. `'background-color': 'rgba(0, 0, 0, 0)'` – zzzzBov Apr 17 '14 at 20:39
  • Sorry, you haven't understood me, maybe I was not clear enough - the `.animate(,1)` command I mentioned was there to remove the css after the previous animation, see http://stackoverflow.com/a/4036868 and my question here: http://stackoverflow.com/q/23142051 – Tomas Apr 17 '14 at 21:05
  • @TMS, as I said, you can't animate to `background-color: transparent`. I had assumed you were making use of jQuery UI's color transformations, because jQuery doesn't support animating colors by default. – zzzzBov Apr 17 '14 at 21:18
  • 1
    1) You are completely mistaken here. I *can* animate to `background-color: transparent`, [I am already doing it and it works](http://stackoverflow.com/q/23142051/684229). 2) You keep to be confused here. Please look at my previous comment again and look at its first linked question. The animation to transparent is already working there! I am only trying to remove the css style *after* the transformation is done using the [Pekka's trick](http://stackoverflow.com/a/4036868) with your `.animate(,1)` trick, but it doesn't seem to work. – Tomas Apr 17 '14 at 21:39
  • @TMS, that must have changed, there was a point where animating to `background-color: transparent` would just immediately jump to transparent. As I'm obviously out of touch with the current state of things, I'm not sure how much help I'll be at the present time. Feel free to ignore my previous comments. – zzzzBov Apr 17 '14 at 21:43
1

Though it's not very elegant but it's a way to achieve the thing you want, try this code snippet :

var elements = $('.obs_list');
elements
.delay(500)
.animate({
        'background-color' : '#ffcc33'
    //see the use of proxy here to change the scope of callback function
}, 200, $.proxy(function(){
        this
        .css({ 'color' : 'red' });
}, elements)

You can find more about proxy here.

MD. Sahib Bin Mahboob
  • 20,246
  • 2
  • 23
  • 45