21

I am wondering how can I remove an event listener after adding one, the way you use on and off in jquery?

document.removeEventListener('touchstart');
document.addEventListener('touchstart', function (e) {
     closePopupOnClick(e, popup);
});

but this does not actually remove the event listener. If I put the addEventListener code in a function and pass that function into the the removeEventListener it will not work bc you cannot pass params into the function. Anyone know how to do this?

Manngo
  • 14,066
  • 10
  • 88
  • 110
FairyQueen
  • 2,283
  • 7
  • 37
  • 57
  • 2
    possible duplicate of [JavaScript: remove event listener](http://stackoverflow.com/questions/4402287/javascript-remove-event-listener) also [Javascript:Removing an anonymous event listener](http://stackoverflow.com/questions/3106605/removing-an-anonymous-event-listener) – Ohgodwhy Feb 26 '13 at 22:25
  • no that question doesn't address the issue of params. – FairyQueen Feb 26 '13 at 22:45

1 Answers1

37

Put the listener as a variable and attach via .addEventListener

var myListener = function (e) {
    closePopupOnClick(e, popup);
};
document.addEventListener('touchstart', myListener, true);

then pass it again when removing with .removeEventListener

document.removeEventListener('touchstart', myListener);

If you're not in strict mode you can make a listener remove itself with arguments.callee

document.addEventListener('touchstart', function (e) {
    closePopupOnClick(e, popup);
    document.removeEventListener('touchstart', arguments.callee);
}, true);

If you are in strict mode, you have to use a named function expression if you want a function to remove itself

document.addEventListener('touchstart', function myListener(e) {
    closePopupOnClick(e, popup);
    document.removeEventListener('touchstart', myListener);
}, true);

If you want to use variables in the listener that may be changed by something (e.g. a loop), then you can write a generator function, for instance

function listenerGenerator(popup) {
    return function (e) {
        closePopupOnClick(e, popup);
    };
}

Now you can create the listener with listenerGenerator(popup) and it will scope the popup variable. Note that if popup is an Object, it will be ByRef and therefore may still be subject to changes.

Paul S.
  • 64,864
  • 9
  • 122
  • 138
  • 1
    how does one pass, the e and popup params to the myListener function in the addEventListener? thats what I'm stuck on the most. is the params. – FairyQueen Feb 26 '13 at 22:33
  • Where are `e` and `popup` coming from? `e` is the _Event_ ? then you need to set _useCapture_ `true` – Paul S. Feb 26 '13 at 22:37
  • The addEventListener function is inside of a function that gets the popup param passed into it. So it comes from the outer function. e is the event. how do I set userCapture? – FairyQueen Feb 26 '13 at 22:45
  • @Tanya _useCapture_ is the third parameter of `addEventListener`; the parameters being _type_, _listener_ and (optional) _useCapture_ (defaults to `false`). Please read the link in my answer for more details. – Paul S. Feb 26 '13 at 22:47
  • Use grave accents `\`` to make code blocks in comments. Simply remove `popup` from the parameter list of `closePopupTouch`; i.e. `closePopupTouch = function (e) { closePopupOnClick(e, popup); };`. This means `popup` inside the function will be taken from the scope in which the function is defined. Where I was talking about `listenerGenerator`, that was to create a new scope for `popup` to protect the copy inside the function from any changes outside. – Paul S. Feb 27 '13 at 23:01
  • Consider this; `var i = 2, fn = function () {return i === 2;};`, now `fn()` gives `true`, but `i = 3; fn();` gives false. However, if you did `var i = 2, fn = (function (i) {return function () {return i === 2;};}(i));`, then `fn()` is `true` and `i = 3; fn();` is true, too, because the `i` in `fn` got protected in it's own scope. – Paul S. Feb 27 '13 at 23:05
  • removeEventListener doesn't seem to work without the same value for useCapture as addEventListener: document.removeEventListener('touchstart', arguments.callee, true); – user1566694 Mar 27 '15 at 20:30