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

nonpassive event modifier #5442

Merged
merged 5 commits into from Sep 24, 2020
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions site/content/docs/02-template-syntax.md
Expand Up @@ -471,6 +471,7 @@ The following modifiers are available:
* `preventDefault` — calls `event.preventDefault()` before running the handler
* `stopPropagation` — calls `event.stopPropagation()`, preventing the event reaching the next element
* `passive` — improves scrolling performance on touch/wheel events (Svelte will add it automatically where it's safe to do so)
* `nonpassive` — explicitly set `passive: false`
* `capture` — fires the handler during the *capture* phase instead of the *bubbling* phase
* `once` — remove the handler after the first time it runs
* `self` — only trigger handler if event.target is the element itself
Expand Down
1 change: 1 addition & 0 deletions site/content/tutorial/05-events/03-event-modifiers/text.md
Expand Up @@ -21,6 +21,7 @@ The full list of modifiers:
* `preventDefault` — calls `event.preventDefault()` before running the handler. Useful for client-side form handling, for example.
* `stopPropagation` — calls `event.stopPropagation()`, preventing the event reaching the next element
* `passive` — improves scrolling performance on touch/wheel events (Svelte will add it automatically where it's safe to do so)
* `nonpassive` — explicitly set `passive: false`
* `capture` — fires the handler during the *capture* phase instead of the *bubbling* phase ([MDN docs](https://developer.mozilla.org/en-US/docs/Learn/JavaScript/Building_blocks/Events#Event_bubbling_and_capture))
* `once` — remove the handler after the first time it runs
* `self` — only trigger handler if event.target is the element itself
Expand Down
10 changes: 9 additions & 1 deletion src/compiler/compile/nodes/Element.ts
Expand Up @@ -80,6 +80,7 @@ const valid_modifiers = new Set([
'capture',
'once',
'passive',
'nonpassive',
'self'
]);

Expand Down Expand Up @@ -770,6 +771,13 @@ export default class Element extends Node {
});
}

if (handler.modifiers.has('passive') && handler.modifiers.has('nonpassive')) {
component.error(handler, {
code: 'invalid-event-modifier',
message: `The 'passive' and 'nonpassive' modifiers cannot be used together`
});
}

handler.modifiers.forEach(modifier => {
if (!valid_modifiers.has(modifier)) {
component.error(handler, {
Expand Down Expand Up @@ -804,7 +812,7 @@ export default class Element extends Node {
}
});

if (passive_events.has(handler.name) && handler.can_make_passive && !handler.modifiers.has('preventDefault')) {
if (passive_events.has(handler.name) && handler.can_make_passive && !handler.modifiers.has('preventDefault') && !handler.modifiers.has('nonpassive')) {
// touch/wheel events should be passive by default
handler.modifiers.add('passive');
}
Expand Down
14 changes: 10 additions & 4 deletions src/compiler/compile/render_dom/wrappers/Element/EventHandler.ts
Expand Up @@ -45,11 +45,17 @@ export default class EventHandlerWrapper {

const args = [];

const opts = ['passive', 'once', 'capture'].filter(mod => this.node.modifiers.has(mod));
const opts = ['nonpassive', 'passive', 'once', 'capture'].filter(mod => this.node.modifiers.has(mod));
if (opts.length) {
args.push((opts.length === 1 && opts[0] === 'capture')
? TRUE
: x`{ ${opts.map(opt => p`${opt}: true`)} }`);
if (opts.length === 1 && opts[0] === 'capture') {
args.push(TRUE);
} else {
args.push(x`{ ${ opts.map(opt =>
opt === 'nonpassive'
? p`passive: false`
: p`${opt}: true`
) } }`);
}
} else if (block.renderer.options.dev) {
args.push(FALSE);
}
Expand Down
36 changes: 22 additions & 14 deletions test/js/samples/event-modifiers/expected.js
Expand Up @@ -16,41 +16,49 @@ import {
} from "svelte/internal";

function create_fragment(ctx) {
let div;
let button0;
let div1;
let div0;
let t1;
let button1;
let button0;
let t3;
let button1;
let t5;
let button2;
let mounted;
let dispose;

return {
c() {
div = element("div");
div1 = element("div");
div0 = element("div");
div0.textContent = "touch me";
t1 = space();
button0 = element("button");
button0.textContent = "click me";
t1 = space();
t3 = space();
button1 = element("button");
button1.textContent = "or me";
t3 = space();
t5 = space();
button2 = element("button");
button2.textContent = "or me!";
},
m(target, anchor) {
insert(target, div, anchor);
append(div, button0);
append(div, t1);
append(div, button1);
append(div, t3);
append(div, button2);
insert(target, div1, anchor);
append(div1, div0);
append(div1, t1);
append(div1, button0);
append(div1, t3);
append(div1, button1);
append(div1, t5);
append(div1, button2);

if (!mounted) {
dispose = [
listen(div0, "touchstart", handleTouchstart, { passive: false }),
listen(button0, "click", stop_propagation(prevent_default(handleClick))),
listen(button1, "click", handleClick, { once: true, capture: true }),
listen(button2, "click", handleClick, true),
listen(div, "touchstart", handleTouchstart, { passive: true })
listen(div1, "touchstart", handleTouchstart, { passive: true })
];

mounted = true;
Expand All @@ -60,7 +68,7 @@ function create_fragment(ctx) {
i: noop,
o: noop,
d(detaching) {
if (detaching) detach(div);
if (detaching) detach(div1);
mounted = false;
run_all(dispose);
}
Expand Down
1 change: 1 addition & 0 deletions test/js/samples/event-modifiers/input.svelte
Expand Up @@ -9,6 +9,7 @@
</script>

<div on:touchstart={handleTouchstart}>
<div on:touchstart|nonpassive={handleTouchstart}>touch me</div>
<button on:click|stopPropagation|preventDefault={handleClick}>click me</button>
<button on:click|once|capture={handleClick}>or me</button>
<button on:click|capture={handleClick}>or me!</button>
Expand Down
@@ -0,0 +1,15 @@
[{
"message": "The 'passive' and 'nonpassive' modifiers cannot be used together",
"code": "invalid-event-modifier",
"start": {
"line": 1,
"column": 5,
"character": 5
},
"end": {
"line": 1,
"column": 51,
"character": 51
},
"pos": 5
}]
@@ -0,0 +1,3 @@
<div on:touchstart|nonpassive|passive={handleWheel}>
oops
</div>
2 changes: 1 addition & 1 deletion test/validator/samples/event-modifiers-invalid/errors.json
@@ -1,5 +1,5 @@
[{
"message": "Valid event modifiers are preventDefault, stopPropagation, capture, once, passive or self",
"message": "Valid event modifiers are preventDefault, stopPropagation, capture, once, passive, nonpassive or self",
"code": "invalid-event-modifier",
"start": {
"line": 1,
Expand Down