//Calculate element position to draw the hint
//Pretty accurate but on fails in some very fancy cases
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;
- y += el.offsetTop;
- x += el.offsetLeft;
- }
- return { x: x, y: y, width: width, height: height };
+ var x = el.offsetLeft;
+ var y = el.offsetTop;
+ var width = el.offsetWidth;
+ var height = el.offsetHeight;
+ while (el.offsetParent) {
+ el = el.offsetParent;
+ y += el.offsetTop;
+ x += el.offsetLeft;
+ }
+ return { x: x, y: y, width: width, height: height };
}
// Simulate a click on the element
//Calculate if an element is visible
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);
+ 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);
}
//Calculate if an element is on the viewport.
function elementInViewport(el) {
- 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;
+ 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.
function removeAllHints() {
- var elements = doc.getElementById(uzbldivid);
- if (elements) {
- elements.parentNode.removeChild(elements);
- }
+ var elements = doc.getElementById(uzbldivid);
+ if (elements) {
+ elements.parentNode.removeChild(elements);
+ }
}
//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 = element_position(el);
- var hint = doc.createElement('div');
- hint.setAttribute('name', uzblid);
- hint.innerText = label;
- hint.style.display = 'inline';
- hint.style.backgroundColor = '#B9FF00';
- hint.style.border = '2px solid #4A6600';
- hint.style.color = 'black';
- hint.style.fontSize = '9px';
- hint.style.fontWeight = 'bold';
- hint.style.lineHeight = '9px';
- hint.style.margin = '0px';
- hint.style.width = 'auto'; // fix broken rendering on w3schools.com
- hint.style.padding = '1px';
- hint.style.position = 'absolute';
- hint.style.zIndex = '1000';
- hint.style.textTransform = 'uppercase';
- 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.x + img[0].height / 2 - 6 + 'px';
- //}
- hint.style.textDecoration = 'none';
- // hint.style.webkitBorderRadius = '6px'; // slow
- return hint;
+ var pos = element_position(el);
+ var hint = doc.createElement('div');
+ hint.setAttribute('name', uzblid);
+ hint.innerText = label;
+ hint.style.display = 'inline';
+ hint.style.backgroundColor = '#B9FF00';
+ hint.style.border = '2px solid #4A6600';
+ hint.style.color = 'black';
+ hint.style.fontSize = '9px';
+ hint.style.fontWeight = 'bold';
+ hint.style.lineHeight = '9px';
+ hint.style.margin = '0px';
+ hint.style.width = 'auto'; // fix broken rendering on w3schools.com
+ hint.style.padding = '1px';
+ hint.style.position = 'absolute';
+ hint.style.zIndex = '1000';
+ hint.style.textTransform = 'uppercase';
+ 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.x + img[0].height / 2 - 6 + 'px';
+ //}
+ hint.style.textDecoration = 'none';
+ // hint.style.webkitBorderRadius = '6px'; // slow
+ return hint;
}
//Here we choose what to do with an element if we
//want to "follow" it. On form elements we "select"
//or pass the focus, on links we try to perform a click,
//but at least set the href of the link. (needs some improvements)
function clickElem(item) {
- removeAllHints();
- if (item) {
- var name = item.tagName;
- if (name == 'A') {
- click_element(item);
- window.location = item.href;
- } else if (name == 'INPUT') {
- var type = item.getAttribute('type').toUpperCase();
- if (type == 'TEXT' || type == 'FILE' || type == 'PASSWORD') {
- item.focus();
- item.select();
- } else {
- item.click();
- }
- } else if (name == 'TEXTAREA' || name == 'SELECT') {
- item.focus();
- item.select();
- } else {
- click_element(item);
- window.location = item.href;
- }
- }
+ removeAllHints();
+ if (item) {
+ var name = item.tagName;
+ if (name == 'A') {
+ click_element(item);
+ window.location = item.href;
+ } else if (name == 'INPUT') {
+ var type = item.getAttribute('type').toUpperCase();
+ if (type == 'TEXT' || type == 'FILE' || type == 'PASSWORD') {
+ item.focus();
+ item.select();
+ } else {
+ item.click();
+ }
+ } else if (name == 'TEXTAREA' || name == 'SELECT') {
+ item.focus();
+ item.select();
+ } else {
+ click_element(item);
+ window.location = item.href;
+ }
+ }
}
//Returns a list of all links (in this version
//just the elements itself, but in other versions, we
//add the label here.
function addLinks() {
- var res = [[], []];
- for (var l = 0; l < links.length; l++) {
- var li = links[l];
- if (isVisible(li) && elementInViewport(li)) {
- res[0].push(li);
- }
- }
- return res;
+ var res = [[], []];
+ for (var l = 0; l < links.length; l++) {
+ var li = links[l];
+ if (isVisible(li) && elementInViewport(li)) {
+ res[0].push(li);
+ }
+ }
+ return res;
}
//Same as above, just for the form elements
function addFormElems() {
- 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];
- if (el && ['INPUT', 'TEXTAREA', 'SELECT'].indexOf(el.tagName) + 1 && isVisible(el) && elementInViewport(el)) {
- res[0].push(el);
- }
- }
- }
- return 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];
+ if (el && ['INPUT', 'TEXTAREA', 'SELECT'].indexOf(el.tagName) + 1 && isVisible(el) && elementInViewport(el)) {
+ res[0].push(el);
+ }
+ }
+ }
+ return res;
}
//Draw all hints for all elements passed. "len" is for
//the number of chars we should use to avoid collisions
function reDrawHints(elems, chars) {
- removeAllHints();
- var hintdiv = doc.createElement('div');
- hintdiv.setAttribute('id', uzbldivid);
- for (var i = 0; i < elems[0].length; i++) {
- if (elems[0][i]) {
- var label = elems[1][i].substring(chars);
- var h = generateHint(elems[0][i], label);
- hintdiv.appendChild(h);
- }
- }
- if (document.body) {
- document.body.appendChild(hintdiv);
- }
+ removeAllHints();
+ var hintdiv = doc.createElement('div');
+ hintdiv.setAttribute('id', uzbldivid);
+ for (var i = 0; i < elems[0].length; i++) {
+ if (elems[0][i]) {
+ var label = elems[1][i].substring(chars);
+ var h = generateHint(elems[0][i], label);
+ hintdiv.appendChild(h);
+ }
+ }
+ if (document.body) {
+ document.body.appendChild(hintdiv);
+ }
}
// pass: number of keys
// returns: key length
}
//Put it all together
function followLinks(follow) {
- if(follow.charAt(0) == 'l') {
- follow = follow.substr(1);
- charset = 'thsnlrcgfdbmwvz-/';
- }
- var s = follow.split('');
- var linknr = labelToInt(follow);
- var linkelems = addLinks();
- var formelems = addFormElems();
- var elems = [linkelems[0].concat(formelems[0]), linkelems[1].concat(formelems[1])];
- var len = labelLength(elems[0].length);
- var oldDiv = doc.getElementById(uzbldivid);
- var leftover = [[], []];
- if (s.length == len && linknr < elems[0].length && linknr >= 0) {
- clickElem(elems[0][linknr]);
- got = '';
- active = 0;
- } else {
- for (var j = 0; j < elems[0].length; j++) {
- var b = true;
- var label = intToLabel(j);
- var n = label.length;
- for (n; n < len; n++) {
- label = charset.charAt(0) + label;
- }
- for (var k = 0; k < s.length; k++) {
- b = b && label.charAt(k) == s[k];
- }
- if (b) {
- leftover[0].push(elems[0][j]);
- leftover[1].push(label);
- }
- }
- reDrawHints(leftover, s.length);
- }
+ if(follow.charAt(0) == 'l') {
+ follow = follow.substr(1);
+ charset = 'thsnlrcgfdbmwvz-/';
+ }
+ var s = follow.split('');
+ var linknr = labelToInt(follow);
+ var linkelems = addLinks();
+ var formelems = addFormElems();
+ var elems = [linkelems[0].concat(formelems[0]), linkelems[1].concat(formelems[1])];
+ var len = labelLength(elems[0].length);
+ var oldDiv = doc.getElementById(uzbldivid);
+ var leftover = [[], []];
+ if (s.length == len && linknr < elems[0].length && linknr >= 0) {
+ clickElem(elems[0][linknr]);
+ got = '';
+ active = 0;
+ } else {
+ for (var j = 0; j < elems[0].length; j++) {
+ var b = true;
+ var label = intToLabel(j);
+ var n = label.length;
+ for (n; n < len; n++) {
+ label = charset.charAt(0) + label;
+ }
+ for (var k = 0; k < s.length; k++) {
+ b = b && label.charAt(k) == s[k];
+ }
+ if (b) {
+ leftover[0].push(elems[0][j]);
+ leftover[1].push(label);
+ }
+ }
+ reDrawHints(leftover, s.length);
+ }
}
// from your event handler you can: return stop_event(e)