How to remove all listeners in an element?

285,857

Solution 1

I think that the fastest way to do this is to just clone the node, which will remove all event listeners:

var old_element = document.getElementById("btn");
var new_element = old_element.cloneNode(true);
old_element.parentNode.replaceChild(new_element, old_element);

Just be careful, as this will also clear event listeners on all child elements of the node in question, so if you want to preserve that you'll have to resort to explicitly removing listeners one at a time.

Solution 2

If you’re using jquery events, this can be done in one line:

For jQuery events (.on()):

$("#myEl").off()

For native javascript events (.addEventListener()):

$('#myEl').replaceWith($('#myEl').clone());

Here’s an example:

http://jsfiddle.net/LkfLezgd/3/

Solution 3

Here's a function that is also based on cloneNode, but with an option to clone only the parent node and move all the children (to preserve their event listeners):

function recreateNode(el, withChildren) {
  if (withChildren) {
    el.parentNode.replaceChild(el.cloneNode(true), el);
  }
  else {
    var newEl = el.cloneNode(false);
    while (el.hasChildNodes()) newEl.appendChild(el.firstChild);
    el.parentNode.replaceChild(newEl, el);
  }
}

Remove event listeners on one element:

recreateNode(document.getElementById("btn"));

Remove event listeners on an element and all of its children:

recreateNode(document.getElementById("list"), true);

If you need to keep the object itself and therefore can't use cloneNode, then you have to wrap the addEventListener function and track the listener list by yourself, like in this answer.

Share:
285,857

Related videos on Youtube

Derek 朕會功夫
Author by

Derek 朕會功夫

Uh oh, sounds like somebody’s got a case of the Mondays! Are you using enough jQuery? http://i.stack.imgur.com/ssRUr.gif "Everybody stand back, I know regular expressions!" ─ xkcd 208

Updated on July 08, 2022

Comments

  • Derek 朕會功夫
    Derek 朕會功夫 almost 2 years

    I have a button, and I added some eventlistners to it:

    document.getElementById("btn").addEventListener("click", funcA, false);
    document.getElementById("btn").addEventListener("click", funcB, false);
    document.getElementById("btn").addEventListener("click", funcC, false);
    document.getElementById("btn").addEventListener("blur" , funcD, false);
    document.getElementById("btn").addEventListener("focus", funcE, false);
    
    <button id="btn">button</button>
    

    I can remove them by:

    document.getElementById("btn").removeEventListener("click",funcA);
    

    What if I want I want to remove all listeners at once, or I don't have the function reference (funcA)? Is there a way of doing that, or I have to remove them one by one?

    • Misiur
      Misiur about 12 years
    • John
      John about 12 years
      Up-voted for attempting to competently code by NOT using frameworks/libraries. :-)
    • Derek 朕會功夫
      Derek 朕會功夫 over 8 years
      @user Impressive, you actually found a question that is even older than this old question where the answers here are still mentioning jQuery 1.7. Can't believe how much time has passed since I asked this question.
  • Derek 朕會功夫
    Derek 朕會功夫 about 12 years
    Thanks! And I used your code like this function unbind(ele){ele.parentNode.replaceChild(ele.cloneNode(true), ele);}
  • Saxoier
    Saxoier about 12 years
    @Derek: Cloning a node and the whole subtree is a bad idea. It is much slower than removing all the EventListeners from the node with node.removeEventListener. In addition you will get a memory leak (node + subtree) and off course all EventListeners were removed from the subtree. If you use your function on document.body you will blow up everything.
  • Derek 朕會功夫
    Derek 朕會功夫 about 12 years
    @Saxoier, Thanks for the reminder but I tested on this page's body and it worked like a charm. Maybe I'm using a fast browser (Google Chrome).
  • Ben D
    Ben D about 12 years
    @Saxoier certainly cloning the node is slower than just removing the listeners, but in most functional scenarios the speed difference will not be discernible (unless you're doing this to a huge number of the page nodes all in one go). As for the memory leak, this will be browser dependent... All the modern browsers should handle garbage collection well enough to not experience a problem (though if the node contains embedded objects I could imagine scenarios where this could happen). Do you have a specific documented memory leak in mind?
  • Ben D
    Ben D about 12 years
    @Saxoier your note about the effect of cloning on event listeners in the sub-tree of the node is worth explicit mention... I've added the warning to my answer, as people should be aware of this.
  • Saxoier
    Saxoier about 12 years
    @Ben D: It seems that the latest versions of Firefox, IE, Opera and Chrome have a decent GC (summary after 10 GC cycles). Under certain circumstances older IE will leak.
  • Shawn
    Shawn about 12 years
    Is it possible to clone a node without loosing its listeners?
  • Ivan Kochurkin
    Ivan Kochurkin over 11 years
    @Saxoier, from your comment I understood that cloning is slow and inefficient operation. But what about just creating a new element (document.createElement('canvas') for example)?
  • Andrew Dunkman
    Andrew Dunkman almost 11 years
    For those who hate mysterious boolean arguments, cloneNode(true) means to clone the node including children. Documentation: developer.mozilla.org/en-US/docs/Web/API/Node.cloneNode
  • Ben D
    Ben D almost 11 years
    A downvote... interesting.
  • AJP
    AJP about 10 years
    @BenD interesting there are 3 down votes but no alternative answers... that's a pretty weak show by those down voters!
  • Eevee
    Eevee over 9 years
    perhaps clone the node without children, then move the children over.
  • Derek 朕會功夫
    Derek 朕會功夫 about 9 years
    That's too long, instead in jQuery you should do this $("#myEl").unbind(); or .off() (1.7+) to remove all listeners.
  • davide
    davide about 9 years
    Do off() or unbind() only remove those listeners attached via jQuery?
  • Duke
    Duke about 9 years
    Just re-read the docs on .off(), and it does allow you to omit all the parameters to remove all event binding. With .unbind(), however, eventType is mandatory and thus unusable for this purpose.
  • AGamePlayer
    AGamePlayer over 8 years
    don't know why that unbind and off doesn't work. However the $('#myEl').replaceWith($('#myEl').clone()); works great!
  • user
    user over 8 years
    @Max: I appreciate your edit suggestion, but I believe that remaking this code into ES2015 isn't justified for this case, the code wouldn't be widely supported then.
  • argaz
    argaz over 7 years
    @davide @Duke indeed off() and unbind() would not work for listeners registered with native javascript addEventListener, as per jquery docs.
  • Nazar Vynnytskyi
    Nazar Vynnytskyi over 7 years
    to remove all children listenes you ca use: element.innerHTML += '';
  • Meow
    Meow over 6 years
    What if the element is the root html which does not have a parent element.
  • Ben D
    Ben D over 6 years
    @Meow - html actually does have a parent: the document itself. I'm not sure I can think of a case where you'd have listeners attached to the html element instead of the body or a wrapper, but In theory, this should work with an <html> node (<html>'s parentNode is just the document, so the logic would work). However, I ran a couple of tests and some browsers seem have trouble replacing the document.html node, so in practical use I'd avoid it (though I'd also avoid adding listeners to html as well)
  • Nathan B
    Nathan B almost 6 years
    It looks like this will only remove events created with jQuery, therefore not a complete solution.
  • Duke
    Duke over 5 years
    The clone should remove all event listeners period. Similar to the accepted answer, just more readable.
  • DarthCadeus
    DarthCadeus over 5 years
    Apparently it does not remove callbacks added with html
  • FinrodFelagund
    FinrodFelagund almost 4 years
    I appreciate that this answer started with "If you're not opposed to jquery" - way too many answers are "just use jquery" (when sometimes, company policy forbids it).
  • stackers
    stackers over 3 years
    might be a bad idea, but seems like the only viable option
  • Javed Iqbal
    Javed Iqbal about 3 years
    $('#myEl').replaceWith($('#myEl').clone()); Its worked for me, thanks
  • Yes Barry
    Yes Barry about 3 years
    @NazarVynnytskyi indeed, that's a quick'n'dirty albeit effective solution!
  • Pangamma
    Pangamma almost 3 years
    This sure is too much of a nuclear option if the event listener was registered on the window object.
  • haridsv
    haridsv over 2 years
    This is not removing attributes like onpsate.