diff options
| author | Stephen Blott | 2015-01-13 17:18:50 +0000 |
|---|---|---|
| committer | Stephen Blott | 2015-01-13 17:18:50 +0000 |
| commit | 7e1c3475ed9241a5e1fbf78b8134e6ed669ea906 (patch) | |
| tree | 058f7276543f244915148edfae97da10dffecc9a /content_scripts | |
| parent | 1191d73c6fea65bcd4ceec807458e81a1a940047 (diff) | |
| download | vimium-7e1c3475ed9241a5e1fbf78b8134e6ed669ea906.tar.bz2 | |
Modes; temporary commit.
Diffstat (limited to 'content_scripts')
| -rw-r--r-- | content_scripts/link_hints.coffee | 2 | ||||
| -rw-r--r-- | content_scripts/mode.coffee | 7 | ||||
| -rw-r--r-- | content_scripts/mode_find.coffee | 5 | ||||
| -rw-r--r-- | content_scripts/mode_insert.coffee | 105 | ||||
| -rw-r--r-- | content_scripts/mode_visual.coffee | 2 | ||||
| -rw-r--r-- | content_scripts/vimium_frontend.coffee | 19 |
6 files changed, 29 insertions, 111 deletions
diff --git a/content_scripts/link_hints.coffee b/content_scripts/link_hints.coffee index 0668e3ae..b0feea8c 100644 --- a/content_scripts/link_hints.coffee +++ b/content_scripts/link_hints.coffee @@ -66,7 +66,7 @@ LinkHints = { id: "vimiumHintMarkerContainer", className: "vimiumReset" }) @handlerMode = - new class HintMode extends InsertModeBlocker + new class HintMode extends Mode constructor: -> super name: "hint/#{mode.name}" diff --git a/content_scripts/mode.coffee b/content_scripts/mode.coffee index 84b76301..98d3df80 100644 --- a/content_scripts/mode.coffee +++ b/content_scripts/mode.coffee @@ -191,13 +191,6 @@ class Mode handler: "setBadge" badge: badge.badge - # Temporarily install a mode to protect a function call, then exit the mode. For example, temporarily - # install an InsertModeBlocker, so that focus events don't unintentionally drop us into insert mode. - @runIn: (mode, func) -> - mode = new mode() - func() - mode.exit() - registerSingleton: do -> singletons = {} # Static. (key) -> diff --git a/content_scripts/mode_find.coffee b/content_scripts/mode_find.coffee index 519e99ad..bf6e7f5b 100644 --- a/content_scripts/mode_find.coffee +++ b/content_scripts/mode_find.coffee @@ -2,14 +2,13 @@ # When we use find mode, the selection/focus can end up in a focusable/editable element. In this situation, # special considerations apply. We implement three special cases: -# 1. Prevent keyboard events from dropping us unintentionally into insert mode. This is achieved by -# inheriting from InsertModeBlocker. +# 1. Prevent keyboard events from dropping us unintentionally into insert mode. This is achieved by... # 2. Prevent all printable keypress events on the active element from propagating. This is achieved by setting the # suppressPrintableEvents option. There's some controversy as to whether this is the right thing to do. # See discussion in #1415. This implements Option 2 from there. # 3. If the very-next keystroke is Escape, then drop immediately into insert mode. # -class PostFindMode extends InsertModeBlocker +class PostFindMode extends Mode constructor: (findModeAnchorNode) -> element = document.activeElement initialSelection = window.getSelection().toString() diff --git a/content_scripts/mode_insert.coffee b/content_scripts/mode_insert.coffee index dd0c8d16..678e35cc 100644 --- a/content_scripts/mode_insert.coffee +++ b/content_scripts/mode_insert.coffee @@ -1,105 +1,34 @@ -# This mode is installed only when insert mode is active. It is a singleton, so a newly-activated instance -# displaces any active instance. class InsertMode extends Mode constructor: (options = {}) -> defaults = name: "insert" - badge: "I" - singleton: InsertMode - keydown: (event) => @stopBubblingAndTrue - keypress: (event) => @stopBubblingAndTrue - keyup: (event) => @stopBubblingAndTrue exitOnEscape: true - blurOnExit: true - targetElement: null + keydown: (event) => @handler event + keypress: (event) => @handler event + keyup: (event) => @handler event - # If options.targetElement blurs, we exit. - options.exitOnBlur ||= options.targetElement super extend defaults, options - triggerSuppressor.suppress() - - exit: (event = null) -> - triggerSuppressor.unsuppress() - super() - if @options.blurOnExit - element = event?.srcElement - if element and DomUtils.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 (just above normal mode and passkeys mode) on the handler stack. -class InsertModeTrigger extends Mode - constructor: -> - super - name: "insert-trigger" - keydown: (event) => - 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 (on every keydown) whether the active element is contentEditable. - return @continueBubbling unless document.activeElement?.isContentEditable - new InsertMode - targetElement: document.activeElement - @stopBubblingAndTrue @push - _name: "mode-#{@id}/activate-on-focus" - focus: (event) => - triggerSuppressor.unlessSuppressed => - @alwaysContinueBubbling => - if DomUtils.isFocusable event.target - new InsertMode - targetElement: event.target + "blur": => @exit() - # We may have already focussed an input element, so check. - if document.activeElement and DomUtils.isEditable document.activeElement - new InsertMode - targetElement: document.activeElement + active: -> + document.activeElement and DomUtils.isFocusable document.activeElement -# Used by InsertModeBlocker to suppress InsertModeTrigger; see below. -triggerSuppressor = new Utils.Suppressor true # Note: true == @continueBubbling + handler: (event) -> + if @active() then @stopBubblingAndTrue else @continueBubbling -# Suppresses InsertModeTrigger. This is used by various modes (usually via inheritance) to prevent -# unintentionally dropping into insert mode on focusable elements. -class InsertModeBlocker extends Mode - constructor: (options = {}) -> - defaults = - name: "insert-blocker" - # The user knows best; so, if the user clicks on something, the insert-mode blocker gets out of the way. - exitOnClick: true - onClickMode: InsertMode - super extend defaults, options - triggerSuppressor.suppress() - - @push - _name: "mode-#{@id}/bail-on-click" - "click": (event) => - @alwaysContinueBubbling => - # The user knows best; so, if the user clicks on something, the insert-mode blocker gets out of the - # way. + exit: () -> + document.activeElement.blur() if @active() + if @options.permanentInsertMode + # We don't really exit if we're permanently installed. + Mode.updateBadge() + else + super() - exit: -> - super() - # If the element associated with the event is focusable, then, had we not been blocking the trigger, we - # would already have been in insert mode. Now, a click on that element will not generate a new focus - # event, so the insert-mode trigger will not fire. We have to handle this case specially. - # @options.onClickMode specifies the mode to use (by default, insert mode). - if @clickEvent?.target? and DomUtils.isFocusable @clickEvent.target - new @options.onClickMode - targetElement: event.target - triggerSuppressor.unsuppress() + chooseBadge: (badge) -> + badge.badge ||= "I" if @active() root = exports ? window root.InsertMode = InsertMode -root.InsertModeTrigger = InsertModeTrigger -root.InsertModeBlocker = InsertModeBlocker diff --git a/content_scripts/mode_visual.coffee b/content_scripts/mode_visual.coffee index 7b5cc0f6..2580106d 100644 --- a/content_scripts/mode_visual.coffee +++ b/content_scripts/mode_visual.coffee @@ -1,5 +1,5 @@ -class VisualMode extends InsertModeBlocker +class VisualMode extends Mode constructor: (element=null) -> super name: "visual" diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee index 09e19486..f2e0cb2a 100644 --- a/content_scripts/vimium_frontend.coffee +++ b/content_scripts/vimium_frontend.coffee @@ -123,17 +123,12 @@ initializePreDomReady = -> settings.addEventListener("load", LinkHints.init.bind(LinkHints)) settings.load() - # Install normal mode. This is near the bottom of the handler stack, and is never deactivated. + # Install permanent modes and handlers. new NormalMode() - - # Initialize the scroller. The scroller installs a key handler, and this is next on the handler stack, - # immediately above normal mode. Scroller.init settings - - # Install passKeys mode and the insert-mode trigger. These too are permanently on the stack. passKeysMode = new PassKeysMode() - new InsertModeTrigger() - Mode.updateBadge() + new InsertMode + permanentInsertMode: true checkIfEnabledForUrl() @@ -375,7 +370,7 @@ extend window, id: "vimiumInputMarkerContainer" className: "vimiumReset" - new class FocusSelector extends InsertModeBlocker + new class FocusSelector extends Mode constructor: -> super name: "focus-selector" @@ -767,7 +762,7 @@ handleEnterForFindMode = -> document.body.classList.add("vimiumFindMode") settings.set("findModeRawQuery", findModeQuery.rawQuery) -class FindMode extends InsertModeBlocker +class FindMode extends Mode constructor: -> super name: "find" @@ -828,8 +823,10 @@ executeFind = (query, options) -> HUD.hide(true) # ignore the selectionchange event generated by find() document.removeEventListener("selectionchange",restoreDefaultSelectionHighlight, true) - Mode.runIn InsertModeBlocker, -> + handlerId = handlerStack.push + focus: -> handlerStack.stopBubblingAndTrue result = window.find(query, options.caseSensitive, options.backwards, true, false, true, false) + handlerStack.remove setTimeout( -> document.addEventListener("selectionchange", restoreDefaultSelectionHighlight, true) 0) |
