How to remove all listeners in an element?
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.
Related videos on Youtube
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, 2022Comments
-
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 about 12 years
-
John about 12 yearsUp-voted for attempting to competently code by NOT using frameworks/libraries. :-)
-
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 朕會功夫 about 12 yearsThanks! And I used your code like this
function unbind(ele){ele.parentNode.replaceChild(ele.cloneNode(true), ele);}
-
Saxoier about 12 years@Derek: Cloning a node and the whole subtree is a bad idea. It is much slower than removing all the
EventListener
s from the node withnode.removeEventListener
. In addition you will get a memory leak (node + subtree) and off course allEventListener
s were removed from the subtree. If you use your function ondocument.body
you will blow up everything. -
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 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 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 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 about 12 yearsIs it possible to clone a node without loosing its listeners?
-
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 almost 11 yearsFor 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 almost 11 yearsA downvote... interesting.
-
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 over 9 yearsperhaps clone the node without children, then move the children over.
-
Derek 朕會功夫 about 9 yearsThat's too long, instead in jQuery you should do this
$("#myEl").unbind();
or.off()
(1.7+) to remove all listeners. -
davide about 9 yearsDo
off()
orunbind()
only remove those listeners attached via jQuery? -
Duke about 9 yearsJust 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 over 8 yearsdon't know why that
unbind
andoff
doesn't work. However the$('#myEl').replaceWith($('#myEl').clone());
works great! -
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 over 7 years@davide @Duke indeed
off()
andunbind()
would not work for listeners registered with native javascriptaddEventListener
, as per jquery docs. -
Nazar Vynnytskyi over 7 yearsto remove all children listenes you ca use: element.innerHTML += '';
-
Meow over 6 yearsWhat if the element is the root
html
which does not have a parent element. -
Ben D over 6 years@Meow -
html
actually does have a parent: thedocument
itself. I'm not sure I can think of a case where you'd have listeners attached to thehtml
element instead of thebody
or a wrapper, but In theory, this should work with an<html>
node (<html>
's parentNode is just thedocument
, so the logic would work). However, I ran a couple of tests and some browsers seem have trouble replacing thedocument.html
node, so in practical use I'd avoid it (though I'd also avoid adding listeners tohtml
as well) -
Nathan B almost 6 yearsIt looks like this will only remove events created with jQuery, therefore not a complete solution.
-
Duke over 5 yearsThe clone should remove all event listeners period. Similar to the accepted answer, just more readable.
-
DarthCadeus over 5 yearsApparently it does not remove callbacks added with html
-
FinrodFelagund almost 4 yearsI 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 over 3 yearsmight be a bad idea, but seems like the only viable option
-
Javed Iqbal about 3 years$('#myEl').replaceWith($('#myEl').clone()); Its worked for me, thanks
-
Yes Barry about 3 years@NazarVynnytskyi indeed, that's a quick'n'dirty albeit effective solution!
-
Pangamma almost 3 yearsThis sure is too much of a nuclear option if the event listener was registered on the window object.
-
haridsv over 2 yearsThis is not removing attributes like
onpsate
.