From 21da3fcafbb29540788037dbcdbdce79ad14e650 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 30 Mar 2016 13:07:05 +0100 Subject: Rename handlerStack constants. Problems: - The meanings of some of the Mode/handlerStack constant names is far from obvious. - The same thing is named different things in different places. This changes various constant names such that: - the names used in the handler stack and in the modes are the same. - ditto vis-a-vis DomUtils. Also, break out the core of the handler stacks' `bubbleEvent` method into a switch statements. This makes it more obvious that the cases are mutually exclusive. --- lib/handler_stack.coffee | 55 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 38 insertions(+), 17 deletions(-) (limited to 'lib/handler_stack.coffee') diff --git a/lib/handler_stack.coffee b/lib/handler_stack.coffee index 2a44d26b..c97c5da0 100644 --- a/lib/handler_stack.coffee +++ b/lib/handler_stack.coffee @@ -9,16 +9,22 @@ class HandlerStack # A handler should return this value to immediately discontinue bubbling and pass the event on to the # underlying page. - @stopBubblingAndTrue = new Object() + @passEventToPage = new Object() # A handler should return this value to indicate that the event has been consumed, and no further # processing should take place. The event does not propagate to the underlying page. - @stopBubblingAndFalse = new Object() + @suppressPropagation = new Object() # A handler should return this value to indicate that bubbling should be restarted. Typically, this is # used when, while bubbling an event, a new mode is pushed onto the stack. @restartBubbling = new Object() + # A handler should return this value to continue bubbling the event. + @continueBubbling = true + + # A handler should return this value to suppress an event. + @suppressEvent = false + # Adds a handler to the top of the stack. Returns a unique ID for that handler that can be used to remove it # later. push: (handler) -> @@ -34,8 +40,8 @@ class HandlerStack handler.id = ++@counter # Called whenever we receive a key or other event. Each individual handler has the option to stop the - # event's propagation by returning a falsy value, or stop bubbling by returning @stopBubblingAndFalse or - # @stopBubblingAndTrue. + # event's propagation by returning a falsy value, or stop bubbling by returning @suppressPropagation or + # @passEventToPage. bubbleEvent: (type, event) -> @eventNumber += 1 eventNumber = @eventNumber @@ -47,12 +53,27 @@ class HandlerStack @currentId = handler.id result = handler[type].call this, event @logResult eventNumber, type, event, handler, result if @debug - if not result + if result + switch result + when @passEventToPage + return true + when @suppressPropagation + DomUtils.suppressPropagation event + return false + when @restartBubbling + return @bubbleEvent type, event + when @continueBubbling + true # Do nothing, continue bubbling. + else + # Any other truthy value also means continue bubbling. + if @debug + console.log "Unknown truthy return value in handler stack: #{eventNumber}, #{type}, #{result}" + else + if @debug and result != false + console.log "Unknown falsy return value in handler stack: #{eventNumber}, #{type}, #{result}" + # Any falsy value means suppress event. DomUtils.suppressEvent event if @isChromeEvent event return false - return true if result == @stopBubblingAndTrue - return false if result == @stopBubblingAndFalse - return @bubbleEvent type, event if result == @restartBubbling else @logResult eventNumber, type, event, handler, "skip" if @debug true @@ -74,21 +95,21 @@ class HandlerStack # Convenience wrappers. Handlers must return an approriate value. These are wrappers which handlers can # use to always return the same value. This then means that the handler itself can be implemented without # regard to its return value. - alwaysContinueBubbling: (handler) -> - handler() - true + alwaysContinueBubbling: (handler = null) -> + handler?() + @continueBubbling - neverContinueBubbling: (handler) -> - handler() - false + alwaysSuppressPropagation: (handler = null) -> + handler?() + @suppressPropagation # Debugging. logResult: (eventNumber, type, event, handler, result) -> label = switch result - when @stopBubblingAndTrue then "stop/true" - when @stopBubblingAndFalse then "stop/false" - when @restartBubbling then "rebubble" + when @passEventToPage then "passEventToPage" + when @suppressPropagation then "suppressPropagation" + when @restartBubbling then "restartBubbling" when "skip" then "skip" when true then "continue" label ||= if result then "continue/truthy" else "suppress" -- cgit v1.2.3 From 69a20856ae711d5d86fc6876f840c62dc4c47ef5 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Wed, 30 Mar 2016 20:06:19 +0100 Subject: Rework handlerStack.bubbleEvent() for greater clarity. --- lib/handler_stack.coffee | 41 +++++++++++++++++------------------------ 1 file changed, 17 insertions(+), 24 deletions(-) (limited to 'lib/handler_stack.coffee') diff --git a/lib/handler_stack.coffee b/lib/handler_stack.coffee index c97c5da0..ac48e725 100644 --- a/lib/handler_stack.coffee +++ b/lib/handler_stack.coffee @@ -45,37 +45,30 @@ class HandlerStack bubbleEvent: (type, event) -> @eventNumber += 1 eventNumber = @eventNumber - # We take a copy of the array in order to avoid interference from concurrent removes (for example, to - # avoid calling the same handler twice, because elements have been spliced out of the array by remove). for handler in @stack[..].reverse() - # A handler may have been removed (handler.id == null), so check. - if handler?.id and handler[type] + # A handler might have been removed (handler.id == null), so check; or there might just be no handler + # for this type of event. + unless handler?.id and handler[type] + @logResult eventNumber, type, event, handler, "skip [#{handler[type]?}]" if @debug + else @currentId = handler.id result = handler[type].call this, event @logResult eventNumber, type, event, handler, result if @debug - if result - switch result - when @passEventToPage - return true - when @suppressPropagation - DomUtils.suppressPropagation event - return false - when @restartBubbling - return @bubbleEvent type, event - when @continueBubbling - true # Do nothing, continue bubbling. - else - # Any other truthy value also means continue bubbling. - if @debug - console.log "Unknown truthy return value in handler stack: #{eventNumber}, #{type}, #{result}" + if result == @passEventToPage + return true + else if result == @suppressPropagation + DomUtils.suppressPropagation event + return false + else if result == @restartBubbling + return @bubbleEvent type, event + else if result == @continueBubbling or result + true # Do nothing, but continue bubbling (for @continueBubbling and all truthy results). else - if @debug and result != false - console.log "Unknown falsy return value in handler stack: #{eventNumber}, #{type}, #{result}" - # Any falsy value means suppress event. + # result is @suppressEvent or falsy. DomUtils.suppressEvent event if @isChromeEvent event return false - else - @logResult eventNumber, type, event, handler, "skip" if @debug + + # None of our handlers want to suppress the event, so pass it to the page. true remove: (id = @currentId) -> -- cgit v1.2.3 From dd04abbfed292d7c73f7c29176dd611107da6805 Mon Sep 17 00:00:00 2001 From: Stephen Blott Date: Thu, 31 Mar 2016 10:20:22 +0100 Subject: Fix @suppressEvent and tweak comments. --- lib/handler_stack.coffee | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'lib/handler_stack.coffee') diff --git a/lib/handler_stack.coffee b/lib/handler_stack.coffee index ac48e725..c17be24f 100644 --- a/lib/handler_stack.coffee +++ b/lib/handler_stack.coffee @@ -61,14 +61,14 @@ class HandlerStack return false else if result == @restartBubbling return @bubbleEvent type, event - else if result == @continueBubbling or result - true # Do nothing, but continue bubbling (for @continueBubbling and all truthy results). + else if result == @continueBubbling or (result and result != @suppressEvent) + true # Do nothing, but continue bubbling. else # result is @suppressEvent or falsy. DomUtils.suppressEvent event if @isChromeEvent event return false - # None of our handlers want to suppress the event, so pass it to the page. + # None of our handlers care about this event, so pass it to the page. true remove: (id = @currentId) -> -- cgit v1.2.3