Cr3aHal0 Cr3aHal0 - 7 months ago 17
Javascript Question

Is it possible from an event to be postponed by Jquery when .off() then .on() are called?

I'm sorry if this question has already been replied but I didn't find anything related on Stackoverflow despite having searched actively.

I'm currently encountering a very strange behaviour in one of my script, behaviour that does not seem natural to me but which may have its reasons (I didn't find which though) :

Actually, my works acts like this : By changing form input (select and radio), a program is then called to calculate specific data (weight, price, etc.). During that time, the final product should not be added to cart, that's why when we change the form inputs, this submit button is

"disabled"
(he's some extra processing thanks to a callback) and its
on('click')
listener is disabled with
off()
.

When the calculation is finished, the program then tells that the button is now clickable again by adding the callback function back.

The actual behaviour is that when the button is disabled (post
off()
), a click on the button won't trigger anything but when the calculation is over and the
on()
listener is added back on that button, the callback linked to that button is called without any action. It feels super weird to me since that it should need another click after the
on()
listener being back to trigger the callback, but probably is that an inner easter-egg or feature I'm not aware of.

function callback () {
// >>
// ...
// <<
}

function start() {
$(".button").off("click");
}

function finish() {
$(".button").on("click", callback);
}

function process() {
start();

// >>
// some inner ajax calls
// <<

finish();
}

$(".button").on("click", callback);


Do you have any idea on what's happening ?

Thanks a lot for your attention, feel free to ask for more information if you need some.

EDIT : As asked, here is a Fiddle I've set up to introduce my case but unfortunately I do manage to reproduce the case above, even if the context is almost the same : https://jsfiddle.net/Cr3aHal0/nfon051x/21/

Answer

See http://javascript.info/tutorial/events-and-timing-depth

To summarise:

Most browsers use single thread for UI and JavaScript, which is blocked by synchronous calls. (your code between off and on is a synchronous call)

So, JavaScript execution blocks the rendering. Events are processed asynchronously with the exception of DOM events.

When an asynchronous event occurs, it gets into the Event queue.

The browser has inner loop, called Event Loop, which checks the queue and processes events, executes functions etc.

For example, if the browser is busy processing your onclick, and another event happened in the background (like another click), it appends to the queue. When the onclick handler is complete, the queue is checked and the script is executed. (in your case, after you've turned the event handler back on)


How do you fix this in your scenario?

Instead of turning the event handler off/on, try to disable the button. Disabled buttons will not get click events.

Alternatively, use a setTimeout to enable the handler, which will occur after the click queue has been cleared, eg:

setTimeout(function() { $(".button").on("click", callback); }, 10);
Comments