Reputation: 17869
so I am trying to do some dynamic hover manipulations, which require using this
in jquery. For some reason that I cannot figure out, the javascript setTimeout
function does not seem to support it.
I understand that the setTimeout
function is not Jquery, but if placed inside a Jquery function, shouldn't it be able to respond to the relevant this
?
Here is some sample code:
var go = false;
var t;
$('.box').mouseenter(function(){
t = setTimeout(function(){
go = true;
alert($('span',this).text());
},1000);
});
$('.box').mouseleave(function(){
clearTimeout(t);
if(go){
alert($('span',this).text());
}
});
when hovering for 1 second it will alert a blank, yet on mouseleave it will alert the correct text even though both alerts are inside a Jquery function with the same selector.
Why does this happen and how can I fix it?
Upvotes: 4
Views: 3966
Reputation: 388396
Since the callback to setTimeout()
is executed separate from the main thread, the execution context of the callback will be different so this
inside the callback does not point the same object as it was outside the setTimeout
, in this case the hovered
.box
element.
One possible solution here is to use the $.proxy() method to pass a custom execution context for the callback method
$('.box').mouseenter(function(){
t = setTimeout($.proxy(function(){
go = true;
alert($('span',this).text());
}, this),1000);
});
Demo: Fiddle
Another solution is to use a closure variable
$('.box').mouseenter(function(){
var self = this;
t = setTimeout(function(){
go = true;
alert($('span', self ).text());
},1000);
});
Demo: Fiddle
Upvotes: 12
Reputation: 12985
You can just save the value of this somewhere:
$('.box').mouseenter(function(){
var elem = this;
t = setTimeout(function(){
go = true;
alert($('span', elem).text());
},1000);
});
The reason you have to do this is that 'this' gets a new value pretty much whenever a new function gets called. So when the timer stuff calls your inner function, 'this' isn't the same as it is when the mouse stuff calls your outer function.
Technically, the 'this' is called the execution context.
What the code above does is creates a variable inside the closure created when the outer function gets called. We store 'this' in that variable, 'elem', and use it later when the timeout occurs.
Upvotes: 4