1

I am trying to loop through a couple of different values. The idea is that if a user clicks a button the loop should start to run, once it runs it should show a piece of code(in the example some basic text). I am trying to show a sort of dialog with different information, the duration depending on the time values(milliseconds), so the first starts with 3 seconds, right after that the second should be visible for 8 seconds, after this the last one should run for 2 second.

I had to make changes so that every loop the time is different. The example below has a kill switch, so that i can kill the loop. I hope that somebody can figure this out, I have tried a lot of hours and hours.

//plugin options

  step:[
      {
          time: 3000,
          name: 'mike',
          age: 30
      },
      {
          time: 8000,
          name: 'john',
          age: 37
      },
      {
          time: 2000,
          name: 'jessica',
          age: 25
      }
  ]

// the loop

  var timeouts = [];

$('.click').click(function(){
  $.each(options.step, function(i, value){

      var time = value.time;                                                        
      timeouts.push(setTimeout(function(){

          $('#target ul').append('<li>'+value.name+'-'+value.age+'</li>')

      },time));

  });

 });

// reset button

  $('.stop').click(function(){
      $.each(timeouts, function (_, id) {
          clearTimeout(id);
      });
      timeouts = [];
  });

EDIT: the issue is that it needs a extra value(0) in the loop(first value should be a 0), as the the first setTimeout runs after 3 seconds, which means that the rest will use the value of there neighbor.

3 Answers 3

3

Your script sets 3 timeouts: show Mike in 3s, John in 8s and Jessica in 2s - so Jessica is first. If you want them to happen one at a time, you will need to accumulate these times:

var timeouts = [],
    accum = 0;
$.each(options.step, function(i, value){
    accum += value.time;                                                        
    timeouts.push(setTimeout(function(){
        $('#target ul').append('<li>'+value.name+'-'+value.age+'</li>')
    }, accum));
    // move the addition here if you want them to start immediately
});

(Demo at jsfiddle.net, with immediate start)

The other way would be to start the next timeout once one just occurs, this would allow easier stop&go:

var cur = 0,
    $ul = $('#target ul'),
    tid;
function next() {
    if (cur >= options.step.length) return; // and call a final callback?
    var value = options.step[cur];
    $ul.append('<li>'+value.name+'-'+value.age+'</li>');
    cur++;
    tid = setTimeout(next, value.time);
}
function stop() {
    clearTimeout(tid);
}

(Demo at jsfiddle.net)

Sign up to request clarification or add additional context in comments.

8 Comments

thanks but this doesn't work, well it works but the timing isn't correct. It waits 3 seconds before it shows the first one(the example it is 3 seconds, my test its a little bit more)
That's in the comment - move the accumulation behind the timeout, then the first one will have a timeout of zero.
tried that, but it's not starting, it still uses the wrong time value
found the solution I think, there should be an extra value of 0 inserted at the beginning of the array(or how its called)
Hm, worksforme. See the demos I've linked (And no, you should not need a 0 value in the steps array)
|
0

This will loop through all the values and the setTimeout will call the function wrt to the time in the data. The 'stop' variable should be a global variable which will act as your kill switch

var stop=0;

$('.stop').click(function(){
     stop=1;
  });
function responseFunction(value)
{
    if(!stop)
   alert(value.name+" "+value.age);
   else return;
}
 $.each(step, function(i, value){
    setTimeout(function(){
                        responseFunction(value);
                        },value.time);
  });

2 Comments

this will give me the same issue that i have, and the issue that i am having is that the timing isn't correct, it should start directly, but i doesn't as there is an tiemout. So i have to insert a extra time value in the loop, with the value 0 i think
so you are saying that the timeout value is not working.. right?
0

I just want to provide an alternative way with less code. You only need to use a plugin named jquery-timing. It makes timing things easier in jQuery.

$('#target ul').repeat().wait(function(i) {
   this.append('<li>'+options.step[i].name+'-'+options.step[i].age+'</li>');
   return options.step[i].time;
}).until(options.step.length);

function stop() {
   $('#target ul').unwait();
}

As I am a big friend of clean code, here exactly the same once again. But this time with named functions instead of anonymous ones:

$('#target ul').repeat(addCodeStep).wait(stepTimeout).until(options.step.length);

function addCodeStep(i) {
   this.append('<li>'+options.step[i].name+'-'+options.step[i].age+'</li>');
}

function stepTimeout(i) {
   return options.step[i].time;
}

function stop() {
   $('#target ul').unwait();
}

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.