diff options
| author | Stephen Blott | 2017-12-02 12:41:56 +0000 | 
|---|---|---|
| committer | GitHub | 2017-12-02 12:41:56 +0000 | 
| commit | b7a1313954eb9125f7310d572c9b4615f7182236 (patch) | |
| tree | 60d877ac06b0de8184e8cc067472eecddb807b6c | |
| parent | 3d05a7fed10b39d664912525091964d0258b711e (diff) | |
| parent | cbc3d21046f35c05bd3138cb0b8ac1309c718fe6 (diff) | |
| download | vimium-b7a1313954eb9125f7310d572c9b4615f7182236.tar.bz2 | |
Merge pull request #2846 from smblott-github/rework-insert-mode
Rework insert mode (check status dynamically).
| -rw-r--r-- | content_scripts/mode_insert.coffee | 87 | 
1 files changed, 18 insertions, 69 deletions
| diff --git a/content_scripts/mode_insert.coffee b/content_scripts/mode_insert.coffee index d2a33091..3b6edf1e 100644 --- a/content_scripts/mode_insert.coffee +++ b/content_scripts/mode_insert.coffee @@ -10,23 +10,23 @@ class InsertMode extends Mode      handleKeyEvent = (event) =>        return @continueBubbling unless @isActive event -      return @passEventToPage if @insertModeLock is document.body + +      # See comment here: https://github.com/philc/vimium/commit/48c169bd5a61685bb4e67b1e76c939dbf360a658. +      activeElement = @getActiveElement() +      return @passEventToPage if activeElement == document.body and activeElement.isContentEditable        # Check for a pass-next-key key.        if KeyboardUtils.getKeyCharString(event) in Settings.get "passNextKeyKeys"          new PassNextKeyMode -        return @suppressEvent - -      return @passEventToPage unless event.type == 'keydown' and KeyboardUtils.isEscape event -      target = event.target -      if target and DomUtils.isFocusable target -        # Remove the focus, so the user can't just get back into insert mode by typing in the same input box. -        target.blur() -      else if target?.shadowRoot and @insertModeLock -        # An editable element in a shadow DOM is focused; blur it. -        @insertModeLock.blur() -      @exit event, event.target -      @suppressEvent + +      else if event.type == 'keydown' and KeyboardUtils.isEscape(event) +        activeElement.blur() if DomUtils.isFocusable activeElement +        @exit() unless @permanent + +      else +        return @passEventToPage + +      return @suppressEvent      defaults =        name: "insert" @@ -36,67 +36,16 @@ class InsertMode extends Mode      super extend defaults, options -    @insertModeLock = -      if options.targetElement and DomUtils.isEditable options.targetElement -        # The caller has told us which element to activate on. -        options.targetElement -      else if document.activeElement and DomUtils.isEditable document.activeElement -        # An input element is already active, so use it. -        document.activeElement -      else -        null - -    @push -      _name: "mode-#{@id}-focus" -      "blur": (event) => @alwaysContinueBubbling => -        target = event.target -        # We can't rely on focus and blur events arriving in the expected order.  When the active element -        # changes, we might get "focus" before "blur".  We track the active element in @insertModeLock, and -        # exit only when that element blurs. -        @exit event, target if @insertModeLock and target == @insertModeLock -      "focus": (event) => @alwaysContinueBubbling => -        if @insertModeLock != event.target and DomUtils.isFocusable event.target -          @activateOnElement event.target -        else if event.target.shadowRoot -          # A focusable element inside the shadow DOM might have been selected. If so, we can catch the focus -          # event inside the shadow DOM. This fixes #853. -          shadowRoot = event.target.shadowRoot -          eventListeners = {} -          for type in [ "focus", "blur" ] -            eventListeners[type] = do (type) -> -              forTrusted (event) -> handlerStack.bubbleEvent type, event -            shadowRoot.addEventListener type, eventListeners[type], true - -          handlerStack.push -            _name: "shadow-DOM-input-mode" -            blur: (event) -> -              if event.target.shadowRoot == shadowRoot -                handlerStack.remove() -                for own type, listener of eventListeners -                  shadowRoot.removeEventListener type, listener, true -      # Only for tests.  This gives us a hook to test the status of the permanently-installed instance.      InsertMode.permanentInstance = this if @permanent    isActive: (event) ->      return false if event == InsertMode.suppressedEvent -    return true if @insertModeLock or @global -    # Some sites (e.g. inbox.google.com) change the contentEditable property on the fly (see #1245); and -    # unfortunately, the focus event fires *before* the change.  Therefore, we need to re-check whether the -    # active element is contentEditable. -    @activateOnElement document.activeElement if document.activeElement?.isContentEditable -    @insertModeLock != null - -  activateOnElement: (element) -> -    @log "#{@id}: activating (permanent)" if @debug and @permanent -    @insertModeLock = element - -  exit: (_, target)  -> -    if (target and target == @insertModeLock) or @global or target == undefined -      @log "#{@id}: deactivating (permanent)" if @debug and @permanent and @insertModeLock -      @insertModeLock = null -      # Exit, but only if this isn't the permanently-installed instance. -      super() unless @permanent +    return true if @global +    DomUtils.isFocusable @getActiveElement() + +  getActiveElement: -> +    document.activeElement?.shadowRoot?.activeElement ? document.activeElement    # Static stuff. This allows PostFindMode to suppress the permanently-installed InsertMode instance.    @suppressedEvent: null | 
