aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--content_scripts/link_hints.coffee2
-rw-r--r--content_scripts/mode.coffee7
-rw-r--r--content_scripts/mode_find.coffee5
-rw-r--r--content_scripts/mode_insert.coffee105
-rw-r--r--content_scripts/mode_visual.coffee2
-rw-r--r--content_scripts/vimium_frontend.coffee19
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)