Merge pull request #1309 from dibdot/dnscrypt-proxy
[project/luci.git] / modules / luci-base / htdocs / luci-static / resources / xhr.js
1 /*
2  * xhr.js - XMLHttpRequest helper class
3  * (c) 2008-2010 Jo-Philipp Wich
4  */
5
6 XHR = function()
7 {
8         this.reinit = function()
9         {
10                 if (window.XMLHttpRequest) {
11                         this._xmlHttp = new XMLHttpRequest();
12                 }
13                 else if (window.ActiveXObject) {
14                         this._xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
15                 }
16                 else {
17                         alert("xhr.js: XMLHttpRequest is not supported by this browser!");
18                 }
19         }
20
21         this.busy = function() {
22                 if (!this._xmlHttp)
23                         return false;
24
25                 switch (this._xmlHttp.readyState)
26                 {
27                         case 1:
28                         case 2:
29                         case 3:
30                                 return true;
31
32                         default:
33                                 return false;
34                 }
35         }
36
37         this.abort = function() {
38                 if (this.busy())
39                         this._xmlHttp.abort();
40         }
41
42         this.get = function(url,data,callback)
43         {
44                 this.reinit();
45
46                 var xhr  = this._xmlHttp;
47                 var code = this._encode(data);
48
49                 url = location.protocol + '//' + location.host + url;
50
51                 if (code)
52                         if (url.substr(url.length-1,1) == '&')
53                                 url += code;
54                         else
55                                 url += '?' + code;
56
57                 xhr.open('GET', url, true);
58
59                 xhr.onreadystatechange = function()
60                 {
61                         if (xhr.readyState == 4) {
62                                 var json = null;
63                                 if (xhr.getResponseHeader("Content-Type") == "application/json") {
64                                         try {
65                                                 json = eval('(' + xhr.responseText + ')');
66                                         }
67                                         catch(e) {
68                                                 json = null;
69                                         }
70                                 }
71
72                                 callback(xhr, json);
73                         }
74                 }
75
76                 xhr.send(null);
77         }
78
79         this.post = function(url,data,callback)
80         {
81                 this.reinit();
82
83                 var xhr  = this._xmlHttp;
84                 var code = this._encode(data);
85
86                 xhr.onreadystatechange = function()
87                 {
88                         if (xhr.readyState == 4)
89                                 callback(xhr);
90                 }
91
92                 xhr.open('POST', url, true);
93                 xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
94                 xhr.send(code);
95         }
96
97         this.cancel = function()
98         {
99                 this._xmlHttp.onreadystatechange = function(){};
100                 this._xmlHttp.abort();
101         }
102
103         this.send_form = function(form,callback,extra_values)
104         {
105                 var code = '';
106
107                 for (var i = 0; i < form.elements.length; i++)
108                 {
109                         var e = form.elements[i];
110
111                         if (e.options)
112                         {
113                                 code += (code ? '&' : '') +
114                                         form.elements[i].name + '=' + encodeURIComponent(
115                                                 e.options[e.selectedIndex].value
116                                         );
117                         }
118                         else if (e.length)
119                         {
120                                 for (var j = 0; j < e.length; j++)
121                                         if (e[j].name) {
122                                                 code += (code ? '&' : '') +
123                                                         e[j].name + '=' + encodeURIComponent(e[j].value);
124                                         }
125                         }
126                         else
127                         {
128                                 code += (code ? '&' : '') +
129                                         e.name + '=' + encodeURIComponent(e.value);
130                         }
131                 }
132
133                 if (typeof extra_values == 'object')
134                         for (var key in extra_values)
135                                 code += (code ? '&' : '') +
136                                         key + '=' + encodeURIComponent(extra_values[key]);
137
138                 return(
139                         (form.method == 'get')
140                                 ? this.get(form.getAttribute('action'), code, callback)
141                                 : this.post(form.getAttribute('action'), code, callback)
142                 );
143         }
144
145         this._encode = function(obj)
146         {
147                 obj = obj ? obj : { };
148                 obj['_'] = Math.random();
149
150                 if (typeof obj == 'object')
151                 {
152                         var code = '';
153                         var self = this;
154
155                         for (var k in obj)
156                                 code += (code ? '&' : '') +
157                                         k + '=' + encodeURIComponent(obj[k]);
158
159                         return code;
160                 }
161
162                 return obj;
163         }
164 }
165
166 XHR.get = function(url, data, callback)
167 {
168         (new XHR()).get(url, data, callback);
169 }
170
171 XHR.poll = function(interval, url, data, callback)
172 {
173         if (isNaN(interval) || interval < 1)
174                 interval = 5;
175
176         if (!XHR._q)
177         {
178                 XHR._t = 0;
179                 XHR._q = [ ];
180                 XHR._r = function() {
181                         for (var i = 0, e = XHR._q[0]; i < XHR._q.length; e = XHR._q[++i])
182                         {
183                                 if (!(XHR._t % e.interval) && !e.xhr.busy())
184                                         e.xhr.get(e.url, e.data, e.callback);
185                         }
186
187                         XHR._t++;
188                 };
189         }
190
191         XHR._q.push({
192                 interval: interval,
193                 callback: callback,
194                 url:      url,
195                 data:     data,
196                 xhr:      new XHR()
197         });
198
199         XHR.run();
200 }
201
202 XHR.halt = function()
203 {
204         if (XHR._i)
205         {
206                 /* show & set poll indicator */
207                 try {
208                         document.getElementById('xhr_poll_status').style.display = '';
209                         document.getElementById('xhr_poll_status_on').style.display = 'none';
210                         document.getElementById('xhr_poll_status_off').style.display = '';
211                 } catch(e) { }
212
213                 window.clearInterval(XHR._i);
214                 XHR._i = null;
215         }
216 }
217
218 XHR.run = function()
219 {
220         if (XHR._r && !XHR._i)
221         {
222                 /* show & set poll indicator */
223                 try {
224                         document.getElementById('xhr_poll_status').style.display = '';
225                         document.getElementById('xhr_poll_status_on').style.display = '';
226                         document.getElementById('xhr_poll_status_off').style.display = 'none';
227                 } catch(e) { }
228
229                 /* kick first round manually to prevent one second lag when setting up
230                  * the poll interval */
231                 XHR._r();
232                 XHR._i = window.setInterval(XHR._r, 1000);
233         }
234 }
235
236 XHR.running = function()
237 {
238         return !!(XHR._r && XHR._i);
239 }