This question already has answers here:
javascript addEventListener not working more than once
(2 answers)
Closed 3 years ago.
I try to add an event listener on a button element. A named function with one argument is triggered on click.
My problem is that the function is automatically triggered on page loading and is not working on click. What is the problem?
Is it possible to use an anonymous function while passing an argument to it?
I tried with an named function simply declared and stored in a variable, both don't work.
I tried with an anonymous function but I didn't find out how to pass an argument to it.
var tab = [-2, 1, 4];
function additionne(x){
return x + 2;
}
function affiche(tab){
alert(additionne(tab[0]));
alert(additionne(tab[tab.length - 1]));
}
var bouton = document.getElementById('bouton');
bouton.addEventListener('click', affiche(tab));
I expect the event to be triggered on click and only then.
It is actually triggered only once, on page loading and not on click.
By writing as affiche(tab) you call the function immediately. In order to pass it as a callback with arguments, you can use bind() to bind scope and arguments.
var tab = [-2, 1, 4];
function additionne(x){
return x + 2;
}
function affiche(tab){
alert(additionne(tab[0]));
alert(additionne(tab[tab.length - 1]));
}
var bouton = document.getElementById('bouton');
bouton.addEventListener('click', affiche.bind(this, tab));
// ^^^^ ^^^
// scope argument(s)
<button id="bouton">Click me</button>
Hope this helps
You need to wrap it in a function.
var tab = [-2, 1, 4];
function additionne(x){
return x + 2;
}
function affiche(tab){
alert(additionne(tab[0]));
alert(additionne(tab[tab.length - 1]));
}
var bouton = document.getElementById('bouton');
bouton.addEventListener('click', function() { affiche(tab);});
<button id="bouton">Alert</button>
addEventListener takes a callback function as the 2nd argument.
You should use
function () { ... }
Instead of
affiche(tab)
Which is a function call (and not a function)
Related
Why bind() passes even the type of event with rest parameters. How to avoid passing the event 'click'?
function say(...numbers) {
for (const number of numbers) {
console.log(number);
}
}
window.addEventListener('DOMContentLoaded', () => {
const el = document.getElementById('input_10_5');
el.addEventListener('click', say.bind(null, 1, 2, 3));
});
Console.log result:
1
2
3
click { target: input#input_10_5.medium, buttons: 0, clientX: 1062, clientY: 732, layerX: 96, layerY: 24
}
You can't. The event handling system always passes the event.
The callback function itself has the same parameters and return value as the handleEvent() method; that is, the callback accepts a single parameter: an object based on Event describing the event that has occurred, and it returns nothing.
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#the_event_listener_callback
If your goal is to iterate the arguments and treat them all the same then how about:
function say(numbers, event)
say.bind(null, [1, 2, 3])
This behavior doesn't have to do with rest parameters .... It is more to do with the behavior of .bind(). When you bind a function with arguments (in this case you've used 1, 2, 3), calling that bound function causes those bound arguments to be passed to the function first, then followed by any additional arguments you call the bound function with, eg:
function foo(one, two, three, evt) {
console.log(one, two, three, evt);
}
const bar = foo.bind(null, 1, 2, 3);
bar({type: "click"}); // becomes the 4th argument (after 1, 2, 3)
Under the hood, JavaScript is calling your bound function that you pass to .addEventListener() with the event object, which ends up becoming the fourth argument to your say function. This is then included as part of the numbers array. You can instead create a wrapper function that gets passed event (which you ignore), and then use .call() to call your function (using .call() here instead of just () allows you to explicitly define the this value like you're doing with .bind()):
window.addEventListener('DOMContentLoaded', () => {
const el = document.getElementById('input_10_5');
el.addEventListener('click', () => say.call(null, 1, 2, 3));
});
Look at the documentation:
The bind() method creates a new function that, when called, has its this keyword set to the provided value, with a given sequence of arguments preceding any provided when the new function is called.
You can't prevent bind from doing that.
If you don't want that, don't use bind.
Just create a new function the traditional way instead.
el.addEventListener('click', function () { say(1, 2, 3) });
I have the following codes:
class Autocomplete {
constructor(ele, options) {
this.ele = ele;
this.options = options;
this.input = this.ele.querySelector('.input');
// with keyup we want to fire it right away
// this.input.addEventListener('keyup', (e) => this.display(e);
}
}
The display function will then display the user's input onto the page. However, I wonder what the difference is between these 3 functions:
1)
this.input.addEventListener('keyup', (e) => this.display(e));
this.input.addEventListener('keyup', this.display);
this.input.addEventListener('keyup', () => this.display());
Only function 1 and 2 work, and to my understanding, function 1 will put e as argument into the display function whereas function 2 will execute immediately on keyup. However, for 3, why does it not work, because I thought the e argument is passed in implicitly by the DOM API?
Out of the first 2 functions, which one is more performant and why?
Arrow function is not bound to the class where it is declared when it is called, you should use function only if you want to use the this in the function because in the arrow function, it's the global this that is get called
This question already has answers here:
addEventListener calls the function without me even asking it to
(5 answers)
Closed 3 years ago.
How can I pass a variable to the onclick function? When using
var number = 123;
document.getElementById('myButton').onclick = myFunction(number);
It will run that function before even clicking the button because the function will be called and the return value will be put into the onclick, which doesnt help me
Without the "()" it will only call the function once I click the button, but how do I pass a variable then ?
var number = 123;
document.getElementById('myButton').onclick = myFunction;
function myFunction(i) {
i += 10;
alert(i);
}
One option would be to make the onclick an anonymous function to call myFunction.
var number = 123;
document.getElementById('myButton').onclick = () => {
myFunction(number)
}
function myFunction(i) {
i += 10;
alert(i);
}
<buton id="myButton"> Test button </buton>
While implementing a closure function, I have noticed that if I provide a "named function" as an event handler then it gets executed straightaway when the event gets attached to the buttons. However, if I keep the function inline as an anonymous function then it doesn't execute straightaway and fires only on the
event happens. Please can anyone explain this behaviour?
var buttons = document.getElementsByTagName('button');
//function buttonHandler(buttonName){
//// return function(){
//// console.log(buttonName);
//// }
// alert("hello");
//}
var buttonHandler = function(name){
alert(name);
}
for(var i = 0; i < buttons.length; i += 1) {
var button = buttons[i];
var buttonName = button.innerHTML;
button.addEventListener('click', buttonHandler(buttonName));
button.addEventListener('click', function(buttonName){
alert("hi");
});
}
Many Thanks!
This has nothing to do with the function being named. This is about your code explicitly calling the function.
If you put (some,arguments) after a function then you will call it.
!foo() // calls the function
!function () { }(); // Also calls the function
So:
button.addEventListener('click', buttonHandler(buttonName));
Calls buttonHandler, passing buttonName as an argument to it
Calls addEventListener, passing "click" and the return value of 1 to it
buttonHandler has no return statement, so that return value of undefined which isn't a useful thing to pass to addEventListener.
The commented out version of buttonHandler returns a function. That would be a useful thing to pass to addEventListener.
As pointed out in the answers above the code
button.addEventListener('click', buttonHandler(buttonName));
is making direct call the function so if you only need to pass parameters to the handler function you may use an anonymous function instead of directly calling the function as recommended here (https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener)
I updated my code as below
button.addEventListener('click', function (){ buttonHandler(buttonName)}, false);
This question already has answers here:
JavaScript: Passing parameters to a callback function
(16 answers)
Closed 7 years ago.
I needed to pass a parameter to a callback function in Javascript, so I did the following which creates an anonymous function as a string and then passes it:
var f = "var r = function(result) {do_render(" + i + ",result.name,result.data);}"
eval(f)
$.getJSON("analysis?file=" + getParameterByName('file') + "&step=" + i,r);
This doesn't seem like a great idea however. Is there a better way?
There's several techniques that you can use to do this. One of which is to create a new function which "seals off" one of the variables:
function myCallback(i, result) { ... }
function createCurriedFunction(i, func, context) {
return function (result) { func.call(context, i, result); }
}
for (i = 0; i < 5; i += 1) {
var curriedFunc = createCurriedFuncion(i, myCallback, this);
$.getJSON(url, curriedFunc);
}
Context is the object for which the "this" will refer to in the callback function. This may or may not be needed for what you're doing; if not you can just pass in null.
There's actually a function that does exactly that called bind, and is used like
var curriedFunc = myCallback.bind(this, i), which will seal off the first variable.
It looks like you are having issues closing over i and to solve it used eval. Instead of that, simply close over it using an immediately invoked function expression (IIFE) like this:
(function(i){
//create a closure of the value of i
//so that it takes the immediate value of it instead of the end value
//based on the assumption i is from a loop iterator
$.getJSON("analysis?file=" + getParameterByName('file') + "&step=" + i,
function(result){
do_render(i, result.name, result.data);
}
);
})(i);//pass i into the IIFE in order to save its immediate value
You can simply do
var url = "myurl";
$.getJSON(url, function(result){
//callback function
});