diff --git a/site/content/tutorial/05-events/03-event-modifiers/text.md b/site/content/tutorial/05-events/03-event-modifiers/text.md index 73386dd096..41154cafcd 100644 --- a/site/content/tutorial/05-events/03-event-modifiers/text.md +++ b/site/content/tutorial/05-events/03-event-modifiers/text.md @@ -23,5 +23,6 @@ The full list of modifiers: * `passive` — improves scrolling performance on touch/wheel events (Svelte will add it automatically where it's safe to do so) * `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 You can chain modifiers together, e.g. `on:click|once|capture={...}`. diff --git a/src/compiler/compile/nodes/Element.ts b/src/compiler/compile/nodes/Element.ts index 80b5c6df00..62bc620590 100644 --- a/src/compiler/compile/nodes/Element.ts +++ b/src/compiler/compile/nodes/Element.ts @@ -63,7 +63,8 @@ const valid_modifiers = new Set([ 'stopPropagation', 'capture', 'once', - 'passive' + 'passive', + 'self' ]); const passive_events = new Set([ diff --git a/src/compiler/compile/render_dom/wrappers/shared/add_event_handlers.ts b/src/compiler/compile/render_dom/wrappers/shared/add_event_handlers.ts index 6b7e62d212..06c679d984 100644 --- a/src/compiler/compile/render_dom/wrappers/shared/add_event_handlers.ts +++ b/src/compiler/compile/render_dom/wrappers/shared/add_event_handlers.ts @@ -10,6 +10,7 @@ export default function add_event_handlers( let snippet = handler.render(block); if (handler.modifiers.has('preventDefault')) snippet = `@prevent_default(${snippet})`; if (handler.modifiers.has('stopPropagation')) snippet = `@stop_propagation(${snippet})`; + if (handler.modifiers.has('self')) snippet = `@self(${snippet}, ${target})`; const opts = ['passive', 'once', 'capture'].filter(mod => handler.modifiers.has(mod)); diff --git a/src/runtime/internal/dom.ts b/src/runtime/internal/dom.ts index 6faf3d9c60..f8c2e7bfcd 100644 --- a/src/runtime/internal/dom.ts +++ b/src/runtime/internal/dom.ts @@ -73,6 +73,14 @@ export function stop_propagation(fn) { }; } +export function self(fn, el) { + return function(event) { + if(event.target !== el) return; + // @ts-ignore + return fn.call(this, event); + }; +} + export function attr(node: Element, attribute: string, value?: string) { if (value == null) node.removeAttribute(attribute); else node.setAttribute(attribute, value); diff --git a/test/runtime/samples/event-handler-modifier-self/_config.js b/test/runtime/samples/event-handler-modifier-self/_config.js new file mode 100644 index 0000000000..6d7d29e482 --- /dev/null +++ b/test/runtime/samples/event-handler-modifier-self/_config.js @@ -0,0 +1,16 @@ +export default { + html: ` +
+ +
+ `, + + async test({ assert, component, target, window }) { + const button = target.querySelector('button'); + const event = new window.MouseEvent('click'); + + await button.dispatchEvent(event); + + assert.ok(!component.inner_clicked); + }, +}; diff --git a/test/runtime/samples/event-handler-modifier-self/main.svelte b/test/runtime/samples/event-handler-modifier-self/main.svelte new file mode 100644 index 0000000000..1becf44a9e --- /dev/null +++ b/test/runtime/samples/event-handler-modifier-self/main.svelte @@ -0,0 +1,11 @@ + + +
+ +
diff --git a/test/validator/samples/event-modifiers-invalid/errors.json b/test/validator/samples/event-modifiers-invalid/errors.json index 0aac0e5327..8be2ca7348 100644 --- a/test/validator/samples/event-modifiers-invalid/errors.json +++ b/test/validator/samples/event-modifiers-invalid/errors.json @@ -1,5 +1,5 @@ [{ - "message": "Valid event modifiers are preventDefault, stopPropagation, capture, once or passive", + "message": "Valid event modifiers are preventDefault, stopPropagation, capture, once, passive or self", "code": "invalid-event-modifier", "start": { "line": 1,