diff options
| author | Stephen Blott | 2015-01-08 11:09:06 +0000 | 
|---|---|---|
| committer | Stephen Blott | 2015-01-08 11:30:55 +0000 | 
| commit | 637d90be6847051d20a4cf3b704d599c877a97d3 (patch) | |
| tree | 15af5d34cc20915579b4e0a19c0680bfe76fd4a0 /content_scripts/mode_insert.coffee | |
| parent | 5d199e6c786bb2874f7ecb700d505e7b2d70d982 (diff) | |
| download | vimium-637d90be6847051d20a4cf3b704d599c877a97d3.tar.bz2 | |
Modes; more changes...
- Simplify InsertMode Trigger/Blocker (yet again).
- Reduce badge flicker for singletons.
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  | 
