3

Adding a sequence of animations to a single dom element using jQuery is extremely easy. jQuery queues everything up nicely for me and I basically don't have to do anything.

However making a sequence of animations over a number of elements (eg pictureDiv fades out, then demographicsDiv fades in) is much harder. I've written a plugin type thing to make it easier as below:

var something.createAnimationQueue = function () {

    // jQuery queues up animations on each dom element (/ jquery object)
    // We want to queue up animations over different dom elements so 
    // use a jquery object on a blank element
    var animationQueue = $({});

    return {
        add: function (animationFunctionContext, animationFunction) {
            var args = $.makeArray(arguments).slice(2);
            animationQueue.queue(function (next) {
                $.when(animationFunction.apply(animationFunctionContext, args)).done(next)
            })
        }
    }
}

Which is used thusly

        var animationQueue = something.createAnimationQueue();

        animationQueue.add(pictureDiv, pictureDiv.fadeOut, 'slow');
        animationQueue.add(demographicsDiv, demographicsDiv.fadeIn, 'slow');

My questions are:

1) Have I missed something? Is there an easier way of doing this that I didn't know about.

2) If not, is there a way to avoid passing pictureDiv and pictureDiv.fadeOut to the animationQueuer? (I tried and couldn't think of one)

Thanks!

Chris Moschini
  • 36,764
  • 19
  • 160
  • 190
cedd
  • 1,741
  • 1
  • 21
  • 34
  • And I assume you want to do this because the built-in callbacks would be too verbose? – Shmiddty Oct 01 '12 at 14:39
  • @Shmiddty Yep, just chaining a couple of things using callbacks or promises is fine, but if you are doing, say, 20 then things get ugly very quickly. – cedd Oct 02 '12 at 15:14
  • One problem is that you can't call callbacks for some of the animations, is there a way to do that? – Aleix Nov 18 '12 at 14:59
  • Hi @Tebb. Are you saying that "$.when(animationFunction.apply(animationFunctionContext, args)).done(next)" doesn't work as you would expect? If not I'm afraid I don't understand the question. – cedd Nov 19 '12 at 15:25
  • I haven't tested this code, but if I want, for example, to make an alert between `animationQueue.add(pictureDiv, pictureDiv.fadeOut, 'slow');` and `animationQueue.add(demographicsDiv, demographicsDiv.fadeIn, 'slow');`, how would I do it? – Aleix Nov 19 '12 at 15:31
  • Hi @Tebb. jquery can handle functions that aren't deferred objects, it just returns straight away. I tried the code out that you wanted, and bizarrely window.alert doesn't have the apply method. I don't really understand this, but you can get round it by using the code below (ie passing in a function which does have the apply method, which then calls window.alert). animationQueue.add(window, function () {window.alert('hello');}); – cedd Nov 22 '12 at 11:08
  • possible duplicate of [How can I animate multiple elements sequentially using jQuery?](http://stackoverflow.com/questions/1218152/how-can-i-animate-multiple-elements-sequentially-using-jquery) – Chris Moschini Oct 19 '14 at 09:05

1 Answers1

3

Since you are using .apply and reassigning this, you could simply use

var animationQueue = something.createAnimationQueue();

animationQueue.add(pictureDiv, $.fn.fadeOut, 'slow');
animationQueue.add(demographicsDiv, $.fn.fadeIn, 'slow');

And if you really wanted to, you could turn that into a string:

var something.createAnimationQueue = function () {

    // jQuery queues up animations on each dom element (/ jquery object)
    // We want to queue up animations over different dom elements so 
    // use a jquery object on a blank element
    var animationQueue = $({});

    return {
        add: function (animationFunctionContext, method) { // <----
            var args = $.makeArray(arguments).slice(2);
            animationQueue.queue(function (next) {
                $.when($.fn[method].apply(animationFunctionContext, args)).done(next) // <----
            })
        }
    }
}

var animationQueue = something.createAnimationQueue();

animationQueue.add(pictureDiv, 'fadeOut', 'slow'); // <----
animationQueue.add(demographicsDiv, 'fadeIn', 'slow'); // <----

Note, however, this can't be used for more than just animations now. You could use this with any jQuery method that returns a promise object, such as .ajax, .post, .get, .getJSON, etc. if you used it like you originally had it.

Chris Moschini
  • 36,764
  • 19
  • 160
  • 190
Kevin B
  • 94,570
  • 16
  • 163
  • 180
  • Couldn't it be taken a step further with just passing in `"fadeOut"` and then `$.fn[animationFunction].apply...`? – Shmiddty Oct 01 '12 at 14:40
  • @Shmiddty Yup, I was writing it up, it is now posted. – Kevin B Oct 01 '12 at 14:41
  • Good answer. I thought about $.fn. but it seemed like I was just replacing (say pictureDiv) with something else and I wasn't that excited about it. Referencing the jquery prototype's properties using the string is really neat and I like it, although I'm probably not going to actually use it, in case I want to add non jquery stuff to the queue. – cedd Oct 01 '12 at 14:56