Quick Tip: Easy Sequential Animations in jQuery
videos

Quick Tip: Easy Sequential Animations in jQuery

In this video quick tip, I’ll demonstrate an easy way to allow for sequential animations of an infinite number of elements. I originally learned this technique from Dave Methvin, but don’t think that many people are aware of this neat little trick.


The Goal

We want to filter through an infinite number of elements on a page, matching some selector, and then make them sequentially fade out.

The HTML

<body>
  <p>Watch</p>
  <p>Me</p>
  <p>Disappear</p>
</body>

The jQuery

var paras = $('p'),
    i = 0;

// If using jQuery 1.4, you don't need to do || [].
(function() {
  $(paras[i++] || []).fadeOut('slow', arguments.callee);
})();

We begin by “caching” all of the paragraphs on the page, wrapped in the jQuery object (var paras). We also create an iterator variable – i. This iterator will allows us to target each new paragraph element, without knowing the specific length of the paras object ahead of time.

Within the self-invoking anonymous function, we get the first paragraph on the page with “paras[i]” … But we want to increment i by one for each iteration. This way, the next time the selection is called, it’ll be referring to the next element in the wrapped set. So, we must be sure to write paras[i++]. Then, it’s a simple matter of calling fadeout, and passing arguments.callee as the callback function, to allow for recursion. This will be equal to the function it’s contained in; so we’re essentially saying “rinse and repeat!”

alert(arguments.callee); // alerts the following

 (function() {
  $(paras[i++] || []).fadeOut('slow', arguments.callee);
})();

Note

If, for some reason, you’re using jQuery 1.3 or older, you need to specify what should happen when paras[i] is equal to an element that doesn’t exist. In older versions of jQuery, it returns an error, “undefined.” To compensate, we pass $(paras[i++] || []) to specify that, if the element doesn’t exist, we instead wrap an empty array, to avoid any errors.

It should be noted that, as of jQuery 1.4, this is unnecessary, as jQuery will return the jQuery object instead.

Note: Want to add some source code? Type <pre><code> before it and </code></pre> after it. Find out more
  • Emir

    Very nice Jeffrey

    • nabeel

      yh jeff, keep it up.

  • http://proworks.com/blog Jason P

    Nice tip!

    Hadn’t seen that method before. Thanks!

  • http://www.tehnrd.com Jason

    Very cool. Great tip.

  • http://r-sully.com Ryan Sullivan

    The i++ confused me for a moment, I thought you would need ++i, but now I understand. Very nice!

    • http://www.jeffrey-way.com Jeffrey Way
      Author

      Nope – because ++i would first increment i. We want to get the first paragraph…and then increment i by one…preparing it for the next loop.

  • http://www.kriesi.at Kriesi

    For those of you that (like me :D ) didnt really get the arguments.callee, this might be interesting for you, a little in depth explanation:

    https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Functions_and_function_scope/arguments/callee#Example.3a_Using_arguments.callee_in_an_anonymous_recursive_function

    Neat little trick Jeffrey! :)

    • http://www.jeffrey-way.com Jeffrey Way
      Author

      Thanks, Kriesi. I’ll add a link to that page in the article above.

  • http://inspiredbywordpress.co.uk Daniel Groves

    Very nice, Will be using it in the near future I suspect.

  • http://www.ipadfactory.fr Thierry

    Great tip. I want to see little screencasts like this everyday ;)

  • http://lickynee.com/ lickynee

    I love these quick tips, they’re the best part of Nettuts

  • http://twitter.com/michalkozak Michal Kozak

    Nicely done, very useful useful.

    I only wish I knew this before :).

  • begs

    I wanted to ask, if the arguments.callee method works infinite in the background and consumes memory, what means that it calls the calling function as long as the user has the page open, or does ist stop the first time it doesn’t find a element in this case.

    Nice tip, and i love quick tips!

    • Richard

      I was wondering the same thing, anyone have any info on this?

      Btw Jeff, thank you as always for sharing your knowledge.

      • http://www.jeffrey-way.com Jeffrey Way
        Author

        No, it does not. Because the jQuery set, after there are no more elements that match the iterator, doesn’t contain any dom elements, nothing is passed to the fadeout method. Any if nothing is passed, the method doesn’t run.

  • http://james.padolsey.com James Padolsey

    Nice trick! Apparently, arguments.callee has been deprecated in ES5 – in strict mode it’ll throw an exception. More info: http://ejohn.org/blog/ecmascript-5-strict-mode-json-and-more/ – this sucks quite a bit – and makes no sense to me.

  • dedego

    You could always get the number of Paragraphs using jQuery .size or .length and make a while loop. Something like this:

    var paras = $(‘p’),
    i = 0;

    // If using jQuery 1.4, you don’t need to do || [].
    (function() {
    // -1 is becouse it gets the number of paragraphs instead of their index number
    while(i < (paras.size()-1)) {
    $(paras[i++] || []).fadeOut('slow', arguments.callee);
    }
    })();

    Offcourse i could be mistaken, since I havent used arguments.callee that much. But i'd like to hear more idea's since Begs got a good point there.

    gr. dedego

  • Dennis

    You could always get the number of Paragraphs using jQuery .size or .length and make a while loop. Something like this:

    while(i < (paras.size()-1))

    Offcourse i could be mistaken, since I havent used arguments.callee before. But i’d like to hear more idea’s since Begs got a good point there.

    gr. dedego

  • Dennis

    You could always get the number of Paragraphs using .size() or .length() and make a while loop (offcourse it isnt the same as an Index number, but it ‘could’ do the trick).

    Offcourse i could be mistaken, since I havent used arguments.callee before. But i’d like to hear more idea’s since Begs got a good point there.

    gr. dedego

  • http://sonergonul.com Soner Gönül

    Nice..

    Thanks !

  • http://luckykind.com Danny

    Nice Job, Jeffrey! Should come in handy and keep my code clean in the future… :)

  • Martin

    What about this solution:

    var i = 0;
    $(‘p’).each( function(){
    $(this).delay(i * 500).fadeOut(“slow”);
    i++;
    } );

  • Dan

    @Jeffery You probably get asked this all the time, but what application do you use that lets you write keywords for snippets of code? Example: you typed in “html body” and all the code to start a basic HTML file appeared.

    • http://www.jeffrey-way.com Jeffrey Way
      Author

      For Mac, check out TextExpander. For PC, see Texter. :)

      • http://tutsvalley.com Slobodan Kustrimovic

        Jeffrey, you have that response in TextExpander, don’t you :)

    • http://www.lipsmack.co.uk/ Gary Chambers

      And in the outside chance that you’re using Linux, the default GNOME text editor (gedit) has a snippets plugin that allows the same functionality. Saves me a lot of time.

  • http://www.alanagius.com Alan

    Nice, Thanks

  • http://www.jordanwalker.net Jordan Walker

    That is a really neat magic show, I wonder what the practical application would be?

  • Marshall

    Jeff,

    I just want to say thank you for all the hard work you do for Nettuts+ (and, of course, its audience :-P ). It’s rare to find someone who has a passion for something like you do, and even more rare for that person to have the will and ability to share what they know. I have learned so much from watching your screencasts, and I am so grateful for the help you’ve been. Keep up the awesome work!

    • http://www.jeffrey-way.com Jeffrey Way
      Author

      Thanks, Marshall!

  • brett

    I don’t really see how this method is any less cluttered than the first thb…

    • http://www.jeffrey-way.com Jeffrey Way
      Author

      How it’s better than using callback functions? It’s much better because it can be more dynamic…not to mention that, in our example, you would need two nested functions to mimic the effect.

      • Pat

        Actually the callback is called implicitly. I guess it makes the code more compact, but it’s not as verbose. Here is an implementation that can be used in the same matter with the possibility to select the amount of iterations.

        This doesn’t check the total size of the array, the code user must know what he is doing.
        //Array of 25 li elements
        var arr = $(“#deckHand ul li”), i=0;

        function seqDisplay(arr, ite, cap) {
        if(ite == cap) return;
        $(arr[ite++]).fadeIn(‘slow’, function() {
        seqDisplay(arr, ite, cap)
        });
        }
        seqDisplay(arr, 0, 10);

  • http://twitter.com/xrommelx xRommelx

    awesome, i prefer to use MoTools but i want to learn some JQuery a i really appreciate this TUT

  • http://blog.devlpr.net Rick Schott

    Love it, great demo.

  • goran

    congrats you have written unreadable code

    • http://www.jeffrey-way.com Jeffrey Way
      Author

      Nobody said it was perfect. But it might be your best option. Have a better idea?

    • http://james.padolsey.com James Padolsey

      How on earth is it unreadable? … If you know JavaScript and have a decent understanding of jQuery’s API then it couldn’t be simpler. What level of understanding should we have to accommodate when considering readability, hmmm?

    • http://www.seowisedesigns.com Yheng

      Do you have a better idea than that? Even me as a beginner does understand how things work and I think Jeffrey did it very well.

  • http://www.4meble.pl Meble

    Very nice tut!

  • w1sh

    Looks really interesting, but I wonder if there is a way to mix and mash elements?

    Like what if I wanted the first 3 p elements to disappear and then 2 divs to slide from the left and then 1 p element turn red?

  • http://tutorialblog.info/ tutorial blog

    thank. tutorial very useful

  • http://boylecreations.com Aidan Boyle

    Great tutorial thanks a lot!

    However, there is one thing. After replicating the effect with some other jquery animations like slideUp, I went to make the effect trigggerable from a click event. I didn’t change any code from what you provided but the end result was that only 1 animation happened instead of all 3. Any thoughts on that? I can post code if you need it. Thanks!

  • http://www.e11world.com e11world

    Nice tutorial and actually taught me something today!

  • http://www.alpaproductions.com alpaproductions

    I just had to tweet this because I know it will help many people as much as it helped me get started with this stuff! jQuery ROCKS!!

  • http://bengiordano.com/ Ben Giordano

    Having a bit of trouble getting this going. Hoping to use the fadeIn instead of fadeOut, does the same code/logic apply?

  • http://- Sarb

    Really like your solution, but i couldn’t get it to work while trying to append each to another div. In my case, i am trying to populate a results container and have each to fadeIn one at a time.

  • Saurabh