35

I want to add an listener exactly once for beforeunload. This is my pseudocode:

if(window.hasEventListener('beforeunload') === false) {
     window.addEventListener('beforeunload', function() { ... }, false);
}

But hasEventListener does not exist obviously. How can I achieve this? Thanks.

Shlomo
  • 3,880
  • 8
  • 50
  • 82

3 Answers3

41

In fact there is no need to check if an listener was added to a target:

If multiple identical EventListeners are registered on the same EventTarget with the same parameters, the duplicate instances are discarded. They do not cause the EventListener to be called twice, and since the duplicates are discarded, they do not need to be removed manually with the removeEventListener method.

Source:https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener#Multiple_identical_event_listeners

user4584026
  • 451
  • 1
  • 4
  • 2
  • 41
    unfortunately it is not true. at least not for chrome. – ses May 20 '15 at 18:07
  • 21
    It is true, if you actually use the exact same listener, not just a listener with the same text: https://jsfiddle.net/myxqu27d/ – Atario Aug 07 '15 at 08:14
  • 1
    @MikeLee The listener function have to be reference of previously added listener, otherwise it will execute more than twice – Rahil Wazir Aug 13 '15 at 16:08
  • @MikeLee updated fiddle showing event listeners are NOT called twice https://jsfiddle.net/mbd5s1ko/39/ – som Sep 23 '17 at 00:13
  • 2
    @MikeLee Lee its true that in case of multiple event listeners, the latest listener overrides the previous one. But for that you have to define a named callback function instead of anonymous callback function. Because event listeners consider both anonymous callback function as different and keep both attached. See this https://jsfiddle.net/hr5d3zuw/ – Akansh Nov 21 '17 at 08:52
  • https://jsfiddle.net/vbhnsa4t/ this fiddle shows the two different cases – Bojidar Stanchev Oct 25 '19 at 08:04
12

Using jquery you can do use data("events") on any object (here the window) :

var hasbeforeunload = $(window).data("events") && $(window).data("events").['beforeunload'];

But this works only for jquery added events.

In a more general case, you should simply store the information that you add a listener somewhere :

   var addedListeners = {};
   function addWindowListenerIfNone(eventType, fun) {
      if (addedListeners[eventType]) return;
      addedListeners[eventType] = fun;
      window.addEventListener(eventType, fun);
   }

I think there is no standard way in javascript to get the existing event handlers. At best you could surcharge the addEventListener function of Node to intercept and store the listeners but I don't recommend it...

EDIT :

From jQuery 1.8, event data are available in $._data(element, "events"). The change log has a warning that should be taken into account :

Note that this is not a supported public interface; the actual data structures may change incompatibly from version to version.

Denys Séguret
  • 372,613
  • 87
  • 782
  • 758
  • +1 for the plain javascript but you could make it cross browser(attachEvent). – The Alpha Jul 11 '12 at 10:41
  • 1
    Maybe. This would be done [as explained by the MDN](https://developer.mozilla.org/en/DOM/element.addEventListener#Legacy_Internet_Explorer_and_attachEvent) – Denys Séguret Jul 11 '12 at 10:42
  • Thanks for the attempt with jQuery, however I need native Javascript, sorry for not mentioning. I will however go with your flag attempt. I will wait for further answers, and if no better, I will choose yours. – Shlomo Jul 11 '12 at 11:08
  • I'm pretty sure there isn't a native way to find what event listeners are added. If you want I could show how to surcharge `Node.addEventListener` but if you can avoid using it it's cleaner. – Denys Séguret Jul 11 '12 at 11:09
  • This seems to stop working in newer jQuery Versions (around 1.8)... Any idea why? http://jsfiddle.net/YEGbM/1/ – thomasf1 Jan 23 '13 at 00:34
  • Yes it changes in 1.8. You must now get the elements with `$._data(element, "events").`. – Denys Séguret Jan 23 '13 at 07:15
  • This got downvoted more than one year and a half after posting... Can the downvoter explain ? – Denys Séguret Mar 26 '14 at 10:41
6

In Chrome Dev tool, you can check all events attached to an element (For debugging)-

// print all events attached to document
var eventObjectAttachedToDocument = getEventListeners(document);

for (var event in eventObjectAttachedToDocument) {
    console.log(event);
}

enter image description here

Varun Kumar
  • 2,543
  • 1
  • 23
  • 22