2
votes

I searched for several questions here bt couldn't find the answer. The accepted answer removeEventListener without knowing the function only works in chrome and that too in non strict mode.

I have three functions. One to attach event listeners to elements using selectors and another to remove event listeners from the element and the third one to remove all event listeners from the page.

The functions are something like:

function listen(node, event, callback, options)
{
    node.addEventListener(event, callback, options);
}



removeAllListeners(node)
{

}


removeListener(node, event)
{

}

The user can pass any type of callback functions to the function which attaches the listener. How do I go about removing the event listeners.

I do not want to use any third party library as well.

Tried:

var eventlistener = getEventListeners(window)["DOMContentLoaded"][index];
window.removeEventListener("DOMContentLoaded", eventlistener.listener, eventlistener.useCapture);

but only works on chrome and that too only in non strict mode.

1
The question you link to already answers this. One answer (with "chrome only" comments) suggests an approach. The other states it is impossible. If you reject the "chrome only" solution, then impossible remains.Quentin
@Quentin - I think this question is different, because the OP is in control of adding the listeners in the first place.T.J. Crowder
@T.J.Crowder — I was just umming about that. The question is really based on a false premise. The title says "without knowing the second parameter", but there's no reason to have that requirement in the question.Quentin
@T.J.Crowder Yes that is exactly my point I have already read the answer and tried to use the code but is not working in "use strict"; and on browsers other than Chrome.Shakti Phartiyal

1 Answers

1
votes

Since you're dealing with your own event listeners, there are lots of ways you can solved this. Two that come to mind:

  1. Use an expando property on the element to keep track of your listener functions, so you do know the second argument to removeEventListener. Be careful when using expando properties to avoid naming conflicts (e.g, choose a long name very specific to your code).

  2. Assign elements an ID in listen and store their handlers (and the events they handle) in a separate object, keyed by that ID. Note that this means you'll keep the functions in memory as long as either the element or the entry in your separate object refers to them, which may not be ideal.

Here's an example of #1:

var handlersKey = "___handlers___" + Math.floor(Math.random() * 100000);

function listen(node, event, callback, options)
{
    node.addEventListener(event, callback, options);
    if (!node[handlersKey]) {
      node[handlersKey] = Object.create(null);
    }
    if (!node[handlersKey][event]) {
      node[handlersKey][event] = [];
    }
    node[handlersKey][event].push(callback);
}


function removeAllListeners(node)
{
    if (!node[handlersKey]) {
        return;
    }
    Object.keys(node[handlersKey]).forEach(function(event) {
        removeListener(node, event);
    });
    delete node[handlersKey];
}


function removeListener(node, event)
{
    var handlers = node[handlersKey];
    var callbacks = handlers && handlers[event];
    if (callbacks) {
        callbacks.forEach(function(callback) {
            node.removeEventListener(event, callback);
        });
        delete handlers[event]
    }
}

listen(document.getElementById("target"), "mouseenter", function() {
    console.log("Got mouseenter");
});
listen(document.getElementById("target"), "mouseleave", function() {
    console.log("Got mouseleave");
});
listen(document.getElementById("target"), "click", function() {
    console.log("Removing all listeners");
    removeAllListeners(this);
});
<div id="target">Click me, I'll respond only once</div>