diff options
Diffstat (limited to 'content_scripts/mode_find.coffee')
| -rw-r--r-- | content_scripts/mode_find.coffee | 79 |
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? |
