Javascript : Replace Event Listener - javascript

I am listening to an event and want to call different methods. For example, I am listening to animation end event and the code is something like this:
this.inAnimationCallback = function() {
console.log('In');
_this.elem.className = _this.settings.className;
};
this.outAnimationCallback = function() {
console.log('Out');
_this.elem.parentNode.removeChild(_this.elem);
};
this.elem.addEventListener(animationEvent, this.inAnimationCallback);
setTimeout(function() {
_this.elem.addEventListener(animationEvent, _this.outAnimationCallback);
// Call some animation here.
}, 3000);
What happens here is that instead of replacing the method attached to the event, JS adds the method and when animation ends, both methods are called. Console looks like this:
(2) In
Out

I'm writing this answer for those like me, who is just started learning JS. And this thread came up first in google to "js replace event listener"..
Although, I am not disagreeing with the answers to use removeEventListener(), but mozilla warns that this function is not always successful. So use it with care. not willing to go that road i have found two other ways to do it.
Use something like GlobalEventHandlers which is simple as target.onclick = functionRef;. Mozilla even warns:
Only one onclick handler can be assigned to an object at a time.
Within listener function add external function call to action function, and then replace reference to another external action function. For example this code will call firstAction(), then seconAction(), then first again...:
const buttonOne = document.getElementById('buttonOne');
buttonOne.addEventListener('click', listenerFunction);
let doAction = firstAction; //assigning doAction to firstAction
function listenerFunction() {
doAction(); //external function call
}
function firstAction() {
doAction = secondAction; //assigning doAction to secondAction
console.log('first action clicked');
}
function secondAction() {
doAction = firstAction; //assigning doAction to firstAction
console.log('second action clicked');
}
<button type="button" id="buttonOne" name="button">button1</button>
I wrote this answer to broaden solution scope: would have saved at least 6 hours of my time. If I had this in the first place...

You can just remove the event listener before adding the new one :
setTimeout(function() {
_this.elem.removeEventListener(animationEvent, _this.inAnimationCallback);
_this.elem.addEventListener(animationEvent, _this.outAnimationCallback);
// Call some animation here.
}, 3000);

Related

Run a function when another function is called

I'm wondering how to run a function when another function is called. addEventListener only runs events like "click", "mouseover", etc. However, I'd like to listen for a function call.
EXAMPLE:
Function 1 is called. Afterwards, Function 2 runs because it saw that Function 1 was called.
Is there an addEventListener alternative for simple functions and not events? I can't seem to find any.
My goal was to simply run a function everytime a user did something like call for when something was hidden in jQuery or by another JavaScript library or just simply another external JavaScript file with some code I added in.
Introducing a very hacky way
Since what you are trying to achieve is basically hacking some existing system (you shouldn't run into this problem if you have control over both sides and design your code properly).
It looks like your function is declared globally as well. In that case:
1. store the existing function in a variable
2. overwrite that function with your implementation
3. call the function variable at the start
function myFunction(){
//This is the main function
alert('Hello, this is part of the message!');
}
var tempfunc = myFunction;
window.myFunction = function() {
tempfunc();
// do what you need to do in the event listener here
alert('Hello, this is the other part of the message!');
}
EDIT:
The original question had the requirement that the original function cannot be modified, hence my solution. Since they it appears the question has changed.
You will have trigger an event inside myFunction and listen to that event.
function myFunction(){
//This is the main function
alert('Hello, this is part of the message!');
// trigger the event
var event = new CustomEvent("event", { "detail": "Example of an event" });
document.dispatchEvent(event);
}
// handle here;
document.addEventListener("event", function(){
//This is the secondary function
//or the function I need to run after the main function is called
alert('Hello, this is the other part of the message!');
});
// call main
myFunction();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p>Simple test!</p>
<p>Long story short, you get message 1, but message 2 never pops up!</p>
Is there an addEventListener alternative for simple functions and not
events? I can't seem to find any.
My goal was to simply run a function everytime a user did something
like call for when something was hidden in jQuery or by another
JavaScript library or just simply another external JavaScript file
with some code I added in.
You can use jQuery.Callbacks()
var callbacks = $.Callbacks();
function handleCallback1(message) {
console.log(message, this)
};
function handleCallback2(message) {
if (this.tagName === "DIV") {
this.style.color = "green";
} else {
this.nextElementSibling.style.color = "blue";
}
};
$("button, div").on("click", function() {
callbacks.fireWith(this, ["called from " + this.tagName])
});
callbacks.add(handleCallback1, handleCallback2);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js">
</script>
<button>click</button>
<div>click</div>

Passing value into function and variable scope in JQuery

Link to code example:
http://jsfiddle.net/99Shr/
This code works for a given click handler, and $(this) takes on the particular class.
I am attempting to take the code that is inside the click function and put it into it's own function. The reason I want to do this is because I would like to replace quantity-- with quantity++ depending on which click handler is called. The issue I am running into is that the variables when called in the function are undefined since $(this) is window.
I am well aware that I may be doing this wrong to achieve what I want and am open to learning a better way to achieve it.
function price(change) {
return change;
}
$('.cart-item-decrease').click(function(){
price('quantity--');
});
or
$('.cart-item-increase').click(function(){
price('quantity++');
});
You can customise the event handler registration so that additional data gets sent to your function:
function myClickHandler(e)
{
// ...
quantity += e.data.increment;
// ...
}
$('.cart-item-increase').on('click', null, {
increment: 1
}, myClickHandler);
$('.cart-item-decrease').on('click', null, {
increment: -1
}, myClickHandler);
Here, the increment property gets sent to myClickHandler as e.data.increment.

jquery change event callback

How to call a function once after change() event complete?
for example, something like this: ( I know jQuery Doesn't have callback method as default )
$('#element').change( function(){
// do something on change
// $('#milestonesSelect').multiselect({ minWidth: 120 , height : '200px' ,selectedList: 4 }).multiselectfilter();
// some animation calls ...
// ...
}, function(){
// do something after complete
alert('another codes has completed when i called');
}
);
Is it possible to call a single callback after all the codes on change method done, except call a complete callback for every functions on it?
I need to do something after the change event has completed
Shall I need to set order to methods in change handler?
You can probably make use of event bubbling and register a callback in the document.
$(document).on('change', '#element', function(){
console.log('after all callbacks')
});
Demo: Fiddle
I just spent some time exploring this myself, and decided to submit my answer to this question as well. This is not utilizing any of jQuery's deferred methods, which might be a better approach. I haven't explored them enough to have an opinion on the matter.
$("#element").change(function() {
handler().after(callBack($("#element").val()));
}
function handler() {
alert("Event handler");
}
function callBack(foo) {
alert(foo);
}
Demo: JSFiddle
If I understand your question correctly, this will execute code only one time after a change event is fired:
var changed = false;
$('#element').on('change', function() {
if ( !changed ) {
// do something on change
changed = true;
}
}
});

Ending an Event Driven Function in JavaScript

I am using JavaScript with HTML5. When the user clicks on a button, an event-driven JavaScript function starts up. When the user clicks on the button again, another instance of this function starts up. So I have two instances of the same function handling a event. However I only want the new instance to be running. How do I end the first instance of the?
An example is a function with the following code
Canvas.paper = Raphael(xOffset,yOffset,imageWidth,imageHeight);
masterBackground = Canvas.paper.rect(0,0,imageWidth,imageHeight);
window.onkeydown=function(e){
// Event handler code
}
document.addEventListener('keydown', function(event) {
// Event handler code
}
masterBackground.mousemove(function(e){
// Event handler code
}
Seems apparent that something asynchronous and long-running is happening.
To prevent concurrent instances from running, just use a flag that is set when one starts so that others can't begin. Then when the current one finishes, reset the flag so that another can start.
// Immediately invoked function, makes a variable and returns the handler
// that uses the variable as a flag.
button.onclick = (function() {
// local variable, only accessible to the returned handler
var running = false;
// This is your event handler.
return function(e) {
if (running === false) {
running = true;
// run your asynchronous operation
// after it's complete, set `running = false;`
}
};
})();
There are several solutions to this, some of them library dependent, but "nicer" to look at:
For example, using jQuery:
<button>Click me</button>
<script>
$('button').on('click', handleButtonClick);
function handleButtonClick() {
$(this).off('click', handleButtonClick); //disable click event
//do various things you don't want duplicated
$(this).on('click', handleButtonClick); //reattach handler
}
</script>
OR:
<button>Click me</button>
<script>
$('button').once('click', handleButtonClick); //attach one-time handler
function handleButtonClick() {
//do various things you don't want duplicated
$(this).once('click', handleButtonClick); //attach one-time handler
}
</script>
Most libraries support similar methods, if you'd rather do it vanilla JS, that is definitely possible of course as well. "am not i am" provided a nice example for that: https://stackoverflow.com/a/15976888/622129
var buttonView = document.getElementById('buttonView');
buttonView.handleEvent = function(event) {
window.alert(this.id);
//this.onclick = null;
};
buttonView.onclick = buttonView.handleEvent;
Try it out: http://jsfiddle.net/KHQ4y/
Edit: I posted this before you supplied your specific code, but you get the idea.
If you want to make sure a function only runs once:
example based on benny's example
function onlyOnce(proc){
return function () {
var result = proc.apply(this,arguments);
proc = function () {};
return result;
}
}

How to cancel the execution of a JavaScript event handler function from the inside of another handler?

When an event handler function gets registered like this:
element.onload = function()
{
var something = Selector("identifier", "inline", 1).FadeIn("inline", 1);
CenterElement(something);
};
Is there a way to stop the execution once it starts from the inside of another handler function? Let that handler function look like this:
another.onclick = function()
{
//Cancel the execution of the above function here
document.getElementById("start").innerHTML = "Start Slideshow";
this.FadeOut();
};
Selector returns a special wrapper object that isn't relevant for the question itself so the implementation has been omitted.
It's quite known that it's possible to prevent execution of a handler function by assigning undefined to the handler variable, but how to stop it if it's already begun executing?
You're missing an important concept here.
In javascript, there is only one thread of execution. While you might think that onclick gets called while onload is executing, that is plain false.
I don't know what framework you're using, but in jQuery you could do the following:
another.onclick = function()
{
//Cancel the execution of the above function here
Selector("identifier", "inline", 1).stop();
// ...other stuff
};

Categories