From: Jason Woofenden Date: Sat, 31 Aug 2013 20:39:59 +0000 (-0400) Subject: make numberlinks work in chromium, cleanup X-Git-Url: https://jasonwoof.com/gitweb/?p=userscripts.git;a=commitdiff_plain;h=ed41a1794bddae541f6a8c0424f07c825e79d863 make numberlinks work in chromium, cleanup --- diff --git a/numbered_links.user.js b/numbered_links.user.js index 30346c1..d29b24a 100644 --- a/numbered_links.user.js +++ b/numbered_links.user.js @@ -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); })();