Question

Please forgive me if this is an obvious one.

I have an unknown amount of elements on a page, which I need to loop through one at a time and do stuff to. However, I need the loop to pause until the functions used on the elements have completed, and then continue on to the next iteration.

I tried doing this in a $.each loop, but it fired off the commands far to quickly and finished without waiting for them to complete.

Any ideas?

$('elem').each(function(){
    $(this).fadeIn().wait(5000).fadeOut();
});

This is what I have, very simple. I got the wait() function from here: jquery cookbook site.

Problem is, the loop doesnt wait - the actual command works as intended, it's just that they all go off at once.

Any help appreciated, thanks.

EDIT: After this is executed, I may want to then execute the loop again, so that the list of elems will be faded in / out again in sequence

EDIT2: Have since gotten the 1.4.2 jQuery lib, was using 1.3.2, hence the custom wait() function. Now using delay() as mentioned by lobstrosity. Managed to cobble together something close to what I need from his answer, thanks lobstrosity :) .

Was it helpful?

Solution

First of all, jQuery 1.4 added the delay function, which I assume is what your custom wait implementation is doing.

Using delay, you can sort of fake the functionality of each element "waiting" on the previous element to finish by using the first parameter to the each callback as a multiplier for an intial delay. Like this:

var duration = 5000;

$('elem').each(function(n) {
    $(this).delay(n * duration).fadeIn().delay(duration).fadeOut();
});

So the first element will fadeIn immediately. The second will fadeIn after 5,000 ms. The third after 10,000 ms and so on. Keep in mind that this is faking it. Each element is not actually waiting on the previous element to finish.

OTHER TIPS

Your main loop using each() will run without delay over your collection of elements. You need to queue these elements instead.

This might need tweaking (and could possibly use jQuery queues?) but to demonstrate using recursion to process the queue:

function animate(elems) {
    var elem = elems.shift();
    $(elem).fadeIn().wait(5000).fadeOut(2000, function() {
        if (elems.length) {
            animate(elems);
        }
    });
}

var elems = $('elem');
animate(elems);

You probably need to call wait before the first function :

  $(this).wait().fadeIn().wait(5000).fadeOut();

The other option is to use the callback.

 $(this).wait().fadeIn('slow', function(){$(this).fadeOut('slow')});

This way the fadeOut does not start until the fadeIn is done.

Here's a demo of my solution.

What you need isn't a loop to handle the processing. What you want is to chain the calls. Seems like there might be a simpler way but here's a brute-force method.

// Create a function that does the chaining.
function fadeNext(x,y) {
  return function() { x.fadeIn(100).delay(100).fadeOut(1000, (y?y.fadeNext:y)); };
}

// Get all the elements to fade in reverse order.
var elements = [];
$('.f').each(function(i,e) {elements.unshift(e);});

// Iterate over the elements and configure a fadeNext for each.
var next;
for (var i in elements) {
  var e = $(elements[i]);
  e.fadeNext = fadeNext(e,next);
  next = e;
}

// Start the fade.
next.fadeNext();
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top