aboutsummaryrefslogtreecommitdiffstats
path: root/content_scripts
diff options
context:
space:
mode:
Diffstat (limited to 'content_scripts')
-rw-r--r--content_scripts/link_hints.coffee1
-rw-r--r--content_scripts/mode.coffee15
-rw-r--r--content_scripts/mode_find.coffee21
-rw-r--r--content_scripts/mode_insert.coffee38
-rw-r--r--content_scripts/vimium_frontend.coffee27
5 files changed, 52 insertions, 50 deletions
diff --git a/content_scripts/link_hints.coffee b/content_scripts/link_hints.coffee
index 3c8240c0..5e41cbbb 100644
--- a/content_scripts/link_hints.coffee
+++ b/content_scripts/link_hints.coffee
@@ -10,7 +10,6 @@
#
# The "name" property below is a short-form name to appear in the link-hints mode name. Debugging only. The
# key appears in the mode's badge.
-# NOTE(smblott) The use of keys in badges is experimental. It may prove too noisy.
#
OPEN_IN_CURRENT_TAB = { name: "curr-tab", key: "" }
OPEN_IN_NEW_BG_TAB = { name: "bg-tab", key: "B" }
diff --git a/content_scripts/mode.coffee b/content_scripts/mode.coffee
index 2ff71ca8..a74acfed 100644
--- a/content_scripts/mode.coffee
+++ b/content_scripts/mode.coffee
@@ -24,8 +24,10 @@
# responds to "focus" events, then push an additional handler:
# @push
# "focus": (event) => ....
-# Any such handlers are removed when the mode is deactivated.
+# Such handlers are removed when the mode is deactivated.
#
+# The following events can be handled:
+# keydown, keypress, keyup, click, focus and blur
# Debug only.
count = 0
@@ -85,8 +87,8 @@ class Mode
"click": (event) => @alwaysContinueBubbling => @exit event
# Some modes are singletons: there may be at most one instance active at any time. A mode is a singleton
- # if @options.singleton is truthy. The value of @options.singleton should be the key the which is
- # intended to be unique. New instances deactivate existing instances with the same key.
+ # if @options.singleton is truthy. The value of @options.singleton should be the key which is intended to
+ # be unique. New instances deactivate existing instances with the same key.
if @options.singleton
do =>
singletons = Mode.singletons ||= {}
@@ -99,7 +101,7 @@ class Mode
# If @options.trackState is truthy, then the mode mainatins the current state in @enabled and @passKeys,
# and calls @registerStateChange() (if defined) whenever the state changes. The mode also tracks the
- # keyQueue in @keyQueue.
+ # current keyQueue in @keyQueue.
if @options.trackState
@enabled = false
@passKeys = ""
@@ -115,7 +117,7 @@ class Mode
Mode.modes.push @
Mode.updateBadge()
- @logStack()
+ @logModes()
# End of Mode constructor.
push: (handlers) ->
@@ -124,7 +126,6 @@ class Mode
unshift: (handlers) ->
handlers._name ||= "mode-#{@id}"
- handlers._name += "/unshifted"
@handlers.push handlerStack.unshift handlers
onExit: (handler) ->
@@ -160,7 +161,7 @@ class Mode
badge: badge.badge
# Debugging routines.
- logStack: ->
+ logModes: ->
if @debug
@log "active modes (top to bottom):"
@log " ", mode.id for mode in Mode.modes[..].reverse()
diff --git a/content_scripts/mode_find.coffee b/content_scripts/mode_find.coffee
index 35352277..dff63949 100644
--- a/content_scripts/mode_find.coffee
+++ b/content_scripts/mode_find.coffee
@@ -33,6 +33,8 @@ class PostFindMode extends SuppressPrintable
super
name: "post-find"
+ # We show a "?" badge, but only while an Escape activates insert mode.
+ badge: "?"
singleton: PostFindMode
exitOnBlur: element
exitOnClick: true
@@ -42,20 +44,23 @@ class PostFindMode extends SuppressPrintable
# If the very-next keydown is Escape, then exit immediately, thereby passing subsequent keys to the
# underlying insert-mode instance.
- self = @
@push
_name: "mode-#{@id}/handle-escape"
- keydown: (event) ->
+ keydown: (event) =>
if KeyboardUtils.isEscape event
DomUtils.suppressKeyupAfterEscape handlerStack
- self.exit()
- false # Suppress event.
+ @exit()
+ @suppressEvent
else
- @remove()
- true # Continue bubbling.
+ handlerStack.remove()
+ @badge = ""
+ Mode.updateBadge()
+ @continueBubbling
- # If PostFindMode is active, then we suppress the "I" badge from insert mode.
- updateBadge: (badge) -> InsertMode.suppressEvent badge # Always truthy.
+ updateBadge: (badge) ->
+ badge.badge ||= @badge
+ # Suppress the "I" badge from insert mode.
+ InsertMode.suppressEvent badge # Always truthy.
root = exports ? window
root.PostFindMode = PostFindMode
diff --git a/content_scripts/mode_insert.coffee b/content_scripts/mode_insert.coffee
index 123c72be..196f910b 100644
--- a/content_scripts/mode_insert.coffee
+++ b/content_scripts/mode_insert.coffee
@@ -11,11 +11,18 @@ class InsertMode extends Mode
# If truthy, then we were activated by the user (with "i").
@global = options.global
+ handleKeyEvent = (event) =>
+ return @continueBubbling unless @isActive event
+ return @stopBubblingAndTrue unless event.type == 'keydown' and KeyboardUtils.isEscape event
+ DomUtils.suppressKeyupAfterEscape handlerStack
+ @exit event, event.srcElement
+ @suppressEvent
+
defaults =
name: "insert"
- keydown: (event) => @handleKeydownEvent event
- keypress: (event) => @handleKeyEvent event
- keyup: (event) => @handleKeyEvent event
+ keypress: handleKeyEvent
+ keyup: handleKeyEvent
+ keydown: handleKeyEvent
super extend defaults, options
@@ -32,11 +39,10 @@ class InsertMode extends Mode
# 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 target == @insertModeLock
+ @exit event, target if @insertModeLock and target == @insertModeLock
"focus": (event) => @alwaysContinueBubbling =>
if @insertModeLock != event.target and DomUtils.isFocusable event.target
- @insertModeLock = event.target
- Mode.updateBadge()
+ @activateOnElement event.target
isActive: (event) ->
return false if event == InsertMode.suppressedEvent
@@ -44,24 +50,18 @@ class InsertMode extends Mode
# 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.
- if @insertModeLock != document.activeElement and document.activeElement?.isContentEditable
- @insertModeLock = document.activeElement
- Mode.updateBadge()
+ @activateOnElement document.activeElement if document.activeElement?.isContentEditable
@insertModeLock != null
- handleKeydownEvent: (event) ->
- return @continueBubbling unless @isActive event
- return @stopBubblingAndTrue unless KeyboardUtils.isEscape event
- DomUtils.suppressKeyupAfterEscape handlerStack
- @exit event, event.srcElement
- @suppressEvent
-
- # Handles keypress and keyup events.
- handleKeyEvent: (event) ->
- if @isActive event then @stopBubblingAndTrue else @continueBubbling
+ activateOnElement: (element) ->
+ @log "#{@id}: activating (permanent)" if @debug and @permanent
+ @insertModeLock = element
+ Mode.updateBadge()
exit: (_, target) ->
+ # Note: target == undefined, here, is required only for tests.
if (target and target == @insertModeLock) or @global or target == undefined
+ @log "#{@id}: deactivating (permanent)" if @debug and @permanent and @insertModeLock
@insertModeLock = null
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.
diff --git a/content_scripts/vimium_frontend.coffee b/content_scripts/vimium_frontend.coffee
index 0a034e28..6a26a133 100644
--- a/content_scripts/vimium_frontend.coffee
+++ b/content_scripts/vimium_frontend.coffee
@@ -117,10 +117,11 @@ initializePreDomReady = ->
keypress: (event) => onKeypress.call @, event
keyup: (event) => onKeyup.call @, event
- # Install the permanent modes and handlers. The permanent insert mode operates only when focusable/editable
- # elements are active.
+ Scroller.init settings
+
+ # Install the permanent modes. The permanently-installed insert mode tracks focus/blur events, and
+ # activates/deactivates itself accordingly.
new NormalMode
- Scroller.init settings
new PassKeysMode
new InsertMode
@@ -242,8 +243,6 @@ enterInsertModeIfElementIsFocused = ->
enterInsertModeWithoutShowingIndicator(document.activeElement)
onDOMActivate = (event) -> handlerStack.bubbleEvent 'DOMActivate', event
-onFocus = (event) -> handlerStack.bubbleEvent 'focus', event
-onBlur = (event) -> handlerStack.bubbleEvent 'blur', event
executePageCommand = (request) ->
return unless frameId == request.frameId
@@ -326,8 +325,7 @@ extend window,
HUD.showForDuration("Yanked URL", 1000)
enterInsertMode: ->
- new InsertMode
- global: true
+ new InsertMode global: true
enterVisualMode: =>
new VisualMode()
@@ -804,17 +802,16 @@ executeFind = (query, options) ->
-> document.addEventListener("selectionchange", restoreDefaultSelectionHighlight, true)
0)
+ # We are either in normal mode ("n"), or find mode ("/"). We are not in insert mode. Nevertheless, if a
+ # previous find landed in an editable element, then that element may still be activated. In this case, we
+ # don't want to leave it behind (see #1412).
+ if document.activeElement and DomUtils.isEditable document.activeElement
+ if not DomUtils.isSelected document.activeElement
+ document.activeElement.blur()
+
# we need to save the anchor node here because <esc> seems to nullify it, regardless of whether we do
# preventDefault()
findModeAnchorNode = document.getSelection().anchorNode
-
- # TODO(smblott). Disabled. This is the wrong test. Should be reinstated when we have the right test, which
- # looks like it should be "isSelected" from #1431.
- # # If the anchor node not a descendent of the active element, then blur the active element. We don't want to
- # # leave behind an inappropriate active element. This fixes #1412.
- # if document.activeElement and not DomUtils.isDOMDescendant document.activeElement, findModeAnchorNode
- # document.activeElement.blur()
-
result
restoreDefaultSelectionHighlight = -> document.body.classList.remove("vimiumFindMode")