diff options
Diffstat (limited to 'content_scripts/mode_insert.coffee')
| -rw-r--r-- | content_scripts/mode_insert.coffee | 80 |
1 files changed, 37 insertions, 43 deletions
diff --git a/content_scripts/mode_insert.coffee b/content_scripts/mode_insert.coffee index 41d82add..5280aada 100644 --- a/content_scripts/mode_insert.coffee +++ b/content_scripts/mode_insert.coffee @@ -17,75 +17,69 @@ isEmbed =(element) -> isFocusable =(element) -> isEditable(element) or isEmbed element +# This mode is installed when insert mode is active. +class InsertMode extends Mode + constructor: (@insertModeLock = null) -> + super + name: "insert" + badge: "I" + singleton: InsertMode + keydown: (event) => @stopBubblingAndTrue + keypress: (event) => @stopBubblingAndTrue + keyup: (event) => @stopBubblingAndTrue + exitOnEscape: true + exitOnBlur: @insertModeLock + + exit: (event = null) -> + super() + element = event?.srcElement + if element and isFocusable element + # Remove the focus so the user can't just get himself back into insert mode by typing in the same + # input box. + # NOTE(smblott, 2014/12/22) Including embeds for .blur() here is experimental. It appears to be the + # right thing to do for most common use cases. However, it could also cripple flash-based sites and + # games. See discussion in #1211 and #1194. + element.blur() + # Automatically trigger insert mode: # - On a keydown event in a contentEditable element. # - When a focusable element receives the focus. # +# The trigger can be suppressed via triggerSuppressor; see InsertModeBlocker, below. # This mode is permanently installed fairly low down on the handler stack. class InsertModeTrigger extends Mode constructor: -> super name: "insert-trigger" keydown: (event) => - return @continueBubbling if InsertModeTrigger.isSuppressed() - # Some sites (e.g. inbox.google.com) change the contentEditable attribute on the fly (see #1245); - # and unfortunately, the focus event happens *before* the change is made. Therefore, we need to - # check again whether the active element is contentEditable. - return @continueBubbling unless document.activeElement?.isContentEditable - new InsertMode document.activeElement - @stopBubblingAndTrue + triggerSuppressor.unlessSuppressed => + # Some sites (e.g. inbox.google.com) change the contentEditable attribute on the fly (see #1245); + # and unfortunately, the focus event happens *before* the change is made. Therefore, we need to + # check again whether the active element is contentEditable. + return @continueBubbling unless document.activeElement?.isContentEditable + new InsertMode document.activeElement + @stopBubblingAndTrue @push focus: (event) => - @alwaysContinueBubbling => - return @continueBubbling if InsertModeTrigger.isSuppressed() + triggerSuppressor.unlessSuppressed => return if not isFocusable event.target new InsertMode event.target # We may already have focussed an input, so check. new InsertMode document.activeElement if document.activeElement and isEditable document.activeElement - # Allow other modes (notably InsertModeBlocker, below) to suppress this trigger. All static. - @suppressors: 0 - @isSuppressed: -> 0 < @suppressors - @suppress: -> @suppressors += 1 - @unsuppress: -> @suppressors -= 1 +# Used by InsertModeBlocker to suppress InsertModeTrigger; see below. +triggerSuppressor = new Utils.Suppressor true # Suppresses InsertModeTrigger. This is used by various modes (usually by inheritance) to prevent # unintentionally dropping into insert mode on focusable elements. class InsertModeBlocker extends Mode constructor: (options = {}) -> - InsertModeTrigger.suppress() + triggerSuppressor.suppress() options.name ||= "insert-blocker" super options - - exit: -> - super() - InsertModeTrigger.unsuppress() - -# This mode is installed when insert mode is active. -class InsertMode extends Mode - constructor: (@insertModeLock = null) -> - super - name: "insert" - badge: "I" - singleton: InsertMode - keydown: (event) => @stopBubblingAndTrue - keypress: (event) => @stopBubblingAndTrue - keyup: (event) => @stopBubblingAndTrue - exitOnEscape: true - exitOnBlur: @insertModeLock - - exit: (event = null) -> - super() - element = event?.srcElement - if element and isFocusable element - # Remove the focus so the user can't just get himself back into insert mode by typing in the same - # input box. - # NOTE(smblott, 2014/12/22) Including embeds for .blur() here is experimental. It appears to be the - # right thing to do for most common use cases. However, it could also cripple flash-based sites and - # games. See discussion in #1211 and #1194. - element.blur() + @onExit -> triggerSuppressor.unsuppress() root = exports ? window root.InsertMode = InsertMode |
