Reputation: 4307
Using jQuery I need to:
I found that get list of current listeners with (some jQuery inner mechanisms):
var eventsSubmitBtn = $._data(submitButton[0], "events");
Then I can remove all event listeners with
submitButton.off();
But last stem seems not to be working
setTimeout(function () {
$._data(submitButton[0], "events", eventsSubmitBtn);
}, 5000);
eventsSubmitBtn
is an empty array.
Is this the way this should be done with initial setting and I'm need something like deep cloning for those objects or this can't be done with $._data
?
N.B. I have possibility to add my cistom code after all other system js code, thus I can't place the code assigning to $.fn.on
before anything. Code that I write will run the last on startup and other event listeners are attached before my scripts will run.
Upvotes: 0
Views: 341
Reputation: 351328
As you get a reference to the object returned by $._data()
, any change to that object will not go unnoticed, i.e. after you invoke .off()
, that object will have changed to reflect that there are no handlers attached any more.
You could solve this by taking a shallow copy of the object, (e.g. with Object.assign
).
But this is not really a recommended way to proceed. According to a jQuery blog, "jQuery._data(element, "events")
... is an internal data structure that is undocumented and should not be modified.". As you are modifying it when restoring the handlers, this cannot be regarded best practice. But even only reading it should only be used for debugging, not production code.
It would be more prudent to put a condition in your event handling code:
var ignoreEventsFor = $(); // empty list
$("#button").on('click', function () {
if (ignoreEventsFor.is(this)) return;
// ...
});
Then, at the time it is needed, set ignoreEventsFor
to the element(s) you want to ignore events for. And when you want to revert back to normal, set it to $()
again.
Now adding this to all your event handlers may become a burden. If you stick to using on()
for attaching event handlers, then you could instead extend $.fn.on
so it will add this logic to the handlers you pass to it.
The following demo has a button which will respond to a click by changing the background color. With a checkbox you can disable this from happening:
/* Place this part immediately after jQuery is loaded, but before any
other library is included
*/
var ignoreEventsFor = $(), // empty list
originalOn = $.fn.on;
$.fn.on = function (...args) {
var f = args[args.length-1];
if (typeof f === 'function') {
args[args.length-1] = function (...args2) {
if (ignoreEventsFor.is(this)) return;
f.call(this, ...args2);
};
}
originalOn.call(this, ...args);
}
/* This next part belongs to the demo, and can be placed anywhere */
$(function () {
$("#colorButton").on('click', function () {
// Just some handler that changes the background
var random = ('00' + (Math.random() * 16*16*16).toString(16)).substr(-3);
$('body').css({ backgroundColor: "#" + random });
});
$("#toggler").on('change', function () {
// Toggle the further handling of events for the color button:
ignoreEventsFor = $(this).is(':checked') ? $("#colorButton") : $();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="colorButton">Change color</button><br>
<input type="checkbox" id="toggler">Disable events
Notice: the above code uses ES6 spread/rest syntax: if you need support for IE then that would have to be written using the arguments
variable, apply
, ...etc.
Upvotes: 2