cookie_daemon.py now deletes abandoned cookie daemon sockets.
[uzbl-mobile] / examples / data / uzbl / scripts / follow_Numbers.js
1 /* This is the basic linkfollowing script.
2  * Its pretty stable, only using numbers to navigate.
3  *
4  * TODO: Some pages mess around a lot with the zIndex which
5  * lets some hints in the background.
6  * TODO: Some positions are not calculated correctly (mostly
7  * because of uber-fancy-designed-webpages. Basic HTML and CSS
8  * works good
9  * TODO: Still some links can't be followed/unexpected things
10  * happen. Blame some freaky webdesigners ;)
11  */
12
13 //Just some shortcuts and globals
14 var uzblid = 'uzbl_link_hint';
15 var uzbldivid = uzblid + '_div_container';
16 var doc = document;
17 var win = window;
18 var links = document.links;
19 var forms = document.forms;
20 //Make onlick-links "clickable"
21 try {
22     HTMLElement.prototype.click = function() {
23         if (typeof this.onclick == 'function') {
24             this.onclick({
25                 type: 'click'
26             });
27         }
28     };
29 } catch(e) {}
30 //Catch the ESC keypress to stop linkfollowing
31 function keyPressHandler(e) {
32     var kC = window.event ? event.keyCode: e.keyCode;
33     var Esc = window.event ? 27 : e.DOM_VK_ESCAPE;
34     if (kC == Esc) {
35         removeAllHints();
36     }
37 }
38 //Calculate element position to draw the hint
39 //Pretty accurate but on fails in some very fancy cases
40 function elementPosition(el) {
41     var up = el.offsetTop;
42     var left = el.offsetLeft;
43     var width = el.offsetWidth;
44     var height = el.offsetHeight;
45     while (el.offsetParent) {
46         el = el.offsetParent;
47         up += el.offsetTop;
48         left += el.offsetLeft;
49     }
50     return [up, left, width, height];
51 }
52 //Calculate if an element is visible
53 function isVisible(el) {
54     if (el == doc) {
55         return true;
56     }
57     if (!el) {
58         return false;
59     }
60     if (!el.parentNode) {
61         return false;
62     }
63     if (el.style) {
64         if (el.style.display == 'none') {
65             return false;
66         }
67         if (el.style.visibility == 'hidden') {
68             return false;
69         }
70     }
71     return isVisible(el.parentNode);
72 }
73 //Calculate if an element is on the viewport.
74 function elementInViewport(el) {
75     offset = elementPosition(el);
76     var up = offset[0];
77     var left = offset[1];
78     var width = offset[2];
79     var height = offset[3];
80     return up < window.pageYOffset + window.innerHeight && left < window.pageXOffset + window.innerWidth && (up + height) > window.pageYOffset && (left + width) > window.pageXOffset;
81 }
82 //Removes all hints/leftovers that might be generated
83 //by this script.
84 function removeAllHints() {
85     var elements = doc.getElementById(uzbldivid);
86     if (elements) {
87         elements.parentNode.removeChild(elements);
88     }
89 }
90 //Generate a hint for an element with the given label
91 //Here you can play around with the style of the hints!
92 function generateHint(el, label) {
93     var pos = elementPosition(el);
94     var hint = doc.createElement('div');
95     hint.setAttribute('name', uzblid);
96     hint.innerText = label;
97     hint.style.display = 'inline';
98     hint.style.backgroundColor = '#B9FF00';
99     hint.style.border = '2px solid #4A6600';
100     hint.style.color = 'black';
101     hint.style.fontSize = '9px';
102     hint.style.fontWeight = 'bold';
103     hint.style.lineHeight = '9px';
104     hint.style.margin = '0px';
105     hint.style.padding = '1px';
106     hint.style.position = 'absolute';
107     hint.style.zIndex = '1000';
108     hint.style.left = pos[1] + 'px';
109     hint.style.top = pos[0] + 'px';
110     var img = el.getElementsByTagName('img');
111     if (img.length > 0) {
112         hint.style.left = pos[1] + img[0].width / 2 + 'px';
113     }
114     hint.style.textDecoration = 'none';
115     hint.style.webkitBorderRadius = '6px';
116     // Play around with this, pretty funny things to do :)
117     hint.style.webkitTransform = 'scale(1) rotate(0deg) translate(-6px,-5px)';
118     return hint;
119 }
120 //Here we choose what to do with an element if we
121 //want to "follow" it. On form elements we "select"
122 //or pass the focus, on links we try to perform a click,
123 //but at least set the href of the link. (needs some improvements)
124 function clickElem(item) {
125     removeAllHints();
126     if (item) {
127         var name = item.tagName;
128         if (name == 'A') {
129             item.click();
130             window.location = item.href;
131         } else if (name == 'INPUT') {
132             var type = item.getAttribute('type').toUpperCase();
133             if (type == 'TEXT' || type == 'FILE' || type == 'PASSWORD') {
134                 item.focus();
135                 item.select();
136             } else {
137                 item.click();
138             }
139         } else if (name == 'TEXTAREA' || name == 'SELECT') {
140             item.focus();
141             item.select();
142         } else {
143             item.click();
144             window.location = item.href;
145         }
146     }
147 }
148 //Returns a list of all links (in this version
149 //just the elements itself, but in other versions, we
150 //add the label here.
151 function addLinks() {
152     res = [[], []];
153     for (var l = 0; l < links.length; l++) {
154         var li = links[l];
155         if (isVisible(li) && elementInViewport(li)) {
156             res[0].push(li);
157         }
158     }
159     return res;
160 }
161 //Same as above, just for the form elements
162 function addFormElems() {
163     res = [[], []];
164     for (var f = 0; f < forms.length; f++) {
165         for (var e = 0; e < forms[f].elements.length; e++) {
166             var el = forms[f].elements[e];
167             if (el && ['INPUT', 'TEXTAREA', 'SELECT'].indexOf(el.tagName) + 1 && isVisible(el) && elementInViewport(el)) {
168                 res[0].push(el);
169             }
170         }
171     }
172     return res;
173 }
174 //Draw all hints for all elements passed. "len" is for
175 //the number of chars we should use to avoid collisions
176 function reDrawHints(elems, chars) {
177     removeAllHints();
178     var hintdiv = doc.createElement('div');
179     hintdiv.setAttribute('id', uzbldivid);
180     for (var i = 0; i < elems[0].length; i++) {
181         if (elems[0][i]) {
182             var label = elems[1][i].substring(chars);
183             var h = generateHint(elems[0][i], label);
184             hintdiv.appendChild(h);
185         }
186     }
187     if (document.body) {
188         document.body.appendChild(hintdiv);
189     }
190 }
191 //Put it all together
192 function followLinks(follow) {
193     var s = follow.split('');
194     var linknr = parseInt(follow, 10);
195     if (document.body) document.body.setAttribute('onkeyup', 'keyPressHandler(event)');
196     var linkelems = addLinks();
197     var formelems = addFormElems();
198     var elems = [linkelems[0].concat(formelems[0]), linkelems[1].concat(formelems[1])];
199     var len = (elems[0].length + '').length;
200     var oldDiv = doc.getElementById(uzbldivid);
201     var leftover = [[], []];
202     if (linknr + 1 && s.length == len && linknr < elems[0].length && linknr >= 0) {
203         clickElem(elems[0][linknr]);
204     } else {
205         for (var j = 0; j < elems[0].length; j++) {
206             var b = true;
207             var label = j + '';
208             var n = label.length;
209             for (n; n < len; n++) {
210                 label = '0' + label;
211             }
212             for (var k = 0; k < s.length; k++) {
213                 b = b && label.charAt(k) == s[k];
214             }
215             if (b) {
216                 leftover[0].push(elems[0][j]);
217                 leftover[1].push(label);
218             }
219         }
220         reDrawHints(leftover, s.length);
221     }
222 }
223 followLinks('%s');