// 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 something like load_start_handler to send
-// "act script /usr/share/examples/scripts/linkfollow.js"
-// (currently, it is recommended to use load_finish_handler since the JS code seems to get
-// flushed. Using a load_start_handler with a 1s delay works but not always)
+// One way would be to use the load_commit_handler:
+// set load_commit_handler = sh 'echo "script /usr/share/uzbl/examples/scripts/linkfollow.js" > "$4"'
//
// when script is loaded, it can be invoked with
-// bind f* = js hints.set("%s")
-// bind f_ = js hints.follow("%s")
+// 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/examples/scripts/linkfollow.js
+// bind :lf = script /usr/share/uzbl/examples/scripts/linkfollow.js
//
-// To enable hint highlighting, add:
+// 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: load the script as soon as the DOM is ready
+// 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';
up += el.offsetTop;
left += el.offsetLeft;
}
- return [up, left, width, height];
+ return {up: up, left: left, width: width, height: height};
}
- function elementInViewport(offset) {
- 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);
+ 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) {
return isVisible(el.parentNode);
}
- var hintable = "//a[@href] | //img | //input";
+ // 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,"i")});
+ 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
- return words.every(function (regex) { return element.node.textContent.match(regex)});
+ var item = matchAgainst(element);
+ return words.every(function (regex) { return item.match(regex)});
}
}
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;
}
var hintNode = doc.createElement('div');
hintNode.name = uzblid;
hintNode.innerText = labelNum;
- hintNode.style.left = this.position[1] + 'px';
- hintNode.style.top = this.position[0] + 'px';
+ hintNode.style.left = this.position.left + 'px';
+ hintNode.style.top = this.position.up + 'px';
hintNode.style.position = "absolute";
doc.body.firstChild.appendChild(hintNode);
}
}
- function update(str) {
+ function update(str,openFun) {
var match = new Matcher(str);
hintdiv = createHintDiv();
var i = 1;
} else {
n.removeHint();
}});
+ if(!requireReturn){
+ if(i==2){ //only been incremented once
+ follow(str,openFun);
+ }
+ }
}
- function hint(str){
+ function hint(str,openFun){
if(str.length == 0) init();
- update(str);
+ update(str,openFun);
}
function keyPressHandler(e) {
}
}
- function follow(str){
- var m = new Matcher(str);
+ this.openNewWindow = function(item){
+ // TODO: this doesn't work yet
+ item.className += " uzbl_follow";
+ window.open(item.href,"uzblnew","");
+ }
+ this.open = function(item){
+ simulateMouseOver(item);
+ item.className += " uzbl_follow";
+ window.location = item.href;
+ }
+ function simulateMouseOver(item){
+ var evt = doc.createEvent("MouseEvents");
+ evt.initMouseEvent("MouseOver",true,true,
+ doc.defaultView,1,0,0,0,0,
+ false,false,false,false,0,null);
+ return item.dispatchEvent(evt);
+ }
+
+
+ function follow(str,openFunction){
+ var m = new Matcher(str);
var items = visible.filter(function (n) { return n.isHinted });
clear();
var num = parseInt(m.numbers,10);
var item = items[0].node;
}
if (item) {
- item.style.borderStyle = "dotted";
- item.style.borderWidth = "thin";
-
var name = item.tagName;
if (name == 'A') {
if(item.click) {item.click()};
- window.location = item.href;
+ openFunction(item);
} else if (name == 'INPUT') {
var type = item.getAttribute('type').toUpperCase();
if (type == 'TEXT' || type == 'FILE' || type == 'PASSWORD') {
item.select();
} else {
item.click();
- window.location = item.href;
+ openFunction(item);
}
}
}
}
var hints = new Hints();
-//document.attachEvent("onKeyUp",hints.keyPressHandler);
-// vim:set et tw=2:
+// vim:set et sw=2: