6

Possible Duplicate:
Removing an anonymous event listener

I have the following cross browser function to add an event listener:

_SU3.addEventListener = function(elem, eventName, fn) {
if(elem.addEventListener ) {
    elem.addEventListener(eventName, fn, false);
  } else if (elem.attachEvent) {
      elem.attachEvent('on'+eventName, fn);
  } 
};

I'm adding the listener like this:

_SU3.addEventListener(_show, "click", function(event) { 
                             _SU3.getChildren(_show, uri, element); 
                    });

Which is all fine. However I want to remove the listener after it has been called once. I.e. something like:

_SU3.getChildren = function(_show, url, element) {

... blah... 

_SU3.removeEventListener(_show, 'click', ANON_FUNCTION);

};

But of course the listener function is anonymous so there's no function name to reference.

How can I remove the listener?

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Richard H
  • 38,037
  • 37
  • 111
  • 138
  • You have to keep a reference somewhere. Either explicitly by passing a reference to your function, or implicitly inside your function. – Felix Kling Jan 06 '11 at 15:33

4 Answers4

8

You need to keep a reference to the function:

var foo = function(event) { _SU3.getChildren(_show, uri, element); };

_SU3.addEventListener(_show, "click",  foo);

...

_SU3.getChildren = function(_show, url, element) {

... blah... 

_SU3.removeEventListener(_show, 'click', foo);

};

Make sure that the variable foo is in the scope of where you remove the event listener.

Matt
  • 74,352
  • 26
  • 153
  • 180
  • Thanks. But this listener is being added to many elements on the page, so I can't have a global variable as this will get overwritten if the listener is called on other elements. – Richard H Jan 06 '11 at 15:42
  • @Richard: I didn't say it had to be global, I said it had to be in the scope. – Matt Jan 06 '11 at 16:30
4

You can't. If you want to remove it, you have to store a reference to it. How else would you be able to distinguish it from the others?

Ivo Wetzel
  • 46,459
  • 16
  • 98
  • 112
4

Instead of removing the event listener, arrange for it to keep track of whether it's been called:

addOneShotListener = function(elem, eventName, fn) {
  var triggered = false, handler = function(ev) {
    if (triggered) return;
    fn(ev);
    triggered = true;
  };

  if(elem.addEventListener ) {
    elem.addEventListener(eventName, handler, false);
  } else if (elem.attachEvent) {
    elem.attachEvent('on'+eventName, handler);
  } 
};

That variation on your original function just wraps the original handler (the "fn" passed in) with a function that only calls the handler the first time it is invoked. After that, it sets a flag and won't ever call the original handler function again.

Pointy
  • 405,095
  • 59
  • 585
  • 614
-1

If you only have one click event assigned at any one time to an element, why not set the onclick property? You can remove it anytime with element.onclick='';

kennebec
  • 102,654
  • 32
  • 106
  • 127