3

how can i remove this event listener I have tried but below code and it does not seam to bare any fruit

class Tag {
  constructor(name){
      this.tag = document.createElement(name);
  }
      removeEvent(e,func){
      this.tag.removeEventListener(e,func,false);
  }
      addEvent(e,func) {
      this.tag.addEventListener(e,func,false);
  }

}

let tag = new Tag();
tag.addEvent('click',(e)=> {
   console.log('something');
});

How do I get the removeEvent to work? please help I specifically need how to reference the anonymous function since this works.

 function handler(e){
     // code for event
 }

 tag.addEventListener('click',handler,false);  
 tag.removeEventlistener('click',handler,false);

I have tried adding

  removeEvent(e,func) {
      func.ref = function (){
          return arguments.callee;
      }

      this.tag.removeEventListener(e,func.ref,false);

  }

Just doesn't work given now we would be referring to func.ref as the function reference;

Breimer
  • 506
  • 8
  • 14
  • I don't think you can do that without saving a reference to the event handler in order to pass it to `removeEventListener`. – Thiatt May 28 '17 at 16:30
  • If you track this all around, jQuery's `off()` method [attaches to this `jQuery.event.remove()`](https://github.com/jquery/jquery/blob/a6b0705294d336ae2f63f7276de0da1195495363/src/event.js#L221), which then does other things. Eventually, it ends up with that `removeEventListener()` call you try. The handle, though, comes from a `privData`, so my guess is they're maintaining a reference somewhere so it can be passed in later. – Jared Farrish May 28 '17 at 16:49

4 Answers4

3

I had the same problem in an extension I was writing. I solved this by adding a new listener that caught / stopped all propagation of the event before it reached the listener / function I wanted to remove.

window.addEventListener(type, function (event) {
    event.stopPropagation();
}, true);

Credit: StackOverflow

ow3n
  • 5,974
  • 4
  • 53
  • 51
2

Simple way to remove anonymous event listener

A nice and simple way I found to remove eventListener that uses anonymous functions is to add these two functions into your code:

let events = new Map();
function addListener(element, event, callback, id) {
    events.set(id, callback);
    element.addEventListener(event, callback);
}

function removeListener(element, event, id) {
    element.removeEventListener(event, events.get(id));
    events.delete(id);
}

Anonymous function are great to keep the this context, and didn't found a good way to have both this, and the ability to remove the eventListener.

Example

let events = new Map();

function addListener(element, event, id, callback) {
  events.set(id, callback);
  element.addEventListener(event, callback);
}

function removeListener(element, event, id) {
  element.removeEventListener(event, events.get(id));
  events.delete(id);
}


let btn = document.getElementById('btn');
let cpt = 1;
addListener(btn, 'click', 'btnClick', e => {
  btn.innerHTML = `x${++cpt}`;

  if (cpt === 3) {
    removeListener(btn, 'click', 'btnClick');
  }
});
<button id="btn">x1</button>
Nicolas.l
  • 21
  • 2
1

Anonymous functions can't be removed because they are not stored with an identifier that is accessible to your code. That's why they call them "anonymous" and that's one of the down sides to using them. Another down side is not being able to write unit tests directly for them. The up side of them is that because they are not stored, a bit of memory is saved. Also, JavaScript, being a functional programming language, allows for anonymous functions to be passed quite easily as data (although you can certainly pass named function references).

Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
  • Thanks guys really helped I decided to keep track of the events in the object tag with this.events['event_name'].click_0 = func; in that way I can delete the event with the reference from the object i.e tag.removeEvent(tag.events.click.click_0) the integer click_[int] is being appended with a loop counter as I create a new event of same type – Breimer Jun 07 '17 at 18:32
0

There is not a way unfortunately to remove anonymous functions attached as listeners.

You can use a little workaround storing every time the functions you pass in and keeping track of all the events, then use the "cached" event listeners for retrieving them and detach the events.

Here a draft of an example:

var events = [];

function storeEvent(id, fn, useCaptureMode, event) {
 var e = findStoredEvent(id, event, useCaptureMode);
  if (!e) {
   events.push({id, fn, useCaptureMode, event});
  }
}

function findStoredEvent(id, event, useCaptureMode) {
 return events.find(el => el.id === id && el.event === event && el.useCaptureMode === el.useCaptureMode);
}

document.getElementById("test").addEventListener('click', function() {
 storeEvent(this.id, arguments.callee, false, 'click');
 console.log('test');
}, false);

function detachEvent() {
 var e = findStoredEvent('test', 'click', false);
  if (e) {
  document.getElementById("test").removeEventListener(e.event, e.fn, e.useCaptureMode);
    events.splice(events.findIndex(el => el === e), 1);
  } 
}
<button id="test">
  Test
</button>
<button id="remove" onclick="detachEvent()">
  Remove Event
</button>

I hope it helps

quirimmo
  • 9,800
  • 3
  • 30
  • 45