js:scope of this inside an object on keypress event - javascript

Here is my JS simple script:
var Chat = function() {
console.log("init");
this.debug = function (txt) {
console.log(txt);
}
document.getElementById('shoutBoxInput').addEventListener("keypress", keyPressedFunction, false);
this.keyPressedFunction = function(e){
console.log("keyPressed");
}
this.sendText = function() {
var texte = document.getElementById('shoutBoxInput').value;
if (texte=="") return;
document.getElementById('shoutBoxInput').value =""
this.debug("sendTexte:"+texte);
}
this.receiveText = function(username, texte) {
}
}
var chat = new Chat();
My problem comes from:
document.getElementById('shoutBoxInput').addEventListener("keypress", keyPressedFunction, false);
this.keyPressedFunction = function(e){
Error Uncaught ReferenceError: keyPressedFunction is not defined
If I use:
document.getElementById('shoutBoxInput').addEventListener("keydown", this.keyPressedFunction, true);
then keyPressedFunction is never called.
Fiddle: http://jsfiddle.net/ghLfhb6z/

Let's start with the problem, and then move to what's dangerous about your code.
The problem is that when you call addEventListener, this.keyPressedEvent doesn't yet exist:
// this.keyPressedFunction doesn't exist...so you are registering a 'keypress'
// event to undefined.
document.getElementById('shoutBoxInput').addEventListener("keypress",
keyPressedFunction, false);
// now you define this.keyPressedFunction
this.keyPressedFunction = function(e){
console.log("keyPressed");
}
// so this is where you should be attaching it to the event
You may be thinking about JavaScript's hosting mechanism, and thinking "ah, the this.keyPressedFunction definition is being hoisted to the top of this function, so it's available for assigment." But hoisting only applies to variable and function definitions; what you're doing is assigning an anonymous function to a member property, so hoisting does not apply.
Now on to the dangerous:
When you use a method (a function property of an object) for a callback, the meaning of this is lost when that callback is invoked. (I know you aren't currently using this in your callback, but you probably will eventually!) In other words, when a key is pressed, and keyPressedFunction is called, the value of this won't be what you expect. The upshot of this is you have to be very careful assigning methods to callbacks or events. If you want to do it, you'll have to use Function.prototype.bind. Here's your code re-written in the correct order, and using bind:
this.keyPressedFunction = function(e){
console.log("keyPressed");
}
document.getElementById('shoutBoxInput').addEventListener("keypress",
this.keyPressedFunction.bind(this), false);

place your function before you use its referenc...then use this.keyPressedFunction...then is 'keypress' a valid native js event ?
http://jsfiddle.net/ghLfhb6z/4/
yes there was the errors I told, in fact most important is to place your event handlers at the end, check the right event, and use this if the function is on this :
var Chat = function() {
console.log("init");
this.debug = function (txt) {
console.log(txt);
}
this.keyPressedFunction = function(e){
console.log("keyPressed");
}
this.sendText = function() {
var texte = document.getElementById('shoutBoxInput').value;
if (texte=="") return;
document.getElementById('shoutBoxInput').value =""
this.debug("sendTexte:"+texte);
}
this.receiveText = function(username, texte) {
}
// place this at the end
document.getElementById('shoutBoxInput').addEventListener("keydown", this.keyPressedFunction, false);
}
var chat = new Chat();

#dmidz has provided a correct answer that will solve your problem, but if your keyPressedFunction only needs to be referred to code inside your Chat() module, then you don't need to make them properties of this (Chat):
var Chat = function() {
console.log("init");
function debug(txt) {
console.log(txt);
}
function keyPressedFunction(e){
console.log("keyPressed");
}
this.sendText = function() {
var texte = document.getElementById('shoutBoxInput').value;
if (texte=="") return;
document.getElementById('shoutBoxInput').value ="";
debug("sendTexte:"+texte);
}
this.receiveText = function(username, texte) {
}
document.getElementById('shoutBoxInput')
.addEventListener("keypress", keyPressedFunction, false);
}
If you do this, then you don't necessarily have to declare your functions before you use them, but it would be good style to do so nonetheless.

Related

Probably a really simple thing but I can't seem to pass an argument into my Javascript function [duplicate]

The situation is somewhat like-
var someVar = some_other_function();
someObj.addEventListener("click", function(){
some_function(someVar);
}, false);
The problem is that the value of someVar is not visible inside the listener function of the addEventListener, where it is probably being treated as a new variable.
Why not just get the arguments from the target attribute of the event?
Example:
const someInput = document.querySelector('button');
someInput.addEventListener('click', myFunc, false);
someInput.myParam = 'This is my parameter';
function myFunc(evt)
{
window.alert(evt.currentTarget.myParam);
}
<button class="input">Show parameter</button>
JavaScript is a prototype-oriented language, remember!
There is absolutely nothing wrong with the code you've written. Both some_function and someVar should be accessible, in case they were available in the context where anonymous
function() { some_function(someVar); }
was created.
Check if the alert gives you the value you've been looking for, be sure it will be accessible in the scope of anonymous function (unless you have more code that operates on the same someVar variable next to the call to addEventListener)
var someVar;
someVar = some_other_function();
alert(someVar);
someObj.addEventListener("click", function(){
some_function(someVar);
}, false);
This question is old but I thought I'd offer an alternative using ES5's .bind() - for posterity. :)
function some_func(otherFunc, ev) {
// magic happens
}
someObj.addEventListener("click", some_func.bind(null, some_other_func), false);
Just be aware that you need to set up your listener function with the first param as the argument you're passing into bind (your other function) and the second param is now the event (instead of the first, as it would have been).
Quite and old question but I had the same issue today. Cleanest solution I found is to use the concept of currying.
The code for that:
someObj.addEventListener('click', some_function(someVar));
var some_function = function(someVar) {
return function curried_func(e) {
// do something here
}
}
By naming the curried function it allows you to call Object.removeEventListener to unregister the eventListener at a later execution time.
You can just bind all necessary arguments with 'bind':
root.addEventListener('click', myPrettyHandler.bind(null, event, arg1, ... ));
In this way you'll always get the event, arg1, and other stuff passed to myPrettyHandler.
http://passy.svbtle.com/partial-application-in-javascript-using-bind
nice one line alternative
element.addEventListener('dragstart',(evt) => onDragStart(param1, param2, param3, evt));
function onDragStart(param1, param2, param3, evt) {
//some action...
}
You can add and remove eventlisteners with arguments by declaring a function as a variable.
myaudio.addEventListener('ended',funcName=function(){newSrc(myaudio)},false);
newSrc is the method with myaudio as parameter
funcName is the function name variable
You can remove the listener with
myaudio.removeEventListener('ended',func,false);
Function.prototype.bind() is the way to bind a target function to a particular scope and optionally define the this object within the target function.
someObj.addEventListener("click", some_function.bind(this), false);
Or to capture some of the lexical scope, for example in a loop:
someObj.addEventListener("click", some_function.bind(this, arg1, arg2), false);
Finally, if the this parameter is not needed within the target function:
someObj.addEventListener("click", some_function.bind(null, arg1, arg2), false);
You could pass somevar by value(not by reference) via a javascript feature known as closure:
var someVar='origin';
func = function(v){
console.log(v);
}
document.addEventListener('click',function(someVar){
return function(){func(someVar)}
}(someVar));
someVar='changed'
Or you could write a common wrap function such as wrapEventCallback:
function wrapEventCallback(callback){
var args = Array.prototype.slice.call(arguments, 1);
return function(e){
callback.apply(this, args)
}
}
var someVar='origin';
func = function(v){
console.log(v);
}
document.addEventListener('click',wrapEventCallback(func,someVar))
someVar='changed'
Here wrapEventCallback(func,var1,var2) is like:
func.bind(null, var1,var2)
Here's yet another way (This one works inside for loops):
var someVar = some_other_function();
someObj.addEventListener("click",
function(theVar){
return function(){some_function(theVar)};
}(someVar),
false);
someVar value should be accessible only in some_function() context, not from listener's.
If you like to have it within listener, you must do something like:
someObj.addEventListener("click",
function(){
var newVar = someVar;
some_function(someVar);
},
false);
and use newVar instead.
The other way is to return someVar value from some_function() for using it further in listener (as a new local var):
var someVar = some_function(someVar);
one easy way to execute that may be this
window.addEventListener('click', (e) => functionHandler(e, ...args));
Works for me.
Use
el.addEventListener('click',
function(){
// this will give you the id value
alert(this.id);
},
false);
And if you want to pass any custom value into this anonymous function then the easiest way to do it is
// this will dynamically create property a property
// you can create anything like el.<your variable>
el.myvalue = "hello world";
el.addEventListener('click',
function(){
//this will show you the myvalue
alert(el.myvalue);
// this will give you the id value
alert(this.id);
},
false);
Works perfectly in my project. Hope this will help
If I'm not mistaken using calling the function with bind actually creates a new function that is returned by the bind method. This will cause you problems later or if you would like to remove the event listener, as it's basically like an anonymous function:
// Possible:
function myCallback() { /* code here */ }
someObject.addEventListener('event', myCallback);
someObject.removeEventListener('event', myCallback);
// Not Possible:
function myCallback() { /* code here */ }
someObject.addEventListener('event', function() { myCallback });
someObject.removeEventListener('event', /* can't remove anonymous function */);
So take that in mind.
If you are using ES6 you could do the same as suggested but a bit cleaner:
someObject.addEventListener('event', () => myCallback(params));
$form.addEventListener('submit', save.bind(null, data, keyword, $name.value, myStemComment));
function save(data, keyword, name, comment, event) {
This is how I got event passed properly.
One way is doing this with an outer function:
elem.addEventListener('click', (function(numCopy) {
return function() {
alert(numCopy)
};
})(num));
This method of wrapping an anonymous function in parentheses and calling it right away is called an IIFE (Immediately-Invoked Function Expression)
You can check an example with two parameters in http://codepen.io/froucher/pen/BoWwgz.
catimg.addEventListener('click', (function(c, i){
return function() {
c.meows++;
i.textContent = c.name + '\'s meows are: ' + c.meows;
}
})(cat, catmeows));
In 2019, lots of api changes, the best answer no longer works, without fix bug.
share some working code.
Inspired by all above answer.
button_element = document.getElementById('your-button')
button_element.setAttribute('your-parameter-name',your-parameter-value);
button_element.addEventListener('click', your_function);
function your_function(event)
{
//when click print the parameter value
console.log(event.currentTarget.attributes.your-parameter-name.value;)
}
Sending arguments to an eventListener's callback function requires creating an isolated function and passing arguments to that isolated function.
Here's a nice little helper function you can use. Based on "hello world's" example above.)
One thing that is also needed is to maintain a reference to the function so we can remove the listener cleanly.
// Lambda closure chaos.
//
// Send an anonymous function to the listener, but execute it immediately.
// This will cause the arguments are captured, which is useful when running
// within loops.
//
// The anonymous function returns a closure, that will be executed when
// the event triggers. And since the arguments were captured, any vars
// that were sent in will be unique to the function.
function addListenerWithArgs(elem, evt, func, vars){
var f = function(ff, vv){
return (function (){
ff(vv);
});
}(func, vars);
elem.addEventListener(evt, f);
return f;
}
// Usage:
function doSomething(withThis){
console.log("withThis", withThis);
}
// Capture the function so we can remove it later.
var storeFunc = addListenerWithArgs(someElem, "click", doSomething, "foo");
// To remove the listener, use the normal routine:
someElem.removeEventListener("click", storeFunc);
There is a special variable inside all functions: arguments. You can pass your parameters as anonymous parameters and access them (by order) through the arguments variable.
Example:
var someVar = some_other_function();
someObj.addEventListener("click", function(someVar){
some_function(arguments[0]);
}, false);
I was stuck in this as I was using it in a loop for finding elements and adding listner to it. If you're using it in a loop, then this will work perfectly
for (var i = 0; i < states_array.length; i++) {
var link = document.getElementById('apply_'+states_array[i].state_id);
link.my_id = i;
link.addEventListener('click', function(e) {
alert(e.target.my_id);
some_function(states_array[e.target.my_id].css_url);
});
}
I suggest you to do something like that:
var someVar = some_other_function();
someObj.addEventListener("click", (event, param1 = someVar) => {
some_function(param1);
}, false);
The PERFECT SOLUTION for this is to use Closures like this:
function makeSizer(size) {
return function () {
document.body.style.fontSize = `${size}px`;
};
}
//pass parameters here and keep the reference in variables:
const size12 = makeSizer(12);
const size24 = makeSizer(24);
const size36 = makeSizer(36);
document.getElementById('size-12').addEventListener("click", size12);
document.getElementById('size-24').addEventListener("click", size24);
document.getElementById('size-36').addEventListener("click", size36);
document.getElementById('remove-12').addEventListener("click", ()=>{
document.getElementById('size-12').removeEventListener("click", size12);
alert("Now click on 'size 12' button and you will see that there is no event listener any more");
});
test<br/>
<button id="size-12">
size 12
</button>
<button id="size-24">
size 24
</button>
<button id="size-36">
size 36
</button>
<button id="remove-12">
remove 12
</button>
So basically you wrap a function inside another function and assign that to a variable that you can register as an event listener, but also unregister as well!
Also try these (IE8 + Chrome. I dont know for FF):
function addEvent(obj, type, fn) {
eval('obj.on'+type+'=fn');
}
function removeEvent(obj, type) {
eval('obj.on'+type+'=null');
}
// Use :
function someFunction (someArg) {alert(someArg);}
var object=document.getElementById('somObject_id') ;
var someArg="Hi there !";
var func=function(){someFunction (someArg)};
// mouseover is inactive
addEvent (object, 'mouseover', func);
// mouseover is now active
addEvent (object, 'mouseover');
// mouseover is inactive
Hope there is no typos :-)
The following answer is correct but the below code is not working in IE8 if suppose you compressed the js file using yuicompressor. (In fact,still most of the US peoples using IE8)
var someVar;
someVar = some_other_function();
alert(someVar);
someObj.addEventListener("click",
function(){
some_function(someVar);
},
false);
So, we can fix the above issue as follows and it works fine in all browsers
var someVar, eventListnerFunc;
someVar = some_other_function();
eventListnerFunc = some_function(someVar);
someObj.addEventListener("click", eventListnerFunc, false);
Hope, it would be useful for some one who is compressing the js file in production environment.
Good Luck!!
var EV = {
ev: '',
fn: '',
elem: '',
add: function () {
this.elem.addEventListener(this.ev, this.fn, false);
}
};
function cons() {
console.log('some what');
}
EV.ev = 'click';
EV.fn = cons;
EV.elem = document.getElementById('body');
EV.add();
//If you want to add one more listener for load event then simply add this two lines of code:
EV.ev = 'load';
EV.add();
The following approach worked well for me. Modified from here.
function callback(theVar) {
return function() {
theVar();
}
}
function some_other_function() {
document.body.innerHTML += "made it.";
}
var someVar = some_other_function;
document.getElementById('button').addEventListener('click', callback(someVar));
<!DOCTYPE html>
<html>
<body>
<button type="button" id="button">Click Me!</button>
</body>
</html>
Since your event listener is 'click', you can:
someObj.setAttribute("onclick", "function(parameter)");
Another workaround is by Using data attributes
function func(){
console.log(this.dataset.someVar);
div.removeEventListener("click", func);
}
var div = document.getElementById("some-div");
div.setAttribute("data-some-var", "hello");
div.addEventListener("click", func);
jsfiddle
The following code worked fine for me (firefox):
for (var i=0; i<3; i++) {
element = new ... // create your element
element.counter = i;
element.addEventListener('click', function(e){
console.log(this.counter);
... // another code with this element
}, false);
}
Output:
0
1
2
You need:
newElem.addEventListener('click', {
handleEvent: function (event) {
clickImg(parameter);
}
});

Attaching different eventListeners for each item in for-of-loop [duplicate]

The situation is somewhat like-
var someVar = some_other_function();
someObj.addEventListener("click", function(){
some_function(someVar);
}, false);
The problem is that the value of someVar is not visible inside the listener function of the addEventListener, where it is probably being treated as a new variable.
Why not just get the arguments from the target attribute of the event?
Example:
const someInput = document.querySelector('button');
someInput.addEventListener('click', myFunc, false);
someInput.myParam = 'This is my parameter';
function myFunc(evt)
{
window.alert(evt.currentTarget.myParam);
}
<button class="input">Show parameter</button>
JavaScript is a prototype-oriented language, remember!
There is absolutely nothing wrong with the code you've written. Both some_function and someVar should be accessible, in case they were available in the context where anonymous
function() { some_function(someVar); }
was created.
Check if the alert gives you the value you've been looking for, be sure it will be accessible in the scope of anonymous function (unless you have more code that operates on the same someVar variable next to the call to addEventListener)
var someVar;
someVar = some_other_function();
alert(someVar);
someObj.addEventListener("click", function(){
some_function(someVar);
}, false);
This question is old but I thought I'd offer an alternative using ES5's .bind() - for posterity. :)
function some_func(otherFunc, ev) {
// magic happens
}
someObj.addEventListener("click", some_func.bind(null, some_other_func), false);
Just be aware that you need to set up your listener function with the first param as the argument you're passing into bind (your other function) and the second param is now the event (instead of the first, as it would have been).
Quite and old question but I had the same issue today. Cleanest solution I found is to use the concept of currying.
The code for that:
someObj.addEventListener('click', some_function(someVar));
var some_function = function(someVar) {
return function curried_func(e) {
// do something here
}
}
By naming the curried function it allows you to call Object.removeEventListener to unregister the eventListener at a later execution time.
You can just bind all necessary arguments with 'bind':
root.addEventListener('click', myPrettyHandler.bind(null, event, arg1, ... ));
In this way you'll always get the event, arg1, and other stuff passed to myPrettyHandler.
http://passy.svbtle.com/partial-application-in-javascript-using-bind
nice one line alternative
element.addEventListener('dragstart',(evt) => onDragStart(param1, param2, param3, evt));
function onDragStart(param1, param2, param3, evt) {
//some action...
}
You can add and remove eventlisteners with arguments by declaring a function as a variable.
myaudio.addEventListener('ended',funcName=function(){newSrc(myaudio)},false);
newSrc is the method with myaudio as parameter
funcName is the function name variable
You can remove the listener with
myaudio.removeEventListener('ended',func,false);
Function.prototype.bind() is the way to bind a target function to a particular scope and optionally define the this object within the target function.
someObj.addEventListener("click", some_function.bind(this), false);
Or to capture some of the lexical scope, for example in a loop:
someObj.addEventListener("click", some_function.bind(this, arg1, arg2), false);
Finally, if the this parameter is not needed within the target function:
someObj.addEventListener("click", some_function.bind(null, arg1, arg2), false);
You could pass somevar by value(not by reference) via a javascript feature known as closure:
var someVar='origin';
func = function(v){
console.log(v);
}
document.addEventListener('click',function(someVar){
return function(){func(someVar)}
}(someVar));
someVar='changed'
Or you could write a common wrap function such as wrapEventCallback:
function wrapEventCallback(callback){
var args = Array.prototype.slice.call(arguments, 1);
return function(e){
callback.apply(this, args)
}
}
var someVar='origin';
func = function(v){
console.log(v);
}
document.addEventListener('click',wrapEventCallback(func,someVar))
someVar='changed'
Here wrapEventCallback(func,var1,var2) is like:
func.bind(null, var1,var2)
Here's yet another way (This one works inside for loops):
var someVar = some_other_function();
someObj.addEventListener("click",
function(theVar){
return function(){some_function(theVar)};
}(someVar),
false);
someVar value should be accessible only in some_function() context, not from listener's.
If you like to have it within listener, you must do something like:
someObj.addEventListener("click",
function(){
var newVar = someVar;
some_function(someVar);
},
false);
and use newVar instead.
The other way is to return someVar value from some_function() for using it further in listener (as a new local var):
var someVar = some_function(someVar);
one easy way to execute that may be this
window.addEventListener('click', (e) => functionHandler(e, ...args));
Works for me.
Use
el.addEventListener('click',
function(){
// this will give you the id value
alert(this.id);
},
false);
And if you want to pass any custom value into this anonymous function then the easiest way to do it is
// this will dynamically create property a property
// you can create anything like el.<your variable>
el.myvalue = "hello world";
el.addEventListener('click',
function(){
//this will show you the myvalue
alert(el.myvalue);
// this will give you the id value
alert(this.id);
},
false);
Works perfectly in my project. Hope this will help
If I'm not mistaken using calling the function with bind actually creates a new function that is returned by the bind method. This will cause you problems later or if you would like to remove the event listener, as it's basically like an anonymous function:
// Possible:
function myCallback() { /* code here */ }
someObject.addEventListener('event', myCallback);
someObject.removeEventListener('event', myCallback);
// Not Possible:
function myCallback() { /* code here */ }
someObject.addEventListener('event', function() { myCallback });
someObject.removeEventListener('event', /* can't remove anonymous function */);
So take that in mind.
If you are using ES6 you could do the same as suggested but a bit cleaner:
someObject.addEventListener('event', () => myCallback(params));
$form.addEventListener('submit', save.bind(null, data, keyword, $name.value, myStemComment));
function save(data, keyword, name, comment, event) {
This is how I got event passed properly.
One way is doing this with an outer function:
elem.addEventListener('click', (function(numCopy) {
return function() {
alert(numCopy)
};
})(num));
This method of wrapping an anonymous function in parentheses and calling it right away is called an IIFE (Immediately-Invoked Function Expression)
You can check an example with two parameters in http://codepen.io/froucher/pen/BoWwgz.
catimg.addEventListener('click', (function(c, i){
return function() {
c.meows++;
i.textContent = c.name + '\'s meows are: ' + c.meows;
}
})(cat, catmeows));
In 2019, lots of api changes, the best answer no longer works, without fix bug.
share some working code.
Inspired by all above answer.
button_element = document.getElementById('your-button')
button_element.setAttribute('your-parameter-name',your-parameter-value);
button_element.addEventListener('click', your_function);
function your_function(event)
{
//when click print the parameter value
console.log(event.currentTarget.attributes.your-parameter-name.value;)
}
Sending arguments to an eventListener's callback function requires creating an isolated function and passing arguments to that isolated function.
Here's a nice little helper function you can use. Based on "hello world's" example above.)
One thing that is also needed is to maintain a reference to the function so we can remove the listener cleanly.
// Lambda closure chaos.
//
// Send an anonymous function to the listener, but execute it immediately.
// This will cause the arguments are captured, which is useful when running
// within loops.
//
// The anonymous function returns a closure, that will be executed when
// the event triggers. And since the arguments were captured, any vars
// that were sent in will be unique to the function.
function addListenerWithArgs(elem, evt, func, vars){
var f = function(ff, vv){
return (function (){
ff(vv);
});
}(func, vars);
elem.addEventListener(evt, f);
return f;
}
// Usage:
function doSomething(withThis){
console.log("withThis", withThis);
}
// Capture the function so we can remove it later.
var storeFunc = addListenerWithArgs(someElem, "click", doSomething, "foo");
// To remove the listener, use the normal routine:
someElem.removeEventListener("click", storeFunc);
There is a special variable inside all functions: arguments. You can pass your parameters as anonymous parameters and access them (by order) through the arguments variable.
Example:
var someVar = some_other_function();
someObj.addEventListener("click", function(someVar){
some_function(arguments[0]);
}, false);
I was stuck in this as I was using it in a loop for finding elements and adding listner to it. If you're using it in a loop, then this will work perfectly
for (var i = 0; i < states_array.length; i++) {
var link = document.getElementById('apply_'+states_array[i].state_id);
link.my_id = i;
link.addEventListener('click', function(e) {
alert(e.target.my_id);
some_function(states_array[e.target.my_id].css_url);
});
}
I suggest you to do something like that:
var someVar = some_other_function();
someObj.addEventListener("click", (event, param1 = someVar) => {
some_function(param1);
}, false);
The PERFECT SOLUTION for this is to use Closures like this:
function makeSizer(size) {
return function () {
document.body.style.fontSize = `${size}px`;
};
}
//pass parameters here and keep the reference in variables:
const size12 = makeSizer(12);
const size24 = makeSizer(24);
const size36 = makeSizer(36);
document.getElementById('size-12').addEventListener("click", size12);
document.getElementById('size-24').addEventListener("click", size24);
document.getElementById('size-36').addEventListener("click", size36);
document.getElementById('remove-12').addEventListener("click", ()=>{
document.getElementById('size-12').removeEventListener("click", size12);
alert("Now click on 'size 12' button and you will see that there is no event listener any more");
});
test<br/>
<button id="size-12">
size 12
</button>
<button id="size-24">
size 24
</button>
<button id="size-36">
size 36
</button>
<button id="remove-12">
remove 12
</button>
So basically you wrap a function inside another function and assign that to a variable that you can register as an event listener, but also unregister as well!
Also try these (IE8 + Chrome. I dont know for FF):
function addEvent(obj, type, fn) {
eval('obj.on'+type+'=fn');
}
function removeEvent(obj, type) {
eval('obj.on'+type+'=null');
}
// Use :
function someFunction (someArg) {alert(someArg);}
var object=document.getElementById('somObject_id') ;
var someArg="Hi there !";
var func=function(){someFunction (someArg)};
// mouseover is inactive
addEvent (object, 'mouseover', func);
// mouseover is now active
addEvent (object, 'mouseover');
// mouseover is inactive
Hope there is no typos :-)
The following answer is correct but the below code is not working in IE8 if suppose you compressed the js file using yuicompressor. (In fact,still most of the US peoples using IE8)
var someVar;
someVar = some_other_function();
alert(someVar);
someObj.addEventListener("click",
function(){
some_function(someVar);
},
false);
So, we can fix the above issue as follows and it works fine in all browsers
var someVar, eventListnerFunc;
someVar = some_other_function();
eventListnerFunc = some_function(someVar);
someObj.addEventListener("click", eventListnerFunc, false);
Hope, it would be useful for some one who is compressing the js file in production environment.
Good Luck!!
var EV = {
ev: '',
fn: '',
elem: '',
add: function () {
this.elem.addEventListener(this.ev, this.fn, false);
}
};
function cons() {
console.log('some what');
}
EV.ev = 'click';
EV.fn = cons;
EV.elem = document.getElementById('body');
EV.add();
//If you want to add one more listener for load event then simply add this two lines of code:
EV.ev = 'load';
EV.add();
The following approach worked well for me. Modified from here.
function callback(theVar) {
return function() {
theVar();
}
}
function some_other_function() {
document.body.innerHTML += "made it.";
}
var someVar = some_other_function;
document.getElementById('button').addEventListener('click', callback(someVar));
<!DOCTYPE html>
<html>
<body>
<button type="button" id="button">Click Me!</button>
</body>
</html>
Since your event listener is 'click', you can:
someObj.setAttribute("onclick", "function(parameter)");
Another workaround is by Using data attributes
function func(){
console.log(this.dataset.someVar);
div.removeEventListener("click", func);
}
var div = document.getElementById("some-div");
div.setAttribute("data-some-var", "hello");
div.addEventListener("click", func);
jsfiddle
The following code worked fine for me (firefox):
for (var i=0; i<3; i++) {
element = new ... // create your element
element.counter = i;
element.addEventListener('click', function(e){
console.log(this.counter);
... // another code with this element
}, false);
}
Output:
0
1
2
You need:
newElem.addEventListener('click', {
handleEvent: function (event) {
clickImg(parameter);
}
});

jQuery mobile touch event handling, this keyword context, and properly using closures

Forgive me if I'm not very clear here. I'm trying to learn a lot of things at once by doing.
I have an event listener with multiple events like this:
$account.on({
tap: function() {
accountOpen = true;
ui.openAccount(this);
},
swiperight: etc. etc.
}
I have all my ui functions in an object literal. Example:
var ui = PROJECT.ui = {
openAccount: function(account) {
var $account = $(account),
$trans = $('.transactions'),
$closeBtn= $account.find('.close-btn');
$account.removeClass('pay-open').removeClass('move-open');
$trans.appendTo($a)
.slideDown(400,function(){
$closeBtn.fadeIn(100);
});
}
}
What's the proper way to send the event target / this from the event handler to ui.openAccount() function without have to repeatedly capture the vars? (i.e. how do I stop repeating myself?) Do I use a constructor? Is there where an account object with a closure would come in handy?
I was thinking something like this:
var account = (function(){
var acct = {
this.container = $(this),
this.closeBtn = $(this).find('.close-btn')
}
return acct;
}());
And I could send the var account to ui.openAccount(), but I know i'm definitely not doing it right.
Try passing the event to the function you are calling:
$account.on({
tap: function(e) {
var my_cool_new_object = {};
console.log("your event is here")
console.log(e)
accountOpen = true;
// populate your object
my_cool_new_object.target = e.target;
my_cool_new_object.foo = bar;
...
// pass to method
ui.openAccount(my_cool_new_object);
},
swiperight: etc. etc.
}

confusion regarding event handling in Javascript

I am new to Javascript. while practicing i encounter a code regarding event handling. Here is the code
//This generic event handler creates an object called eventHandler
var etHandler = {};
if (document.addEventListener) {
//eventHandler object has two methods added to it, add()and remove(),
etHandler.add = function(element, eventType, eventFunction) {
/**
* The add method in each model determines whether the event type is a load event, meaning that
* the function needs to be executed on page load.
*/
if (eventType == "load") {
.......
}
};// end of eventHandler.add = function()
etHandler.remove = function(element, eventType, eventFunction) {
element.detachEvent("on" + eventType, eventFunction);
}; //end of etHandler.remove = function()
}
function sendAlert() {
alert("Hello");
} //end of sendAlert()
function startTimer() {
var timerID = window.setTimeout(sendAlert,3000);
}//end of startTimer()
var mainBody = document.getElementById("mainBody");
etHandler.add(mainBody, "load", function() {
startTimer();
}
);
The questions that i want to ask are this. We create an empty object.var etHandler = {};. It's fine. Then we are checking condition if (document.addEventListener) {}. we didn't add any event listener to the document, but this condition is true. Why this condition is returning true?
Then we write etHandler.add = function(element, eventType, eventFunction) {}. Why we are writing etHandler.add? etHandler object has no property, when we created it. It's a null object. If we create etHandler like this
var etHandler = {
add: function() {
},
remove: function(){
}
};
Then we can write etHandler.add. The same question is for etHandler.remove also.
Thanks
The call if (document.addEventListener) is checking whether the browser supports this method. It is checking to see whether it exists on the document object. This is called feature detection and is frequently used to detect differences between browsers.
The call etHandler.add = function(element, eventType, eventFunction) defines the add method and creates it simultaneously. It is basically the same as in your example.

How to pass arguments to addEventListener listener function?

The situation is somewhat like-
var someVar = some_other_function();
someObj.addEventListener("click", function(){
some_function(someVar);
}, false);
The problem is that the value of someVar is not visible inside the listener function of the addEventListener, where it is probably being treated as a new variable.
Why not just get the arguments from the target attribute of the event?
Example:
const someInput = document.querySelector('button');
someInput.addEventListener('click', myFunc, false);
someInput.myParam = 'This is my parameter';
function myFunc(evt)
{
window.alert(evt.currentTarget.myParam);
}
<button class="input">Show parameter</button>
JavaScript is a prototype-oriented language, remember!
There is absolutely nothing wrong with the code you've written. Both some_function and someVar should be accessible, in case they were available in the context where anonymous
function() { some_function(someVar); }
was created.
Check if the alert gives you the value you've been looking for, be sure it will be accessible in the scope of anonymous function (unless you have more code that operates on the same someVar variable next to the call to addEventListener)
var someVar;
someVar = some_other_function();
alert(someVar);
someObj.addEventListener("click", function(){
some_function(someVar);
}, false);
This question is old but I thought I'd offer an alternative using ES5's .bind() - for posterity. :)
function some_func(otherFunc, ev) {
// magic happens
}
someObj.addEventListener("click", some_func.bind(null, some_other_func), false);
Just be aware that you need to set up your listener function with the first param as the argument you're passing into bind (your other function) and the second param is now the event (instead of the first, as it would have been).
Quite and old question but I had the same issue today. Cleanest solution I found is to use the concept of currying.
The code for that:
someObj.addEventListener('click', some_function(someVar));
var some_function = function(someVar) {
return function curried_func(e) {
// do something here
}
}
By naming the curried function it allows you to call Object.removeEventListener to unregister the eventListener at a later execution time.
You can just bind all necessary arguments with 'bind':
root.addEventListener('click', myPrettyHandler.bind(null, event, arg1, ... ));
In this way you'll always get the event, arg1, and other stuff passed to myPrettyHandler.
http://passy.svbtle.com/partial-application-in-javascript-using-bind
nice one line alternative
element.addEventListener('dragstart',(evt) => onDragStart(param1, param2, param3, evt));
function onDragStart(param1, param2, param3, evt) {
//some action...
}
You can add and remove eventlisteners with arguments by declaring a function as a variable.
myaudio.addEventListener('ended',funcName=function(){newSrc(myaudio)},false);
newSrc is the method with myaudio as parameter
funcName is the function name variable
You can remove the listener with
myaudio.removeEventListener('ended',func,false);
Function.prototype.bind() is the way to bind a target function to a particular scope and optionally define the this object within the target function.
someObj.addEventListener("click", some_function.bind(this), false);
Or to capture some of the lexical scope, for example in a loop:
someObj.addEventListener("click", some_function.bind(this, arg1, arg2), false);
Finally, if the this parameter is not needed within the target function:
someObj.addEventListener("click", some_function.bind(null, arg1, arg2), false);
You could pass somevar by value(not by reference) via a javascript feature known as closure:
var someVar='origin';
func = function(v){
console.log(v);
}
document.addEventListener('click',function(someVar){
return function(){func(someVar)}
}(someVar));
someVar='changed'
Or you could write a common wrap function such as wrapEventCallback:
function wrapEventCallback(callback){
var args = Array.prototype.slice.call(arguments, 1);
return function(e){
callback.apply(this, args)
}
}
var someVar='origin';
func = function(v){
console.log(v);
}
document.addEventListener('click',wrapEventCallback(func,someVar))
someVar='changed'
Here wrapEventCallback(func,var1,var2) is like:
func.bind(null, var1,var2)
Here's yet another way (This one works inside for loops):
var someVar = some_other_function();
someObj.addEventListener("click",
function(theVar){
return function(){some_function(theVar)};
}(someVar),
false);
someVar value should be accessible only in some_function() context, not from listener's.
If you like to have it within listener, you must do something like:
someObj.addEventListener("click",
function(){
var newVar = someVar;
some_function(someVar);
},
false);
and use newVar instead.
The other way is to return someVar value from some_function() for using it further in listener (as a new local var):
var someVar = some_function(someVar);
one easy way to execute that may be this
window.addEventListener('click', (e) => functionHandler(e, ...args));
Works for me.
$form.addEventListener('submit', save.bind(null, data, keyword, $name.value, myStemComment));
function save(data, keyword, name, comment, event) {
This is how I got event passed properly.
Use
el.addEventListener('click',
function(){
// this will give you the id value
alert(this.id);
},
false);
And if you want to pass any custom value into this anonymous function then the easiest way to do it is
// this will dynamically create property a property
// you can create anything like el.<your variable>
el.myvalue = "hello world";
el.addEventListener('click',
function(){
//this will show you the myvalue
alert(el.myvalue);
// this will give you the id value
alert(this.id);
},
false);
Works perfectly in my project. Hope this will help
If I'm not mistaken using calling the function with bind actually creates a new function that is returned by the bind method. This will cause you problems later or if you would like to remove the event listener, as it's basically like an anonymous function:
// Possible:
function myCallback() { /* code here */ }
someObject.addEventListener('event', myCallback);
someObject.removeEventListener('event', myCallback);
// Not Possible:
function myCallback() { /* code here */ }
someObject.addEventListener('event', function() { myCallback });
someObject.removeEventListener('event', /* can't remove anonymous function */);
So take that in mind.
If you are using ES6 you could do the same as suggested but a bit cleaner:
someObject.addEventListener('event', () => myCallback(params));
One way is doing this with an outer function:
elem.addEventListener('click', (function(numCopy) {
return function() {
alert(numCopy)
};
})(num));
This method of wrapping an anonymous function in parentheses and calling it right away is called an IIFE (Immediately-Invoked Function Expression)
You can check an example with two parameters in http://codepen.io/froucher/pen/BoWwgz.
catimg.addEventListener('click', (function(c, i){
return function() {
c.meows++;
i.textContent = c.name + '\'s meows are: ' + c.meows;
}
})(cat, catmeows));
In 2019, lots of api changes, the best answer no longer works, without fix bug.
share some working code.
Inspired by all above answer.
button_element = document.getElementById('your-button')
button_element.setAttribute('your-parameter-name',your-parameter-value);
button_element.addEventListener('click', your_function);
function your_function(event)
{
//when click print the parameter value
console.log(event.currentTarget.attributes.your-parameter-name.value;)
}
Sending arguments to an eventListener's callback function requires creating an isolated function and passing arguments to that isolated function.
Here's a nice little helper function you can use. Based on "hello world's" example above.)
One thing that is also needed is to maintain a reference to the function so we can remove the listener cleanly.
// Lambda closure chaos.
//
// Send an anonymous function to the listener, but execute it immediately.
// This will cause the arguments are captured, which is useful when running
// within loops.
//
// The anonymous function returns a closure, that will be executed when
// the event triggers. And since the arguments were captured, any vars
// that were sent in will be unique to the function.
function addListenerWithArgs(elem, evt, func, vars){
var f = function(ff, vv){
return (function (){
ff(vv);
});
}(func, vars);
elem.addEventListener(evt, f);
return f;
}
// Usage:
function doSomething(withThis){
console.log("withThis", withThis);
}
// Capture the function so we can remove it later.
var storeFunc = addListenerWithArgs(someElem, "click", doSomething, "foo");
// To remove the listener, use the normal routine:
someElem.removeEventListener("click", storeFunc);
There is a special variable inside all functions: arguments. You can pass your parameters as anonymous parameters and access them (by order) through the arguments variable.
Example:
var someVar = some_other_function();
someObj.addEventListener("click", function(someVar){
some_function(arguments[0]);
}, false);
I was stuck in this as I was using it in a loop for finding elements and adding listner to it. If you're using it in a loop, then this will work perfectly
for (var i = 0; i < states_array.length; i++) {
var link = document.getElementById('apply_'+states_array[i].state_id);
link.my_id = i;
link.addEventListener('click', function(e) {
alert(e.target.my_id);
some_function(states_array[e.target.my_id].css_url);
});
}
I suggest you to do something like that:
var someVar = some_other_function();
someObj.addEventListener("click", (event, param1 = someVar) => {
some_function(param1);
}, false);
The PERFECT SOLUTION for this is to use Closures like this:
function makeSizer(size) {
return function () {
document.body.style.fontSize = `${size}px`;
};
}
//pass parameters here and keep the reference in variables:
const size12 = makeSizer(12);
const size24 = makeSizer(24);
const size36 = makeSizer(36);
document.getElementById('size-12').addEventListener("click", size12);
document.getElementById('size-24').addEventListener("click", size24);
document.getElementById('size-36').addEventListener("click", size36);
document.getElementById('remove-12').addEventListener("click", ()=>{
document.getElementById('size-12').removeEventListener("click", size12);
alert("Now click on 'size 12' button and you will see that there is no event listener any more");
});
test<br/>
<button id="size-12">
size 12
</button>
<button id="size-24">
size 24
</button>
<button id="size-36">
size 36
</button>
<button id="remove-12">
remove 12
</button>
So basically you wrap a function inside another function and assign that to a variable that you can register as an event listener, but also unregister as well!
Also try these (IE8 + Chrome. I dont know for FF):
function addEvent(obj, type, fn) {
eval('obj.on'+type+'=fn');
}
function removeEvent(obj, type) {
eval('obj.on'+type+'=null');
}
// Use :
function someFunction (someArg) {alert(someArg);}
var object=document.getElementById('somObject_id') ;
var someArg="Hi there !";
var func=function(){someFunction (someArg)};
// mouseover is inactive
addEvent (object, 'mouseover', func);
// mouseover is now active
addEvent (object, 'mouseover');
// mouseover is inactive
Hope there is no typos :-)
The following answer is correct but the below code is not working in IE8 if suppose you compressed the js file using yuicompressor. (In fact,still most of the US peoples using IE8)
var someVar;
someVar = some_other_function();
alert(someVar);
someObj.addEventListener("click",
function(){
some_function(someVar);
},
false);
So, we can fix the above issue as follows and it works fine in all browsers
var someVar, eventListnerFunc;
someVar = some_other_function();
eventListnerFunc = some_function(someVar);
someObj.addEventListener("click", eventListnerFunc, false);
Hope, it would be useful for some one who is compressing the js file in production environment.
Good Luck!!
var EV = {
ev: '',
fn: '',
elem: '',
add: function () {
this.elem.addEventListener(this.ev, this.fn, false);
}
};
function cons() {
console.log('some what');
}
EV.ev = 'click';
EV.fn = cons;
EV.elem = document.getElementById('body');
EV.add();
//If you want to add one more listener for load event then simply add this two lines of code:
EV.ev = 'load';
EV.add();
The following approach worked well for me. Modified from here.
function callback(theVar) {
return function() {
theVar();
}
}
function some_other_function() {
document.body.innerHTML += "made it.";
}
var someVar = some_other_function;
document.getElementById('button').addEventListener('click', callback(someVar));
<!DOCTYPE html>
<html>
<body>
<button type="button" id="button">Click Me!</button>
</body>
</html>
Since your event listener is 'click', you can:
someObj.setAttribute("onclick", "function(parameter)");
Another workaround is by Using data attributes
function func(){
console.log(this.dataset.someVar);
div.removeEventListener("click", func);
}
var div = document.getElementById("some-div");
div.setAttribute("data-some-var", "hello");
div.addEventListener("click", func);
jsfiddle
The following code worked fine for me (firefox):
for (var i=0; i<3; i++) {
element = new ... // create your element
element.counter = i;
element.addEventListener('click', function(e){
console.log(this.counter);
... // another code with this element
}, false);
}
Output:
0
1
2
You need:
newElem.addEventListener('click', {
handleEvent: function (event) {
clickImg(parameter);
}
});

Categories

Resources