How to check if click event is already bound - JQuery
JqueryJquery Problem Overview
I am binding a click event with a button:
$('#myButton').bind('click', onButtonClicked);
In one scenario, this is getting called multiple times, so when I do a trigger
I see multiple ajax calls which I want to prevent.
How do I bind
only if its not bound before.
Jquery Solutions
Solution 1 - Jquery
One more way - mark such buttons with a CSS class and filter:
$('#myButton:not(.bound)').addClass('bound').bind('click', onButtonClicked);
In recent jQuery versions replace bind
with on
:
$('#myButton:not(.bound)').addClass('bound').on('click', onButtonClicked);
Solution 2 - Jquery
Update 24 Aug '12: In jQuery 1.8, it is no longer possible to access the element's events using .data('events')
. (See this bug for details.) It is possible to access the same data with jQuery._data(elem, 'events')
, an internal data structure, which is undocumented and therefore not 100% guaranteed to remain stable. This shouldn't, however, be a problem, and the relevant line of the plugin code above can be changed to the following:
var data = jQuery._data(this[0], 'events')[type];
jQuery events are stored in a data object called events
, so you could search in this:
var button = $('#myButton');
if (-1 !== $.inArray(onButtonClicked, button.data('events').click)) {
button.click(onButtonClicked);
}
It would be best, of course, if you could structure your application so this code only gets called once.
This could be encapsulated into a plugin:
$.fn.isBound = function(type, fn) {
var data = this.data('events')[type];
if (data === undefined || data.length === 0) {
return false;
}
return (-1 !== $.inArray(fn, data));
};
You could then call:
var button = $('#myButton');
if (!button.isBound('click', onButtonClicked)) {
button.click(onButtonClicked);
}
Solution 3 - Jquery
If using jQuery 1.7+:
You can call off
before on
:
$('#myButton').off('click', onButtonClicked) // remove handler
.on('click', onButtonClicked); // add handler
If not:
You can just unbind it first event:
$('#myButton').unbind('click', onButtonClicked) //remove handler
.bind('click', onButtonClicked); //add handler
Solution 4 - Jquery
The best way I see is to use live() or delegate() to capture the event in a parent and not in each child element.
If your button is inside a #parent element, you can replace:
$('#myButton').bind('click', onButtonClicked);
by
$('#parent').delegate('#myButton', 'click', onButtonClicked);
even if #myButton doesn't exist yet when this code is executed.
Solution 5 - Jquery
I wrote a very tiny plugin called "once" which do that. Execute off and on in element.
$.fn.once = function(a, b) {
return this.each(function() {
$(this).off(a).on(a,b);
});
};
And simply:
$(element).once('click', function(){
});
Solution 6 - Jquery
Why not use this
unbind()
before bind()
$('#myButton').unbind().bind('click', onButtonClicked);
Solution 7 - Jquery
Here's my version:
Utils.eventBoundToFunction = function (element, eventType, fCallback) {
if (!element || !element.data('events') || !element.data('events')[eventType] || !fCallback) {
return false;
}
for (runner in element.data('events')[eventType]) {
if (element.data('events')[eventType][runner].handler == fCallback) {
return true;
}
}
return false;
};
Usage:
Utils.eventBoundToFunction(okButton, 'click', handleOkButtonFunction)
Solution 8 - Jquery
To avoid to check/bind/unbind, you can change your approach! Why don't you use Jquery .on() ?
Since Jquery 1.7, .live(), .delegate() is deprecated, now you can use .on() to
> Attach an event handler for all elements which match the current selector, now and in the future
It means that you can attach an event to a parent element that is still existing and attach children elements whether they are present or not!
When you use .on() like this:
$('#Parent').on('click', '#myButton' onButtonClicked);
You catch event click on parent and it search child '#myButton' if exists...
So when you remove or add a child element, you do not have to worry about whether to add or remove the event binding.
Solution 9 - Jquery
Based on @konrad-garus answer, but using data
, since I believe class
should be used mostly for styling.
if (!el.data("bound")) {
el.data("bound", true);
el.on("event", function(e) { ... });
}
Solution 10 - Jquery
Try:
if (typeof($("#myButton").click) != "function")
{
$("#myButton").click(onButtonClicked);
}
Solution 11 - Jquery
if ($("#btn").data('events') != undefined && $("#btn").data('events').click != undefined) {
//do nothing as the click event is already there
} else {
$("#btn").click(function (e) {
alert('test');
});
}
Solution 12 - Jquery
As of June 2019, I've updated the function (and it's working for what I need)
$.fn.isBound = function (type) {
var data = $._data($(this)[0], 'events');
if (data[type] === undefined || data.length === 0) {
return false;
}
return true;
};
Solution 13 - Jquery
JQuery has solution:
$( "#foo" ).one( "click", function() {
alert( "This will be displayed only once." );
});
equivalent:
$( "#foo" ).on( "click", function( event ) {
alert( "This will be displayed only once." );
$( this ).off( event );
});