DEV Community

Discussion on: Function identity in JavaScript, or how to remove event listeners properly

Collapse
 
smotchkkiss profile image
Emanuel Tannert

Hi,

you have exactly the problem that I tried to describe here :)

You'll have to save your actual event listener function (the event => { preventOnWheel(event) }) part in a variable so you can call removeEventListener with that exact same function afterwards; something like this should work:

// first save the event listener function to a variable
const eventListener = event => {
  preventOnWheel(event);
},

document.addEventListener(
  "wheel",
  eventListener, // <= use it here first time
  { passive: false }
);

element.onmouseout = function() {
  document.removeEventListener(
    "wheel",
    eventListener, // <= use same function here
    { passive: false }
  );
};

Actually your preventOnWheel function already seems to be a single-argument function that you could use as an eventListener directly – no need to wrap it in an extra function, so the above could be simplified to something like this:

document.addEventListener(
  "wheel",
  preventOnWheel, // <= just use preventOnWheel directly
  { passive: false }
);

element.onmouseout = function() {
  document.removeEventListener(
    "wheel",
    preventOnWheel, // <= same again
    { passive: false }
  );
};

Also, you're mixing "old-style" event listener registration via assignment to element.onmouseout with the newer addEventListener/removeEventListener API, and you're mixing arrow functions (() => {}) with inline function() {}, so, if I may suggest a few more changes:

document.addEventListener("wheel", preventOnWheel, { passive: false });

// use `addEventListener` API here, too
// also use arrow function inline
element.addEventListener("mouseout", () => {
  document.removeEventListener("wheel", preventOnWheel, { passive: false });
});

Hope it works!

Collapse
 
nenadra profile image
nenadra

Hi Emanuel,

Thank you so much for your fast reply and descriptive answer.

Some background of the problem:

I have a image slider which changes images on wheel event. While you use the wheel and you are inside the element the wheel scroll is blocked with event.preventDefault and it changes the images. When you leave the element with the mouse, the wheel scroll is unblocked with event.preventDefault = false.

I did it using "old-style" and it worked well until Google in Chrome 73 decided to make the wheel event listener passive by default, and now the event.preventDefault does not work and there is no way to add {passive:false} except rewriting those functions in addEventListener style.

So I was trying to just make it work, and not make any unnecessary changes to the other code.

I will try your suggestions and I will write you the result.

Thanks again.

Collapse
 
nenadra profile image
nenadra

It worked!

Thanks again!

Thread Thread
 
smotchkkiss profile image
Emanuel Tannert

Glad to hear that it worked!

And sorry for the stylistic comments, I assumed you had written the whole code just now. Thank you for the additional explanations!