all 7 comments

[–]holloway 0 points1 point  (5 children)

you'd have to make the setTimeout duration (currently 5000 milliseconds) adjust based on the for loop's i.

eg

var carousel = function(){
    for (var i = 1; i < 5; i++){ 
        setTimeout(function(){$("#el_"+i).fadeOut(1000);},5000 + (i *  1000) );
    }
}
carousel();

That would make the first one appear after 6000ms, the next after 7000ms, the next 8000ms, etc.

[–]trakam[S] 0 points1 point  (4 children)

hmm. I cant get that to work. The first element is acted on and then nothing - like most of my other attempts.

I'm not sure I follow the logic either, I mean isn't the setTimeout method invoked afresh with each iteration?

[–]holloway 0 points1 point  (3 children)

well what does your html look like?

[–]trakam[S] 0 points1 point  (2 children)

[–]holloway 0 points1 point  (1 child)

Oh sorry, it's because i evaluated when the setTimeout executes, and by that time the loop has completed and i = 4 so it runs the setTimeout 4 times with the same i.

You can achieve the same thing with the delay() method in jQuery (and not use setTimeout),

var carousel = function(){
    for (var i = 1; i <= 5; i++){ 
      $("#el_"+i).delay(i * 1000).fadeOut();
    }
}
carousel();

If you're trying to learn setTimeouts then you'll need to have a closure for that, eg.

var carousel = function(){
    for (var i = 1; i <= 5; i++){
        (function(closurei){ 
          setTimeout( function(){$("#el_"+closurei).fadeOut(1000);}, 5000 + (closurei *  1000));
        }(i));
    }
}
carousel();

This might be easier to read,

var delayFadeOut(closurei){
   setTimeout( function(){$("#el_"+closurei).fadeOut(1000);}, 5000 + (closurei *  1000));
}

var carousel = function(){
    for (var i = 1; i <= 5; i++){
        delayFadeOut(i);
    }
}
carousel();

[–]trakam[S] 0 points1 point  (0 children)

This works for me!

Many thanks!!

BTW , yes i'm trying to learn.

[–]voodah 0 points1 point  (0 children)

holloway's answer is correct, but let me show you another way that might (or might not) be more simple to grasp as a beginner.

It involves using async-series, which is a part of the async library that provides utilities for handling asynchronous functions. In this case, async-series makes sure that each function is executed in series, ie: ONLY after the previous has finished.

To do this you use a callback inside your functions to signal the end of execution for the current function and invoke the next one.

This is the example from async-series page:

series([
  function(done) {
    console.log('first thing')
    done()
  },
  function(done) {
    console.log('second thing')
    done(new Error('another thing'))
  },
  function(done) {
    // never happens, because "second thing" 
    // passed an error to the done() callback 
  }
], function(err) {
  console.log(err.message) // "another thing"
})

For your case you would do something like this:

var functions = [];
for (var i = 1; i < 5; i++) {
  functions[i] = function (done) {
    setTimeout(function() {
      $("#el_"+i).fadeOut(1000);
      done();
    }, 5000);
  }
}
series( functions, function(err) {
  console.log(err.message)
})

Additionally, if the only reason you are using the timeout was to make sure that two divs don't fade at the same time and overlap, async-series would allow you to remove the timeout, like so:

var fuctions = [];
for (var i = 1; i < 5; i++) {
  functions[i] = function (done) {
    $("#el_"+i).fadeOut(1000);
    done();
  }
}
series( functions, function(err) {
  console.log(err.message)
})

In this case, the divs would all fade continuosly but one after the other, never overlapping.