index.md - sites - public wiki contents of suckless.org | |
git clone git://git.suckless.org/sites | |
Log | |
Files | |
Refs | |
--- | |
index.md (8644B) | |
--- | |
1 Keyboard link hinting | |
2 ===================== | |
3 | |
4 Description | |
5 ----------- | |
6 | |
7 This script enables link hinting support to surf. Deploy it into ~/.surf… | |
8 | |
9 Keybindings | |
10 ----------- | |
11 ^f (open link in current window) | |
12 ^F (open link in new window) | |
13 ^c (cancel hinting) | |
14 | |
15 Azerty keyboards | |
16 ---------------- | |
17 Just replace like this to use `&é"'(-è_çà` as numbers : | |
18 | |
19 "U+a0c3" : "0", | |
20 "U+0026" : "1", | |
21 "U+a9c3" : "2", | |
22 "U+0022" : "3", | |
23 "U+0027" : "4", | |
24 "U+0028" : "5", | |
25 "U+002d" : "6", | |
26 "U+a8c3" : "7", | |
27 "U+005f" : "8", | |
28 "U+a7c3" : "9", | |
29 | |
30 Author | |
31 ------ | |
32 | |
33 - The code was originally from chromium but was adapted by nibble(.ds(at… | |
34 | |
35 Code | |
36 ---- | |
37 | |
38 /* based on chromium plugin code, adapted by Nibble<[email protected]… | |
39 var hint_num_str = ''; | |
40 var hint_elems = []; | |
41 var hint_open_in_new_tab = false; | |
42 var hint_enabled = false; | |
43 | |
44 function hintMode(newtab){ | |
45 hint_enabled = true; | |
46 if (newtab) { | |
47 hint_open_in_new_tab = true; | |
48 } else { | |
49 hint_open_in_new_tab = false; | |
50 } | |
51 setHints(); | |
52 document.removeEventListener('keydown', initKeyBind, fal… | |
53 document.addEventListener('keydown', hintHandler, false); | |
54 hint_num_str = ''; | |
55 } | |
56 | |
57 function hintHandler(e){ | |
58 e.preventDefault(); //Stop Default Event | |
59 var pressedKey = get_key(e); | |
60 if (pressedKey == 'Enter') { | |
61 if (hint_num_str == '') | |
62 hint_num_str = '1'; | |
63 judgeHintNum(Number(hint_num_str)); | |
64 } else if (/[0-9]/.test(pressedKey) == false) { | |
65 removeHints(); | |
66 } else { | |
67 hint_num_str += pressedKey; | |
68 var hint_num = Number(hint_num_str); | |
69 if (hint_num * 10 > hint_elems.length + 1) { | |
70 judgeHintNum(hint_num); | |
71 } else { | |
72 var hint_elem = hint_elems[hint_num - 1]; | |
73 if (hint_elem != undefined && hint_elem.… | |
74 setHighlight(hint_elem, true); | |
75 } | |
76 } | |
77 } | |
78 } | |
79 | |
80 function setHighlight(elem, is_active) { | |
81 if (is_active) { | |
82 var active_elem = document.body.querySelector('a… | |
83 if (active_elem != undefined) | |
84 active_elem.setAttribute('highlight', 'h… | |
85 elem.setAttribute('highlight', 'hint_active'); | |
86 } else { | |
87 elem.setAttribute('highlight', 'hint_elem'); | |
88 } | |
89 | |
90 } | |
91 | |
92 function setHintRules() { | |
93 if (document.styleSheets.length < 1) { | |
94 var style = document.createElement("style"); | |
95 style.appendChild(document.createTextNode("")); | |
96 document.head.appendChild(style); | |
97 } | |
98 var ss = document.styleSheets[0]; | |
99 ss.insertRule('a[highlight=hint_elem] {background-color:… | |
100 ss.insertRule('a[highlight=hint_active] {background-colo… | |
101 } | |
102 | |
103 function deleteHintRules() { | |
104 var ss = document.styleSheets[0]; | |
105 ss.deleteRule(0); | |
106 ss.deleteRule(0); | |
107 } | |
108 | |
109 function judgeHintNum(hint_num) { | |
110 var hint_elem = hint_elems[hint_num - 1]; | |
111 if (hint_elem != undefined) { | |
112 execSelect(hint_elem); | |
113 } else { | |
114 removeHints(); | |
115 } | |
116 } | |
117 | |
118 function execSelect(elem) { | |
119 var tag_name = elem.tagName.toLowerCase(); | |
120 var type = elem.type ? elem.type.toLowerCase() : ""; | |
121 if (tag_name == 'a' && elem.href != '') { | |
122 setHighlight(elem, true); | |
123 // TODO: ajax, <select> | |
124 if (hint_open_in_new_tab) | |
125 window.open(elem.href); | |
126 else location.href=elem.href; | |
127 | |
128 } else if (tag_name == 'input' && (type == "submit" || t… | |
129 elem.click(); | |
130 } else if (tag_name == 'input' && (type == "radio" || ty… | |
131 // TODO: toggle checkbox | |
132 elem.checked = !elem.checked; | |
133 } else if (tag_name == 'input' || tag_name == 'textarea'… | |
134 elem.focus(); | |
135 elem.setSelectionRange(elem.value.length, elem.v… | |
136 } | |
137 removeHints(); | |
138 } | |
139 | |
140 function setHints() { | |
141 setHintRules(); | |
142 var win_top = window.scrollY; | |
143 var win_bottom = win_top + window.innerHeight; | |
144 var win_left = window.scrollX; | |
145 var win_right = win_left + window.innerWidth; | |
146 // TODO: <area> | |
147 var elems = document.body.querySelectorAll('a, input:not… | |
148 var div = document.createElement('div'); | |
149 div.setAttribute('highlight', 'hints'); | |
150 document.body.appendChild(div); | |
151 for (var i = 0; i < elems.length; i++) { | |
152 var elem = elems[i]; | |
153 if (!isHintDisplay(elem)) | |
154 continue; | |
155 var pos = elem.getBoundingClientRect(); | |
156 var elem_top = win_top + pos.top; | |
157 var elem_bottom = win_top + pos.bottom; | |
158 var elem_left = win_left + pos.left; | |
159 var elem_right = win_left + pos.left; | |
160 if ( elem_bottom >= win_top && elem_top <= win_b… | |
161 hint_elems.push(elem); | |
162 setHighlight(elem, false); | |
163 var span = document.createElement('span'… | |
164 span.style.cssText = [ | |
165 'left: ', elem_left, 'px;', | |
166 'top: ', elem_top, 'px;', | |
167 'position: absolute;', | |
168 'font-size: 13px;', | |
169 'background-color: ' + (hint_ope… | |
170 'color: white;', | |
171 'font-weight: bold;', | |
172 'padding: 0px 1px;', | |
173 'z-index: 100000;' | |
174 ].join(''); | |
175 span.innerHTML = hint_elems.length; | |
176 div.appendChild(span); | |
177 if (elem.tagName.toLowerCase() == 'a') { | |
178 if (hint_elems.length == 1) { | |
179 setHighlight(elem, true); | |
180 } else { | |
181 setHighlight(elem, false… | |
182 } | |
183 } | |
184 } | |
185 } | |
186 } | |
187 | |
188 function isHintDisplay(elem) { | |
189 var pos = elem.getBoundingClientRect(); | |
190 return (pos.height != 0 && pos.width != 0); | |
191 } | |
192 | |
193 function removeHints() { | |
194 if (!hint_enabled) | |
195 return; | |
196 hint_enabled = false; | |
197 deleteHintRules(); | |
198 for (var i = 0; i < hint_elems.length; i++) { | |
199 hint_elems[i].removeAttribute('highlight'); | |
200 } | |
201 hint_elems = []; | |
202 hint_num_str = ''; | |
203 var div = document.body.querySelector('div[highlight=hin… | |
204 if (div != undefined) { | |
205 document.body.removeChild(div); | |
206 } | |
207 document.removeEventListener('keydown', hintHandler, fal… | |
208 document.addEventListener('keydown', initKeyBind, false); | |
209 } | |
210 | |
211 function addKeyBind( key, func, eve ){ | |
212 var pressedKey = get_key(eve); | |
213 if( pressedKey == key ){ | |
214 eve.preventDefault(); //Stop Default Event | |
215 eval(func); | |
216 } | |
217 } | |
218 | |
219 document.addEventListener( 'keydown', initKeyBind, false ); | |
220 | |
221 function initKeyBind(e){ | |
222 var t = e.target; | |
223 if( t.nodeType == 1){ | |
224 addKeyBind( 'C-f', 'hintMode()', e ); | |
225 addKeyBind( 'C-F', 'hintMode(true)', e ); | |
226 addKeyBind( 'C-c', 'removeHints()', e ); | |
227 } | |
228 } | |
229 | |
230 var keyId = { | |
231 "U+0008" : "BackSpace", | |
232 "U+0009" : "Tab", | |
233 "U+0018" : "Cancel", | |
234 "U+001B" : "Esc", | |
235 "U+0020" : "Space", | |
236 "U+0021" : "!", | |
237 "U+0022" : "\"", | |
238 "U+0023" : "#", | |
239 "U+0024" : "$", | |
240 "U+0026" : "&", | |
241 "U+0027" : "'", | |
242 "U+0028" : "(", | |
243 "U+0029" : ")", | |
244 "U+002A" : "*", | |
245 "U+002B" : "+", | |
246 "U+002C" : ",", | |
247 "U+002D" : "-", | |
248 "U+002E" : ".", | |
249 "U+002F" : "/", | |
250 "U+0030" : "0", | |
251 "U+0031" : "1", | |
252 "U+0032" : "2", | |
253 "U+0033" : "3", | |
254 "U+0034" : "4", | |
255 "U+0035" : "5", | |
256 "U+0036" : "6", | |
257 "U+0037" : "7", | |
258 "U+0038" : "8", | |
259 "U+0039" : "9", | |
260 "U+003A" : ":", | |
261 "U+003B" : ";", | |
262 "U+003C" : "<", | |
263 "U+003D" : "=", | |
264 "U+003E" : ">", | |
265 "U+003F" : "?", | |
266 "U+0040" : "@", | |
267 "U+0041" : "a", | |
268 "U+0042" : "b", | |
269 "U+0043" : "c", | |
270 "U+0044" : "d", | |
271 "U+0045" : "e", | |
272 "U+0046" : "f", | |
273 "U+0047" : "g", | |
274 "U+0048" : "h", | |
275 "U+0049" : "i", | |
276 "U+004A" : "j", | |
277 "U+004B" : "k", | |
278 "U+004C" : "l", | |
279 "U+004D" : "m", | |
280 "U+004E" : "n", | |
281 "U+004F" : "o", | |
282 "U+0050" : "p", | |
283 "U+0051" : "q", | |
284 "U+0052" : "r", | |
285 "U+0053" : "s", | |
286 "U+0054" : "t", | |
287 "U+0055" : "u", | |
288 "U+0056" : "v", | |
289 "U+0057" : "w", | |
290 "U+0058" : "x", | |
291 "U+0059" : "y", | |
292 "U+005A" : "z", | |
293 //"U+005B" : "[", | |
294 //"U+005C" : "\\", | |
295 //"U+005D" : "]", | |
296 "U+00DB" : "[", | |
297 "U+00DC" : "\\", | |
298 "U+00DD" : "]", | |
299 "U+005E" : "^", | |
300 "U+005F" : "_", | |
301 "U+0060" : "`", | |
302 "U+007B" : "{", | |
303 "U+007C" : "|", | |
304 "U+007D" : "}", | |
305 "U+007F" : "Delete", | |
306 "U+00A1" : "¡", | |
307 "U+0300" : "CombGrave", | |
308 "U+0300" : "CombAcute", | |
309 "U+0302" : "CombCircum", | |
310 "U+0303" : "CombTilde", | |
311 "U+0304" : "CombMacron", | |
312 "U+0306" : "CombBreve", | |
313 "U+0307" : "CombDot", | |
314 "U+0308" : "CombDiaer", | |
315 "U+030A" : "CombRing", | |
316 "U+030B" : "CombDblAcute", | |
317 "U+030C" : "CombCaron", | |
318 "U+0327" : "CombCedilla", | |
319 "U+0328" : "CombOgonek", | |
320 "U+0345" : "CombYpogeg", | |
321 "U+20AC" : "€", | |
322 "U+3099" : "CombVoice", | |
323 "U+309A" : "CombSVoice", | |
324 } | |
325 | |
326 function get_key(evt){ | |
327 var key = keyId[evt.keyIdentifier] || evt.keyIdentifier, | |
328 ctrl = evt.ctrlKey ? 'C-' : '', | |
329 meta = (evt.metaKey || evt.altKey) ? 'M-' : '', | |
330 shift = evt.shiftKey ? 'S-' : ''; | |
331 if (evt.shiftKey){ | |
332 if (/^[a-z]$/.test(key)) | |
333 return ctrl+meta+key.toUpperCase(); | |
334 if (/^[0-9]$/.test(key)) { | |
335 switch(key) { | |
336 // TODO | |
337 case "4": | |
338 key = "$"; | |
339 break; | |
340 }; | |
341 return key; | |
342 } | |
343 if (/^(Enter|Space|BackSpace|Tab|Esc|Home|End|Le… | |
344 return ctrl+meta+shift+key; | |
345 } | |
346 return ctrl+meta+key; | |
347 } |