3

Is there a way to temporarily disable an event listener?

In my case, I have a third party library (not jQuery centric) that creates mouseover/mouseout events on an element using addEventListener/attachEvent.

Under certain circumstances another event fires on a different element and I need to disable those event listeners. My solution thus far has been to simply unbind the mouseover/mouseout. This usually works fine because that event generally causes the page to refresh.

However, every now and again an error can occur (think validation error) that results in the page not refreshing, and I need to re-attach the mouseover/mouseout event listeners.

Helpful information

It's probably worth mentioning that because the mouseover/mouseout event listeners are created and attached within a third party library I cannot simply assign the event to a variable and bind/unbind it in that manner (which AFIK is the best way to do this).

Update

I had originally asked

Is there a way in jQuery to get the event listeners already assigned to an object?

I have since found out it is impossible to access events assigned by addEventListener/attachEvent: Access events added with attachEvent() / addEventListener() in JavaScript

Community
  • 1
  • 1
xzyfer
  • 13,937
  • 5
  • 35
  • 46

3 Answers3

1

jQuery uses data to store events internally, so you can use it to get all of the event handlers for an object:

$("#foo").data("events")

You can then remove a specific handler by using unbind:

$("#foo").unbind('click', $("#foo").data("events").click[42]);
Emmett
  • 14,035
  • 12
  • 56
  • 81
  • I should probably have mentioned that the library that originally attaches the mouseover/mouseout event listeners isn't a jQuery plugin, but instead uses the native addEventListener/attachEvent. – xzyfer Mar 02 '11 at 00:40
  • Ah, ok. My answer will probably still help people arriving from Google, so I'll leave it up. Are you trying to disable *all* event listeners, or just some of them? – Emmett Mar 02 '11 at 00:47
  • I'm trying to disable a specif mouseover and mouseout event. But since they're the only events on the element it's safe to remove all events from that element. Which is easy enough using `unbind` but I need to keep a reference to then so I can re-bind them if there is an error. It appears however that what I need isn't possible see: http://stackoverflow.com/questions/681120/access-events-added-with-attachevent-addeventlistener-in-javascript – xzyfer Mar 02 '11 at 00:53
  • You could try using `cloneNode` to create copy of the element without events. Then you could achieve unbinding and rebinding effects by swapping the element with its clone, and vice versa. – Emmett Mar 02 '11 at 00:59
  • That is the approach I was considering. Although I think I might just settle for refreshing the page on failure as well. It looks like this is going to get messy. – xzyfer Mar 02 '11 at 01:01
1

Unfortunately, you can't access them. At best, you can remove event listeners using W3C's removeEventListener (docs) and/or Microsofts detachEvent (docs). Once the listener is removed, however, it's gone for good.

There's one caveat with removeEventListener, in that if the event was registered twice, once indicating to capture, and once indicating not to capture, you must remove it twice; once for each case.

To learn more about capturing and not capturing, see the W3C spec.

ntownsend
  • 7,462
  • 9
  • 38
  • 35
  • I'm aware of this, thanks. But using jQuery's `unbind` effectively removes events event those attached using addEventListener/attachEvent. My issue is caching the event listeners locally so I can re-attach it, or temporarily disabling/re-enabling it, without explicitly removing it. – xzyfer Mar 02 '11 at 01:03
  • You can't cache the listeners and re-attach them. They cannot be accessed. – ntownsend Mar 17 '11 at 17:29
0

If you want to temporarily disable an event handler being run, why not just add escape code to the function?

like so:

$('#button').click(function(){
    var clicked_element = $(this);
    if(elem.hasClass('event-click-disabled'))
    {
        // logging code so we know exactly what events are being skipped
        console.info(
            'The click event on following element was skipped',
            clicked_element
        );
        return;
    }
    alert('Button clicked');
});

Then if you want to disable an event on a specific element, just call

element.addClass('event-click-disabled');

The event handler is still run, but it will return immediately.

AlexMorley-Finch
  • 6,785
  • 15
  • 68
  • 103