X-Git-Url: https://jasonwoof.com/gitweb/?p=userscripts.git;a=blobdiff_plain;f=numbered_links.user.js;h=e442ca8fc7fbee6bedaa5924c3dc5591ef386176;hp=ec51ef0cd653d29f5a36d866cb1a5f410f6e6729;hb=7166ff6b129b4116ac548c51c5bd9467e6e77903;hpb=77de05f977c5dfaf03d2c29a31dab7fdf31d2df9 diff --git a/numbered_links.user.js b/numbered_links.user.js index ec51ef0..e442ca8 100644 --- a/numbered_links.user.js +++ b/numbered_links.user.js @@ -8,53 +8,114 @@ // @name numbered links // @namespace http://patcavit.com/greasemonkey // @description make all links followable with the keyboard -// @include http://* +// @include * // ==/UserScript== -(function() +(function() { - -// This is activated (and canceled) by pressing the `/~ key. To change it to a -// differet key, edit the ascii value on line 301 -// -// Also, you can change the character set a few lines down. Don't use the "L" -// key unless you change the on line 235. - - +var active = 0; +var got = ''; + +// This is activated (and canceled) by pressing the ^C +// Press L (first) to switch to one-hand mode + +// I was getting some very funky return values from String.fromCharCode() for +// punctuation keys so I made my own table. You might need to change this for +// your computer/keyboard. You'll need to have every character in "charset" in +// here. + +var key_to_char = { + '84': 't', + '72': 'h', + '83': 's', + '78': 'n', + '68': 'd', + '189': '-', + '82': 'r', + '67': 'c', + '71': 'g', + '77': 'm', + '86': 'v', + '87': 'w', + '66': 'b', + '191': '/', + '186': ';', + '55': '7', + '56': '8', + '57': '9', + '65': 'a', + '69': 'e', + '70': 'f', + '73': 'i', + '74': 'j', + '75': 'k', + '79': 'o', + '80': 'p', + '81': 'q', + '85': 'u', + '88': 'x', + '89': 'y', + '90': 'z', + '50': '2', + '51': '3', + '52': '4', + '222': "'", + '76': 'l' // switch to one-hand mode +}; //Just some shortcuts and globals -var charset = 'thsnd-rcgmvwb/;789aefijkopquxyz234'; +var charset = 'thsnd-rcgmvwb/;789aefijkopquxyz234'; // update key_to_char if you add to this var uzblid = 'uzbl_link_hint'; var uzbldivid = uzblid + '_div_container'; 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) { @@ -78,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. @@ -96,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; @@ -113,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 @@ -132,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(); @@ -146,7 +203,7 @@ function clickElem(item) { item.focus(); item.select(); } else { - item.click(); + click_element(item); window.location = item.href; } } @@ -155,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)) { @@ -166,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]; @@ -268,37 +325,26 @@ 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 = ''; +function init() { document.addEventListener( - 'keypress', + 'keydown', function(e) { - if(e.keyCode == 96) { // change this if you want a different activation key + // [de]activate on ^C + // deactivate on ESC + if( + (e.ctrlKey && e.keyCode == 67) + || (e.keyCode == 27 && active == 1) + ) { if(active) { got = ''; removeAllHints(); @@ -306,13 +352,39 @@ function followLinks(follow) { followLinks(got); } active = 1 - active; - return; + return stop_event(e); } else { - if(active == 1) { - got += String.fromCharCode(e.keyCode); - followLinks(got); + 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); + } + } else { + // general keybinding, unrelated to numbered links + if (document.activeElement == document.body) { // FIXME get more specific + var c = key_to_char[e.keyCode]; + switch (c) { + case 'c': + window.scrollBy(0, -200); + stop_event(e); + break; + case 't': + window.scrollBy(0, 200); + stop_event(e); + break; + } + } else if (e.keyCode == 27) { + // unfocus on ESC + document.activeElement.blur(); + stop_event(e); + } } } }, true); +} + +init(); + })();