4

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?

jsfiddle

2 Answers 2

12

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

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

1 Comment

thank you! I used the first one...I use jquery functions inside the setTimeout with their own this selectors and the other one made that buggy even if I kept their individual thiss for some reason
4

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.

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.