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