diff options
| author | Jez Ng | 2012-01-19 02:51:43 +0800 |
|---|---|---|
| committer | Jez Ng | 2012-01-26 02:48:00 -0500 |
| commit | ff8ebd2eadb68ca9fb2b75273f03b9c1706fc969 (patch) | |
| tree | 2470f8b9f06e0916dce226f743eb533ec73fd00f | |
| parent | 40963e7b35490de8a8629355a5b26b1e00cd4260 (diff) | |
| download | vimium-ff8ebd2eadb68ca9fb2b75273f03b9c1706fc969.tar.bz2 | |
Favor next / prev links with fewer words.
Also favor exact word matches over inexact ones.
| -rw-r--r-- | vimiumFrontend.js | 70 |
1 files changed, 56 insertions, 14 deletions
diff --git a/vimiumFrontend.js b/vimiumFrontend.js index ea2c33d5..6a3fd698 100644 --- a/vimiumFrontend.js +++ b/vimiumFrontend.js @@ -837,21 +837,65 @@ function getLinkFromSelection() { return null; } +// used by the findAndFollow* functions. +function followLink(link) { + domUtils.simulateClick(link); + // blur the element just in case it already has focus. then when we re-focus it, the browser will scroll + // such that it is visible. + link.blur(); + link.focus(); +} + +/** + * Find and follow the shortest link (shortest == fewest words) which matches any one of a list of strings. + * If there are multiple shortest links, strings are prioritized for exact word matches, followed by their + * position in :linkStrings. Practically speaking, this means we favor 'next page' over 'the next big thing', + * and 'more' over 'nextcompany', even if 'next' occurs before 'more' in :linkStrings. + */ function findAndFollowLink(linkStrings) { - for (i = 0; i < linkStrings.length; i++) { - var hasResults = window.find(linkStrings[i], false, true, true, false, true, false); - if (hasResults) { - var link = getLinkFromSelection(); - if (link) { - domUtils.simulateClick(link); - // blur the element just in case it already has focus. then when we re-focus it, the browser will - // scroll such that it is visible. - link.blur(); - link.focus(); - return true; + var linksXPath = domUtils.makeXPath(["a", "*[@onclick or @role='link']"]); + var links = domUtils.evaluateXPath(linksXPath, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE); + var shortestLinks = []; + var shortestLinkLength = null; + + for (var i = 0, count = links.snapshotLength; i < count; i++) { + var link = links.snapshotItem(i); + var linkMatches = false; + for (var j = 0; j < linkStrings.length; j++) { + if (link.innerText.toLowerCase().indexOf(linkStrings[j]) !== -1) { + linkMatches = true; + break; } } + if (!linkMatches) continue; + + var wordCount = link.innerText.trim().split(/\s+/).length; + if (shortestLinkLength === null || wordCount < shortestLinkLength) { + shortestLinkLength = wordCount; + shortestLinks = [ link ]; + } + else if (wordCount === shortestLinkLength) { + shortestLinks.push(link); + } } + + for (var i = 0; i < linkStrings.length; i++) + for (var j = 0; j < shortestLinks.length; j++) { + var exactWordRegex = new RegExp("\\b" + linkStrings[i] + "\\b", "i"); + if (exactWordRegex.test(shortestLinks[j].innerText)) { + followLink(shortestLinks[j]); + return true; + } + } + + for (var i = 0; i < linkStrings.length; i++) + for (var j = 0; j < shortestLinks.length; j++) { + if (shortestLinks[j].innerText.toLowerCase().indexOf(linkStrings[i]) !== -1) { + followLink(shortestLinks[j]); + return true; + } + } + return false; } @@ -861,9 +905,7 @@ function findAndFollowRel(value) { var elements = document.getElementsByTagName(relTags[i]); for (j = 0; j < elements.length; j++) { if (elements[j].hasAttribute('rel') && elements[j].rel == value) { - domUtils.simulateClick(elements[j]); - link.blur(); - link.focus(); + followLink(elements[j]); return true; } } |
