Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
javascript: (function(_HaH) {
var originalTitle = document.title;
var hintKeys = new String('asdfghjkl');
var choices = [];
var choice = '';
var xpath = '//a[@href]|//input[not(@type=\x22hidden\x22)]|//textarea|//select|//img[@onclick]|//button';
xpath += '|' + xpath.replace(/\/\//g, '//xhtml:');
var defaultType = 'HaHxlink';
function defaultAction(e) {
e.focus();
var ev = document.createEvent('MouseEvents');
ev.initEvent('click', null, null);
e.dispatchEvent(ev)
}
var HaHElements = [{
accessor: function(e) {
var tag = e.tagName.toLowerCase();
return ((tag == 'a' && /^(#|javascript:void\(0\);?)$/.test(e.href)) || /^(textarea|button|select|input|img)$/.test(tag));
},
type:defaultType,
action:defaultAction
},
{
accessor: function(e) {
return e.tagName.toLowerCase() == 'a';
},
type: 'HaHlink',
action: (window.opera)?defaultAction:function(e){if(e.href)location.href = e.href;}
}];
if (_HaH && _HaH.types) {
_HaH.types.forEach(function(item) {
if (item.xpath) xpath += '|' + item.xpath;
HaHElements.unshift({
accessor: item.accessor,
type: item.type || defaultType,
action: item.action || defaultAction,
color: item.color,
})
})
}
function addCSS() {
var style = document.getElementById('HaH-style-element');
var d = '#HaH-div-element';
var cssText = [d, 'span{font-size:10pt; padding:0pt \x20 1pt; margin:0; line-height:10pt; position:absolute; z-index:2147483647; opacity:.7; color:#000;}', d, '.HaHlink{background-color:#FF0;}', d, '.HaHxlink{background-color:#0FF;}', d, '.HaHselected{background-color:#F0F;}'].join('\x20');
HaHElements.forEach(function(item){if(item.color)cssText+=d+'\x20.'+item.type+'{background-color:'+item.color+';}'});
if (style) {
if(style.innerHTML!=cssText)style.innerHTML=cssText;
}else{
style = document.createElement('style');
style.type = 'text/css';
style.id = 'HaH-style-element';
style.innerHTML = cssText;
document.getElementsByTagName('head')[0].appendChild(style);
}
}
hints = [];
var df = document.createDocumentFragment();
function castHint(_ele, _x, _y) {
for (var i = 0; i < HaHElements.length; i++) {
if (HaHElements[i].accessor(_ele)) {
var _type = HaHElements[i].type;
var _action = HaHElements[i].action;
break;
}
}
if (!_type) return;
if (!hints.length) addCSS();
var _text = createText(hints.length);
var hint = {
element: _ele,
type: _type,
action: _action,
text: _text,
x: _x,
y: _y
};
hint.hintNode = addHintNode(hint);
hints[hints.length] = hint;
}
function addHintNode(hint) {
var span = document.createElement('span');
span.className = hint.type;
span.style.left = Math.max(0,hint.x-8) + 'px';
span.style.top = Math.max(0,hint.y-8) + 'px';
span.innerHTML = hint.text;
df.appendChild(span);
return span;
}
function getHintByText(txt) {
return hints[retrieveNumber(txt)];
}
function retrieveNumber(text) {
text += '';
var num = 0;
for (var i = 0,
l = text.length; i < l; i++) {
var fix = (i == 0) ? 0 : 1;
var t = text.charAt(l - i - 1);
num += (hintKeys.indexOf(t) + fix) * Math.pow(hintKeys.length, i);
}
return num;
}
function createText(num) {
var text = '';
var l = hintKeys.length;
var iter = 0;
while (num >= 0) {
var n = num;
num -= Math.pow(l, 1 + iter++);
}
for (var i = 0; i < iter; i++) {
r = n % l;
n = Math.floor(n / l);
text = hintKeys.charAt(r) + text;
}
return text;
}
function rectFixForOpera(e, s) {
if (!window.opera || e.tagName.toLowerCase() != 'a' || s.cssFloat != 'none') return null;
var c = e.firstChild;
var cIsAfterWhiteSpace = true;
while (cIsAfterWhiteSpace) {
if (!c) return {
left: 0,
right: 0
};
cIsAfterWhiteSpace = (c.nodeName.toLowerCase() == 'br' || c.nodeType == 8 || c.nodeType == 3 && !/\S/.test(c.nodeValue));
if (c instanceof HTMLImageElement || c.tagName && c.tagName.toLowerCase() != 'br' && getComputedStyle(c, null).display == 'block') return c.getBoundingClientRect();
c = c.nextSibling;
}
return null;
}
/* function rectFixForOpera(e, s) {
if(!window.opera||s.display!='inline'||s.cssFloat!='none')return null;
var c = e.firstChild,ec = e.firstElementChild;
if(!ec){
if(!/img/i.test(e.tagName))
while(c){
if(c.nodeType==3&&/\S/.test(c.nodeValue))return null;
c=c.nextSibling;
}
return {left:0,right:0};
}else{
if(!/(br|img)/i.test(ec.tagName)&&getComputedStyle(ec,null).display=='inline')return null;
while(c){
if(c.nodeType==3&&/\S/.test(c.nodeValue))return null;
c=c.nextSibling;
}
return ec.getBoundingClientRect();
}
}*/
function getAbsolutePosition(elem) {
var style = getComputedStyle(elem, null);
var rect = rectFixForOpera(elem, style) || elem.getClientRects()[0];
if (rect && rect.right - rect.left > 0 && style.visibility != 'hidden' && style.opacity != 0 && rect.left >= 0 && rect.top >= -5 && rect.bottom <= window.innerHeight + 5 && rect.right <= window.innerWidth) {
var html = document.documentElement;
var body = document.body;
return {
top: (body.scrollTop || html.scrollTop) - html.clientTop + rect.top,
left: (body.scrollLeft || html.scrollLeft) - html.clientLeft + rect.left
}
}
return false;
}
function drawHints() {
var div = document.getElementById('HaH-div-element');
if (div) div.innerHTML = '';
function resolv(p){
if(p=='xhtml')return 'http://www.w3.org/1999/xhtml';
}
var result = document.evaluate(xpath,document,resolv,7,null);
for(var i=0,l=result.snapshotLength;i<l;i++ ) {
var ele=result.snapshotItem(i);
var pos = getAbsolutePosition(ele);
if (!pos) continue;
castHint(ele, pos.left, pos.top);
}
if (!hints.length) return;
if (!div) {
div = document.createElement('div');
div.id = 'HaH-div-element';
}
div.appendChild(df);
document.body.appendChild(div);
document.addEventListener('keypress', interpretHaHKeyStroke, true);
document.title += '\x20-\x20';
}
function removeHints() {
document.title = originalTitle;
if (interpretHaHKeyStroke) {
document.removeEventListener('keypress', interpretHaHKeyStroke, true);
}
document.body.removeChild(document.getElementById('HaH-div-element'));
delete hints,df,choices;
}
var baseFuncs = {
doNothing: function() {
},
pushChoice: function(mod) {
if (mod) return removeHints;
if (choice != '') {
choices.push(choice);
getHintByText(choice).hintNode.className = 'HaHselected';
choice = '';
document.title += '\x20';
}
},
popChoice: function(mod) {
if (mod) return removeHints;
if (choice != '') {
choice = '';
} else {
if (choices.length) {
var lastchoice = getHintByText(choices.pop());
lastchoice.hintNode.className = lastchoice.type;
}
}
document.title = originalTitle + '\x20-\x20' + choices.join('\x20');
},
pushLetter: function(mod, key) {
if (mod) return removeHints();
choice += '';
if (getHintByText(choice + key)) {
choice += key;
var lastHint = '' + hints[hints.length - 1].text;
if (choice.length == lastHint.length || choice.length == lastHint.length - 1 && retrieveNumber(choice) > retrieveNumber(lastHint.substr(0, choice.length))) {
getHintByText(choice).hintNode.className = 'HaHselected';
choices.push(choice);
choice = '';
document.title += '\x20';
}
}
var choicestring = (choices.length) ? choices.join('\x20') + '\x20' + choice: choice;
document.title = originalTitle + '\x20-\x20' + choicestring;
}
};
var keyMap = {
'8' : 'Bkspc',
'32': 'Space',
'16': 'Shift',
'17': 'Ctrl',
'18': 'Alt'
};
var keyFuncMap = {
'Bkspc': baseFuncs.popChoice,
'Space': baseFuncs.pushChoice,
};
hintKeys.split('').forEach(function(l){keyMap[l.charCodeAt(0)] = l});
hintKeys.split('').forEach(function(k){keyFuncMap[k] = baseFuncs.pushLetter;});
['Shift', 'Ctrl', 'Alt'].forEach(function(k){keyFuncMap[k] = baseFuncs.doNothing;});
function defaultFuncTemplate(func){
return function(mod){
if(choice)choices.push(choice);
var ary=[];
choices.forEach(function(c,i){
var hint = getHintByText(c);
if(hint && choices.indexOf(c)==i) ary.push(hint);
});
func(mod,ary);
removeHints();
}
}
function addExtraFunc(func,keyName,keyCode){
keyMap[(keyCode||keyName.charCodeAt(0))] = keyName;
keyFuncMap[keyName] = defaultFuncTemplate(func);
}
addExtraFunc(function(mod,ary){
var windowname = (ary.length==1&&!mod) ?'_top':'_blank';
ary.forEach(function(e){if(e.type=='HaHlink')window.open(e.element,windowname)});
},'Enter',13);
addExtraFunc(function(mod,ary){
if(mod)return;
var firstHint=ary[0];
if(firstHint)firstHint.action(firstHint.element);
},';');
if (_HaH && _HaH.keys) {
_HaH.keys.forEach(function(e){addExtraFunc(e.func,e.keyName,e.keyCode)});
}
function interpretHaHKeyStroke(e) {
var key = keyMap[(e.keyCode || e.which)];
e.preventDefault();
e.stopPropagation();
if (!key) return removeHints();
var modified = (e.ctrlKey || e.altKey || e.shiftKey || e.metaKey);
keyFuncMap[key](modified, key) && removeHints();
}
drawHints();
})(window.HitaHint);
@shohey1226

This comment has been minimized.

Copy link

commented Jan 17, 2018

This is just awesome. Looks working fine on Safari too. Many thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.