diff options
| author | Stephen Blott | 2015-01-03 13:20:04 +0000 |
|---|---|---|
| committer | Stephen Blott | 2015-01-03 13:20:04 +0000 |
| commit | baccd7c5cef14480e21e41519e20ee19fa238655 (patch) | |
| tree | 26f1252bd952d0a2ab3b88259768cdcd30f0c26a /content_scripts/mode.coffee | |
| parent | 00573389c63cebb42c225e10786aeb05e72fab39 (diff) | |
| download | vimium-baccd7c5cef14480e21e41519e20ee19fa238655.tar.bz2 | |
Modes; Fix various mode changes.
Diffstat (limited to 'content_scripts/mode.coffee')
| -rw-r--r-- | content_scripts/mode.coffee | 92 |
1 files changed, 40 insertions, 52 deletions
diff --git a/content_scripts/mode.coffee b/content_scripts/mode.coffee index 8041f462..9e886a63 100644 --- a/content_scripts/mode.coffee +++ b/content_scripts/mode.coffee @@ -11,86 +11,74 @@ class Mode stopBubblingAndFalse: handlerStack.stopBubblingAndFalse # Default values. - name: "" # The name of this mode. - badge: "" # A badge to display on the popup when this mode is active. - keydown: "suppress" # A function, or "suppress", "bubble" or "pass"; see checkForBuiltInHandler(). - keypress: "suppress" # A function, or "suppress", "bubble" or "pass"; see checkForBuiltInHandler(). - keyup: "suppress" # A function, or "suppress", "bubble" or "pass"; see checkForBuiltInHandler(). + name: "" + badge: "" + keydown: (event) => @continueBubbling + keypress: (event) => @continueBubbling + keyup: (event) => @continueBubbling constructor: (options) -> + Mode.modes.unshift @ extend @, options @handlers = [] @handlers.push handlerStack.push - keydown: @checkForBuiltInHandler "keydown", @keydown - keypress: @checkForBuiltInHandler "keypress", @keypress - keyup: @checkForBuiltInHandler "keyup", @keyup - updateBadgeForMode: (badge) => @updateBadgeForMode badge - - Mode.modes.unshift @ - - # Allow the strings "suppress" and "pass" to be used as proxies for the built-in handlers. - checkForBuiltInHandler: (type, handler) -> - switch handler - when "suppress" then @generateHandler type, @suppressEvent - when "bubble" then @generateHandler type, @continueBubbling - when "pass" then @generateHandler type, @stopBubblingAndTrue - else handler - - # Generate a default handler which always always yields the same result; except Esc, which pops the current - # mode. - generateHandler: (type, result) -> - (event) => - return result unless type == "keydown" and KeyboardUtils.isEscape event - @exit() - @suppressEvent + keydown: @keydown + keypress: @keypress + keyup: @keyup + updateBadge: (badge) => handlerStack.alwaysContinueBubbling => @chooseBadge badge exit: -> handlerStack.remove handlerId for handlerId in @handlers Mode.modes = Mode.modes.filter (mode) => mode != @ Mode.updateBadge() - # Default updateBadgeForMode handler. This is overridden by sub-classes. The default is to install the - # current mode's badge, unless the bade is already set. - updateBadgeForMode: (badge) -> - handlerStack.alwaysContinueBubbling => badge.badge ||= @badge + # The badge is chosen by bubbling an "updateBadge" event down the handler stack allowing each mode the + # opportunity to choose a badge. chooseBadge, here, is the default: choose the current mode's badge unless + # one has already been chosen. This is overridden in sub-classes. + chooseBadge: (badge) -> + badge.badge ||= @badge - # Static method. Used externally and internally to initiate bubbling of an updateBadgeForMode event. - # Do not update the badge: - # - if this document does not have the focus, or - # - if the document's body is a frameset + # Static method. Used externally and internally to initiate bubbling of an updateBadge event and to send + # the resulting badge to the background page. We only update the badge if this document has the focus, and + # the document's body isn't a frameset. @updateBadge: -> if document.hasFocus() unless document.body?.tagName.toLowerCase() == "frameset" badge = {badge: ""} - handlerStack.bubbleEvent "updateBadgeForMode", badge - Mode.sendBadge badge.badge - - # Static utility to update the browser-popup badge. - @sendBadge: (badge) -> - chrome.runtime.sendMessage({ handler: "setBadge", badge: badge }) + handlerStack.bubbleEvent "updateBadge", badge + chrome.runtime.sendMessage({ handler: "setBadge", badge: badge.badge }) - # Install a mode, call a function, and exit the mode again. + # Temporarily install a mode. @runIn: (mode, func) -> mode = new mode() func() mode.exit() -# A SingletonMode is a Mode of which there may be at most one instance of the same name (@singleton) active at -# any one time. New instances cancel previous instances on startup. +# A SingletonMode is a Mode of which there may be at most one instance (of @singleton) active at any one time. +# New instances cancel previous instances on startup. class SingletonMode extends Mode - constructor: (@singleton, options) -> - @cancel @singleton - super options - @instances: {} - cancel: (instance) -> - SingletonMode[instance].exit() if SingletonMode[instance] - exit: -> - delete SingletonMode[@instance] + delete SingletonMode[@singleton] super() + constructor: (@singleton, options={}) -> + SingletonMode[@singleton].exit() if SingletonMode[@singleton] + SingletonMode[@singleton] = @ + super options + +# MultiMode is a collection of modes which are installed or uninstalled together. +class MultiMode extends Mode + constructor: (modes...) -> + @modes = (new mode() for mode in modes) + super {name: "multimode"} + + exit: -> + mode.exit() for mode in modes + root = exports ? window root.Mode = Mode +root.SingletonMode = SingletonMode +root.MultiMode = MultiMode |
