2

I've tried the answer suggested here, which follows with nearly all answers to similar/duplicate questions. Checking .data('events') simply isn't working, returning undefined for objects I had previously (immediately at that) registered an event to.

Now, the caveat is that I'm actually registering said events with .live(), rather than .bind() or the alias methods.


I just read (previous to my even posting the question) the following from jQuery on .live():

The .live() method is able to affect elements that have not yet been added to the DOM through the use of event delegation: a handler bound to an ancestor element is responsible for events that are triggered on its descendants. The handler passed to .live() is never bound to an element; instead, .live() binds a special handler to the root of the DOM tree. In the example above, when the new element is clicked...

Given this information, what would I do (if possible at all) to check whether an event is "registered" to a given object with .live()? With this new-found information, I'm guessing it'll start with the window or document object...


Idea update: If there is a way to tap into the DOM monitoring capabilities of .live(), perhaps I could simply re-bind events via .bind() whenever a change occurs (identically to that of .live(), with however, support for the .data('events') inspection as the events are directly bound.)

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Dan Lugg
  • 20,192
  • 19
  • 110
  • 174

3 Answers3

1

I think you are on the right track...you can find the handlers bound by calls to live() in the document's data object: $.data(document, "events").live

Something like this should be a good starting point to accomplish what you want:

function isRegisteredByLive(selector, eventType)
{
    var isRegistered = false;

    // iterate through all "live"  event handlers and check whether the
    // handler applies to the specified selector and event type
    $.each($.data(document, "events").live, function(idx, obj) {
        if (obj.selector === selector && obj.origType === eventType)
        {
            isRegistered = true;
            return false; // break
        } 
    });

    return isRegistered;
}

$('a').live('click', function() { alert('test'); });

isRegisteredByLive('a', 'click'); // returns true

You could also do something like this to identify all live handlers bound to a specific DOM element:

function getLiveEvents(el)
{
    $.each($.data(document, "events").live, function(idx, obj) {
        if ($(el).closest(obj.selector).length > 0)
        {
            console.log(obj.handler);
        } 
    });
}
RoccoC5
  • 4,185
  • 16
  • 20
  • Great! Thanks @RocccoC5 - Worked like a charm, I just needed to add an offset to `obj` in the first solution (*`obj[0].selector` since it returns a single-element array*) – Dan Lugg Sep 14 '11 at 06:31
  • @Bracketworks - Glad to hear it. Not sure about why you would need to specify an index on `obj`, though. The call to `each()` should be iterating through each of the objects in the `$.data(document, "events").live` array and passing to the function the index of the object as the `idx` param, and the actual object as the `obj` param. Take a look at this: http://jsfiddle.net/Xu3Yn/1/ – RoccoC5 Sep 14 '11 at 06:43
1

I recently updated jQuery to the latest (1.7.1) and I realized that I cannot use

var liveEvents = $.data(document, "events").live;

because live is not there anymore. Instead you check for click, change, etc. Here is the updated version of the code that I posted on SO before (with older jQuery versions use the other one posted on this page):

(function ($) {
    $.fn.eventRegistered = function (eventName, includeLiveEvents) {
        if (includeLiveEvents != true)
            includeLiveEvents = false;

        if (this == null || this.length == 0)
            return false;

        for (var i = 0; i < this.length; ++i) {
            var events = $(this[0]).data("events");

            if (events == null)
                continue;

            if (events[eventName] != null)
                return true;
        }

        if (includeLiveEvents) {
            return this.eventRegisteredLive(eventName);
        }

        return false;
    };
})(jQuery);

(function ($) {
    $.fn.eventRegisteredLive = function (eventName) {
        var liveEvents = $.data(document, "events")[eventName];

        if (!liveEvents)
        {
            return false;
        }

        for (var i = 0; i < liveEvents.length; ++i) {
            if (liveEvents[i].selector == this.selector)
                return true;
        }
        return false;
    };
})(jQuery);
Michal B.
  • 5,676
  • 6
  • 42
  • 70
0

I wrote a jQuery function that checks if events for an element is registered (on element and live if necessary)

Code:

(function ($) {
    $.fn.eventRegistered = function (eventName, includeLiveEvents) {
        if (includeLiveEvents != true)
            includeLiveEvents = false;

        if (this == null || this.length == 0)
            return false;

        for (var i = 0; i < this.length; ++i) {
            var events = $(this[0]).data("events");

            if (events == null)
                continue;

            if (events[eventName] != null)
                return true;
        }

        if (includeLiveEvents) {
            var liveEvents = $.data(document, "events").live;

            for (var i = 0; i < liveEvents.length; ++i) {
                if (liveEvents[i].selector == this.selector && liveEvents[i].origType == eventName)
                    return true;
            }
        }

        return false;
    };
})(jQuery);

Examplary usage: var isRegistered = $('.className').eventRegistered("click"); // will return true if click is registeren on at least one element that has a class className

var isRegistered = $('.className').eventRegistered("change", true); // will return true if change is registered on at least one element that has a class className or using live function

Be careful. This function breaks the chain, so you cannot use it like:

$('.className').eventRegistered("change").change(function() {
    // ...
});
Michal B.
  • 5,676
  • 6
  • 42
  • 70