views:

197

answers:

5

I'm using jQuery and I have a function that serves as an event callback, and so in that function "this" represents the object that that captured the event. However, there's an instance where I want to call the function explicitly from another function - how do I set what "this" will equal within the function in this case?

For example:

function handleEvent(event) {
    $(this).removeClass("sad").addClass("happy");
}

$("a.sad").click(handleEvent); // in this case, "this" is the anchor clicked

function differentEvent(event) {
    $("input.sad").keydown(e) {
        doSomeOtherProcessing();
        handleEvent(e); // in this case, "this" will be the window object
                        // but I'd like to set it to be, say, the input in question
    }
}
+4  A: 

Just parameterize the function you're interested in:

function doStuff(el) {
    $(el).removeClass("sad").addClass("happy");
}

function handleEvent(event) {
    doStuff(this);
}

$("a.sad").click(handleEvent); // in this case, "this" is the anchor clicked

function differentEvent(event) {
    $("input.sad").keydown(e) {
        doSomeOtherProcessing();
        doStuff(this);
    }
}
cletus
lolz... i liked it. Nice work-around.
simplyharsh
I can't believe people are upvoting this over Patrick's answer, which is exactly what is needed for the original question. That's how jQuery assigns the 'this' keyword in the code it calls, and should be how this gets done. To change parameters of a function to accomodate something that is easily performed by built-in and commonly-understood functions is a case of the tail wagging the dog...
Jason Bunting
I guess this just goes to show that there are a lot of people that don't grok JavaScript and perhaps the use of libraries like jQuery has ensured their ignorance, since they don't take the time to really understand the language itself.
Jason Bunting
@Jason: please, I beg of you, have pity on the poor knaves who don't grok JavaScript like you do. I can assure you everyone is in awe of your vast knowledge of the correct, non-tail-wagging way to do things. I know it must be frustrating seeing the legion of ignorant buffoons on Stack Overflow who have the choice to vote the way they want, rather than the way you know deep down inside your heart of hearts is correct. I can understand your frustration, it's not as if Cletus' way works or anything. Sad how there is just no justice in the world, isn't it?
Hooray Im Helping
+1  A: 

Use

e.target
BYK
+7  A: 

Use apply call.

handleEvent.call(this, e);
Patrick McElhaney
Alternative: use call(), which is exactly the same as apply() except you pass a series of arguments instead of an array of arguments. (https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/Function/call)
Daniel Lew
apply() and call() are exactly what I was looking for (although in the answer's code above, it should be [e] because, as Daniel said, apply() takes an array of arguments).
Charles
Thanks for the correction. I updated the answer.
Patrick McElhaney
+1  A: 

I'd advice you re-factoring your function as a jQuery plugin.

But here's a quick Fix:

handleEvent.apply(this,e) //transfers this from one scope, to another
duckyflip
+1 apply seems appropriate
annakata
Why would refactoring as a jQuery plugin be a better option than using call()?
Charles
Charles because then it can be used universally on all jQUery objects, like $("div").handleEvent() or $(this).handleEvent(), plus you will get the extra benefit of being able to chain functions as well.
duckyflip
A: 

If you're simply looking to call a single event handler as if it were being triggered normally, apply/call will work fine. However, depending on your needs, it may be more robust to use the zero-argument version of jQuery's click() function, which will trigger all click handlers for that element:

function differentEvent(event) {
    $("input.sad").keydown(e) {
        doSomeOtherProcessing();
        $(this).click(); // simulate a click
    }
}
Ben Blank