build: introduce luci-base
[project/luci.git] / modules / base / htdocs / luci-static / resources / xhr.js
diff --git a/modules/base/htdocs/luci-static/resources/xhr.js b/modules/base/htdocs/luci-static/resources/xhr.js
new file mode 100644 (file)
index 0000000..701c12a
--- /dev/null
@@ -0,0 +1,241 @@
+/*
+ * xhr.js - XMLHttpRequest helper class
+ * (c) 2008-2010 Jo-Philipp Wich
+ */
+
+XHR = function()
+{
+       this.reinit = function()
+       {
+               if (window.XMLHttpRequest) {
+                       this._xmlHttp = new XMLHttpRequest();
+               }
+               else if (window.ActiveXObject) {
+                       this._xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
+               }
+               else {
+                       alert("xhr.js: XMLHttpRequest is not supported by this browser!");
+               }
+       }
+
+       this.busy = function() {
+               if (!this._xmlHttp)
+                       return false;
+
+               switch (this._xmlHttp.readyState)
+               {
+                       case 1:
+                       case 2:
+                       case 3:
+                               return true;
+
+                       default:
+                               return false;
+               }
+       }
+
+       this.abort = function() {
+               if (this.busy())
+                       this._xmlHttp.abort();
+       }
+
+       this.get = function(url,data,callback)
+       {
+               this.reinit();
+
+               var xhr  = this._xmlHttp;
+               var code = this._encode(data);
+
+               url = location.protocol + '//' + location.host + url;
+
+               if (code)
+                       if (url.substr(url.length-1,1) == '&')
+                               url += code;
+                       else
+                               url += '?' + code;
+
+               xhr.open('GET', url, true);
+
+               xhr.onreadystatechange = function()
+               {
+                       if (xhr.readyState == 4) {
+                               var json = null;
+                               if (xhr.getResponseHeader("Content-Type") == "application/json") {
+                                       try {
+                                               json = eval('(' + xhr.responseText + ')');
+                                       }
+                                       catch(e) {
+                                               json = null;
+                                       }
+                               }
+
+                               callback(xhr, json);
+                       }
+               }
+
+               xhr.send(null);
+       }
+
+       this.post = function(url,data,callback)
+       {
+               this.reinit();
+
+               var xhr  = this._xmlHttp;
+               var code = this._encode(data);
+
+               xhr.onreadystatechange = function()
+               {
+                       if (xhr.readyState == 4)
+                               callback(xhr);
+               }
+
+               xhr.open('POST', url, true);
+               xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
+               xhr.setRequestHeader('Content-length', code.length);
+               xhr.setRequestHeader('Connection', 'close');
+               xhr.send(code);
+       }
+
+       this.cancel = function()
+       {
+               this._xmlHttp.onreadystatechange = function(){};
+               this._xmlHttp.abort();
+       }
+
+       this.send_form = function(form,callback,extra_values)
+       {
+               var code = '';
+
+               for (var i = 0; i < form.elements.length; i++)
+               {
+                       var e = form.elements[i];
+
+                       if (e.options)
+                       {
+                               code += (code ? '&' : '') +
+                                       form.elements[i].name + '=' + encodeURIComponent(
+                                               e.options[e.selectedIndex].value
+                                       );
+                       }
+                       else if (e.length)
+                       {
+                               for (var j = 0; j < e.length; j++)
+                                       if (e[j].name) {
+                                               code += (code ? '&' : '') +
+                                                       e[j].name + '=' + encodeURIComponent(e[j].value);
+                                       }
+                       }
+                       else
+                       {
+                               code += (code ? '&' : '') +
+                                       e.name + '=' + encodeURIComponent(e.value);
+                       }
+               }
+
+               if (typeof extra_values == 'object')
+                       for (var key in extra_values)
+                               code += (code ? '&' : '') +
+                                       key + '=' + encodeURIComponent(extra_values[key]);
+
+               return(
+                       (form.method == 'get')
+                               ? this.get(form.getAttribute('action'), code, callback)
+                               : this.post(form.getAttribute('action'), code, callback)
+               );
+       }
+
+       this._encode = function(obj)
+       {
+               obj = obj ? obj : { };
+               obj['_'] = Math.random();
+
+               if (typeof obj == 'object')
+               {
+                       var code = '';
+                       var self = this;
+
+                       for (var k in obj)
+                               code += (code ? '&' : '') +
+                                       k + '=' + encodeURIComponent(obj[k]);
+
+                       return code;
+               }
+
+               return obj;
+       }
+}
+
+XHR.get = function(url, data, callback)
+{
+       (new XHR()).get(url, data, callback);
+}
+
+XHR.poll = function(interval, url, data, callback)
+{
+       if (isNaN(interval) || interval < 1)
+               interval = 5;
+
+       if (!XHR._q)
+       {
+               XHR._t = 0;
+               XHR._q = [ ];
+               XHR._r = function() {
+                       for (var i = 0, e = XHR._q[0]; i < XHR._q.length; e = XHR._q[++i])
+                       {
+                               if (!(XHR._t % e.interval) && !e.xhr.busy())
+                                       e.xhr.get(e.url, e.data, e.callback);
+                       }
+
+                       XHR._t++;
+               };
+       }
+
+       XHR._q.push({
+               interval: interval,
+               callback: callback,
+               url:      url,
+               data:     data,
+               xhr:      new XHR()
+       });
+
+       XHR.run();
+}
+
+XHR.halt = function()
+{
+       if (XHR._i)
+       {
+               /* show & set poll indicator */
+               try {
+                       document.getElementById('xhr_poll_status').style.display = '';
+                       document.getElementById('xhr_poll_status_on').style.display = 'none';
+                       document.getElementById('xhr_poll_status_off').style.display = '';
+               } catch(e) { }
+
+               window.clearInterval(XHR._i);
+               XHR._i = null;
+       }
+}
+
+XHR.run = function()
+{
+       if (XHR._r && !XHR._i)
+       {
+               /* show & set poll indicator */
+               try {
+                       document.getElementById('xhr_poll_status').style.display = '';
+                       document.getElementById('xhr_poll_status_on').style.display = '';
+                       document.getElementById('xhr_poll_status_off').style.display = 'none';
+               } catch(e) { }
+
+               /* kick first round manually to prevent one second lag when setting up
+                * the poll interval */
+               XHR._r();
+               XHR._i = window.setInterval(XHR._r, 1000);
+       }
+}
+
+XHR.running = function()
+{
+       return !!(XHR._r && XHR._i);
+}