diff options
Diffstat (limited to 'content_scripts/mode.coffee')
| -rw-r--r-- | content_scripts/mode.coffee | 78 |
1 files changed, 70 insertions, 8 deletions
diff --git a/content_scripts/mode.coffee b/content_scripts/mode.coffee index f7bf9e69..e4b6017c 100644 --- a/content_scripts/mode.coffee +++ b/content_scripts/mode.coffee @@ -1,12 +1,74 @@ -root = exports ? window -class root.Mode - constructor: (onKeydown, onKeypress, onKeyup, @popModeCallback) -> +class Mode + # Static members. + @modes: [] + @current: -> Mode.modes[0] + @suppressPropagation = false + @propagate = true + + # 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" or "pass"; the latter are replaced with suitable functions. + keypress: "suppress" # A function, or "suppress" or "pass"; the latter are replaced with suitable functions. + keyup: "suppress" # A function, or "suppress" or "pass"; the latter are replaced with suitable functions. + onDeactivate: -> # Called when leaving this mode. + onReactivate: -> # Called when this mode is reactivated. + + constructor: (options) -> + extend @, options + @handlerId = handlerStack.push - keydown: onKeydown - keypress: onKeypress - keyup: onKeyup + keydown: @checkForBuiltInHandler "keydown", @keydown + keypress: @checkForBuiltInHandler "keypress", @keypress + keyup: @checkForBuiltInHandler "keyup", @keyup + reactivateMode: => + @onReactivate() + Mode.setBadge() + return Mode.suppressPropagation + + Mode.modes.unshift @ + Mode.setBadge() + + # Allow the strings "suppress" and "pass" to be used as proxies for the built-in handlers. + checkForBuiltInHandler: (type, handler) -> + switch handler + when "suppress" then @generateSuppressPropagation type + when "pass" then @generatePassThrough type + else handler - popMode: -> + # Generate a default handler which always passes through; except Esc, which pops the current mode. + generatePassThrough: (type) -> + me = @ + (event) -> + if type == "keydown" and KeyboardUtils.isEscape event + me.popMode event + return Mode.suppressPropagation + handlerStack.passThrough + + # Generate a default handler which always suppresses propagation; except Esc, which pops the current mode. + generateSuppressPropagation: (type) -> + handler = @generatePassThrough type + (event) -> handler(event) and Mode.suppressPropagation # Always falsy. + + # Leave the current mode; event may or may not be provide. It is the responsibility of the creator of this + # object to know whether or not an event will be provided. Bubble a "reactivateMode" event to notify the + # now-active mode that it is once again top dog. + popMode: (event) -> + Mode.modes = Mode.modes.filter (mode) => mode != @ handlerStack.remove @handlerId - @popModeCallback() + @onDeactivate event + handlerStack.bubbleEvent "reactivateMode", event + + # Set the badge on the browser popup to indicate the current mode; static method. + @setBadge: -> + badge = Mode.getBadge() + chrome.runtime.sendMessage({ handler: "setBadge", badge: badge }) + + # Static convenience methods. + @is: (mode) -> Mode.current()?.name == mode + @getBadge: -> Mode.current()?.badge || "" + @isInsert: -> Mode.is "insert" + +root = exports ? window +root.Mode = Mode |
