7

I am trying to use JQuery to iterate through a number of <li> objects using a timer, i.e. - for every 5 seconds, I would like to access the next <li> object of my <ul>.

I know you can iterate using the .each function, but I am having trouble with integrating the timer with it to iterate through each one individually.

I tried the following, but it was not working correctly. It kept giving me the last LI element. I am assuming it is because setTimeout is not sequential.

$("#div_image_thumb ul li").each(function(){    
  var myLIobj = $(this);
  setTimeout(function(){doThis(myLIobj);}, 5000);
});

5 Answers 5

17

John Fishers approach looks good. But if you want to stick with jQuery's each, which is quite elegant, try this (based on JasonWoof's hint to set timeouts to 5s, 10s etc.):

$("#div_image_thumb ul li").each(function (i) {
    var $li = $(this);
    setTimeout(function () { doThis($li); }, 5000 * (i + 1));
});
Sign up to request clarification or add additional context in comments.

4 Comments

Awesome! Worked perfectly. Any idea on how I can mod this so that it keeps iterating through the LI's as opposed to just 1 time ?
The problem was that when calling all functions "at the same time" there was a race condition and $li was messed up? BTW, why are you using $li and not just li?
@elcuco, I suspectFabian is using $li so it is clear the variable holds an jQuery object, javascript doesn't care if it's li or $li.
@Bamerza, you'll need to wrap this code in a function, then call it with another timeout after finishing this loop. It would have many similarities to the code I posted below.
7

Something like this ought to work properly:

var elements = $("#div_image_thumb ul li");
var index = 0;

var doNext = null;
doNext = function() {
  var element = elements.eq(index);
  // do work 
  if (index < elements.length) {
    index++;
    setTimeout(doNext, 5000);
  }
}

5 Comments

While my answer may be the more elegant way, I vote for this as being more robust. One question: why do you initialize doNext with null? Is it because you need to reference it from within itself? Then var doNext = function doNext() { … } should be sufficient, too, right?
or arguments.callee instead of doNext in the setTimeout, then it doesn't even need to be named and you can wrap it up and call it immediately.
Yes, I created doNext before the function definition itself, so it can reference itself.
Is a doNext.call() line required to actually start doNext's function? It was the only way I could get your code snippet to work. Otherwise, it's awesome.
@Matthew Ruston, all you should need is a "doNext();" statement in the appropriate place.
3

Based on your comment to the accepted answer - You want to continue looping through the collection of elements, for this you can use a setInterval and some helping functions

$(function() {
  var $lis = $("#div_image_thumb ul li");
  var index = 0;

  // setup a function to show the current one and increase the index
  var doNext = function() { 
    // assuming doThis is defined somewhere else.
    doThis($lis.eq(index));
    // increment the index - if it is beyond the number of li's - reset it to 0
    if (++index >= $lis.length) index = 0;
  };

  // call it once as we load
  doNext();
  // set it up to be called every 5000 ms
  setInterval(doNext, 5000);
});

Comments

0

I think the problem with your code, is that you're setting many timers to expire at the same time (5 seconds from now)

So you either need to set one timer, for 5 seconds from now, and have that trigger the next 5 second timer, or you need to set a bunch of timers for different times, eg set for 5s, 10s, 15s, 20s, etc

Comments

0

I found this a really helpful item. While I know that this is older, I found this tidbit helpful in constructing a function I could use for different sets of items. I have a few galleries on a page and I'd like to be able to use this across the board. I'm not sure if this is redundant next to Gnarf's excellent reply. Maybe I suck at the javascripts. I decided to require a parameter and set the default for that parameter per pre ECSMA2015 standards so this should work for older versions.

The utility of this is that I can initialize it during my js init and feed it anything depending on the page I might be on, allowing me to cycle through different objects easily.

     function gallery($lis) {
  $lis = typeof a !== 'undefined' ? $lis : $("#div_image_thumb ul li");
  var index = 0;

  // setup a function to show the current one and increase the index
  var doNext = function() {
    // assuming doThis is defined somewhere else.
    doThis($lis.eq(index));
    // increment the index - if it is beyond the number of li's - reset it to 0
    if (++index >= $lis.length) index = 0;
  };

  // call it once as we load
  doNext();
  // set it up to be called every 5000 ms
  setInterval(doNext, 5000);
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.