aboutsummaryrefslogtreecommitdiffstats
path: root/content_scripts/mode_find.coffee
diff options
context:
space:
mode:
Diffstat (limited to 'content_scripts/mode_find.coffee')
-rw-r--r--content_scripts/mode_find.coffee79
1 files changed, 68 insertions, 11 deletions
diff --git a/content_scripts/mode_find.coffee b/content_scripts/mode_find.coffee
index 8621edf8..f19b5db4 100644
--- a/content_scripts/mode_find.coffee
+++ b/content_scripts/mode_find.coffee
@@ -6,7 +6,7 @@ class SuppressPrintable extends Mode
constructor: (options) ->
super options
handler = (event) => if KeyboardUtils.isPrintable event then @suppressEvent else @continueBubbling
- type = document.getSelection().type
+ type = DomUtils.getSelectionType()
# We use unshift here, so we see events after normal mode, so we only see unmapped keys.
@unshift
@@ -16,7 +16,7 @@ class SuppressPrintable extends Mode
keyup: (event) =>
# If the selection type has changed (usually, no longer "Range"), then the user is interacting with
# the input element, so we get out of the way. See discussion of option 5c from #1415.
- if document.getSelection().type != type then @exit() else handler event
+ @exit() if DomUtils.getSelectionType() != type
# When we use find, the selection/focus can land in a focusable/editable element. In this situation, special
# considerations apply. We implement three special cases:
@@ -47,7 +47,6 @@ class PostFindMode extends SuppressPrintable
_name: "mode-#{@id}/handle-escape"
keydown: (event) =>
if KeyboardUtils.isEscape event
- DomUtils.suppressKeyupAfterEscape handlerStack
@exit()
@suppressEvent
else
@@ -80,15 +79,16 @@ class FindMode extends Mode
exit: (event) ->
super()
- handleEscapeForFindMode() if event
+ FindMode.handleEscape() if event
restoreSelection: ->
+ return unless @initialRange
range = @initialRange
selection = getSelection()
selection.removeAllRanges()
selection.addRange range
- findInPlace: (query) ->
+ findInPlace: (query, options) ->
# If requested, restore the scroll position (so that failed searches leave the scroll position unchanged).
@checkReturnToViewPort()
FindMode.updateQuery query
@@ -96,7 +96,7 @@ class FindMode extends Mode
# match as the user adds matching characters, or removes previously-matched characters. See #1434.
@restoreSelection()
query = if FindMode.query.isRegex then FindMode.getNextQueryFromRegexMatches(0) else FindMode.query.parsedQuery
- FindMode.query.hasResults = FindMode.execute query
+ FindMode.query.hasResults = FindMode.execute query, options
@updateQuery: (query) ->
@query.rawQuery = query
@@ -179,7 +179,13 @@ class FindMode extends Mode
# ignore the selectionchange event generated by find()
document.removeEventListener("selectionchange", @restoreDefaultSelectionHighlight, true)
- result = window.find(query, options.caseSensitive, options.backwards, true, false, true, false)
+ try
+ result = window.find(query, options.caseSensitive, options.backwards, true, false, true, false)
+ catch # Failed searches throw on Firefox.
+
+ # window.find focuses the |window| that it is called on. This gives us an opportunity to (re-)focus
+ # another element/window, if that isn't the behaviour we want.
+ options.postFindFocus?.focus()
if options.colorSelection
setTimeout(
@@ -194,22 +200,73 @@ class FindMode extends Mode
result
- @restoreDefaultSelectionHighlight: -> document.body.classList.remove("vimiumFindMode")
+ @restoreDefaultSelectionHighlight: forTrusted -> document.body.classList.remove("vimiumFindMode")
+
+ # The user has found what they're looking for and is finished searching. We enter insert mode, if possible.
+ @handleEscape: ->
+ document.body.classList.remove("vimiumFindMode")
+ # Removing the class does not re-color existing selections. we recreate the current selection so it reverts
+ # back to the default color.
+ selection = window.getSelection()
+ unless selection.isCollapsed
+ range = window.getSelection().getRangeAt(0)
+ window.getSelection().removeAllRanges()
+ window.getSelection().addRange(range)
+ focusFoundLink() || selectFoundInputElement()
+
+ # Save the query so the user can do further searches with it.
+ @handleEnter: ->
+ focusFoundLink()
+ document.body.classList.add("vimiumFindMode")
+ FindMode.saveQuery()
+
+ @findNext: (backwards) ->
+ Marks.setPreviousPosition()
+ FindMode.query.hasResults = FindMode.execute null, {backwards}
+
+ if FindMode.query.hasResults
+ focusFoundLink()
+ new PostFindMode()
+ else
+ HUD.showForDuration("No matches for '#{FindMode.query.rawQuery}'", 1000)
checkReturnToViewPort: ->
window.scrollTo @scrollX, @scrollY if @options.returnToViewport
getCurrentRange = ->
selection = getSelection()
- if selection.type == "None"
+ if DomUtils.getSelectionType(selection) == "None"
range = document.createRange()
range.setStart document.body, 0
range.setEnd document.body, 0
range
else
- selection.collapseToStart() if selection.type == "Range"
+ selection.collapseToStart() if DomUtils.getSelectionType(selection) == "Range"
selection.getRangeAt 0
-root = exports ? window
+getLinkFromSelection = ->
+ node = window.getSelection().anchorNode
+ while (node && node != document.body)
+ return node if (node.nodeName.toLowerCase() == "a")
+ node = node.parentNode
+ null
+
+focusFoundLink = ->
+ if (FindMode.query.hasResults)
+ link = getLinkFromSelection()
+ link.focus() if link
+
+selectFoundInputElement = ->
+ # Since the last focused element might not be the one currently pointed to by find (e.g. the current one
+ # might be disabled and therefore unable to receive focus), we use the approximate heuristic of checking
+ # that the last anchor node is an ancestor of our element.
+ findModeAnchorNode = document.getSelection().anchorNode
+ if (FindMode.query.hasResults && document.activeElement &&
+ DomUtils.isSelectable(document.activeElement) &&
+ DomUtils.isDOMDescendant(findModeAnchorNode, document.activeElement))
+ DomUtils.simulateSelect(document.activeElement)
+
+root = exports ? (window.root ?= {})
root.PostFindMode = PostFindMode
root.FindMode = FindMode
+extend window, root unless exports?