valen
valen

Reputation: 845

setTimeout not working with jquery.each, this

I'm trying to add a delay between the jquery .removeClass calls while iterating through the cells of a table. The cells display properly with no setTimeout, but with setTimeout the code breaks. What am I doing wrong?

function reveal_board() {
$("td").each(function() {
    var t=setTimeout('$(this).removeClass("invisible")', 500);
});
}

Upvotes: 8

Views: 17398

Answers (4)

Richard Dalton
Richard Dalton

Reputation: 35793

Try this:

function reveal_board() {
    $("div").each(function(index) {        
        (function(that, i) { 
            var t = setTimeout(function() { 
                $(that).removeClass("invisible"); 
            }, 500 * i);
        })(this, index);
    });
}

It's generally a bad practice to pass a string to setTimeout() and also I don't think you can pass any variables when using it that way.

I have also wrapped it in a closure to ensure that that always applies to the right element and is not replaced.

Although, like NiftyDude says you might want to pass in the index and use that to display each element in turn.

Working example - http://jsfiddle.net/Cc5sG/

EDIT

Looks like you don't need the closure:

function reveal_board() {
    $("div").each(function(index) {        
        var that = this;
        var t = setTimeout(function() { 
            $(that).removeClass("invisible"); 
        }, 500 * index);        
    });
}

http://jsfiddle.net/Cc5sG/1/

Upvotes: 27

ZyDucksLover
ZyDucksLover

Reputation: 487

Well, I've had the same problem and I solved it that way... But I have no idea about the performances or whatever, I used it in a very short loop (10 elements max) and it worked perfectly ... By the way I used it to add a class so I'll let you figure out what it gives to remove a class ;).

var elements = $(".elements");
var timeout;

elements.each(function(e){
    timeout = setTimeout(function(index) {
       elements[elements.length-e-1].setAttribute('class', elements[elements.length-e-1].getAttribute('class')+' MY-NEW-CLASS');
    }, 500 * e);
});

Upvotes: 1

Andreas Wong
Andreas Wong

Reputation: 60516

First thing first, avoid using string for the first argument of setTimeout, use anon function instead as it's easier to debug and maintain:

$("td").each(function() {
    var $this = $(this);
    var t=setTimeout(function() {
       $this.removeClass("invisible")
    }, 500);
});

Also, I'm not really sure what you are trying to achieve here (update your question later and I'll adapt my answer), but if you want to remove invisible class from each td 500 ms after one another, you can use index:

$("td").each(function() {
    var $this = $(this);
    var t=setTimeout(function(index) {
       $this.removeClass("invisible")
    }, 500 * (index+1));
});

Upvotes: 1

xdazz
xdazz

Reputation: 160833

Your this is pointed to the global window.

function reveal_board() {
  $("td").each(function() {
    $this = $(this);
    var t=setTimeout(function(){$this.removeClass("invisible");}, 500);
  });
}

Upvotes: 2

Related Questions