What is the difference between this code:
$('.percentage_field').change(function() {
update_percentage();
});
$('.inspect1').change(function(){
show_hide_targets();
});
And this code:
$('.percentage_field').change(
update_percentage
);
$('.inspect1').change(
show_hide_targets
);
When a callback runs in response to an event, this inside the function is set to the DOM element that is the target of the event.
In your first example, the anonymous function gets the this of the target element, but that this is not forwarded to the inner function call. Instead, the inner function runs with a this according to how it is invoked. (Here, it's a direct "raw" call (i.e., not called as a member function), so it runs with a this equal to window, in non-script mode.)
In your second example, the functions update_percentage and show_hide_targets get the this of the target element directly.
Consider an example:
function sayThis() { alert(this); }
someElem.addEventListener("click", function() { sayThis() });
someElem.addEventListener("click", sayThis);
someElem.addEventListener("click", function() { sayThis.call(this) });
The first will alert window (or undefined in strict mode); the second will alert the element the listener fired on. The third listener uses an anonymous function, but it invokes the inner function using .call(this), which forwards the original this to the inner function.
Related
I have an event listener set up on a button using jQuery, and for some reason the function within the click listener is called without the button being clicked. I know that usually functions are anonymous in listeners, but it won't work as an anonymous function. The function I am calling also has to accept parameters, which is why I don't think I can just call a reference to the function. Any ideas on how I can fix the problem of the function getting called without a click even registered and still pass the necessary parameters to the function?
$('#keep-both').click(keepBothFiles(file, progress, audioSrc));
calls this function
function keepBothFiles(file, progress, audioSrc) {
...
...
}
You're referencing the function incorrectly. Try this instead:
$('#keep-both').click(function(){
keepBothFiles(file, progress, audioSrc);
});
Whenever you use the syntax funcName(), the () tell the interpreter to immediately invoke the function. The .click method requires that you pass it a reference to a function. Function references are passed by name only. You could also do:
$('#keep-both').click(keepBothFiles);
But you can't pass it your other arguments. It's given an event object by default
You must pass a function reference to the .click() function, not the result of calling a function. When you include the () like this keepBothFiles(...) at the end of the function name, you are telling javascript to execute the function now. When you just use the name of the function like keepBothFiles, you are getting a reference to the function (which can be called later).
You are currently calling your function immediately and then passing the return value of that function (which is not a function reference) to the .click() function, thus it does not do what you want.
The click handler callback function is passed exactly one parameter (the event) in jQuery so you cannot have it call your keepBothFiles(file, progress, audioSrc) function directly like you have it.
Instead, it could be done like this with a second wrapper function:
$('#keep-both').click(function(e) {
keepBothFiles(file, progress, audioSrc);
});
I have a simple event listener:
function listen(evnt, elem, func) {
if (elem.addEventListener) // W3C DOM
elem.addEventListener(evnt,func,false);
else if (elem.attachEvent) { // IE DOM
var r = elem.attachEvent("on"+evnt, func);
return r;
}
return false;
}
I want to set listeners with a parameter. (the parameter is not set by the event, it is part of specific listener.
What I do and seems to work is:
function setlistener (param){
listen ('custom event', document,
function (e){
run_func_with_param(param);
}
);
}
But I dont understand if its correct because param is not supposed to be defined when the event is fired.
My question is - is it the right way to have run_func_with_param called, each time with the params that was set for it in setlistener? In other words, is param remembered and will be set to the right values when run_func_with_param will be called as result of an event? (there will be multiple listeners with different params for the same event).
Notes: No jQuery/other libraries please.
I'm using a custom event in this case.
When you use an anonymous function, the arguments and local variables from the parent scope are still available in the anonymous function.
Thus, your argument named param is available inside your anonymous function that is passed to listen(). It isn't passed to that function - it's just available directly from the parent scope.
Here's your function with some annotation in comments:
function setlistener (param){
// param is available here as an argument to setlistener
// as a normal function argument
listen ('custom event', document, function (e) {
// param is still available here directly from the parent scope
// in this anonymous function.
// This is one advantage of using anonymous functions.
if (e.data.back_button==false){
run_func_with_param(param);
}
});
}
window.onload = function() {
document.getElementById('clickMe').onclick = runTheExample;
}
function runTheExample() {
alert('running the example');
}
This is a simple event handler for the onclick event for an html input button with id = clickMe.
In line 2, why is the call to function runTheExample not immediately followed by ()? I thought that to call a function you must pass it any variables/objects it expects in an open/close parenthesis, and if the function isn't expecting anything, you must still include the open and close parenthesis like runTheExample().
document.getElementById('clickMe').onclick = runTheExample;
The intention here is not to call runTheExample() but to assign the reference to the function runTheExample to the onclick event.
Internally, when the onclick event is fired, Javascript is able to call the function runTheExample through the reference you provided on the code above.
Snippet
var myFunction = function() { return 42; };
// Assigning the reference
myObject.callback = myFunction;
myObject.callback(); // Has the same effect as calling myFunction();
// Assigning by calling the function
myObject.callback = myFunction();
myObject.callback; // Returns 42
myObject.callback(); // Exception! Cannot call "42();"
That's not Javascript-specific. Passing functions by reference is available in many languages.
You use the parenthesis only to invoke (call) a function. When you're assigning it to onclick, you're merely passing it by reference.
To better understand this, think about the other method of declaring a function:
var runTheExample = function () {
alert('running the example');
}
Regardless of what method you use, runTheExample will contain a reference to the function (there are some differences, like the function reference not being available before assignment, but that's a different story).
Functions are objects in javascript. That line sets the onclick property of the click me element to the runTheExample function, it doesn't call that function right then.
var a =runTheExample; //sets a to runTheExample
a(); //runs the runTheExample function
So when the function name is referenced without the () it is referring to the function object, when you add the () it is a call to the function, and the function executes.
It's not calling it, but rather setting the property onclick. When a call is made to onclick(), it will then run the function you've defined. Note however that the context of this will be the object that calls it (document.getElementById('clickMe')).
You're not calling the function here. You're setting the function as an event handler, and the function is not actually called called until the event is fired. What you've written references the function; that's a different notion than actually calling it.
In this case, the runTheExample function is being treated as a variable and being assigned to the onclick event handler. You use () after a function name to call a function. If you added them here, what would happen is that runTheExample() would be called once during load, showing an alert, and then a null value would be assigned to the onclick handler.
Because it binds runTheExample to onclick event.
When you add () it triggers the function.
I've got a function, like this:
menu[0].onclick = function() {
filters.reset_all();
clients.get();
}
So it's called when user clicks on the first menu element. Now I need to call it form the other place and what I've done is this:
if (li.onclick) { //li and menu[0] above are the same
li.onclick.call();
}
and it works well.
But now I need to pass some params to onclick function. I've tried this .call(some_param); but arguments array in onclick is empty.
What am I doing wrong?
edit: changed into this:
menu[0].onclick = function(arg) {
console.log(arg);
filters.reset_all();
clients.get();
}
and
li.onclick.call(li,param);
still nothing
The first argument to .call() is the value for the this pointer. The 2nd, 3rd, etc... arguments get passed to the function. You only need to use .call() if you're explicitly trying to set the this pointer. Otherwise, you can just directly call the function li.onclick().
Event handlers are generally called by the system and when that happens, they are passed the event object as the first argument. If you want a function available that takes different arguments, you should create your own function for that and not use the event handling function. Your event handler can also call this other function if desired.
menu[0].onclick = function() {
myFunc("aaa");
}
function myFunc(arg1) {
// do whatever here
filters.reset_all();
clients.get();
}
if (li.onclick) {
myFunc("bbb");
}
it should be
call(object, param1, param2, param3...);
In your case you can write
li.onclick.call(li, param1);
The first parameter of call() is the context (in this case this) the rest of the parameters go into the arguments array in order. If you use apply() instead of call then you have just two parameters: apply(this, arguments_array)
I'm trying to register on +1 clicks from within my module, which is wrapped as an annonymous function.
For this end, I created a global object MyModule, and exported my click handler function through it. The problem is - my click handler doesn't get called.
Live demo. Code:
// Initialize +1 button
gapi.plusone.go();
(function(){
window.MyModule = {};
function plusOneClicked() {
alert("+1!");
}
window.MyModule.plusOneClicked = plusOneClicked;
})()
...
<g:plusone callback='window.MyModule.plusOneClicked'></g:plusone>
When I give as a callback an external function, whose only purpose is to forward the calls to window.MyModule.plusOneClicked, it works:
function foo() {
window.MyModule.plusOneClicked();
}
...
<g:plusone callback='foo'></g:plusone>
Why would the click handler miss window.MyModule.plusOneClicked(), but find foo()?
Google is probably writing
window[callback]();
in their code.
This requires that the callback string refer to a property of window, not a property of another object.
I believe because callback expects a direct handler method (as in foo()) rather than a reference (as in window.MyModule.plusOneClicked). So basically, you cannot simply assign such a reference to click handler, but write a (wrapper) method as the handler and have it perform the necessary invocation.