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

feat: x-on .passive.false modifier #4404

Open
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

hirasso
Copy link

@hirasso hirasso commented Oct 17, 2024

As discussed in #4403 , this PR adds a way to set event listeners to {passive: false}:

<div x-on.touchmove.passive.false="console.log($event.cancelable)"></div>

Use case

In horizontal sliders, it's necessary to stop vertical scrolling of the viewport when flicking through the slides. Registering a non-passive touchmove handler makes this possible:

  • register a touchstart event and save the x-coordinate
  • register a touchmove event with {passive: false} and check if the x-coordinate is more than 3 (or whatever) pixels away from the touchstart coordinate. If so, disable vertical scrolling by calling e.preventDefault()
{
  touching: false,
  touchStartCoords: {x: 0, y: 0},

  bindings: {
    "@touchstart.document.capture": "onTouchStart",
    "@touchmove.document.passive.false": "onTouchMove", // possible through this PR
  },
  
  onTouchStart(e: TouchEvent) {
    const target = e.target as HTMLElement;
    this.touching = this.$root.contains(target);
  
    this.touchStartCoords = {
      x: e.touches[0].pageX,
      y: e.touches[0].pageY,
    };
  },
  
  onTouchMove(e: TouchEvent) {
    const { cancelable } = e;
    const { touching } = this;
  
    if (!touching || !cancelable) return;
  
    const moveVector = {
      x: e.touches[0].pageX - this.touchStartCoords.x,
      y: e.touches[0].pageY - this.touchStartCoords.y,
    };
  
    if (Math.abs(moveVector.x) > 3) {
      e.preventDefault();
    }
  },
}

Checks

  • New test included
  • Documentation updated

Questions

  • I tried to also add an explicit way to set {passive: true} using x-on.passive.true but wasn't able to get it to work. The handler in the cypress test just didn't fire at all (defaultPrevented stayed null, even after the click). But then I thought why even provide passive.true if that's the current behavior of .passive already?
  • further down in on.js, would we need to add "false" to the list in isListeningForASpecificKeyThatHasntBeenPressed? Not sure what the function does exactly.
  • Naming: are there better alternatives to .passive.false, as there are no other options as for example in the .transition modifier?
    • .no-passive as suggested by @ekwoka ?
    • .passive-false ?
    • is there some convention already in Alpine.js on how to deal with boolean values where both explicit true as false is possible?

@hirasso hirasso marked this pull request as ready for review October 17, 2024 21:51
Copy link
Contributor

@ekwoka ekwoka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I'm mostly against the idea of someone actually preventing default on any of these events, the PR is at least quick and simple.

@hirasso
Copy link
Author

hirasso commented Oct 18, 2024

@ekwoka thank you for approving this.

While I'm mostly against the idea of someone actually preventing default on any of these events

Sure... but I would still prefer if Alpine.js would make all native event listener options available instead of deciding for users what's good for them 🙂

I'd hope that the opt-in shape of the modifier .passive.false is a good-enough safeguard for not using this unintentionally.

@ekwoka
Copy link
Contributor

ekwoka commented Oct 18, 2024

An alternative would be no-passive...not sure if that's better.

@hirasso
Copy link
Author

hirasso commented Oct 18, 2024

An alternative would be no-passive...not sure if that's better.

Added naming to the questions section in the PR description.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants