Stop propagation of a specific event inside another event listener

会有一股神秘感。 提交于 2021-01-29 11:15:45

问题


I have a listener attached to resize event on window object. Deeper in my code, I have some input fields.

To avoid some issues on android devices, I’d like to prevent resize listeners from being fired when an input field is focused (android device resize browser window when opening keyboard, unlike IOS).

main.js

window.addEventListener(‘resize’, () => {
  // Some stuff here
});

someFile.js

field.addEventListener(‘input’, () => {
  // Here I want to disable the resize event only once
});

I came accross the following solutions, without any success so far :

removeEventListener()

Not suitable at all, since I need to specify a reference to the listener function. Not only do I have to remove listeners one by one, I also have to list them all, and rebind them after.

event.stopPropagation()

someFile.js

field.addEventListener(‘focusin’, () => {
  window.addEventListener(‘resize’, event => {
    event.stopPropagation();
    // also tried event.stopImmediatePropagation()
  });
});

But since listeners are called in declared order, it doesn’t prevent anything (it is declared last). Plus I have to rebind everything again on focusout.

What I want

I’m aware of some tricks using global variables that can achieve what I want, but they are kinda ugly, not to mention I try to avoid global variables as much as I can.

Is there any elegant way, to invoke an early stopPropagation() like function on all resize listeners, and prevent them from firing from deep function inside code ?

Or is there a better architecture, for example a global function that can trigger when any input element on the page gets focus, and prevent the resize event regardless of the focused element ?


回答1:


I'd add a resize listener unconditionally, and inside it, check if document.activeElement is one of the fields:

window.addEventListener(
  'resize',
  (e) => {
    if (document.activeElement && document.activeElement.matches('input')) {
      console.log('propagation stopped');
      e.stopPropagation();
    } else {
      console.log('propagation not stopped');
    }
  },
  true // enable useCapture here with this third argument
       // to stop propagation as early as possible
);
<input>

Change the selector string passed to matches to match your needs. The above snippet uses input, which will match any input field. If you only want to stop propagation when the focused input has a class of foo, you'd use

.matches('input.foo')

To match multiple selectors, separate them with a comma, eg

.matches('input, textarea')

will match both an input and a textarea.

Also keep in mind that Javascript syntax requires straight quotes, not so-called smart quotes, which will cause syntax errors.



来源:https://stackoverflow.com/questions/57142999/stop-propagation-of-a-specific-event-inside-another-event-listener

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!