sites

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

commit f0b44dc6ede940322c342bedd84761f8fb7d42be
parent 29160ebcd2f642a94d1e465dc4f19d3e3e4034db
Author: pancake <unknown>
Date:   Thu, 14 Jan 2010 13:34:15 +0100

* Added link_hints script.js for surf
Diffstat:
Asurf.suckless.org/files/link_hints.md | 333+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 333 insertions(+), 0 deletions(-)

diff --git a/surf.suckless.org/files/link_hints.md b/surf.suckless.org/files/link_hints.md @@ -0,0 +1,333 @@ +KEYBOARD LINK HINTING +===================== + +Description +----------- + +This script enables link hinting support to surf. Deploy it into ~/.surf/user.js. + +Keybindings +----------- + ^f (open link in current window) + ^F (open link in new window) + ^c (cancel hinting) + +Author +------ + +- The code was originally from chromium but was adapted by nibble(.ds(at)gmail(dot).com) to work with surf. + +Code +---- + + /* based on chromium plugin code */ + var hint_num_str = ''; + var hint_elems = []; + var hint_open_in_new_tab = false; + var hint_enabled = false; + + function hintMode(newtab){ + hint_enabled = true; + if (newtab) hint_open_in_new_tab = true; + else hint_open_in_new_tab = false; + setHints(); + document.removeEventListener('keydown', initKeyBind, false); + document.addEventListener('keydown', hintHandler, false); + hint_num_str = ''; + } + + function hintHandler(e){ + e.preventDefault(); //Stop Default Event + var pressedKey = get_key(e); + if (pressedKey == 'Enter') { + if (hint_num_str == '') + hint_num_str = '1'; + judgeHintNum(Number(hint_num_str)); + } else if (/[0-9asdfghjkl;]/.test(pressedKey) == false || pressedKey =='Esc') { + removeHints(); + } else { + // TODO + if (pressedKey == 'U+00BA') { + pressedKey = ';'; + } + var num = ';asdfghjkl'.indexOf(pressedKey); + if (num >= 0) { + pressedKey = num; + } + hint_num_str += pressedKey; + var hint_num = Number(hint_num_str); + if (hint_num * 10 > hint_elems.length + 1) { + judgeHintNum(hint_num); + } else { + var hint_elem = hint_elems[hint_num - 1]; + if (hint_elem != undefined && hint_elem.tagName.toLowerCase() == 'a') { + setHighlight(hint_elem, true); + } + } + } + } + + function setHighlight(elem, is_active) { + if (is_active) { + var active_elem = document.body.querySelector('a[highlight=hint_active]'); + if (active_elem != undefined) + active_elem.setAttribute('highlight', 'hint_elem'); + elem.setAttribute('highlight', 'hint_active'); + } else { + elem.setAttribute('highlight', 'hint_elem'); + } + + } + + function setHintRules() { + var ss = document.styleSheets[0]; + ss.insertRule('a[highlight=hint_elem] {background-color: yellow}', 0); + ss.insertRule('a[highlight=hint_active] {background-color: lime}', 0); + } + + function deleteHintRules() { + var ss = document.styleSheets[0]; + ss.deleteRule(0); + ss.deleteRule(0); + } + + function judgeHintNum(hint_num) { + var hint_elem = hint_elems[hint_num - 1]; + if (hint_elem != undefined) { + execSelect(hint_elem); + } else { + removeHints(); + } + } + + function execSelect(elem) { + var tag_name = elem.tagName.toLowerCase(); + var type = elem.type ? elem.type.toLowerCase() : ""; + if (tag_name == 'a' && elem.href != '') { + setHighlight(elem, true); + // TODO: ajax, <select> + if (hint_open_in_new_tab) + window.open(elem.href); + else location.href=elem.href; + + } else if (tag_name == 'input' && (type == "submit" || type == "button" || type == "reset")) { + elem.click(); + } else if (tag_name == 'input' && (type == "radio" || type == "checkbox")) { + // TODO: toggle checkbox + elem.checked = !elem.checked; + } else if (tag_name == 'input' || tag_name == 'textarea') { + elem.focus(); + elem.setSelectionRange(elem.value.length, elem.value.length); + } + removeHints(); + } + + function setHints() { + setHintRules(); + var win_top = window.scrollY; + var win_bottom = win_top + window.innerHeight; + var win_left = window.scrollX; + var win_right = win_left + window.innerWidth; + // TODO: <area> + var elems = document.body.querySelectorAll('a, input:not([type=hidden]), textarea, select, button'); + var div = document.createElement('div'); + div.setAttribute('highlight', 'hints'); + document.body.appendChild(div); + for (var i = 0; i < elems.length; i++) { + var elem = elems[i]; + if (!isHintDisplay(elem)) + continue; + var pos = elem.getBoundingClientRect(); + var elem_top = win_top + pos.top; + var elem_bottom = win_top + pos.bottom; + var elem_left = win_left + pos.left; + var elem_right = win_left + pos.left; + if ( elem_bottom >= win_top && elem_top <= win_bottom) { + hint_elems.push(elem); + setHighlight(elem, false); + var span = document.createElement('span'); + span.style.cssText = [ + 'left: ', elem_left, 'px;', + 'top: ', elem_top, 'px;', + 'position: absolute;', + 'font-size: 13px;', + 'background-color: ' + (hint_open_in_new_tab ? '#ff6600' : 'red') + ';', + 'color: white;', + 'font-weight: bold;', + 'padding: 0px 1px;', + 'z-index: 100000;' + ].join(''); + span.innerHTML = hint_elems.length; + div.appendChild(span); + if (elem.tagName.toLowerCase() == 'a') { + if (hint_elems.length == 1) { + setHighlight(elem, true); + } else { + setHighlight(elem, false); + } + } + } + } + } + + function isHintDisplay(elem) { + var pos = elem.getBoundingClientRect(); + return (pos.height != 0 && pos.width != 0); + } + + function removeHints() { + if (!hint_enabled) + return; + hint_enabled = false; + deleteHintRules(); + for (var i = 0; i < hint_elems.length; i++) { + hint_elems[i].removeAttribute('highlight'); + } + hint_elems = []; + hint_num_str = ''; + var div = document.body.querySelector('div[highlight=hints]'); + if (div != undefined) { + document.body.removeChild(div); + } + document.removeEventListener('keydown', hintHandler, false); + document.addEventListener('keydown', initKeyBind, false); + } + + function addKeyBind( key, func, eve ){ + var pressedKey = get_key(eve); + if( pressedKey == key ){ + eve.preventDefault(); //Stop Default Event + eval(func); + } + } + + document.addEventListener( 'keydown', initKeyBind, false ); + + function initKeyBind(e){ + var t = e.target; + if( t.nodeType == 1){ + tn=t.tagName.toLowerCase(); + addKeyBind( 'C-f', 'hintMode()', e ); + addKeyBind( 'C-F', 'hintMode(true)', e ); + addKeyBind( 'C-c', 'removeHints()', e ); + } + } + + var keyId = { + "U+0008" : "BackSpace", + "U+0009" : "Tab", + "U+0018" : "Cancel", + "U+001B" : "Esc", + "U+0020" : "Space", + "U+0021" : "!", + "U+0022" : "\"", + "U+0023" : "#", + "U+0024" : "$", + "U+0026" : "&", + "U+0027" : "'", + "U+0028" : "(", + "U+0029" : ")", + "U+002A" : "*", + "U+002B" : "+", + "U+002C" : ",", + "U+002D" : "-", + "U+002E" : ".", + "U+002F" : "/", + "U+0030" : "0", + "U+0031" : "1", + "U+0032" : "2", + "U+0033" : "3", + "U+0034" : "4", + "U+0035" : "5", + "U+0036" : "6", + "U+0037" : "7", + "U+0038" : "8", + "U+0039" : "9", + "U+003A" : ":", + "U+003B" : ";", + "U+003C" : "<", + "U+003D" : "=", + "U+003E" : ">", + "U+003F" : "?", + "U+0040" : "@", + "U+0041" : "a", + "U+0042" : "b", + "U+0043" : "c", + "U+0044" : "d", + "U+0045" : "e", + "U+0046" : "f", + "U+0047" : "g", + "U+0048" : "h", + "U+0049" : "i", + "U+004A" : "j", + "U+004B" : "k", + "U+004C" : "l", + "U+004D" : "m", + "U+004E" : "n", + "U+004F" : "o", + "U+0050" : "p", + "U+0051" : "q", + "U+0052" : "r", + "U+0053" : "s", + "U+0054" : "t", + "U+0055" : "u", + "U+0056" : "v", + "U+0057" : "w", + "U+0058" : "x", + "U+0059" : "y", + "U+005A" : "z", + //"U+005B" : "[", + //"U+005C" : "\\", + //"U+005D" : "]", + "U+00DB" : "[", + "U+00DC" : "\\", + "U+00DD" : "]", + "U+005E" : "^", + "U+005F" : "_", + "U+0060" : "`", + "U+007B" : "{", + "U+007C" : "|", + "U+007D" : "}", + "U+007F" : "Delete", + "U+00A1" : "¡", + "U+0300" : "CombGrave", + "U+0300" : "CombAcute", + "U+0302" : "CombCircum", + "U+0303" : "CombTilde", + "U+0304" : "CombMacron", + "U+0306" : "CombBreve", + "U+0307" : "CombDot", + "U+0308" : "CombDiaer", + "U+030A" : "CombRing", + "U+030B" : "CombDblAcute", + "U+030C" : "CombCaron", + "U+0327" : "CombCedilla", + "U+0328" : "CombOgonek", + "U+0345" : "CombYpogeg", + "U+20AC" : "€", + "U+3099" : "CombVoice", + "U+309A" : "CombSVoice", + } + + function get_key(evt){ + var key = keyId[evt.keyIdentifier] || evt.keyIdentifier, + ctrl = evt.ctrlKey ? 'C-' : '', + meta = (evt.metaKey || evt.altKey) ? 'M-' : '', + shift = evt.shiftKey ? 'S-' : ''; + if (evt.shiftKey){ + if (/^[a-z]$/.test(key)) + return ctrl+meta+key.toUpperCase(); + if (/^[0-9]$/.test(key)) { + switch(key) { + // TODO + case "4": + key = "$"; + break; + }; + return key; + } + if (/^(Enter|Space|BackSpace|Tab|Esc|Home|End|Left|Right|Up|Down|PageUp|PageDown|F(\d\d?))$/.test(key)) + return ctrl+meta+shift+key; + } + return ctrl+meta+key; + }