Javascript/Dom: How to Remove All Event Listeners of a Dom Object

Javascript/DOM: How to remove all event listeners of a DOM object?

I am not sure what you mean with remove all events. Remove all handlers for a specific type of event or all event handlers for one type?

Remove all event handlers

If you want to remove all event handlers (of any type), you could clone the element and replace it with its clone:

var clone = element.cloneNode(true);

Note: This will preserve attributes and children, but it will not preserve any changes to DOM properties.



Remove "anonymous" event handlers of specific type

The other way is to use removeEventListener() but I guess you already tried this and it didn't work. Here is the catch:

Calling addEventListener to an anonymous function creates a new listener each time. Calling removeEventListener to an anonymous function has no effect. An anonymous function creates a unique object each time it is called, it is not a reference to an existing object though it may call one. When adding an event listener in this manner be sure it is added only once, it is permanent (cannot be removed) until the object it was added to, is destroyed.

You are essentially passing an anonymous function to addEventListener as eventReturner returns a function.

You have two possibilities to solve this:

  1. Don't use a function that returns a function. Use the function directly:

     function handler() {
    dosomething();
    }

    div.addEventListener('click',handler,false);
  2. Create a wrapper for addEventListener that stores a reference to the returned function and create some weird removeAllEvents function:

     var _eventHandlers = {}; // somewhere global

    const addListener = (node, event, handler, capture = false) => {
    if (!(event in _eventHandlers)) {
    _eventHandlers[event] = []
    }
    // here we track the events and their nodes (note that we cannot
    // use node as Object keys, as they'd get coerced into a string
    _eventHandlers[event].push({ node: node, handler: handler, capture: capture })
    node.addEventListener(event, handler, capture)
    }

    const removeAllListeners = (targetNode, event) => {
    // remove listeners from the matching nodes
    _eventHandlers[event]
    .filter(({ node }) => node === targetNode)
    .forEach(({ node, handler, capture }) => node.removeEventListener(event, handler, capture))

    // update _eventHandlers global
    _eventHandlers[event] = _eventHandlers[event].filter(
    ({ node }) => node !== targetNode,
    )
    }

And then you could use it with:

    addListener(div, 'click', eventReturner(), false)
// and later
removeAllListeners(div, 'click')

DEMO

Note: If your code runs for a long time and you are creating and removing a lot of elements, you would have to make sure to remove the elements contained in _eventHandlers when you destroy them.

Remove all event listeners on a DOM object

One method I found that I used (and worked rather well) was the cloneNode function.

var new_el = el.cloneNode(true); //true means a deep copy
el.parentNode.replaceChild(new_el,el);

When you clone the element, it does not clone any events.

Removing all eventListeners by class

The 2nd argument to removeEventListener() must be a reference to the function that is assigned to the event as listener but you are passing a new, literal arrow function.

In the example, the 2nd occurrence of () => {selectSelf(name)} is a new arrow function declared literally. The one that was already added as an event handler is a different function so you cannot expect it to be removed.

To make it work, save a reference to each handler function that you can later pass to removeEventListener():

let names = document.querySelectorAll('.playerName');
const handlers = [];

names.forEach((name) => {
// Use a unique identifier for each function reference
handlers[name.id] = () => selectSelf(name);

name.addEventListener('click', handlers[name.id]);
});

function dropEvents() {
let drops = document.querySelectorAll('.playerName');
drops.forEach((drop) => {
drop.removeEventListener('click', handlers[drop.id]);
});
}

Remove all event listener of document in javascript not using the event name

Personally, I would name the event listeners, so you can remove them properly.
I get what you are trying to do though. However, since this is the document node, it is unlikely you will find a parent node for it. It is the root of your DOM tree after all.
If this was a specific element to which you have bound the event listener, your approach would work.

  1. You could extend the addEventListener and removeEventListener to register the functions in a data-structure that you could later use in your function to methodically remove every event listener. See this answer for details.
  2. Yet another option, if you do not mind moving to JQuery, is to use JQuery to attach the listeners and then simply using $(document).off() would remove the listeners attached. It may not work in conjunction with native addEventListener methods.

Remove All Event Listeners of Specific Type

That is not possible without intercepting addEventListener calls and keep track of the listeners or use a library that allows such features unfortunately. It would have been if the listeners collection was accessible but the feature wasn't implemented.

The closest thing you can do is to remove all listeners by cloning the element, which will not clone the listeners collection.

Note: This will also remove listeners on element's children.

var el = document.getElementById('el-id'),
elClone = el.cloneNode(true);

el.parentNode.replaceChild(elClone, el);


Related Topics



Leave a reply



Submit