force tabless in kiosk mode
[xxxterm.git] / hinting.js
blobccaafa776a26dec7d35bc3a6be4f161968bde51e
1 /*
2     (c) 2009 by Leon Winter
3     (c) 2009, 2010 by Hannes Schueller
4     (c) 2010 by Hans-Peter Deifel
5     see LICENSE file
6 */
8 function vimprobable_clearfocus() {
9     if(document.activeElement && document.activeElement.blur)
10         document.activeElement.blur();
13 function vimprobable_show_hints(inputText) {
14     if (document.getElementsByTagName("body")[0] !== null && typeof(document.getElementsByTagName("body")[0]) == "object") {
15         var height = window.innerHeight;
16         var width = window.innerWidth;
17         var scrollX = document.defaultView.scrollX;
18         var scrollY = document.defaultView.scrollY;
19         /* prefixing html: will result in namespace error */
20         var hinttags;
21         if (typeof(inputText) == "undefined" || inputText == "") {
22             hinttags = "//*[@onclick or @onmouseover or @onmousedown or @onmouseup or @oncommand or @class='lk' or @role='link' or @href] | //input[not(@type='hidden')] | //a | //area | //iframe | //textarea | //button | //select";
23         } else {
24             /* only elements which match the text entered so far */
25             hinttags = "//*[(@onclick or @onmouseover or @onmousedown or @onmouseup or @oncommand or @class='lk' or @role='link' or @href) and contains(., '" + inputText + "')] | //input[not(@type='hidden') and contains(., '" + inputText + "')] | //a[contains(., '" + inputText + "')] | //area[contains(., '" + inputText + "')] | //iframe[contains(@name, '" + inputText + "')] | //textarea[contains(., '" + inputText + "')] | //button[contains(@value, '" + inputText + "')] | //select[contains(., '" + inputText + "')]";
26         }
28         /* iterator type isn't suitable here, because: "DOMException NVALID_STATE_ERR: The document has been mutated since the result was returned." */
29         var r = document.evaluate(hinttags, document,
30             function(p) {
31                 return 'http://www.w3.org/1999/xhtml';
32             }, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
33         div = document.createElement("div");
34         /* due to the different XPath result type, we will need two counter variables */
35         vimprobable_j = 0;
36         var i;
37         vimprobable_a = [];
38         vimprobable_colors = [];
39         vimprobable_backgrounds = [];
40         for (i = 0; i < r.snapshotLength; i++)
41         {
42             var elem = r.snapshotItem(i);
43             rect = elem.getBoundingClientRect();
44             if (!rect || rect.top > height || rect.bottom < 0 || rect.left > width || rect.right < 0 || !(elem.getClientRects()[0]))
45                 continue;
46             var computedStyle = document.defaultView.getComputedStyle(elem, null);
47             if (computedStyle.getPropertyValue("visibility") != "visible" || computedStyle.getPropertyValue("display") == "none")
48                 continue;
49             var leftpos = Math.max((rect.left + scrollX), scrollX);
50             var toppos = Math.max((rect.top + scrollY), scrollY);
51             vimprobable_a.push(elem);
52             /* making this block DOM compliant */
53             var hint = document.createElement("span");
54             hint.setAttribute("class", "hinting_mode_hint");
55             hint.setAttribute("id", "vimprobablehint" + vimprobable_j);
56             hint.style.position = "absolute";
57             hint.style.left = leftpos + "px";
58             hint.style.top =  toppos + "px";
59             hint.style.background = "red";
60             hint.style.color = "#fff";
61             hint.style.font = "bold 10px monospace";
62             hint.style.zIndex = "99";
63             var text = document.createTextNode(vimprobable_j + 1);
64             hint.appendChild(text);
65             div.appendChild(hint);
66             /* remember site-defined colour of this element */
67             vimprobable_colors[vimprobable_j] = elem.style.color;
68             vimprobable_backgrounds[vimprobable_j] = elem.style.background;
69             /* make the link black to ensure it's readable */
70             elem.style.color = "#000";
71             elem.style.background = "#ff0";
72             vimprobable_j++;
73         }
74         i = 0;
75         while (typeof(vimprobable_a[i]) != "undefined") {
76             vimprobable_a[i].className += " hinting_mode_hint";
77             i++;
78         }
79         document.getElementsByTagName("body")[0].appendChild(div);
80         vimprobable_clearfocus();
81         vimprobable_h = null;
82         if (i == 1) {
83             /* just one hinted element - might as well follow it */
84             return vimprobable_fire(1);
85         }
86     }
88 function vimprobable_fire(n)
90     if (typeof(vimprobable_a[n - 1]) != "undefined") {
91         el = vimprobable_a[n - 1];
92         tag = el.nodeName.toLowerCase();
93         vimprobable_clear();
94         if(tag == "iframe" || tag == "frame" || tag == "textarea" || tag == "input" && (el.type == "text" || el.type == "password" || el.type == "checkbox" || el.type == "radio") || tag == "select") {
95             el.focus();
96             if (tag == "textarea" || tag == "input")
97                 console.log('insertmode_on');
98         } else {
99             if (el.onclick) {
100                 var evObj = document.createEvent('MouseEvents');
101                 evObj.initMouseEvent('click', true, true, window, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, null);
102                 el.dispatchEvent(evObj);
103             } else if (el.href) {
104                 if (el.href.match(/^javascript:/)) {
105                     var evObj = document.createEvent('MouseEvents');
106                     evObj.initMouseEvent('click', true, true, window, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, null);
107                     el.dispatchEvent(evObj);
108                 } else {
109                     /* send signal to open link */
110                     return "open;" + el.href;
111                 }
112             } else {
113                 var evObj = document.createEvent('MouseEvents');
114                 evObj.initMouseEvent('click', true, true, window, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, null);
115                 el.dispatchEvent(evObj);
116             }
117         }
118     }
120 function vimprobable_cleanup()
122     for(e in vimprobable_a) {
123         if (typeof(vimprobable_a[e].className) != "undefined") {
124             vimprobable_a[e].className = vimprobable_a[e].className.replace(/hinting_mode_hint/,'');
125             /* reset to site-defined colour */
126             vimprobable_a[e].style.color = vimprobable_colors[e];
127             vimprobable_a[e].style.background = vimprobable_backgrounds[e];
128         }
129     }
130     div.parentNode.removeChild(div);
131     window.onkeyup = null;
133 function vimprobable_clear()
135     vimprobable_cleanup();
136     console.log("hintmode_off")
139 function vimprobable_update_hints(n)
141     if(vimprobable_h != null) {
142         vimprobable_h.className = vimprobable_h.className.replace("_focus","");
143         vimprobable_h.style.background = "#ff0";
144     }
145     if (vimprobable_j - 1 < n * 10 && typeof(vimprobable_a[n - 1]) != "undefined") {
146         /* return signal to follow the link */
147         return "fire;" + n;
148     } else {
149         if (typeof(vimprobable_a[n - 1]) != "undefined") {
150             (vimprobable_h = vimprobable_a[n - 1]).className = vimprobable_a[n - 1].className.replace("hinting_mode_hint", "hinting_mode_hint_focus");
151             vimprobable_h.style.background = "#8f0";
152         }
153     }
156 function vimprobable_focus_input()
158     if (document.getElementsByTagName("body")[0] !== null && typeof(document.getElementsByTagName("body")[0]) == "object") {
159         /* prefixing html: will result in namespace error */
160         var hinttags = "//input[@type='text'] | //input[@type='password'] | //textarea";
161         var r = document.evaluate(hinttags, document,
162             function(p) {
163                 return 'http://www.w3.org/1999/xhtml';
164             }, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
165         var i;
166         var j = 0;
167         var k = 0;
168         var first = null;
169         for (i = 0; i < r.snapshotLength; i++) {
170             var elem = r.snapshotItem(i);
171             if (k == 0) {
172                 if (elem.style.display != "none" && elem.style.visibility != "hidden") {
173                     first = elem;
174                 } else {
175                     k--;
176                 }
177             }
178             if (j == 1 && elem.style.display != "none" && elem.style.visibility != "hidden") {
179                 elem.focus();
180                 var tag = elem.nodeName.toLowerCase();
181                 if (tag == "textarea" || tag == "input")
182                     console.log('insertmode_on');
183                 break;
184             } else {
185                 if (elem == document.activeElement)
186                     j = 1;
187             }
188             k++;
189         }
190         if (j == 0) {
191             /* no appropriate field found focused - focus the first one */
192             if (first !== null) {
193                 first.focus();
194                 var tag = elem.nodeName.toLowerCase();
195                 if (tag == "textarea" || tag == "input")
196                     console.log('insertmode_on');
197             }
198         }
199     }