5

In some place of an external library (which, of course, I can't change), an event listener is created this way:

someElement.addEventListener('keydown', function(e) {
    whatever();
});

I need to get rid of this listener or override it somehow. But it seems that it can't be done, as I don't have any way to reference the anonymous function used.

It's not necessary that this is the only listener removed. Removing ALL the keydown listeners would be also OK, if it were possible.

I've seen that an option would be cloning the element and replace it, but I can't do that, because there is a lot of initialization, and a lot of other events listeners are created. I just need to cancel the keydown one.

Is there anything I can do?

nicholaswmin
  • 21,686
  • 15
  • 91
  • 167
César García Tapia
  • 3,326
  • 4
  • 27
  • 51
  • If you want the quick dirty solution, delete the element and then add it again dynamically. – kemicofa ghost Feb 05 '19 at 16:20
  • @kemicofa Unless it's a delegated event – zero298 Feb 05 '19 at 16:41
  • If you're able to sneak in some code before the external library runs, you can monkeypatch addEventListener to make it possible to find and remove them later: https://stackoverflow.com/a/31087882/3412322 – Daniel Beck Feb 05 '19 at 16:41

1 Answers1

7

You can listen for the event in the capture phase and stop its immediate propagation.

const input = document.querySelector('input')
const log = () => console.log('I shouldnt log')

input.addEventListener('keydown', e => {
  e.stopImmediatePropagation()
}, true)

input.addEventListener('keydown', log)
<input placeholder="Type here"/>

Passing true as the 3rd parameter of addEventListener listens for the event on its capture phase (or an options object with { capture: true }.

But that's assuming you have the chance to add this listener before the listener you want to disable and the element doesn't have any inline listeners.

Otherwise you can just wrap it into an element that follows the same concept:

const disablers = document.querySelectorAll('[disable-event]')
const input = document.querySelector('input')
const log = () => console.log('I shouldnt log')

input.addEventListener('keydown', log)

disablers.forEach(disabler => {
  disabler.addEventListener(disabler.getAttribute('disable-event'), e => {
    e.stopPropagation()
  }, true)
})
<span disable-event="keydown">
  <input onkeydown="log()" placeholder="Type here"/>
</span>

This stops the event propagation on the parent element so it never reaches the element itself.

ssice
  • 3,564
  • 1
  • 26
  • 44
nicholaswmin
  • 21,686
  • 15
  • 91
  • 167