41

Some of the third party plugin will attach the eventListener into the site. How to I remove the eventListener without knowing the function that attached.

I refer this removeEventListener but I can't get any clue to remove this.

Eg: getEventListeners(window) shows the events attached. But, when I try to remove the event using window.removeEventListener("eventname") is not working without knowing that function.

Please help, Thanks in advance.

Dineshkani
  • 2,899
  • 7
  • 31
  • 43
  • See also the different answers on this related question (I posted an answer also): https://stackoverflow.com/questions/4386300/javascript-dom-how-to-remove-all-event-listeners-of-a-dom-object – baptx Nov 18 '22 at 19:24

4 Answers4

29

getEventListeners(window) will return a map of events and their registered event listeners.

So for DOMContentLoaded event for example you can have many event listeners. If you know the index of the listener you want to remove (or if there exists only one), you can do:

var eventlistener = getEventListeners(window)["DOMContentLoaded"][index];
window.removeEventListener("DOMContentLoaded", 
                           eventlistener.listener,
                           eventlistener.useCapture);
manji
  • 47,442
  • 5
  • 96
  • 103
  • 2
    Even more convenient because it also returns deregistration function `remove`: `getEventListeners(window).DOMContentLoaded[0].remove()`. – dfsq Nov 10 '14 at 14:16
  • 3
    @dfsq, `chrome` yes, but not `firefox`. (can't test for ie). – manji Nov 10 '14 at 14:24
  • 21
    @Dineshkani That's not implemented in every browsers and is not part of the spec. That shouldn't be the accepted answer, unless your question targets Chrome only. In this case it should be stated in the question. – plalx Nov 10 '14 at 14:31
  • @plalx Yes I know about that. I will definetly find the answer for all the browser. I accepted this answer because it gives some clue. – Dineshkani Nov 10 '14 at 14:33
  • 2
    @Dineshkani Well, that is confusing for every other people that will look at this question. The correct answer was already given below by jAndy. – plalx Nov 10 '14 at 14:36
  • @plalx, it works in `chrome` and `firefox` (`remove()` does not work in `firefox`) – manji Nov 10 '14 at 14:38
  • @manji A feature that is not in the spec and cannot be emulated/shimmed in all browsers is not to be used anywhere in my opinion. What about IE? You must code for the standards... – plalx Nov 10 '14 at 14:44
  • @plalx, you are right in the absolute, but it can help in resolving some situation. Should I delete the answer, I don't think so. Should the Op change the accepted answer, that's his decision to make. Saying that there is no way to do this, is also not true. And IE will catch up to this someday. – manji Nov 10 '14 at 14:50
  • `getEventListeners(window)` does not work in Android 4.4 WebViews which are stuck on Chrome 33. [Chromium bug 336472](https://bugs.chromium.org/p/chromium/issues/detail?id=336472) was supposedly fixed in time for Chrome 33 but apparently the fix did not make it as far as Android WebViews. More recent versions of Chrome will take `getEventListeners(window)`. The old version only takes `getEventListeners(document)`, which doesn't usually cover events like `scroll` :-( – Silas S. Brown Oct 26 '18 at 21:58
  • No such method in Firefox, still. This shouldn't be an accepted solution. – ADTC May 30 '22 at 01:37
  • For Firefox, you can use a polyfill, see https://github.com/colxi/getEventListeners/issues/1. – baptx Nov 18 '22 at 19:30
14

Unfortunately, you cannot do that. You need to have a reference to the event handler function in order to remove it by removeEventListener.

Your only option if you cannot get that reference would be by entirely replacing that Node.

jAndy
  • 231,737
  • 57
  • 305
  • 359
  • jAndy is there any way to get that reference via jquery or javascript. Because that event is added by thirdparty and that event is attached in window element – Dineshkani Nov 10 '14 at 14:07
  • @Dineshkani AFAIK there isn't (but hopefully some Ninja will correct me here if I'm wrong). Natively added events via `addEventListener` are not stored anywhere accessible by Javascript. – jAndy Nov 10 '14 at 14:08
  • @Dineshkani Could you explain why you are trying to do that instead? If the third-party code added the listener, it's because it probably needs it to do it's work properly... – plalx Nov 10 '14 at 14:11
  • @jAndy Unless the third-party's code stored the listener functions, like the code should be doing, so that plugins can be properly destroyed or un-applied. However, these references could be hidden within unaccessible scopes... – plalx Nov 10 '14 at 14:12
  • 3
    Actually it is possible with `getEventListeners`, since it holds event listeners functions. – dfsq Nov 10 '14 at 14:13
  • @jAndy Because it prevent all the other events before it fired even after close that popup plugin. – Dineshkani Nov 10 '14 at 14:13
  • I'd add that not being able to do that, makes that API utterly brilliant. Imagine if some horrible library could wreck all of *your* listeners? – doug65536 Dec 23 '22 at 03:49
0

Caveat: Uses browser specific getEventListeners, which is available in Chrome and Edge.

If you need to remove all event listeners:

// selector is optional - defaults to all elements including window and document
// Do not pass window / document objects. Instead use pseudoselectors: 'window' or 'document'
// eTypeArray is optional - defaults to clearing all event types
function removeAllEventListeners(selector = '*', eTypeArray = ['*']) {
  switch (selector.toLowerCase()) {
    case 'window':
      removeListenersFromElem(window);
      break;
    case 'document':
      removeListenersFromElem(document);
      break;
    case '*':
      removeListenersFromElem(window);
      removeListenersFromElem(document);
    default:
      document.querySelectorAll(selector).forEach(removeListenersFromElem);
  }
  
  function removeListenersFromElem(elem) {
    let eListeners = getEventListeners(elem);
    let eTypes = Object.keys(eListeners);
    for (let eType of inBoth(eTypes, eTypeArray)) {
      eListeners[eType].forEach((eListener)=>{
        let options = {};
        inBoth(Object.keys(eListener), ['capture', 'once', 'passive', 'signal'])
          .forEach((key)=>{ options[key] = eListener[key] });
        elem.removeEventListener(eType, eListener.listener, eListener.useCapture);
        elem.removeEventListener(eType, eListener.listener, options);
      });
    }
  }

  function inBoth(arrA, arrB) {
    setB = new Set(arrB);
    if (setB.has('*')) {
      return arrA;
    } else {
      return arrA.filter(a => setB.has(a));
    }
  }
}

Use:

removeAllEventListeners('a.fancyLink'); // remove all event types
removeAllEventListeners('a.fancyLink', ['click', 'hover']); // remove these types
removeAllEventListeners('*', ['click', 'hover']); // remove these types everywhere
removeAllEventListeners(); // remove everything you can

Note, this may not always work. Per MDN:

It's worth noting that some browser releases have been inconsistent on this, and unless you have specific reasons otherwise, it's probably wise to use the same values used for the call to addEventListener() when calling removeEventListener().

My use of options tries to deal with this issue by hopefully calling removeEventListener with the same values used when the listener was added.

Travis Bemrose
  • 379
  • 1
  • 12
-1

Update: 2023

EventListeners can be removed without knowing the actual function reference. But it will only work in modern browsers.

Use AbortController to remove the event. With AbortSignal, you can simply get the signal to remove it for you:

Sample Code:

const controller = new AbortController();
const { signal } = controller;

window.addEventListener('resize', () => doSomething(), { signal });

controller.abort(); // It wll remove the "resize" event handler.

You can check and add a polyfill for older browsers

Dineshkani
  • 2,899
  • 7
  • 31
  • 43
  • 1
    This will remove the event listener you just added. But only that one, so it's only usable if it is you adding the event listener in the first place. But if you are adding the event listener then you might as well just keep a ref to the function and do a normal remove. – AntonOfTheWoods Mar 23 '23 at 07:13