Introduction
Introduction Statistics Contact Development Disclaimer Help
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 }
You are viewing proxied material from suckless.org. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.