From f2abc3b9b9abc086d23995a70ce72a54d8a9a5b0 Mon Sep 17 00:00:00 2001 From: Rasso Hilber Date: Thu, 17 Oct 2024 22:29:47 +0200 Subject: [PATCH 1/3] Add test `.passive.false modifier should enable e.preventDefault()` --- .../cypress/integration/directives/x-on.spec.js | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/tests/cypress/integration/directives/x-on.spec.js b/tests/cypress/integration/directives/x-on.spec.js index 47d598ec1..5d06e89a6 100644 --- a/tests/cypress/integration/directives/x-on.spec.js +++ b/tests/cypress/integration/directives/x-on.spec.js @@ -79,6 +79,23 @@ test('.passive modifier should disable e.preventDefault()', } ) +test('.passive.false modifier should enable e.preventDefault()', + html` +
+
+
+ `, + ({ get }) => { + get('div').trigger('touchmove') + get('div').should(haveData('defaultPrevented', true)) + } +) + test('.stop modifier', html`
From 0f2432b9b2ece43eb525f0cf8ab99acf88630585 Mon Sep 17 00:00:00 2001 From: Rasso Hilber Date: Thu, 17 Oct 2024 23:28:01 +0200 Subject: [PATCH 2/3] Implement `passive.false` modifier for `x-on` --- packages/alpinejs/src/utils/on.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/packages/alpinejs/src/utils/on.js b/packages/alpinejs/src/utils/on.js index d877d87c9..4fb275215 100644 --- a/packages/alpinejs/src/utils/on.js +++ b/packages/alpinejs/src/utils/on.js @@ -14,11 +14,15 @@ export default function on (el, event, modifiers, callback) { if (modifiers.includes("dot")) event = dotSyntax(event) if (modifiers.includes('camel')) event = camelCase(event) - if (modifiers.includes('passive')) options.passive = true if (modifiers.includes('capture')) options.capture = true if (modifiers.includes('window')) listenerTarget = window if (modifiers.includes('document')) listenerTarget = document + if (modifiers.includes('passive')) { + let nextModifier = modifiers[modifiers.indexOf('passive')+1] + options.passive = nextModifier === 'false' ? false : true + } + // By wrapping the handler with debounce & throttle first, we ensure that the wrapping logic itself is not // throttled/debounced, only the user's callback is. This way, if the user expects // `e.preventDefault()` to happen, it'll still happen even if their callback gets throttled. @@ -73,7 +77,7 @@ export default function on (el, event, modifiers, callback) { if (isListeningForASpecificKeyThatHasntBeenPressed(e, modifiers)) { return } - + next(e) }) } From bb0fbb8eac841d3352d902dbfaa0dfb9e2a4b6d0 Mon Sep 17 00:00:00 2001 From: Rasso Hilber Date: Thu, 17 Oct 2024 23:51:17 +0200 Subject: [PATCH 3/3] Add documentation for `.passive.false` --- packages/docs/src/en/directives/on.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/packages/docs/src/en/directives/on.md b/packages/docs/src/en/directives/on.md index 7ccf7a0ec..f293a1cc8 100644 --- a/packages/docs/src/en/directives/on.md +++ b/packages/docs/src/en/directives/on.md @@ -343,6 +343,15 @@ If you are listening for touch events, it's important to add `.passive` to your [→ Read more about passive listeners](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#improving_scrolling_performance_with_passive_listeners) + +### .passive.false + +In modern browsers, `wheel` and `touchmove` event listeners are passive by default. If, for some reason, you need to call `preventDefault` on such an event, you can do so by adding `.passive.false` to your listener. + +```alpine +
...
+``` + ### .capture Add this modifier if you want to execute this listener in the event's capturing phase, e.g. before the event bubbles from the target element up the DOM.