diff options
| author | Stephen Blott | 2016-04-08 13:36:24 +0100 | 
|---|---|---|
| committer | Stephen Blott | 2016-04-08 13:36:24 +0100 | 
| commit | 9d7351903d0148373a2ad4c06d006e8ee0613be2 (patch) | |
| tree | 0bd0437e687b04412cca2e49e3789a053fbac84d | |
| parent | 5704688e2ab7effef701f2ac5282b3bd4e0c53c7 (diff) | |
| parent | 77ea849b0849219550c7a8caa47698a35ed2fdab (diff) | |
| download | vimium-9d7351903d0148373a2ad4c06d006e8ee0613be2.tar.bz2 | |
Merge pull request #2088 from smblott-github/filtered-hints-better-typed-text-matching
Filtered hints: better typed text handling.
| -rw-r--r-- | content_scripts/link_hints.coffee | 54 | ||||
| -rw-r--r-- | tests/dom_tests/dom_tests.coffee | 12 | 
2 files changed, 46 insertions, 20 deletions
| diff --git a/content_scripts/link_hints.coffee b/content_scripts/link_hints.coffee index 70c51eac..c012edba 100644 --- a/content_scripts/link_hints.coffee +++ b/content_scripts/link_hints.coffee @@ -13,22 +13,22 @@  isMac = KeyboardUtils.platform == "Mac"  OPEN_IN_CURRENT_TAB =    name: "curr-tab" -  indicator: "Open link in current tab." +  indicator: "Open link in current tab"  OPEN_IN_NEW_BG_TAB =    name: "bg-tab" -  indicator: "Open link in new tab." +  indicator: "Open link in new tab"    clickModifiers: metaKey: isMac, ctrlKey: not isMac  OPEN_IN_NEW_FG_TAB =    name: "fg-tab" -  indicator: "Open link in new tab and switch to it." +  indicator: "Open link in new tab and switch to it"    clickModifiers: shiftKey: true, metaKey: isMac, ctrlKey: not isMac  OPEN_WITH_QUEUE =    name: "queue" -  indicator: "Open multiple links in new tabs." +  indicator: "Open multiple links in new tabs"    clickModifiers: metaKey: isMac, ctrlKey: not isMac  COPY_LINK_URL =    name: "link" -  indicator: "Copy link URL to Clipboard." +  indicator: "Copy link URL to Clipboard"    linkActivator: (link) ->      if link.href?        chrome.runtime.sendMessage handler: "copyToClipboard", data: link.href @@ -39,11 +39,11 @@ COPY_LINK_URL =        HUD.showForDuration "No link to yank.", 2000  OPEN_INCOGNITO =    name: "incognito" -  indicator: "Open link in incognito window." +  indicator: "Open link in incognito window"    linkActivator: (link) -> chrome.runtime.sendMessage handler: 'openUrlInIncognito', url: link.href  DOWNLOAD_LINK_URL =    name: "download" -  indicator: "Download link URL." +  indicator: "Download link URL"    clickModifiers: altKey: true, ctrlKey: false, metaKey: false  availableModes = [OPEN_IN_CURRENT_TAB, OPEN_IN_NEW_BG_TAB, OPEN_IN_NEW_FG_TAB, OPEN_WITH_QUEUE, COPY_LINK_URL, @@ -138,7 +138,7 @@ class LinkHintsMode    # A count of the number of Tab presses since the last non-Tab keyboard event.    tabCount: 0 -  constructor: (hintDescriptors, mode = OPEN_IN_CURRENT_TAB) -> +  constructor: (hintDescriptors, @mode = OPEN_IN_CURRENT_TAB) ->      # We need documentElement to be ready in order to append links.      return unless document.documentElement @@ -153,7 +153,7 @@ class LinkHintsMode      @markerMatcher.fillInMarkers @hintMarkers      @hintMode = new Mode -      name: "hint/#{mode.name}" +      name: "hint/#{@mode.name}"        indicator: false        singleton: "link-hints-mode"        passInitialKeyupEvents: true @@ -164,22 +164,28 @@ class LinkHintsMode        keydown: @onKeyDownInMode.bind this        keypress: @onKeyPressInMode.bind this +    @setIndicator()      @hintMode.onExit (event) =>        if event?.type == "click" or (event?.type == "keydown" and          (KeyboardUtils.isEscape(event) or event.keyCode in [keyCodes.backspace, keyCodes.deleteKey]))            HintCoordinator.sendMessage "exit", isSuccess: false -    @setOpenLinkMode mode, false -      # Note(philc): Append these markers as top level children instead of as child nodes to the link itself,      # because some clickable elements cannot contain children, e.g. submit buttons.      @hintMarkerContainingDiv = DomUtils.addElementList (marker for marker in @hintMarkers when marker.isLocalMarker),        id: "vimiumHintMarkerContainer", className: "vimiumReset"    setOpenLinkMode: (@mode, shouldPropagateToOtherFrames = true) -> -    @hintMode.setIndicator @mode.indicator if windowIsFocused()      if shouldPropagateToOtherFrames        HintCoordinator.sendMessage "setOpenLinkMode", modeIndex: availableModes.indexOf @mode +    else +      @setIndicator() + +  setIndicator: -> +    if windowIsFocused() +      typedCharacters = @markerMatcher.linkTextKeystrokeQueue?.join("") ? "" +      indicator = @mode.indicator + (if typedCharacters then ": \"#{typedCharacters}\"" else "") + "." +      @hintMode.setIndicator indicator    #    # Creates a link marker for the given link. @@ -262,7 +268,7 @@ class LinkHintsMode      else        return -    # We've handled the event, so suppress it. +    # We've handled the event, so suppress it and update the mode indicator.      DomUtils.suppressEvent event    # Handles normal input. @@ -293,6 +299,8 @@ class LinkHintsMode        @hideMarker marker for marker in @hintMarkers        @showMarker matched, @markerMatcher.hintKeystrokeQueue.length for matched in linksMatched +    @setIndicator() +    # When only one hint remains, activate it in the appropriate way.  The current frame may or may not contain    # the matched link, and may or may not have the focus.  The resulting four cases are accounted for here by    # selectively pushing the appropriate HintCoordinator.onExit handlers. @@ -469,15 +477,21 @@ class FilterHints      linkSearchString = @linkTextKeystrokeQueue.join("").trim().toLowerCase()      do (scoreFunction = @scoreLinkHint linkSearchString) ->        linkMarker.score = scoreFunction linkMarker for linkMarker in hintMarkers -    hintMarkers = hintMarkers[..].sort (a,b) -> +    matchingHintMarkers = hintMarkers[..].sort (a,b) ->        if b.score == a.score then b.stableSortCount - a.stableSortCount else b.score - a.score -    linkHintNumber = 1 -    for linkMarker in hintMarkers -      continue unless 0 < linkMarker.score -      linkMarker.hintString = @generateHintString linkHintNumber++ -      @renderMarker linkMarker -      linkMarker +    matchingHintMarkers = (linkMarker for linkMarker in matchingHintMarkers when 0 < linkMarker.score) + +    if matchingHintMarkers.length == 0 and @hintKeystrokeQueue.length == 0 and 0 < @linkTextKeystrokeQueue.length +      # We don't accept typed text which doesn't match any hints. +      @linkTextKeystrokeQueue.pop() +      @filterLinkHints hintMarkers +    else +      linkHintNumber = 1 +      for linkMarker in matchingHintMarkers +        linkMarker.hintString = @generateHintString linkHintNumber++ +        @renderMarker linkMarker +        linkMarker    # Assign a score to a filter match (higher is better).  We assign a higher score for matches at the start of    # a word, and a considerably higher score still for matches which are whole words. diff --git a/tests/dom_tests/dom_tests.coffee b/tests/dom_tests/dom_tests.coffee index 76c09f13..75cc5da7 100644 --- a/tests/dom_tests/dom_tests.coffee +++ b/tests/dom_tests/dom_tests.coffee @@ -284,6 +284,18 @@ context "Filtered link hints",        sendKeyboardEvent "A"        assert.equal "1", hintMarkers[3].hintString +    # This test is the same as above, but with an extra non-matching character. +    should "narrow the hints and ignore typing mistakes", -> +      hintMarkers = getHintMarkers() +      sendKeyboardEvent "T" +      sendKeyboardEvent "R" +      sendKeyboardEvent "X" +      assert.equal "none", hintMarkers[0].style.display +      assert.equal "3", hintMarkers[1].hintString +      assert.equal "", hintMarkers[1].style.display +      sendKeyboardEvent "A" +      assert.equal "1", hintMarkers[3].hintString +    context "Image hints",      setup -> | 
