JasonWoof Got questions, comments, patches, etc.? Contact Jason Woofenden
make numberlinks work in chromium, cleanup
authorJason Woofenden <jason@jasonwoof.com>
Sat, 31 Aug 2013 20:39:59 +0000 (16:39 -0400)
committerJason Woofenden <jason@jasonwoof.com>
Sat, 31 Aug 2013 20:39:59 +0000 (16:39 -0400)
numbered_links.user.js

index 30346c1..d29b24a 100644 (file)
@@ -8,12 +8,14 @@
 // @name          numbered links
 // @namespace     http://patcavit.com/greasemonkey
 // @description   make all links followable with the keyboard
-// @include       http://*
+// @include       *
 // ==/UserScript==
 
-(function() 
+(function()
 {
 
+var active = 0;
+var got = '';
 
 // This is activated (and canceled) by pressing the ^C
 // Press L (first) to switch to one-hand mode
@@ -60,7 +62,7 @@ var key_to_char = {
         '52': '4',
        '222': "'",
         '76': 'l' // switch to one-hand mode
-}
+};
 
 //Just some shortcuts and globals
 var charset = 'thsnd-rcgmvwb/;789aefijkopquxyz234'; // update key_to_char if you add to this
@@ -70,30 +72,50 @@ var doc = document;
 var win = window;
 var links = document.links;
 var forms = document.forms;
-//Make onlick-links "clickable"
-try {
-    HTMLElement.prototype.click = function() {
-        if (typeof this.onclick == 'function') {
-            this.onclick({
-                type: 'click'
-            });
-        }
-    };
-} catch(e) {}
+
 //Calculate element position to draw the hint
 //Pretty accurate but on fails in some very fancy cases
-function elementPosition(el) {
-    var up = el.offsetTop;
-    var left = el.offsetLeft;
+function element_position(el) {
+    var x = el.offsetLeft;
+    var y = el.offsetTop;
     var width = el.offsetWidth;
     var height = el.offsetHeight;
     while (el.offsetParent) {
         el = el.offsetParent;
-        up += el.offsetTop;
-        left += el.offsetLeft;
+        y += el.offsetTop;
+        x += el.offsetLeft;
     }
-    return [up, left, width, height];
+    return { x: x, y: y, width: width, height: height };
 }
+
+// Simulate a click on the element
+function click_element(target, options) {
+       var event = target.ownerDocument.createEvent('MouseEvents');
+       var pos = element_position(target);
+       options = options || {};
+
+
+       event.initMouseEvent(
+               options.type            || 'click',
+               options.canBubble       || true,
+               options.cancelable      || true,
+               options.view            || target.ownerDocument.defaultView,
+               options.detail          || 1,
+               options.screenX         || pos.x - window.pageXOffset,
+               options.screenY         || pos.y - window.pageYOffset,
+               options.clientX         || pos.x,
+               options.clientY         || pos.y,
+               options.ctrlKey         || false,
+               options.altKey          || false,
+               options.shiftKey        || false,
+               options.metaKey         || false,
+               options.button          || 0, //0 = left, 1 = middle, 2 = right
+               options.relatedTarget   || null
+       );
+
+       target.dispatchEvent(event);
+}
+
 //Calculate if an element is visible
 function isVisible(el) {
     if (el == doc) {
@@ -117,12 +139,8 @@ function isVisible(el) {
 }
 //Calculate if an element is on the viewport.
 function elementInViewport(el) {
-    offset = elementPosition(el);
-    var up = offset[0];
-    var left = offset[1];
-    var width = offset[2];
-    var height = offset[3];
-    return up < window.pageYOffset + window.innerHeight && left < window.pageXOffset + window.innerWidth && (up + height) > window.pageYOffset && (left + width) > window.pageXOffset;
+    var pos = element_position(el);
+    return pos.y < window.pageYOffset + window.innerHeight && pos.x < window.pageXOffset + window.innerWidth && (pos.y + pos.height) > window.pageYOffset && (pos.x + pos.width) > window.pageXOffset;
 }
 //Removes all hints/leftovers that might be generated
 //by this script.
@@ -135,7 +153,7 @@ function removeAllHints() {
 //Generate a hint for an element with the given label
 //Here you can play around with the style of the hints!
 function generateHint(el, label) {
-    var pos = elementPosition(el);
+    var pos = element_position(el);
     var hint = doc.createElement('div');
     hint.setAttribute('name', uzblid);
     hint.innerText = label;
@@ -152,11 +170,11 @@ function generateHint(el, label) {
     hint.style.position = 'absolute';
     hint.style.zIndex = '1000';
     hint.style.textTransform = 'uppercase';
-    hint.style.left = Math.max(-1, (pos[1] - (7 + label.length * 9))) + 'px';
-    hint.style.top = (pos[0] + 1) + 'px';
+    hint.style.left = Math.max(-1, (pos.x - (7 + label.length * 9))) + 'px';
+    hint.style.top = (pos.y + 1) + 'px';
     var img = el.getElementsByTagName('img');
     //if (img.length > 0) {
-        //hint.style.top = pos[1] + img[0].height / 2 - 6 + 'px';
+        //hint.style.top = pos.x + img[0].height / 2 - 6 + 'px';
     //}
     hint.style.textDecoration = 'none';
     // hint.style.webkitBorderRadius = '6px'; // slow
@@ -171,7 +189,7 @@ function clickElem(item) {
     if (item) {
         var name = item.tagName;
         if (name == 'A') {
-            item.click();
+            click_element(item);
             window.location = item.href;
         } else if (name == 'INPUT') {
             var type = item.getAttribute('type').toUpperCase();
@@ -185,7 +203,7 @@ function clickElem(item) {
             item.focus();
             item.select();
         } else {
-            item.click();
+            click_element(item);
             window.location = item.href;
         }
     }
@@ -194,7 +212,7 @@ function clickElem(item) {
 //just the elements itself, but in other versions, we
 //add the label here.
 function addLinks() {
-    res = [[], []];
+    var res = [[], []];
     for (var l = 0; l < links.length; l++) {
         var li = links[l];
         if (isVisible(li) && elementInViewport(li)) {
@@ -205,7 +223,7 @@ function addLinks() {
 }
 //Same as above, just for the form elements
 function addFormElems() {
-    res = [[], []];
+    var res = [[], []];
     for (var f = 0; f < forms.length; f++) {
         for (var e = 0; e < forms[f].elements.length; e++) {
             var el = forms[f].elements[e];
@@ -332,43 +350,41 @@ function followLinks(follow) {
 
 
 
-       // from your event handler you can: return stop_event(e)
-       function stop_event(e) {
-               // try {
-                       e.stopPropagation();
-                       e.preventDefault();
-               // } catch (ex) {
-               //      return false; // IE-compat
-               // }
-       }
-       var active = 0;
-       var got = '';
-       document.addEventListener(
-               'keydown',
-               function(e) {
-                       // [de]activate on ^C
-                       // deactivate on ESC
-                       if(
-                               (e.ctrlKey && e.keyCode == 67)
-                               || (e.keyCode == 27 && active == 1)
-                       ) {
-                               if(active) {
-                                       got = '';
-                                       removeAllHints();
-                               } else {
-                                       followLinks(got);
-                               }
-                               active = 1 - active;
-                               return stop_event(e);
+// from your event handler you can: return stop_event(e)
+function stop_event(e) {
+       // try {
+               e.stopPropagation();
+               e.preventDefault();
+       // } catch (ex) {
+       //      return false; // IE-compat
+       // }
+}
+document.addEventListener(
+       'keydown',
+       function(e) {
+               // [de]activate on ^C
+               // deactivate on ESC
+               if(
+                       (e.ctrlKey && e.keyCode == 67)
+                       || (e.keyCode == 27 && active == 1)
+               ) {
+                       if(active) {
+                               got = '';
+                               removeAllHints();
                        } else {
-                               if(active == 1 && !e.ctrlKey && !e.shiftKey && !e.altKey) {
-                                       if(key_to_char[e.keyCode]) {
-                                               got += key_to_char[e.keyCode];
-                                               followLinks(got);
-                                               return stop_event(e);
-                                       }
+                               followLinks(got);
+                       }
+                       active = 1 - active;
+                       return stop_event(e);
+               } else {
+                       if(active == 1 && !e.ctrlKey && !e.shiftKey && !e.altKey) {
+                               if(key_to_char[e.keyCode]) {
+                                       got += key_to_char[e.keyCode];
+                                       followLinks(got);
+                                       return stop_event(e);
                                }
                        }
-               },
-               true);
+               }
+       },
+       true);
 })();