aboutsummaryrefslogtreecommitdiffstats
path: root/content_scripts
diff options
context:
space:
mode:
authorStephen Blott2015-01-09 10:51:19 +0000
committerStephen Blott2015-01-09 11:22:04 +0000
commit2e6eb69e99f29acc432b750501168d2a15116e6f (patch)
tree345ccca18c55aa9893f94e09b6236a8f94b15d88 /content_scripts
parent5d653d8fbab350ae7737d6f91a93df10477b172d (diff)
downloadvimium-2e6eb69e99f29acc432b750501168d2a15116e6f.tar.bz2
Modes; various changes...
- Refactor insert-mode constructor. - Gneralise focusInput.
Diffstat (limited to 'content_scripts')
-rw-r--r--content_scripts/mode_find.coffee3
-rw-r--r--content_scripts/mode_insert.coffee42
-rw-r--r--content_scripts/vimium_frontend.coffee19
3 files changed, 41 insertions, 23 deletions
diff --git a/content_scripts/mode_find.coffee b/content_scripts/mode_find.coffee
index 40245d14..3b9f951e 100644
--- a/content_scripts/mode_find.coffee
+++ b/content_scripts/mode_find.coffee
@@ -35,7 +35,8 @@ class PostFindMode extends InsertModeBlocker
keydown: (event) ->
if element == document.activeElement and KeyboardUtils.isEscape event
self.exit()
- new InsertMode element
+ new InsertMode
+ targetElement: element
DomUtils.suppressKeyupAfterEscape handlerStack
return false
@remove()
diff --git a/content_scripts/mode_insert.coffee b/content_scripts/mode_insert.coffee
index bfc79aa9..c0a61d31 100644
--- a/content_scripts/mode_insert.coffee
+++ b/content_scripts/mode_insert.coffee
@@ -1,8 +1,8 @@
# This mode is installed when insert mode is active.
class InsertMode extends Mode
- constructor: (@insertModeLock = null) ->
- super
+ constructor: (options = {}) ->
+ defaults =
name: "insert"
badge: "I"
singleton: InsertMode
@@ -10,18 +10,23 @@ class InsertMode extends Mode
keypress: (event) => @stopBubblingAndTrue
keyup: (event) => @stopBubblingAndTrue
exitOnEscape: true
- exitOnBlur: @insertModeLock
+ blurOnExit: true
+
+ options = extend defaults, options
+ options.exitOnBlur = options.targetElement || null
+ super options
exit: (event = null) ->
super()
- 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()
+ 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.
@@ -39,18 +44,21 @@ class InsertModeTrigger extends Mode
# 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
+ new InsertMode
+ targetElement: document.activeElement
@stopBubblingAndTrue
@push
focus: (event) =>
triggerSuppressor.unlessSuppressed =>
return unless DomUtils.isFocusable event.target
- new InsertMode event.target
+ new InsertMode
+ targetElement: event.target
# We may already have focussed an input, so check.
if document.activeElement and DomUtils.isEditable document.activeElement
- new InsertMode document.activeElement
+ new InsertMode
+ targetElement: document.activeElement
# Used by InsertModeBlocker to suppress InsertModeTrigger; see below.
triggerSuppressor = new Utils.Suppressor true
@@ -61,6 +69,7 @@ class InsertModeBlocker extends Mode
constructor: (options = {}) ->
triggerSuppressor.suppress()
options.name ||= "insert-blocker"
+ options.onClickMode ||= InsertMode
super options
@onExit -> triggerSuppressor.unsuppress()
@@ -72,10 +81,11 @@ class InsertModeBlocker extends Mode
# However, there's a corner case. If the active element is focusable, then we would have been in
# insert mode had we not been blocking the trigger. Now, clicking on the element will not generate
# a new focus event, so the insert-mode trigger will not fire. We have to handle this case
- # specially.
+ # specially. @options.onClickMode is the mode to use.
if document.activeElement and
event.target == document.activeElement and DomUtils.isEditable document.activeElement
- new InsertMode document.activeElement
+ new @options.onClickMode
+ targetElement: document.activeElement
root = exports ? window
root.InsertMode = InsertMode
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index 97d4cd73..99fe4990 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -6,7 +6,7 @@
#
passKeysMode = null
-insertModeLock = null
+targetElement = null
findMode = false
findModeQuery = { rawQuery: "", matchCount: 0 }
findModeQueryHasResults = false
@@ -342,10 +342,11 @@ extend window,
enterVisualMode: =>
new VisualMode()
- focusInput: (count) ->
+ focusInput: (count, targetMode = InsertMode) ->
# Focus the first input element on the page, and create overlays to highlight all the input elements, with
# the currently-focused element highlighted specially. Tabbing will shift focus to the next input element.
# Pressing any other key will remove the overlays and the special tab behavior.
+ # targetMode is the mode we want to enter.
resultSet = DomUtils.evaluateXPath(textInputXPath, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE)
visibleInputs =
for i in [0...resultSet.snapshotLength] by 1
@@ -382,6 +383,8 @@ extend window,
# Be a singleton. It doesn't make any sense to have two instances active at the same time; and that
# shouldn't happen anyway. However, it does no harm to enforce it.
singleton: FocusSelector
+ targetMode: targetMode
+ onClickMode: targetMode # For InsertModeBlocker super-class.
keydown: (event) =>
if event.keyCode == KeyboardUtils.keyCodes.tab
hints[selectedInputIndex].classList.remove 'internalVimiumSelectedInputHint'
@@ -404,8 +407,12 @@ extend window,
super()
DomUtils.removeElement hintContainingDiv
if document.activeElement == visibleInputs[selectedInputIndex].element
- # InsertModeBlocker handles the "click" case.
- new InsertMode document.activeElement unless event?.type == "click"
+ # The InsertModeBlocker super-class handles the "click" case.
+ unless event?.type == "click"
+ # In the legacy (and probably common) case, we're entering insert mode here. However, it could be
+ # some other mode.
+ new @options.targetMode
+ targetElement: document.activeElement
# Decide whether this keyChar should be passed to the underlying page.
# Keystrokes are *never* considered passKeys if the keyQueue is not empty. So, for example, if 't' is a
@@ -634,8 +641,8 @@ isEditable = (target) ->
#
# We cannot count on 'focus' and 'blur' events to happen sequentially. For example, if blurring element A
# causes element B to come into focus, we may get "B focus" before "A blur". Thus we only leave insert mode
-# when the last editable element that came into focus -- which insertModeLock points to -- has been blurred.
-# If insert mode is entered manually (via pressing 'i'), then we set insertModeLock to 'undefined', and only
+# when the last editable element that came into focus -- which targetElement points to -- has been blurred.
+# If insert mode is entered manually (via pressing 'i'), then we set targetElement to 'undefined', and only
# leave insert mode when the user presses <ESC>.
# Note. This returns the truthiness of target, which is required by isInsertMode.
#