Is there a way to cache a global variable for a function within a group of functions, without calling that function directly from another?
For example, if I have a group of functions wrapped in a parent function like this:
function parentFunction() {
var myVariable;
someDiv.addEventListener('click', function (e) {
myVariable = e.target;
});
anotherDiv.addEventListener('click', function (e) {
// use myVariable without it changing when the above is fired again.
});
}
The global variable is declared at the start, it is given a value in the first function, which carries over to the second for use.
But how can I stop it from continually updating in the second function, if the first function fires again?
Could I add another event-listener inside the second function to check if the first fires again and ensure the variable doesn't change?
You can set the variable only once in the first function:
someDiv.addEventListener('click', function (e) {
if (!clickedLink) {
clickedLink = e.target;
}
});
Or, you can apply any logic you want there. Sometimes, saving state like this in a semi-global for later use in a different event handler is a warning sign that you might have a design issue. If you explain more about what you're really trying to do, we could offer an opinion on whether there's a better way to solve your design issue.
Not sure if I fully understand the question. If you want to have two distinct bindings, you need two variables. Maybe so:
function parentFunction() {
var myVariable, anotherVariable;
someDiv.addEventListener('click', function (e) {
myVariable = e.target;
if (!anotherVariable) {
anotherVariable = e.target;
}
});
anotherDiv.addEventListener('click', function (e) {
// use anotherVariable
});
}
Related
Can I retrieve and modify a previously assigned event function?
For example I originally add an onclick event handler to a node, like this :
var someNode = document.getElementByID('someNode');
someNode.onclick = function(){
//some stuff
};
Ideally later I would need to get back this event and modify the "some stuff" code content.
Is it doable in javascript?
You can modify the onclick event. Simply assign that to a new function will do. However, similar to most dynamic languages, function is not a data structure that you can easily modify. So keeping the same function but modifying it is AFAIK impossible.
The way I would suggest is to create a new function for your use, and assign it to the onclick property. However, JS is a very nice language that provide closure to your variables. So you can make a function that return a function to fit your need if you need some flexibility.
It's not really clear what you are trying to accomplish. But do you mean something like that ?
var someNode = document.getElementByID('someNode');
let customizablePart = function (e) {
// do some stuff
}
someNode.onclick = function (e) {
// unchangeable instructions
customizablePart.call(this, e)
}
// later ...
customizablePart = function (e) {
// do new stuff
}
I'd like to remove an event listener from an element but its function has to take a parameter and it seems to not work. I was trying to find a solution on internet but anyone seems to have the same problem as me.
The role of the function is to simply change the visibility of the element
It doesn't make much sense to remove the listener immediatly but it's only for the example.
function createHoverEqElts() {
slotElts.forEach(function(slot, i) {
if(existValueElts[i].value == "true") {
let infoElt = document.createElement('div');
infoElt.style.position = "relative";
infoElt.style.bottom = "71px";
slot.appendChild(infoElt);
slotListenersElts.push(infoElt);
slot.addEventListener('mouseover', _slotListener(infoElt));
slot.removeEventListener('mouseover', _slotListener(infoElt));
slot.addEventListener('mouseout', function() {
infoElt.style.visibility = "hidden";
});
}
});
}
let _slotListener = function(elt) {
return function() {
elt.style.visibility = "visible";
}
}
I think your problem is that you return a function for some reason. You should pass a function that does something. Try this.
let _slotListener = function(elt) {
elt.style.visibility = "visible";
}
And then do this. In this scenario, you can also pass null instead of this, try either one.
slot.addEventListener('mouseover', _slotListener.bind(this, infoElt));
Since your function returns an anonymous function, you lose its reference. removeEventListener needs the same occurrence to work properly.
In other words _slotListener(infoElt) == _slotListener(infoElt) will always return false, so removeEventListener('event', _slotListener(infoElt)) will never work.
Store the function returned by _slotListener() somewhere and use it back to remove the event. In your example, it could be in a variable. In a more complex example, it could be in an object with some kind of reference or in a property in the DOM element.
var callback = _slotListener(infoElt); // save reference
slot.addEventListener('mouseover', callback);
slot.removeEventListener('mouseover', callback);
The reason you cannot remove the event listener effectively is because the function that you are passing to addEventListener is not the same as the function that you are passing to removeEventListener. JavaScript cannot compare two functions that have the exact same contents and tell they are the same function. Every single time you call _slotlistener, it creates a new function that is not the same as functions that were previously returned by _slotlistener. Instead, the proper way to do this would be to assign the result of _slotlistener to a variable, and then pass that variable into addEventListener and removeEventListener. For example,
var myListenerFunc = _slotListener(elt);
slot.addEventListener("mouseover", myListenerFunc);
slot.removeEventListener("mouseover", myListenerFunc);
This is another Javascript closure question. I run the following code as soon as the document loads:
var handlers = (function () {
var clickHandler = function() { alert ('click!'); }
return {
clickHandler : clickHandler
}
}());
$('#element').addEventListener('click', handlers.clickHandler);
Then at some later point I want to replace the functionality of the handler and thus do something like:
handlers.clickHandler = function() { alert ('changed handler!'); }
From my understand of Javascript closures the event listener should keep a reference of the clickHandler function, and thus the functionality should change accordingly. Yet, this is not what happens. The event listener triggers the initial function. I have managed to achieve the result I want using eval but this feels like a hack. Is there a legitimate way to do what I want?
$('#element').on('click', /*the solution: */ () => handlers.clickHandler());
You need to resolve the identifier on execution of the handler, not on registration. That can be done by wrapping the call into a function, like i did above ( with an arrow function).
I am creating a little javascript/jQuery application with differents steps.
For that I am using a js file with different functions.
At the top of the file I call my first function.
Inside my first function I call a second function when clicking on a button.
Inside the second function I'd like to call back the first one, but "outside" the second one : I mean I don't want the first function to be run inside the second one, because of looping effects...
myFirstFunction();
function myFirstFunction() {
// some code
$('myButton').click(function() {
mySecondFunction();
}
}
function mySecondFunction() {
// some code
$('myOtherButton').click(function() {
myFirstFunction();
}
}
I don't know if this is possible, may be I'd better use objects or else, but I'm pretty new to Javascript...
Thanks in advance for your help.
You can use single event handler there:
var handler = myFirstFunction;
$('myButton').click(function() { handler(); });
function myFirstFunction() { handler = mySecondFunction; }
function mySecondFunction() { handler = myFirstFunction; }
That handler will call either one of your functions.
Update: Or if these are two distinct buttons then
$('myButton').click( mySecondFunction );
$('myOtherButton').click( myFirstFunction );
You're right that it's good to avoid nesting functions within eachother for reasons that you mentioned it might get messy. I'm sure somebody else can weight in, but if you want to stick in vanilla JS i would create a variable that you modify the state of and have a conditional statement determine what function to run.
var state = 1;
function handler(){
if(state == 1){
myFirstFunction();
state = 2;
}
else if(state == 2){
mySecondFunction();
state = 1;
}
}
Then have your myButton execute the handler() function.
I was trying the following:
f.addEventListener('submit',(function(frm){
var func = (function(e){somefunction(e,frm);})(e);
})(f),false);
But this is failing. I want to pass the form (f) as a static reference and the dynamic event object to the named function 'somefunction'.
What I have above isnt working, what is the right syntax for passing both?
The issue is that each of the functions is being called right away, with undefined actually being passed to addEventListener().
You'll want to instead return one of the functions without its calling parenthesis so the event can call it later:
f.addEventListener('submit', (function (frm) {
return function (e) {
someFunction(e, frm);
};
})(f), false);
Though, with event bindings, you may not necessarily need the closure, as the <form> will be the context (this) of the function passed:
f.addEventListener('submit', someFunction, false);
function someFunction(e) {
var frm = this;
// ...
}
not saure exactly what you are trying to do but, to looks like you are trying to manually pass in the form via the event handler. Instead save a reference and just refer to it in the handler such as
f.addEventListener('submit',function(){
var func = function(e){
somefunction(e,f);
};
},false);
you shouldn't need the self executing functions unless I am missing your intent here