// link follower for uzbl // requires http://github.com/DuClare/uzbl/commit/6c11777067bdb8aac09bba78d54caea04f85e059 // // first, it needs to be loaded before every time it is used. // One way would be to use the load_commit_handler: // set load_commit_handler = sh 'echo "script /usr/share/uzbl/examples/data/scripts/linkfollow.js" > "$4"' // // when script is loaded, it can be invoked with // bind f* = js hints.set("%s", hints.open) // bind f_ = js hints.follow("%s",hints.open) // // At the moment, it may be useful to have way of forcing uzbl to load the script // bind :lf = script /usr/share/uzbl/examples/data/scripts/linkfollow.js // // The default style for the hints are pretty ugly, so it is recommended to add the following // to config file // set stylesheet_uri = /usr/share/uzbl/examples/data/style.css // // based on follow_Numbers.js // // TODO: fix styling for the first element // TODO: emulate mouseover events when visiting some elements // TODO: rewrite the element->action handling function Hints(){ // Settings //////////////////////////////////////////////////////////////////////////// // if set to true, you must explicitly call hints.follow(), otherwise it will // follow the link if there is only one matching result var requireReturn = true; // Case sensitivity flag var matchCase = "i"; // For case sensitive matching, uncomment: // var matchCase = ""; var uzblid = 'uzbl_hint'; var uzblclass = 'uzbl_highlight'; var uzblclassfirst = 'uzbl_h_first'; var doc = document; var visible = []; var hintdiv; this.set = hint; this.follow = follow; this.keyPressHandler = keyPressHandler; function elementPosition(el) { var up = el.offsetTop; var left = el.offsetLeft; var width = el.offsetWidth; var height = el.offsetHeight; while (el.offsetParent) { el = el.offsetParent; up += el.offsetTop; left += el.offsetLeft; } return {up: up, left: left, width: width, height: height}; } function elementInViewport(p) { return (p.up < window.pageYOffset + window.innerHeight && p.left < window.pageXOffset + window.innerWidth && (p.up + p.height) > window.pageYOffset && (p.left + p.width) > window.pageXOffset); } function isVisible(el) { if (el == doc) { return true; } if (!el) { return false; } if (!el.parentNode) { return false; } if (el.style) { if (el.style.display == 'none') { return false; } if (el.style.visibility == 'hidden') { return false; } } return isVisible(el.parentNode); } // the vimperator defaults minus the xhtml elements, since it gave DOM errors var hintable = " //*[@onclick or @onmouseover or @onmousedown or @onmouseup or @oncommand or @class='lk' or @role='link' or @href] | //input[not(@type='hidden')] | //a | //area | //iframe | //textarea | //button | //select"; function Matcher(str){ var numbers = str.replace(/[^\d]/g,""); var words = str.replace(/\d/g,"").split(/\s+/).map(function (n) { return new RegExp(n,matchCase)}); this.test = test; this.toString = toString; this.numbers = numbers; function matchAgainst(element){ if(element.node.nodeName == "INPUT"){ return element.node.value; } else { return element.node.textContent; } } function test(element) { // test all the regexp var item = matchAgainst(element); return words.every(function (regex) { return item.match(regex)}); } } function HintElement(node,pos){ this.node = node; this.isHinted = false; this.position = pos; this.num = 0; this.addHint = function (labelNum) { // TODO: fix uzblclassfirst if(!this.isHinted){ this.node.className += " " + uzblclass; } this.isHinted = true; // create hint var hintNode = doc.createElement('div'); hintNode.name = uzblid; hintNode.innerText = labelNum; hintNode.style.left = this.position.left + 'px'; hintNode.style.top = this.position.up + 'px'; hintNode.style.position = "absolute"; doc.body.firstChild.appendChild(hintNode); } this.removeHint = function(){ if(this.isHinted){ var s = (this.num)?uzblclassfirst:uzblclass; this.node.className = this.node.className.replace(new RegExp(" "+s,"g"),""); this.isHinted = false; } } } function createHintDiv(){ var hintdiv = doc.getElementById(uzblid); if(hintdiv){ hintdiv.parentNode.removeChild(hintdiv); } hintdiv = doc.createElement("div"); hintdiv.setAttribute('id',uzblid); doc.body.insertBefore(hintdiv,doc.body.firstChild); return hintdiv; } function init(){ // WHAT? doc.body.setAttribute("onkeyup","hints.keyPressHandler(event)"); hintdiv = createHintDiv(); visible = []; var items = doc.evaluate(hintable,doc,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,null); for (var i = 0;i