How to pass a parameter to a dynamically set JavaScript function? - javascript

Ok, I have one JavaScript that creates rows in a table like this:
function AddRow(text,rowID) {
var tbl = document.getElementById('tblNotePanel');
var row = tbl.insertRow(tbl.rows.length);
var cell = row.insertCell();
var textNode = document.createTextNode(text);
cell.id = rowID;
cell.style.backgroundColor = "gold";
cell.onclick = clickTest;
cell.appendChild(textNode);
}
In the above function, I set the cell's onclick function to call another JavaScript function called clickTest. My question is when I assign the onclick event to call clickTest, how do I set parameter information to be sent when the clickTest method is called on the cell's onclick event? Or, how do I access the cell's ID in the clickTest function?
Thanks,
Jeff

Try this:
cell.onclick = function() { clickTest(rowID); };
The idea is that you are binding the onclick handler to the anonymous function. The anonymous function calls clickTest with rowID as the parameter.

In the clickTest function you should have access to a the this variable. Try this inside of clickTest function:
alert(this.id);
This will refer to the DOM element that fired the event.
Basically, there isn't really a way to pass parameters to an event handler function. The reason for that is that the browser is executing the function based on an event and you are not actually calling the function.
You can use closures which allow you to access local variables (to the closure) when you assign the event handler function. That would look like this:
cell.onclick = function() { alert(this.id); alert(cell.id); };
Were cell.id is the locally scoped variable that is still considered in scope when the event handler is executed.

The suggested solutions work most of the time except for special scenarios.
In case you have a for loop adding onclicks calling another function with different parameters and when testing you realize all your item's behave like the last item, you may consider adding onclick as a text:
for(var loopObj of loopObjList)
mydiv.setAttribute('onclick', 'javascript: pick_option(' + loopObj.id + ', "' + loopObj.value + '");' );

Related

Can't understand how function's parameter work in a particular piece of code [duplicate]

This question already has answers here:
What exactly is the parameter e (event) and why pass it to JavaScript functions?
(5 answers)
Closed 4 years ago.
There is an example in "Head first JavaScript" book. This piece of code is unblurring an image on click. The code works, but I don't understand how, though it's an extremely simple piece of code.
The function init is called when a window is loaded. getElementsByTagName gives an HTMLCollection. A click on an image invokes a showAnswer function.
Now there is a mystery for me.
window.onload = init;
function init() {
var images = document.getElementsByTagName("img");
for (var i = 0; i < images.length; i++) {
images[i].onclick = showAnswer;
}
};
function showAnswer(e) {
var image = e.target;
var name = image.id;
name = name + ".jpg";
image.src = name;
}
There should be a parameter e. How this parameter is being created, from where? When showAnswer is called in init, there are no parameters given to it.
Considering the fact that I'm using a .target method on it, it should be an object. How does the browser know that this object has name e?
Why images[i].onclick = showAnswer; and not showAnswer();?
images[i].onclick = showAnswer is defining the event handler function to be run when images[i] is clicked. If you were to use showAnswer() there, it would run immediately in the init function which is probably not what you want.
images[i].addEventListener('click', showAnswer) is another way to write that, which might be more intuitive.
Event handler functions pass in an event object, which is what the 'e' is referring to. 'e.target' is referring to the element itself.
A reference for DOM events:
https://developer.mozilla.org/en-US/docs/Web/API/Document_Object_Model/Events
(breaking myself of the habit of answering questions in comments...)
There should be a parameter e. How this parameter is being created, from where?
When you do images[i].onclick = showAnswer, that assigns "showAnswer" as the event handler for the "click" event for the DOM element named in images[i].
Later, when the user clicks that element (or the event gets triggered by some other method), the browser constructs the Event object, which contains a whole lot of information about that specific event. It then calls your event handler, passing along the Event object as the first (and only) parameter.
When showAnswer is called in init, there are no parameters given to it.
In your init function, you don't call showAnswer; you assign it as the event handler for clicks on images. The event is what passes the parameter to the handler, not your init.
Considering the fact that I'm using a .target method on it, it should be an object. How does the browser know that this object has name e?
That's the name you gave the parameter in the function. You could use any name, but e or evt are a common convention for event objects.
Why images[i].onclick = showAnswer; and not showAnswer();?
If it were showAnswer() you'd be assigning the return value of the function to the click handler. (Which in this case would be undefined, because showAnswer doesn't return anything.) With showAnswer you assign the function itself to the handler.

How does an event object work in this code

window.onload = unblurMonaLisa;
function unblurMonaLisa() {
var images = document.getElementsByTagName("img");
for (var i = 0; i < images.length; i++) {
images[i].onclick = showAnswer;
}
};
function showAnswer(eventObj) {
var image = eventObj.target;
var name = image.id;
name = name + ".jpg";
image.src = name;
};
The above code switches a blurred image for an image that is not blurred when said image is clicked. The code works just fine. My questions are about the eventObj that is passed to the showAnswer function. When is the eventObj created in this code? Is the scope of eventObj local? If I assigned the onclick event to two different variables would that create two eventObj and if so how would I access them individually?
When is the "eventObj" created in this code?
When the the event you are interested in happens, in this case a click, your callback function is automatically executed by the environment. When the callback function is executed, it is given an event object as an argument, which you can choose to ignore it in your function signature. (i.e. your showAnswer function could be like this function showAnswer() {...}). The event object is a regular object that holds information about the event that just happened.
Is the scope of "eventObj" local?
Yes, it is.
If I assigned the onclick event to two different variables
You cannot add two different callback functions by using .onclick. You should use addEventListener() if you want to add multiple callback functions to the same event.
would that create two "eventObj" and if so how would I access them individually?
The event object that would be created for that event would be just one, and it would be passed to all callback functions.
For more info on events read this: https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Creating_and_triggering_events
Also check out the answer to this question, which is similar
UPDATE:
To answer to your comment:
the browser creates a unique Event Object every time an event occurs whether we have a handler listening for that event or not?
Correct.
We can pass this unique object to our handler
Correct again.
I noticed on your other post they used "e" in place of "eventObj"
You can name it whatever you want in your function. As long as you put something as your function parameter (function(e) {} for example) your function will accept the event object.
People usually name that parameter e, short for event, or event, to indicate what kind of thing is this parameter, but you can name it however you want, like any other parameter of any other function.

Function call with parameters to addEventListener inside a loop [duplicate]

This question already has answers here:
How to pass arguments to addEventListener listener function?
(36 answers)
Closed 7 years ago.
Problem : I would like to call a function "test " with passing parameters using the click event of the button.
using addEventListener ('click', test ); works.
using addEventListener ('click', test(parameter)); the function is activated automatically when loading and not to click on the button .
Question: how to pass parameters ?
//create 3 button (n is a counter):
var btn = document.createElement("INPUT");
btn.setAttribute("id", "demo"+n);
btn.setAttribute("type", "button");
btn.setAttribute("value", ("click"));
document.body.appendChild(btn);
call Without parameters works correcty:
function test(m) {
alert("YOU CLICKED ME!");
}
var m=0;
while(m!=3){
document.getElementById("demo"+m).addEventListener("click", test);
m=m+1;
}
`
with parameters not works (the function is activated immediately):
function test(m) {
alert("YOU CLICKED ME!"+m);
}
var m=0;
while(m!=3){
document.getElementById("demo"+m).addEventListener("click", test(m));
m=m+1;
}
Wrap your function in another function to avoid invoking it immediately
document.getElementById("demo"+m).addEventListener("click",(function(x){
return function(){
test(x);
}
})(m));
In your case addEventListener expects a function object so you can't use parenthesis in front of function as it invokes the function and passes the returning value. So you need to return the function object which invokes test function( using an anonymous function to avoid closure property of javascript functions)
EDIT: Reason for returning wrapper function of test using an anonymous function
We can't pass
function(){
test(m);
}
to addEventListener directly.
As every function object in javascript remembers the environment( in our case variable m) outside their lexical scope . If you just create different function(like in while loop) in same environment( variable m ) then they will reference to same environment.
You have two use a function factory to avoid creating closures in loop like described above.
Explanation about why addEventListener('click', test(parameter)) doesn't work
The addEventListener function can accept two parameters, a event type and a listener object that receives the event. In most cases, the listener object is simply a JavaScript function.
So when you use
addEventListener('click', test);
You are passing the string click as the event type, and a function test as the listener, which is what you have expected.
But when you use
addEventListener('click', test(parameter));
The listener is actually the value that the expression test(parameter) evaluates to. Since test(parameter) is a function call, you actually pass in what what is returned by test(parameter), in your case, 'undefined' since test function does not return anything. This is why test is called immediately - it need to be invoked to get the return value as a parameter of your addEventListener function call.
So to execute a function with custom parameters when the event happens, as others have suggested, you can use the anonymous function approach.
Try this:
function test(m) {
alert("YOU CLICKED ME!"+m);
}
var m=0;
while (m!=3) {
(function(m) {
document.getElementById("demo"+m).addEventListener("click", function() {
test(m);
});
})(m);
m=m+1;
}
this will create new scope for variable inside to loop.
You need to build versions of the test function, using what is called a "high-order function":
// this is a high order function, since it returns a function
function buildTestFunction(m) {
return function () {
alert("YOU CLICKED ME!"+m);
};
}
var m=0;
while(m!=3){
var test = buildTestFunction(m);
document.getElementById("demo"+m).addEventListener("click", test);
m=m+1;
}
PS. You might want to use a for loop here, for clarity.
for (var m = 0; m < 3; m++) { ... }

JavaScript - added function to onclick attribute of <a> runs without click

I have a function that creates a new <a> element and I want to add a onclick event to it, which is a function that increases the given value by 1.
In the function, I create these elements:
A number within spantags:
var spantags = document.createElement("span");
var anzahl = 1;
spantags.innerHTML = anzahl;
And the mentioned <a> element:
var plus = document.createElement("a");
plus.innerHTML = "+";
plus.onclick = more(spantags.innerHTML);
This, however, executed the function already in the function that creates this, so the number was increased to 2 on creation.
I read this answer on a similar question:
https://stackoverflow.com/a/249084/1972372
This example worked, the alert only came up when the + was clicked on, but it is an inner function there, not a declared one like my "more(element)".
So my question is: Is it possible to set the onclick attribute to a declared function on a newly created element, like in my example, but prevent it from running immediately?
(The other article had a jQuery answer too, but unfortunately I have no knowledge about jQuery and cannot use it)
Yes, just wrap it in a "proxy" function:
plus.onclick = function() {
more(spantags.innerHTML);
};
Sure, but first you have to understand that plus.onclick = more(spantags.innerHTML); will call more with the argument spantags.innerHTML and assign the result that is returned from that function call to plus.onclick.
You could wrap it in a proxy function as suggested previously, or you could take advantage of the bind method to bind the arguments to the function itself:
plus.onclick = more.bind(null, spantags.innerHTML);
Read up on Bind here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

jQuery - passing id element to a non-anonymous callback function without using an anonymous function

I'm trying to pass an element's id to storePair
$("#someid").click(storePair($(this).val(),$(this).attr("id"));
using $(this) doesn't work. no value.
Another stackoverflow post suggests that I use an anonymous function as a wrapper for StorePair(val,id), i.e.,
$("#someid").click(function(){storePair($(this).val(),$(this).attr("id")});
That seems kind of roundabout... Is there a way to call StorePair and pass the value and id without using the anon function?
You can use this inside the storePair function to get what you're after, like this:
function storePair() {
var val = $(this).val();
var id = this.id;
//do stuff
}
Then bind it like this:
$("#someid").click(storePair);
Or, use an anonymous function like you already have, round-about or not, it's the way it works :)
It's not a roundabout, it's supposed to work that way. The click function (and any of the binding function cousins) accept a function object to be evaluated when the event triggers.
You are evaluating the function storePair when defining the callback, so it won't work.
use the event data?
var someId = $("#someid");
someId.bind("click",
{ value : someId.val(), id: someId.attr("id") },
storePair);
but you have access to the element that raised the event inside of storePair through event.target, so you can wrap this in $() and get values inside the function

Categories

Resources