JQuery do click events stack - javascript

I have the following code;
$("#myID").click(function () {
//do something
})
At some point, a user action on another part of the webpage needs to change the action that occurs on the click e.g.
$("#myID").click(function () {
//do something different
})
My question is, what's the correct/most efficient way of doing this? Currently I'm just implementing the second chunk of code above, but will this cause some odd behaviour? i.e. will there now be two different actions performed on click? Or does the second block of code override the first.

They will both execute so no, the second call does not overwrite the first.
Basic jsFiddle example
And as pimvdb notes, they will be executed in the order they were bound.

You can always unbind the click function first: http://api.jquery.com/unbind/

Right, they "stack". I.e. $("#myID") will maintain a list of event handlers, and execute both on click.
If you no longer want the original handler, you need to unbind it, using $("#myID").off('click') or if you're using an old version of jquery, $("#myID").unbind('click')`. http://api.jquery.com/unbind/

In your code, both clicks will be executed.
Try to unbind click event before
$("#myID").unbind("click")
http://api.jquery.com/unbind/

You can add a global variable isAnotherEvent = false and then check on click event which part of code you need to execute, to execute another part simply make isAnotherEvent = true
var isAnotherEvent = false;
$("#myID").click(function () {
if(!isAnotjerEvent){
//do something
} else {
//do something else
}
})
$("#btnChangeEvent").click(function(){
isAnotherEvent = true;
}

Related

jQuery call animation before debounce method executes

I have a piece of code like following:
$('.cardButton').click($.debounce(1500, function () {
console.log("OK");
}));
The debounce in this case works just perfectly..
However - I need to add animation function which will replace ".cardButton" element before the debounce occurs...
Doing something like this:
$('.cardButton').click($.debounce(1500, function () {
StartAnimationLoader();
console.log("OK");
}));
// In this case - animation starts as soon as console writes out "OK" ...
Or like following:
$('.cardButton').click(function(){
StartAnimationLoader();
$.debounce(1500, function () {
console.log("OK");
})
});
// When I execute code like this - there is nothing written in the console... - thus this method doesn't works
I need to execute animation before debounce occurs ...
What am I doing wrong here?
Can someone help me out ?
Adding a 2nd (or more) event handler to the same element will fire both events (unless stopped) so you can create two actions by having two separate event handlers:
// existing debounce fire only after user stops clicking
$('.cardButton').click($.debounce... );
// additional event will fire on every click
$(".cardButton").click(function() { StartAnimationloader() });

Bug or i do a mistake with inboxsdk "presending" event

When i use the inboxSDK with the newGmail I face an issue that the "event" did not get the composeView like the other events.
sdk.Compose.registerComposeViewHandler(function (composeView) {
composeView.on("presending", function (event) {
// Only get event.cancel();
});
}
Did i do something wrong or it's a bug with the new Gmail UI ?
As of the documentation the presending callbacks event object only has the cancel method attached. And actually that is no problem at all since you already have the composeView availbale from the registerComposeViewHandlers scope. Just access that composeView object.
sdk.Compose.registerComposeViewHandler(function (composeView ) {
composeView.on("presending", function (event) {
console.log(composeView);
});
}
If the presending event triggers you can just use event.cancel() to stop the sending, do whatever you wanna do on the composeView like you would for example in the registerComposeViewHandler callback and when you're done do composeView.send() to finally send the email. Just make sure to have a condition for the cancel event so you actually be able to send at one point and not get stuck in the presend event forever.

Unable to unbind event listener - trouble with turbolinks caching

I'm binding then unbinding the ready event listener to the document.
$(document).bind("ready", readyEventHandler);
function readyEventHandler() {
// run some code
$(document).unbind("ready");
}
The code produces no errors and will work. However, my javascript is cached and duplicates the code so I'll end up with having this code run more than once if I go back and then forward a page in the browser. When this happens, the ready event listener is not called at all. Am I properly unbinding this event listener? I know the caching issue becomes problematic(it's own separate issue) but I just want to bind the ready event listener, have it run code, then unbind it.
Not so sure it will help, but here are my 2 cents - instead of trying to unbind the readyEventHandler - make sure that if you run the function once it will not run twice:
var readyHandlerRun = false;
$(document).bind("ready", readyEventHandler);
function readyEventHandler() {
if (readyHandlerRun) {
return;
}
readyHandlerRun = true;
// Rest of your code...
}
Another options that popped just now:
$(document).bind("ready", readyEventHandler);
function readyEventHandler() {
readyEventHandler = function() { }
console.log('ready');
// Rest of your code...
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
UPDATE (by #jason328)
After talking with Dekel he provided me the appropriate answer.
$(document).bind("ready", function() {
readyEventHandler();
readyEventHandler = function() { }
});
Elegant and works like a charm!
if you just would like to use an eventhamdler only once, you could use one instead of bind
$(document).one("ready", function() {
// code to run on document ready just for once
});

Javascript sequential execution after trigger

I'm having trouble with the way javascript execute the code (async)
I have this small piece of code that will trigger events and check the value of 'valid'.
My problem is that 'valid' is always true when entering the if statement because the events have not finished processing yet :
valid = true;
$(this).find('input').trigger('blur');
//valid will be modified in the triggered events
if(valid){
//Do something
}
So I'd like to wait till the events are finished to enter the statement, but trigger doesn't take a callback
I have seen some questions about this already solved but I didn't understand them and how to implement them.
What should I use to solve this ?
Thanks to JamesThorpe I found the answer I was looking for :
valid = true;
$.when($(this).find('input').trigger('blur')).done(function(){
if(valid){
//Do something
}
});
And now the if statement only gets executed after the events are triggered
As you want to have it triggered on blur, you can do it like this:
$(this).find('input').on('blur', function(){
if(valid){
//Do something
}
});
Note that the function will be triggered on all blur events. To have it only once use .one()
I don't understand why you are using trigger. I think you can directly use blur event:
$(this).find('input').blur(function(){
if(valid)
//do something
});

How to let JavaScript wait until certain event happens?

I am writing a webpage with the following structure:
One section (table A) depends on another section (table B);
Another section (table B) has elements that require recalculation on each update. The calculation is handled by external tools, and will cause an event when finished.
In order to guarantee correctness, the table need to be updated only after the other table is fully updated (i.e., done with computation). However, I don't know how to effectively achieve this, and I could not find any wait facility within JavaScript.
For now, I am using the following method:
Declare a global variable updated and make it false;
After the first table received input, I make an empty while loop until updated is true;
Add an listener, once the calculation is done and the event received, set updated to true.
This seems unintuitive to me but I cannot think of any other way of doing it. Is there any good ways to do this?
Thanks for any inputs!
In 2022, it's useful to have an event listener that fires off a Promise (which can be used in promise-chains, or async/await code). A clean way to make one:
function getPromiseFromEvent(item, event) {
return new Promise((resolve) => {
const listener = () => {
item.removeEventListener(event, listener);
resolve();
}
item.addEventListener(event, listener);
})
}
async function waitForButtonClick() {
const div = document.querySelector("div")
const button = document.querySelector("button")
div.innerText = "Waiting for you to press the button"
await getPromiseFromEvent(button, "click")
div.innerText = "The button was pressed!"
}
waitForButtonClick()
<button>ClickMe</button>
<div></div>
Add an listener, once the calculation is done and the event received, set updated to true.
Instead of setting updated to true, and then waiting for updated to be true- just do whatever you want to do in the listener.
myEventBus.addListener(function () {
// do whatever
updateTable();
alert('table updated!');
});
Doing empty while loops is a bad idea. Not only do you burn CPU cycles, but Javacript is single threaded so you will loop forever without giving anyone a chance to change the variable.
What you can do is rewrite the table that has other people depending on it to "fire an event itself". There are many ways to do this, but basicaly you just want it to call a "continuation' function instead of blindily returning. This function can be predefined or you can pass it as a parameter somewhere.
//this is just illustrative
//Your actual code will be probably very different from this.
function update_part(){
//do something
signal_finished_part()
}
var parts_done = 0;
function signal_finished_part(){
parts_done ++;
if(parts_done >= 5){
signal_all_parts_done();
}
}
function signal_all_parts_done()
{
//do something to table A
}
You could write a callback function for whatever triggers the update. To avoid messy callbacks, you could use promises too, and update parts of the table depending on the data retrieved in the update operation. Open to suggestions.

Categories