diff --git a/docs/reference/actions.md b/docs/reference/actions.md index 45366577..ab4f9fa6 100644 --- a/docs/reference/actions.md +++ b/docs/reference/actions.md @@ -107,6 +107,7 @@ Custom action option | Description -------------------- | ----------- `:stop` | calls `.stopPropagation()` on the event before invoking the method `:prevent` | calls `.preventDefault()` on the event before invoking the method +`:self` | only invokes the method if the event was fired by the element itself ## Event Objects diff --git a/src/core/binding.ts b/src/core/binding.ts index 5e5fe768..643d9506 100644 --- a/src/core/binding.ts +++ b/src/core/binding.ts @@ -31,7 +31,7 @@ export class Binding { } handleEvent(event: Event) { - if (this.willBeInvokedByEvent(event)) { + if (this.willBeInvokedByEvent(event) && this.shouldBeInvokedPerSelf(event)) { this.processStopPropagation(event); this.processPreventDefault(event); @@ -77,6 +77,14 @@ export class Binding { } } + private shouldBeInvokedPerSelf(event: Event): boolean { + if (this.action.eventOptions.self === true) { + return this.action.element === event.target + } else { + return true + } + } + private willBeInvokedByEvent(event: Event): boolean { const eventTarget = event.target if (this.element === eventTarget) { diff --git a/src/core/event_modifiers.ts b/src/core/event_modifiers.ts index e105f4a9..d4a1a2a7 100644 --- a/src/core/event_modifiers.ts +++ b/src/core/event_modifiers.ts @@ -1,4 +1,5 @@ export interface EventModifiers extends AddEventListenerOptions { stop?: boolean; prevent?: boolean; + self?: boolean; } diff --git a/src/tests/modules/core/event_options_tests.ts b/src/tests/modules/core/event_options_tests.ts index 9e87cece..459f42b2 100644 --- a/src/tests/modules/core/event_options_tests.ts +++ b/src/tests/modules/core/event_options_tests.ts @@ -190,6 +190,26 @@ export default class EventOptionsTests extends LogControllerTestCase { ) } + async "test self option"() { + this.setAction(this.buttonElement, "click->c#log:self") + await this.nextFrame + + await this.triggerEvent(this.buttonElement, "click") + + this.assertActions( + { name: "log", eventType: "click" } + ) + } + + async "test self option on parent"() { + this.setAction(this.element, "click->c#log:self") + await this.nextFrame + + await this.triggerEvent(this.buttonElement, "click") + + this.assertNoActions() + } + setAction(element: Element, value: string) { element.setAttribute("data-action", value) }