Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add default passive logic to all components #83

Closed
userquin opened this issue Jan 3, 2020 · 7 comments
Closed

Add default passive logic to all components #83

userquin opened this issue Jan 3, 2020 · 7 comments
Assignees
Labels
enhancement New feature or request

Comments

@userquin
Copy link

userquin commented Jan 3, 2020

To avoid chrome warnings about passive events you can use this (since sveltejs cannot add modifiers to on:*** listeners to no DOM elements (except once), the default behavior can be passive and no capturing by default):

  1. create detectPassiveEvents.js on @smui/common to detect passive-events:
const detectPassiveEvents = {
  update() {
    if (typeof window !== 'undefined' && typeof window.addEventListener === 'function') {
      let passive = false;
      const options = Object.defineProperty({}, 'passive', {
        get() { passive = true; },
      });
      // note: have to set and remove a no-op listener instead of null
      // (which was used previously), becasue Edge v15 throws an error
      // when providing a null callback.
      // https://github.com/rafrex/detect-passive-events/pull/3
      const noop = () => {};
      window.addEventListener('testPassiveEventSupport', noop, options);
      window.removeEventListener('testPassiveEventSupport', noop, options);
      detectPassiveEvents.hasSupport = passive;
    }
  },
};

detectPassiveEvents.update();

export default detectPassiveEvents;
  1. change @smui/common/forwardEvents.js with:
import {bubble, listen} from 'svelte/internal';
import detectPassiveEvents from "./detectPassiveEvents";
const defaultOptions = detectPassiveEvents.hasSupport ? { passive: true, capture: false } : false;
export function forwardEventsBuilder(component, additionalEvents = []) {
  const events = [
    'focus', 'blur',
    'fullscreenchange', 'fullscreenerror', 'scroll',
    'cut', 'copy', 'paste',
    'keydown', 'keypress', 'keyup',
    'auxclick', 'click', 'contextmenu', 'dblclick', 'mousedown', 'mouseenter', 'mouseleave', 'mousemove', 'mouseover', 'mouseout', 'mouseup', 'pointerlockchange', 'pointerlockerror', 'select', 'wheel',
    'drag', 'dragend', 'dragenter', 'dragstart', 'dragleave', 'dragover', 'drop',
    'touchcancel', 'touchend', 'touchmove', 'touchstart',
    'pointerover', 'pointerenter', 'pointerdown', 'pointermove', 'pointerup', 'pointercancel', 'pointerout', 'pointerleave', 'gotpointercapture', 'lostpointercapture',
    ...additionalEvents
  ];

  function forward(e) {
    bubble(component, e);
  }

  return node => {
    const destructors = [];

    // https://github.com/zzarcon/default-passive-events
    for (let i = 0; i < events.length; i++) {
      switch (events[i]) {
        case "scroll":
        case "wheel":
        case "touchstart":
        case "touchmove":
        case "touchenter":
        case "touchend":
        case "touchleave":
        case "mouseout":
        case "mouseleave":
        case "mouseup":
        case "mousedown":
        case "mousemove":
        case "mouseenter":
        case "mousewheel":
        case "mouseover":
          destructors.push(listen(node, events[i], forward, defaultOptions));
          break;
        default:
          destructors.push(listen(node, events[i], forward));
      }
    }
    // for (let i = 0; i < events.length; i++) {
    //   destructors.push(listen(node, events[i], forward));
    // }

    return {
      destroy: () => {
        for (let i = 0; i < destructors.length; i++) {
          destructors[i]();
        }
      }
    }
  };
}

Bye.

@hperrin hperrin added the enhancement New feature or request label Jan 6, 2020
@hperrin
Copy link
Owner

hperrin commented Jan 7, 2020

I wonder if this might be causing the FOUC with Sapper.

@hperrin
Copy link
Owner

hperrin commented Jan 7, 2020

Does adding an event listener ever cause a render?

@userquin
Copy link
Author

userquin commented Jan 8, 2020

I'm using it with sveltejs, not tested yet with sapper, but adding passive: true must not change the default behavior, it is only for scrolling behavior...

@userquin
Copy link
Author

userquin commented Jan 8, 2020

passive: true instructs chrome that no body will call e.preventDefault() so chrome can optimized scrolling just because no body will call e.preventDefault and so there is no need to wait listeners...

@userquin
Copy link
Author

userquin commented Jan 8, 2020

There is no rerender, when you call listen, then all scroll events will warn on chrome. See this entry from svelte: breaking the web

@userquin
Copy link
Author

userquin commented Jan 8, 2020

You can also see this repo: default-passive-events.

@hperrin
Copy link
Owner

hperrin commented Apr 15, 2021

Done! This is now an option when you bind to events in SMUI:

<Card on:wheel:passive={myPassiveHandler}>
  ...
</Card>

Do note that event modifiers on SMUI components have a slightly different syntax (":") than event modifiers on DOM elements ("|").

<!-- SMUI component: -->
<Button on:click:preventDefault:capture={myHandler}>Click me</Button>

<!-- DOM element: -->
<button on:click|preventDefault|capture={myHandler}>Click me</button>

@hperrin hperrin closed this as completed Apr 15, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants