41

I would like to remove ALL handlers for a given event type. Let's say I've added twice "onclick event" to a button and now I would like to return back to the original state where no event handler was set to the button.

How can I do that?

P.S.: I've found removeEventListener (non-IE)/detachEvent (IE) methods but the functions want me to pass as a parameter the function that handles the event which seems to me quite clumsy because I would have to store the functions somewhere.

EDIT: http://ejohn.org/blog/flexible-javascript-events/ - I'm now using this code

MartyIX
  • 27,828
  • 29
  • 136
  • 207
  • 1
    Are you using the inline onclick attribute? – Mottie May 14 '10 at 20:55
  • A better, more direct option is to use @jiggy's solution http://stackoverflow.com/questions/803936/how-to-clear-remove-javascript-event-handler – chowey Apr 10 '13 at 06:00

6 Answers6

14

It might be a good idea to use jQuery or a similar framework to manage all event handlers. This will give you easy-to-use, unobtrusive functions to add and remove event handlers:

$(...).on('click', function() { ... });
$(...).off('click');
// or, to unbind all events:
$(...).off();
ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
  • I would like to understand how it works. Does it simply store the functions somewhere and unbind() simply go through the list of functions and call removeEventListener? – MartyIX May 14 '10 at 21:09
  • 2
    It stores an event list internally – ThiefMaster May 15 '10 at 10:21
  • `$("*").unbind();` will remove all Event Handlers of all elements, if you are trying to do that. – palswim Oct 27 '15 at 06:38
  • For anyone looking at this thread today, `unbind()` has been deprecated for a long time. Use `.off()` instead. – ykadaru Jul 15 '20 at 16:36
  • 1
    since ykadaru updated this, I'll also point out that jQuery wasn't part of the original question, though in 2010 it might have been the best approach. Now, it is not. In general, with ES6 now widely supported by modern browsers, jQuery itself is basically deprecated as a whole. IMO, its overhead isn't worth it anymore. – Carnix Jan 27 '21 at 18:24
13

If you have only one child element under your element's parent (or if you don't mind all sibling's event handlers lost too):

elem.parentElement.innerHTML = elem.parentElement.innerHTML;

Tested in Chrome 49, FF 44, IE 11

It removes all 'addEventListener'-s.

fenyoapa
  • 161
  • 1
  • 6
  • 1
    I like this solution, because it's so simple. If it's not the only child element under a parent node, you can always wrap the element (e.g., ` – Ringo Dec 05 '19 at 21:36
  • This also does not work when used in websites with complicated frameworks. The element dies. – Edza Sep 04 '20 at 15:17
10

According to this thread, you can use cloneNode to strip all the event listeners from a javascript element, like so:

 var new_element = old_element.cloneNode(true);
 old_element.parentNode.replaceChild(new_element, old_element);
Mathew
  • 8,203
  • 6
  • 37
  • 59
  • 1
    Yeah, but the following sentence is: I believe that attachEvent persists even when an element is cloned though, so I’m not sure what you would do for Internet Explorer users. – MartyIX May 14 '10 at 21:10
  • This does not work when the website is built using complicated frameworks. After clone the element is broken. – Edza Sep 04 '20 at 15:14
9

http://www.quirksmode.org/js/events_advanced.html - "Which event handlers are registered?" - it seems it's not possible without DOM 3 level :-(

EDIT: I've come up with this code. It suits my needs. Maybe it will be helpful for someone else.

Javascript:

function DomLib() {


}


/**
* Based on: http://ejohn.org/blog/flexible-javascript-events/
* Function that register event and enables it to be removed without explicitly giving the function definition
*/
DomLib.prototype.regEventEx = function (el, eventName, funct) {

  if (el.attachEvent) {
    el['e'+eventName+funct] = funct;
    el[eventName+funct] = function(){el['e'+eventName+funct](window.event);}
    el.attachEvent( 'on'+eventName, el[eventName+funct] );
  } else {    
    el.addEventListener(eventName, funct, false);
  } 

  if(!el.eventHolder) el.eventHolder = [];
  el.eventHolder[el.eventHolder.length] = new Array(eventName, funct);  
}

DomLib.prototype.removeEvent = function (obj, type, fn) {
  if (obj.detachEvent) {
    obj.detachEvent( 'on'+type, obj[type+fn] );
    obj[type+fn] = null;
  } else {
    obj.removeEventListener( type, fn, false );
  }  
}


DomLib.prototype.hasEventEx = function (el, eventName, funct) {

  if (!el.eventHolder) {  
    return false;
  } else {
    for (var i = 0; i < el.eventHolder.length; i++) {
      if (el.eventHolder[i][0] == eventType && String(el.eventHolder[i][1]) == String(funct)) {
        return true;  
      }  
    }
  }
  return false;  
}

/** 
* @return - returns true if an event was removed
*/
DomLib.prototype.removeEventsByTypeEx = function (el, eventType) {

  if (el.eventHolder) {  

    var removed = 0;
    for (var i = 0; i < el.eventHolder.length; i++) {
      if (el.eventHolder[i][0] == eventType) {                
        this.removeEvent(el, eventType, el.eventHolder[i][1]);
        el.eventHolder.splice(i, 1);
        removed++;
        i--;
      }  
    }

    return (removed > 0) ? true : false;
  } else {
    return false; 
  }
}

Testing HTML page:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<meta http-equiv="Expires" content="Fri, Jan 01 1900 00:00:00 GMT">
<meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-Control" content="no-cache">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="Lang" content="en">
<meta name="author" content="">
<meta http-equiv="Reply-to" content="@.com">
<meta name="generator" content="PhpED 5.8">
<meta name="description" content="">
<meta name="keywords" content="">
<meta name="creation-date" content="01/01/2009">
<meta name="revisit-after" content="15 days">
<title>DomLibTest</title>
<link rel="stylesheet" type="text/css" href="my.css">
<!-- FILL IN: Location of your jQuery library -->
<script type="text/javascript" src="jQuery/jQuery-current.js"></script>
<!-- FILL IN: Plugin for debugging ... http://www.ecitadel.net/blog/2009/12/08/developing-jquery-use-dump-instead-alert -->
<script type="text/javascript" src="jQuery/jQuery.dump.js"></script>
<script type="text/javascript" src="DomLib.js"></script>
</head>
<body>

  <div id="testElem-1"></div>
  <script type="text/javascript">
  <!--

    var domLib = new DomLib();

    function removeTest(el) {

      var funct = function() { alert("#1: How Are You?");};
      var funct2 = function() { alert("#2: How Are You?");};                  

      domLib.regEventEx(el, "click", funct);
      domLib.regEventEx(el, "mousemove", funct2);
      domLib.regEventEx(el, "mousemove", funct2);
      domLib.regEventEx(el, "mousemove", funct2);

      $.dump(el.eventHolder);      
      domLib.removeEventsByTypeEx(el, "mousemove");      
      $.dump(el.eventHolder);
    }

    removeTest(document.getElementById('testElem-1'));

  -->
  </script>
</body>
</html>
MartyIX
  • 27,828
  • 29
  • 136
  • 207
-1
function removeEvents(elem) {
  var children = elem.children;
  for (var i = 0; i < children.length; i++) {
    var el = children[i];
    el.removeAttribute("onkeyup");
    el.removeAttribute("onmouseover");
    el.removeAttribute("onmouseout");
    el.removeAttribute("onclick");
    removeEvents(el);
  }
}

this worked for me

anuradha
  • 123
  • 1
  • 9
-9

As far as I know, you cannot add two onclick handlers to an element at all.

Say obj is an element then the property onclick of obj is considered a function and then called as a method whenever that event occurs. If it's not a function nothing will happen.

JavaScript inherited from Scheme a very interesting property, in JavaScript, you don't define functions as in PHP or C. You create anonymous functions and store them in a variable. Javascript is 'Lisp-1', there are no function identifiers, there are variables, which can house numbers, arrays, and functions.

function name(arg) {return arg;}

Is if I'm not mistaken truly sugar for:

name = function(arg) {return arg;};

'name' here is a variable, we can also re-asign it no matter how we defined that function. Unlike Java's object model, in Javascript, a 'method' is purely a property, a variable that simply holds a function that may or may not use the 'this' keyword. This is why you can't have two onclick event at the same time. The runtime environment simply calls the property (which is expected to house a function) of the element called 'onclick' whenever you click on it. See it as the same ad hoc type behaviour of calling 'main' to start a program.

To assign multiple event handlers, you use a function with a side effect, like.

obj.onclick = function {firstEvent();secondEvent();}

To change or remove it, we re-assign or de-assign it like any variable.

obj.onclick = null;

And in case we need to invoke that behaviour in another way:

obj.onclick();

We can also use this in that function of course to change the object itself or reference it.

Edit: Oh wait, I see now that you mean wih 'a button' many different buttons.

Well, then you just collect all elements like:

allElements = document.getElementsByTagName('*');

And then you use a loop:

var i = 0; while(obj = allElements[i++]) obj.onclick = null;

(and no, that single = is not a typo)

Zorf
  • 6,334
  • 2
  • 29
  • 24
  • http://pastebin.org/237133 - this is an example of a code that calls two onclick handlers for one button. (Tested in Firefox and Chrome) – MartyIX May 14 '10 at 21:50
  • 6
    -1 misinformation in first sentence. Learn how event handling in JavaScript works and fix the post to make it a +1 – naugtur Jan 09 '13 at 12:34