diff options
Diffstat (limited to 'itjs/loader.js')
-rw-r--r-- | itjs/loader.js | 275 |
1 files changed, 275 insertions, 0 deletions
diff --git a/itjs/loader.js b/itjs/loader.js new file mode 100644 index 0000000..de6ae9d --- /dev/null +++ b/itjs/loader.js @@ -0,0 +1,275 @@ +/** + * Create loader to request data from server + * + * @param handler Object providing clear()/render() function when data arrives + */ +function it_loader(handler) +{ + /* Clear cache etc. if completely new data */ + this.loader = null; + this.handler = handler; + this.instance = it_loader.instances++; + this.callid = 0; + this.clear(); +} + +/* Methods */ +it_loader.prototype = +{ + +/* Clear cache and initialize handler */ +clear: function() +{ + /* Clear cache etc. if completely new data */ + this.entry = new Array(); + this.start = this.end = 0; + this.attr = { num: 0, loadtime: 0 }; + this.method = "GET"; + this.post_data = null; + + if (this.handler.clear) + this.handler.clear(); +}, + +load: function(baseurl, pos, num, query_volatile, retry) +{ + /* Convert to int */ + pos -= 0; + num -= 0; + + if (isNaN(retry)) + retry = 0; + + if (baseurl != this.baseurl) + { + this.clear(); + this.baseurl = baseurl; + this.start = this.end = pos; + } + + this.pos = pos; + this.num = num; + this.query_volatile = query_volatile; + + if (this.loader) + this.stop(); + + while ((num > 0) && this.entry[pos]) + { + pos++; + num--; + } + + if (this.attr.eof) + num = Math.min(num, this.end - pos); + + if (num > 0) + { + this.loader = null; + var samehost = (baseurl.indexOf('http://') < 0 || baseurl.indexOf(window.location.hostname) > 0); + + if (retry) + baseurl += "&retry=" + retry; + + // use XMLHTTP request if available + if (samehost) + { + try + { + this.loader = new XMLHttpRequest(); + } + catch (e) + { + var classnames = [ 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP' ]; + + for (var i in classnames) + { + try + { + this.loader = new ActiveXObject(classnames[i]); + break; + } + catch (e) { } + } + } + + try + { + this.loader.open(this.method, baseurl + "&pos=" + pos + "&num=" + num + (query_volatile ? query_volatile : "")); + var me = this; + this.loader.onreadystatechange = function() { me.readyStateChanged(); } + var workingxmlhttp = this.loader.onreadystatechange; + + if (!workingxmlhttp) /* Old Konqueror */ + this.loader = null; + } + catch (e) { } + } + + this.starttime = new Date().getTime(); + this.retry = retry; + + if (this.loader) + { + if (this.method == "POST") + this.loader.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); + + this.loader.send(this.post_data); + } + else + { + var req_url = baseurl + "&pos=" + pos + "&num=" + num + (query_volatile ? query_volatile : "") + (this.post_data ? '&' + this.post_data : "") + "&itjs_call=it_loader.__inst" + this.instance + "&itjs_callid=" + ++this.callid; + + if (samehost || (window.opera && !window.XMLHttpRequest)) // Opera 7 only works with iframes + { + this.scrpt = document.createElement("iframe"); + this.scrpt.style.width = this.scrpt.style.height = 1; + req_url += "&itjs_iframe=1"; + } + else + this.scrpt = document.createElement("script"); + + it_loader['__inst'+this.instance] = this; + this.loader = { starttime: this.starttime, retry: retry }; + try + { + if (!document.all) this.scrpt.src = req_url; + document.body.appendChild(this.scrpt); + if (document.all) this.scrpt.src = req_url; + } + catch (e) { return false; } + } + } + else + this.handler.render(this); + + return true; +}, + +post: function(baseurl, data) +{ + this.clear(); + this.method = "POST"; + this.baseurl = baseurl; + this.start = this.end = 10; + this.post_data = ""; + + if (typeof data == 'object') + { + for (var k in data) + this.post_data += (this.post_data ? "&" : "") + k + "=" + escape(data[k]); + } + else + this.post_data = data; + + this.load(baseurl, 0, 1, ""); +}, + +readyStateChanged: function() +{ + var loader = this.loader; // Avoid race conditions + it_loader.sequence += "r"; + + if (loader && (loader.readyState == 4)) + { + var data = null; + + try + { + if (loader.responseText != "") + data = eval("("+ loader.responseText + ")"); + } + catch (e) + { + var retry = this.retry + 1; + + if (retry < 10) + it_timer({ object: this, method: "retryload", timeout: Math.pow(5, Math.min(retry, 5)), baseurl: this.baseurl, pos: this.pos, num: this.num, query_volatile: this.query_volatile, retry: retry }); + else + ED(e, loader.responseText); + } + + if (data) + this.dataReady(data, this.callid); + } +}, + +retryload: function(p) +{ + this.load(p.baseurl, p.pos, p.num, p.query_volatile, p.retry); +}, + +dataReady: function(data, callid) +{ + var fixkonqueror33gcbug = this.loader; + var loadtime = new Date().getTime() - this.starttime; + it_loader.sequence += "e"; + + this.loader = null; + + if ((typeof data == "object") && (this.callid == callid)) + { + this.attr = { loadtime: loadtime }; + + for (var key in data) + { + var value = data[key]; + var id = key - 0; + + if (!isNaN(id)) + { + this.start = Math.min(this.start, id); + this.end = Math.max(this.end, id + 1); + this.entry[id] = data[key]; + } + else + this.attr[key] = data[key]; + } + + if (this.attr.eof) + this.attr.num = this.end; /* Fix bogus # of result value */ + + this.handler.render(this); + + if (!this.attr.eof && (this.end < this.pos + this.num)) + this.load(this.baseurl, this.end, this.pos + this.num - this.end); + + it_loader.sequence += "h"; + } + + this.unlink(); +}, + +stop: function() +{ + try + { + this.loader.abort(); + } + catch (e) { } + + this.unlink(); +}, + +unlink: function() +{ + if (it_loader['__inst'+this.instance]) + it_loader['__inst'+this.instance] = null; + + if (this.loader) + this.loader = null; + + if (this.scrpt) + { + document.body.removeChild(this.scrpt); + this.scrpt = null; + } + + it_loader.sequence = ""; +}/* NO COMMA */ + +} + +// static properties +it_loader.instances = 0; +it_loader.sequence = ""; |