0

I'm trying to combine matching something like:

$(".item").each(function(i) {
    //animation here
});

with jQuery's inherent chaining functionality that forces the animation to wait until the previous animation has completed, e.g.:

$(".item").each(function(i) {
    $(this).animate({marginLeft:"0"}, 60);
});

And then trigger a .load function after the animations have completed. Basically, I want to fade four items out in order [one after the next, not all at once], then load four new items into the same div, replacing the first four.

How can I do this in a reusable/variable way?

Mike G
  • 4,232
  • 9
  • 40
  • 66
Aaron
  • 4,634
  • 1
  • 27
  • 43

5 Answers5

5

How about checking if the element is the last one and then adding a callback?

$(".item").each(function(i, elem) {
    var callback = $(elem).is(':last') ? function() {
        //dosomething
    } : function(){};
    $(this).animate({marginLeft:"0"}, {duration: 60, complete: callback);
});
David Hellsing
  • 106,495
  • 44
  • 176
  • 212
4

Just specify a callback for the animations and track how many items have been faded out. Then, when they're all done, remove them and add the new ones.

var items = $('.item');
var parent = items.parent();
var itemCount = items.length;
items.each(function()
{
    $(this).fadeOut('medium', function()
    {
        itemCount--;
        if (itemCount == 0)
        {
            // Remove the items and add the new ones.
            items.remove();
            parent.append('...')
        }
    });
});
Will Vousden
  • 32,488
  • 9
  • 84
  • 95
  • Thanks for the help - upvoted, but ultimately marked David's. – Aaron Jan 04 '10 at 21:53
  • Ok, finally getting a chance to read though these. Neither of these is accomplishing the task. jQuery's animation chaining sets up animations such that one must complete before the next begins. That's what I'm looking for :\ – Aaron Jan 05 '10 at 15:13
  • So you want to fade them out one by one, then add them one by one? – Will Vousden Jan 05 '10 at 15:30
  • Yes, I have appended a solution I wrote that gets the job done. – Aaron Jan 05 '10 at 15:34
2
$("#more:not(.disabled)").live("click", function(event) {
    event.preventDefault();

    var urlPieces = (event.target.href).split("/");
    var nextURL = urlPieces[urlPieces.length - 2] + "/" + urlPieces[urlPieces.length - 1];
    var items = $(".item");
    var itemCount = items.length;   

    items.each(function(i) {
        var passthru = this;
        window.setTimeout(function() {
            $(passthru).animate({opacity:"0"}, 60, function() {
                if (i == itemCount - 1) {
                    $("#browse").load(nextURL + " .item, #controls", fadeInNew);
                }
            });
        }, 60*i);
    });
});

fadeInNew handles the new one by one fade in elsewhere, but this was what I was looking for more or less with a bit of extra code around it to maybe shed some light on what was happening (there's a next arrow with a url in its href, if javascript is on, I need the URL of the next page relative to the current, if it's off, it follows that url as an href and loads a new page which has the same content on the page except for the new items that would have been $.load-ed.

Aaron
  • 4,634
  • 1
  • 27
  • 43
1

Just update delay like this:

$(".item").each(function(i) {
    $(this).delay(200*i).animate({marginLeft:"0"}, 60);
});
ul li.item {
  margin-left: 50px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
  <li class="item">List 1</li>
  <li class="item">List 2</li>
  <li class="item">List 3</li>
  <li class="item">List 4</li>
  <li class="item">List 5</li>
  <li class="item">List 6</li>
</ul>
maxtess
  • 91
  • 1
  • 2
0

My contribution, based on @david-hellsing algorithm :)

function pop_in(array_elem, index) {
    $(array_elem[index]).animate({
        width: 'toggle',
        height: 'toggle'
    }, 700)// callback will be a promise
    .promise()
    .then(() => {
        $(array_elem[index]).css({visibility: 'hidden'}); //hide after reduce size

        if(index > 0)
            pop_in(array_elem, --index) //recursive call
        else
            console.log("Animation finished. Execute another function from here.");
    });
}
const items_menu = $(".item");
pop_in(items_menu, items_menu.length-1); //start from last to first element

Note which you can change width and height properties to your own purpose.