[jquery] How to check if click event is already bound - JQuery

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.

This question is related to jquery

The answer is


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;
};

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);

Try:

if (typeof($("#myButton").click) != "function") 
{
   $("#myButton").click(onButtonClicked);
}

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.


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');
    });
}

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(){
});

Why not use this

unbind() before bind()

$('#myButton').unbind().bind('click',  onButtonClicked);

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 );
});

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

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)

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.


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) { ... });
}