From 066f6bf03cc410c151bd1b4d5eaf39519e9e94c1 Mon Sep 17 00:00:00 2001 From: Nathan Sobo Date: Tue, 23 Sep 2014 17:23:46 -0600 Subject: [PATCH] Forward stop[Immediate]Propagation to original event in CommandRegistry Previously, stopping propagation would work on the synthetic bubbling phase of the command registry itself, but the original event would continue to propagate which is counterintuitive. --- spec/command-registry-spec.coffee | 20 ++++++++++++++++++-- src/command-registry.coffee | 10 ++++++---- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/spec/command-registry-spec.coffee b/spec/command-registry-spec.coffee index 03c0b4717..6d64bb9c0 100644 --- a/spec/command-registry-spec.coffee +++ b/spec/command-registry-spec.coffee @@ -66,8 +66,11 @@ describe "CommandRegistry", -> registry.add '.child', 'command', -> calls.push('child-2') registry.add '.child', 'command', (event) -> calls.push('child-1'); event.stopPropagation() - grandchild.dispatchEvent(new CustomEvent('command', bubbles: true)) + dispatchedEvent = new CustomEvent('command', bubbles: true) + spyOn(dispatchedEvent, 'stopPropagation') + grandchild.dispatchEvent(dispatchedEvent) expect(calls).toEqual ['child-1', 'child-2'] + expect(dispatchedEvent.stopPropagation).toHaveBeenCalled() it "stops invoking callbacks when .stopImmediatePropagation() is called on the event", -> calls = [] @@ -76,8 +79,21 @@ describe "CommandRegistry", -> registry.add '.child', 'command', -> calls.push('child-2') registry.add '.child', 'command', (event) -> calls.push('child-1'); event.stopImmediatePropagation() - grandchild.dispatchEvent(new CustomEvent('command', bubbles: true)) + dispatchedEvent = new CustomEvent('command', bubbles: true) + spyOn(dispatchedEvent, 'stopImmediatePropagation') + grandchild.dispatchEvent(dispatchedEvent) expect(calls).toEqual ['child-1'] + expect(dispatchedEvent.stopImmediatePropagation).toHaveBeenCalled() + + it "forwards .preventDefault() calls from the synthetic event to the original", -> + calls = [] + + registry.add '.child', 'command', (event) -> event.preventDefault() + + dispatchedEvent = new CustomEvent('command', bubbles: true) + spyOn(dispatchedEvent, 'preventDefault') + grandchild.dispatchEvent(dispatchedEvent) + expect(dispatchedEvent.preventDefault).toHaveBeenCalled() it "allows listeners to be removed via a disposable returned by ::add", -> calls = [] diff --git a/src/command-registry.coffee b/src/command-registry.coffee index 945cbd450..73cbdfe22 100644 --- a/src/command-registry.coffee +++ b/src/command-registry.coffee @@ -179,24 +179,26 @@ class CommandRegistry @listenersByCommandName = _.deepClone(snapshot) @setRootNode(rootNode) # restore listeners for commands in snapshot - handleCommandEvent: (event) => + handleCommandEvent: (originalEvent) => propagationStopped = false immediatePropagationStopped = false matched = false - currentTarget = event.target + currentTarget = originalEvent.target - syntheticEvent = Object.create event, + syntheticEvent = Object.create originalEvent, eventPhase: value: Event.BUBBLING_PHASE currentTarget: get: -> currentTarget stopPropagation: value: -> + originalEvent.stopPropagation() propagationStopped = true stopImmediatePropagation: value: -> + originalEvent.stopImmediatePropagation() propagationStopped = true immediatePropagationStopped = true loop matchingListeners = - (@listenersByCommandName[event.type] ? []) + (@listenersByCommandName[originalEvent.type] ? []) .filter (listener) -> currentTarget.webkitMatchesSelector(listener.selector) .sort (a, b) -> a.compare(b)