From The Compiler, 6 Years ago, written in JavaScript.
Embed
  1. // Generated by CoffeeScript 1.6.3
  2. (function() {
  3.   var DomUtils, findAndFollowLink, findAndFollowRel, followLink, root;
  4.  
  5.   DomUtils = {
  6.     makeXPath: function(elementArray) {
  7.       var i, xpath;
  8.       xpath = [];
  9.       for (i in elementArray) {
  10.         xpath.push("//" + elementArray[i], "//xhtml:" + elementArray[i]);
  11.       }
  12.       return xpath.join(" | ");
  13.     },
  14.     evaluateXPath: function(xpath, resultType) {
  15.       var namespaceResolver;
  16.       namespaceResolver = function(namespace) {
  17.         if (namespace === "xhtml") {
  18.           return "http://www.w3.org/1999/xhtml";
  19.         } else {
  20.           return null;
  21.         }
  22.       };
  23.       return document.evaluate(xpath, document.documentElement, namespaceResolver, resultType, null);
  24.     },
  25.     simulateClick: function(element, modifiers) {
  26.       var event, eventSequence, mouseEvent, _i, _len, _results;
  27.       modifiers || (modifiers = {});
  28.       eventSequence = ["mouseover", "mousedown", "mouseup", "click"];
  29.       _results = [];
  30.       for (_i = 0, _len = eventSequence.length; _i < _len; _i++) {
  31.         event = eventSequence[_i];
  32.         mouseEvent = document.createEvent("MouseEvents");
  33.         mouseEvent.initMouseEvent(event, true, true, window, 1, 0, 0, 0, 0, modifiers.ctrlKey, false, false, modifiers.metaKey, 0, null);
  34.         _results.push(element.dispatchEvent(mouseEvent));
  35.       }
  36.       return _results;
  37.     }
  38.   };
  39.  
  40.   root = typeof exports !== "undefined" && exports !== null ? exports : window;
  41.  
  42.   root.DomUtils = DomUtils;
  43.  
  44.   window.goPrevious = function() {
  45.     var previousPatterns, previousStrings;
  46.     previousPatterns = settings.get("previousPatterns") || "";
  47.     previousStrings = previousPatterns.split(",").filter(function(s) {
  48.       return s.length;
  49.     });
  50.     return findAndFollowRel("prev") || findAndFollowLink(previousStrings);
  51.   };
  52.  
  53.   window.goNext = function() {
  54.     var nextPatterns, nextStrings;
  55.     nextPatterns = settings.get("nextPatterns") || "";
  56.     nextStrings = nextPatterns.split(",").filter(function(s) {
  57.       return s.length;
  58.     });
  59.     return findAndFollowRel("next") || findAndFollowLink(nextStrings);
  60.   };
  61.  
  62.   findAndFollowRel = function(value) {
  63.     var element, elements, relTags, tag, _i, _j, _len, _len1;
  64.     relTags = ["link", "a", "area"];
  65.     for (_i = 0, _len = relTags.length; _i < _len; _i++) {
  66.       tag = relTags[_i];
  67.       elements = document.getElementsByTagName(tag);
  68.       for (_j = 0, _len1 = elements.length; _j < _len1; _j++) {
  69.         element = elements[_j];
  70.         if (element.hasAttribute("rel") && element.rel === value) {
  71.           followLink(element);
  72.           return true;
  73.         }
  74.       }
  75.     }
  76.   };
  77.  
  78.   followLink = function(linkElement) {
  79.     if (linkElement.nodeName.toLowerCase() === "link") {
  80.       return window.location.href = linkElement.href;
  81.     } else {
  82.       linkElement.scrollIntoView();
  83.       linkElement.focus();
  84.       return DomUtils.simulateClick(linkElement);
  85.     }
  86.   };
  87.  
  88.   findAndFollowLink = function(linkStrings) {
  89.     var boundingClientRect, candidateLink, candidateLinks, computedStyle, exactWordRegex, i, link, linkMatches, linkString, links, linksXPath, _i, _j, _k, _l, _len, _len1, _len2, _len3, _m, _ref;
  90.     linksXPath = DomUtils.makeXPath(["a", "*[@onclick or @role='link' or contains(@class, 'button')]"]);
  91.     links = DomUtils.evaluateXPath(linksXPath, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);
  92.     candidateLinks = [];
  93.     for (i = _i = _ref = links.snapshotLength - 1; _i >= 0; i = _i += -1) {
  94.       link = links.snapshotItem(i);
  95.       boundingClientRect = link.getBoundingClientRect();
  96.       if (boundingClientRect.width === 0 || boundingClientRect.height === 0) {
  97.         continue;
  98.       }
  99.       computedStyle = window.getComputedStyle(link, null);
  100.       if (computedStyle.getPropertyValue("visibility") !== "visible" || computedStyle.getPropertyValue("display") === "none") {
  101.         continue;
  102.       }
  103.       linkMatches = false;
  104.       for (_j = 0, _len = linkStrings.length; _j < _len; _j++) {
  105.         linkString = linkStrings[_j];
  106.         if (link.innerText.toLowerCase().indexOf(linkString) !== -1) {
  107.           linkMatches = true;
  108.           break;
  109.         }
  110.       }
  111.       if (!linkMatches) {
  112.         continue;
  113.       }
  114.       candidateLinks.push(link);
  115.     }
  116.     if (candidateLinks.length === 0) {
  117.       return;
  118.     }
  119.     for (_k = 0, _len1 = candidateLinks.length; _k < _len1; _k++) {
  120.       link = candidateLinks[_k];
  121.       link.wordCount = link.innerText.trim().split(/\s+/).length;
  122.     }
  123.     candidateLinks.forEach(function(a, i) {
  124.       return a.originalIndex = i;
  125.     });
  126.     candidateLinks = candidateLinks.sort(function(a, b) {
  127.       if (a.wordCount === b.wordCount) {
  128.         return a.originalIndex - b.originalIndex;
  129.       } else {
  130.         return a.wordCount - b.wordCount;
  131.       }
  132.     }).filter(function(a) {
  133.       return a.wordCount <= candidateLinks[0].wordCount + 1;
  134.     });
  135.     for (_l = 0, _len2 = linkStrings.length; _l < _len2; _l++) {
  136.       linkString = linkStrings[_l];
  137.       exactWordRegex = /\b/.test(linkString[0]) || /\b/.test(linkString[linkString.length - 1]) ? new RegExp("\\b" + linkString + "\\b", "i") : new RegExp(linkString, "i");
  138.       for (_m = 0, _len3 = candidateLinks.length; _m < _len3; _m++) {
  139.         candidateLink = candidateLinks[_m];
  140.         if (exactWordRegex.test(candidateLink.innerText)) {
  141.           followLink(candidateLink);
  142.           return true;
  143.         }
  144.       }
  145.     }
  146.     return false;
  147.   };
  148.  
  149.   ({
  150.     previousPatterns: "prev,previous,back,<,\u2190,\xab,\u226a,<<",
  151.     nextPatterns: "next,more,>,\u2192,\xbb,\u226b,>>"
  152.   });
  153.  
  154. }).call(this);