summaryrefslogtreecommitdiff
path: root/devel-utf8/itjs
diff options
context:
space:
mode:
Diffstat (limited to 'devel-utf8/itjs')
-rw-r--r--devel-utf8/itjs/0.gifbin0 -> 43 bytes
-rw-r--r--devel-utf8/itjs/boot.js253
-rw-r--r--devel-utf8/itjs/error.gif11
-rwxr-xr-xdevel-utf8/itjs/http.js245
-rw-r--r--devel-utf8/itjs/it.js297
-rw-r--r--devel-utf8/itjs/loader.js141
-rw-r--r--devel-utf8/itjs/state.html31
-rw-r--r--devel-utf8/itjs/state.js120
-rw-r--r--devel-utf8/itjs/timer.js64
9 files changed, 1162 insertions, 0 deletions
diff --git a/devel-utf8/itjs/0.gif b/devel-utf8/itjs/0.gif
new file mode 100644
index 0000000..5bfd67a
--- /dev/null
+++ b/devel-utf8/itjs/0.gif
Binary files differ
diff --git a/devel-utf8/itjs/boot.js b/devel-utf8/itjs/boot.js
new file mode 100644
index 0000000..059bd78
--- /dev/null
+++ b/devel-utf8/itjs/boot.js
@@ -0,0 +1,253 @@
+// $Id$
+
+var it_boot_status = "boot";
+var it_panictimer = window.setTimeout("it_panic({reason:it_boot_status})", 31337), it_domtimer;
+var it_starttime = new Date().getTime();
+
+function it_stacktrace()
+{
+ var stacktrace = "";
+ var callstack_done = false;
+
+ try { i.dont.exist += 0; } // does not exist - that's the point
+ catch (e)
+ {
+ if (e.stack) // Firefox
+ {
+ stacktrace = e.stack.replace(/^[^\n]*\n/,'').replace(/(\n@)?\s+$/,'$1').replace(/^\(/g,'{anonymous}(') + ';';
+ callstack_done = true;
+ }
+ else if (window.opera && e.message) // Opera
+ {
+ var entry, lines = e.message.split("\n");
+ for (var i=1, len=lines.length; i < len; i++)
+ {
+ if (lines[i].match(/^\s*[A-Za-z0-9\-_\$]+\(/))
+ {
+ entry = lines[i];
+ // append next line also since it has the file info
+ if (lines[i+1])
+ {
+ entry += " at " + lines[i+1];
+ i++;
+ }
+ stacktrace += entry + ',';
+ }
+ }
+ callstack_done = true;
+ }
+ }
+
+ if (!callstack_done) // IE and Safari
+ {
+ var fname, current_func = arguments.callee.caller;
+ while (current_func)
+ {
+ fname = /function\s*([\w\-$]+)?\s*\(/.test(current_func.toString()) ? RegExp.$1 || 'anonymous' : 'anonymous';
+ stacktrace += fname + ',';
+ current_func = current_func.caller;
+ }
+ }
+
+ return stacktrace;
+}
+
+function it_catcherr(msg, url, line)
+{
+ var stacktrace = it_stacktrace();
+
+ if (typeof it_boot.sequence != 'undefined')
+ {
+ // trigger it_boot retry if error occured while evaluating loaded script
+ if (it_boot.sequence == 'ble' && it_boot.file)
+ {
+ it_boot(it_boot.file, true);
+ return true;
+ }
+
+ stacktrace += "it_boot=" + it_boot.sequence + ";it_boot_file=" + it_boot.file;
+ }
+ if (typeof window.it_loader != 'undefined' && it_loader.sequence)
+ stacktrace += "it_loader=" + it_loader.sequence + ";";
+
+ it_boot_report({msg:msg, url:url, line:line, stacktrace:stacktrace});
+
+ return !window.env || !!window.env.is_live_server; // No env or live server -> suppress error
+}
+
+window.onerror = it_catcherr;
+
+function it_boot_addparam(url, param)
+{
+ return url + (url.match(/\?/) ? "&" : "?") + param;
+}
+
+function it_panic(p)
+{
+ if (!document.location.href.match(/[?&]static=/)) // Avoid loop
+ window.setTimeout("document.location.href = it_boot_addparam(document.location.href, 'static=" + p.reason + "')", 500);
+
+ p.type = "panic";
+ p.stacktrace = it_stacktrace();
+ return it_boot_report(p);
+}
+
+function it_boot_report(p)
+{
+ window.clearTimeout(window.it_domtimer);
+ window.clearTimeout(window.it_panictimer);
+ var loader = null;
+ var data = "";
+ var postdata = p.data;
+ delete p.data;
+ p.time = new Date().getTime() - it_starttime;
+
+ for (var k in p)
+ data += (data ? '&' : '') + k + "=" + escape(p[k]).replace(/\+/g, "%2B");
+
+ var url = "/itjs/error.gif?" + data;
+
+ if (postdata)
+ {
+ loader = it_boot_getloader();
+ for (var k in postdata)
+ data += (data ? '&' : '') + k + "=" + escape(postdata[k]).replace(/\+/g, "%2B");
+ }
+
+ try
+ {
+ loader.open('POST', url);
+ loader.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+ loader.send(data);
+ }
+ catch (e)
+ {
+ new Image().src = url;
+ }
+}
+
+function it_boot_checkcss(style, key, value)
+{
+ return navigator.userAgent.match(/konqueror/i) || (style && style.getPropertyValue && (style.getPropertyValue(key) == value));
+}
+
+function it_boot_init()
+{
+ it_boot.sequence += "i";
+ window.it_domtimer = null;
+ var konqueror = navigator.userAgent.match(/konqueror/i);
+ var doc = document;
+ var dom = doc && (dom = doc.getElementById('it_boot_dom')); // HTML has been rendered
+ var view = dom && doc.defaultView; // We can check if stylesheet is active
+ var style = view && view.getComputedStyle && view.getComputedStyle(dom, '');
+ var css = window.it_boot_checkcss(style, "visibility", "hidden"); // CSS active (inline style on tag)
+ var stylesheet = window.it_boot_checkcss(style, "display", "none"); // External stylesheet loaded
+
+ if (!(doc || !(it_boot_status = "doc")) || !(dom || !(it_boot_status = "dom")) || (style && !(stylesheet || !(it_boot_status = "stylesheet"))))
+ {
+ window.it_domtimer = window.setTimeout("it_boot_init()" , 42);
+
+ if (style && !css)
+ it_panic({reason:"css"});
+
+ return;
+ }
+
+ window.clearTimeout(window.it_panictimer);
+ it_boot.sequence += "s";
+ window.it_boot_start();
+ it_boot.sequence = "";
+}
+
+function it_boot_getloader()
+{
+ var result = null;
+
+ if (!navigator.userAgent.match(/iPhone|iP.d/)) // Do not use XMLHttpRequest on iOS devices as it does not use cache
+ {
+ try
+ {
+ result = new XMLHttpRequest();
+ }
+ catch (e)
+ {
+ var classnames = [ 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP' ];
+
+ for (var i in classnames)
+ try { result = new ActiveXObject(classnames[i]); break; } catch (e) {}
+ }
+ }
+
+ return result;
+}
+
+function it_boot(file, isretry)
+{
+ it_boot.file = file;
+ it_boot.sequence = isretry ? "r" : "b";
+ var loader = it_boot_getloader();
+
+ if (loader)
+ {
+ it_boot.sequence += "l";
+ loader.open("GET", it_boot_addparam(file, "boot=1" + (isretry ? "&retry=1" : "")));
+ loader.onreadystatechange = function()
+ {
+ var error = "", code = "";
+
+ if (loader.readyState == 4)
+ {
+ if (loader.status < 400) // Opera gives back 304 if from cache
+ {
+ // check length cookie
+ var ln = String(loader.responseText).match(/\*sln:([0-9]+)[^\n]*\n([\s\S]*\n)\/\*eln:\1/);
+ code = ln ? unescape(ln[2]) : loader.responseText;
+ if (ln && ln[1]-0 == code.length)
+ {
+ it_boot.sequence += "e";
+ if (!window.env || !!window.env.is_live_server)
+ code = "try {" + code + "} catch (e) { it_catcherr(e.message, it_boot.file, -1); }"; // Wrapped in try/catch as Konqueror does not support window.onerror
+ if (window.execScript)
+ window.execScript(code, "javascript"); // IE work-around to get script executed in global scope
+ else
+ window.setTimeout(code, 0); // Standard compliant version
+ }
+ else
+ error = (ln ? "length mismatch: " + ln[1] + " != " + code.length : "no length cookie");
+ }
+ else
+ error = loader.statusText;
+
+ if (error)
+ {
+ if (isretry)
+ it_panic({reason:'load', error:error, data:{code:code}});
+ else
+ it_boot(file, true);
+ }
+ }
+ }
+ loader.send(null);
+ }
+ else
+ {
+ var doc = document;
+ var dom = doc && (dom = doc.getElementById('it_boot_dom')); // HTML has been rendered
+ it_boot.sequence += "n";
+
+ if (window.opera || (document.all && navigator.platform.indexOf("Mac") >= 0))
+ document.write('<sc'+'ript type="text/javascript" src="'+it_boot_addparam(file, 'boot=1&script=1')+'"><\/sc'+'ript>');
+ else if (dom)
+ {
+ var tag = doc.createElement("script");
+ tag.src = it_boot_addparam(file, 'boot=1&script=1&retry=1');
+ dom.appendChild(tag);
+ }
+ else
+ window.it_domtimer = window.setTimeout("it_boot('" + file + "')" , 42);
+ }
+}
+
+if (document.documentElement)
+ document.documentElement.className += ' js';
+
diff --git a/devel-utf8/itjs/error.gif b/devel-utf8/itjs/error.gif
new file mode 100644
index 0000000..d743ef1
--- /dev/null
+++ b/devel-utf8/itjs/error.gif
@@ -0,0 +1,11 @@
+<?php
+
+if ($_POST)
+{
+ $data = "<?php return " . var_export($_POST, true) . ";\n";
+ @mkdir("/tmp/itjs");
+ file_put_contents("/tmp/itjs/error-" . date("YmdHis"), $data);
+}
+
+header("Content-Type: image/gif");
+readfile(dirname($_SERVER['SCRIPT_FILENAME']) . "/itjs/0.gif");
diff --git a/devel-utf8/itjs/http.js b/devel-utf8/itjs/http.js
new file mode 100755
index 0000000..5773cda
--- /dev/null
+++ b/devel-utf8/itjs/http.js
@@ -0,0 +1,245 @@
+/**
+ * Create http loader to request data from server
+ *
+ * @param cb Callback function or object with keys 'object', 'method', ['errorhandler']
+ */
+function it_http(cb)
+{
+ this.instance = it_http.instances++;
+ this.callback = cb ? cb : {};
+ this.req = null;
+ this.scrpt = [];
+ this.callid = 0;
+ this.busy = false;
+
+ // register global reference
+ it_http['__inst' + this.instance] = this;
+}
+
+/* Methods */
+it_http.prototype = {
+
+/* send GET request and trigger callback */
+get: function(url, callback)
+{
+ if (typeof callback != 'undefined')
+ this.callback = callback;
+ this.send(url, 'GET');
+},
+
+/* send POST request with data and trigger callback */
+post: function(url, data, callback)
+{
+ if (typeof callback != 'undefined')
+ this.callback = callback;
+
+ var postdata = '';
+ if (typeof data == 'object')
+ {
+ for (var k in data)
+ postdata += (postdata ? '&' : '') + it_url_encode(k) + "=" + it_url_encode(data[k]);
+ }
+ else
+ postdata = data;
+
+ this.send(url, 'POST', postdata);
+},
+
+/* private method that finally sends the request */
+send: function(url, method, postdata)
+{
+ this.stop();
+
+ this.busy = true;
+ this.req = null;
+ var samehost = (url.indexOf('http://') < 0 || url.indexOf(window.location.hostname) > 0);
+
+ if (samehost) // use XMLHTTP request only if on same host
+ {
+ try
+ {
+ this.req = new XMLHttpRequest();
+ }
+ catch (e)
+ {
+ var classnames = [ 'MSXML2.XMLHTTP', 'Microsoft.XMLHTTP' ];
+
+ for (var i=0; i < classnames.length; i++)
+ {
+ try
+ {
+ this.req = new ActiveXObject(classnames[i]);
+ break;
+ }
+ catch (e) { }
+ }
+ }
+
+ try
+ {
+ this.req.open(method, url);
+ var me = this;
+ this.req.onreadystatechange = function() { me.ready_state_changed(); }
+ var workingxmlhttp = this.req.onreadystatechange;
+
+ if (!workingxmlhttp) /* Old Konqueror */
+ this.req = null;
+ }
+ catch (e) { }
+ }
+
+ this.starttime = new Date().getTime();
+
+ if (this.req)
+ {
+ if (method == "POST")
+ this.req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
+
+ this.req.send(postdata);
+ }
+ else
+ {
+ url += (url.match(/\?/) ? "&" : "?") + "itjs_call=it_http.__inst" + this.instance + "&itjs_callid=" + (++this.callid) + (postdata ? '&' + postdata : "");
+
+ if (samehost || (window.opera && !window.XMLHttpRequest)) // Opera 7 only works with iframes
+ {
+ var scrpt = document.createElement("iframe");
+ scrpt.style.width = scrpt.style.height = 1;
+ url += "&itjs_iframe=1";
+ }
+ else
+ {
+ var scrpt = document.createElement("script");
+ this.req = { starttime: this.starttime };
+ try
+ {
+ this.scrpt[this.callid] = scrpt;
+ if (!document.all) scrpt.src = url;
+ document.body.appendChild(scrpt);
+ if (document.all) scrpt.src = url;
+ }
+ catch (e) { return false; }
+ }
+ }
+
+ return true;
+},
+
+ready_state_changed: function()
+{
+ var req = this.req; // Avoid race conditions
+
+ if (req && !req.aborted && req.readyState == 4) // Check aborted flag because IE9 throws error c00c023f when accessing aborted request
+ {
+ var data = null;
+
+ try
+ {
+ if (req.responseText != "")
+ data = eval("(" + req.responseText + ")");
+ }
+ catch (e)
+ {
+ // trigger error handler (if defined)
+ if (typeof this.callback == 'object' && this.callback.errorhandler)
+ {
+ var obj = this.callback.object ? this.callback.object : window;
+ if (typeof obj[this.callback.errorhandler] == 'function')
+ obj[this.callback.errorhandler](req.responseText);
+ }
+ else
+ ED(e, req.responseText);
+ }
+
+ if (data)
+ this.dataReady(data, this.callid);
+
+ this.unlink(this.callid);
+ }
+},
+
+dataReady: function(data, callid)
+{
+ var fixkonqueror33gcbug = this.req;
+ var loadtime = new Date().getTime() - this.starttime;
+
+ this.req = null;
+
+ if ((typeof data == "object") && (this.callid == callid))
+ {
+ data.loadtime = loadtime;
+
+ // trigger callback function
+ if (typeof this.callback == 'function')
+ this.callback(data);
+ else if (typeof this.callback == 'object' && this.callback.method)
+ {
+ // it_set(data, this.callback);
+ var obj = this.callback.object ? this.callback.object : window;
+ if (typeof obj[this.callback.method] == 'function')
+ obj[this.callback.method](data);
+ }
+ }
+},
+
+stop: function()
+{
+ try {
+ this.req.aborted = true; // Set aborted flag as IE9 throws error c00c023f when accessing aborted request
+ if (this.req.readyState >= 2) // Do not abort request never used before as it can throw error e.g. on Firefox
+ this.req.abort();
+ } catch (e) { }
+
+ this.unlink(this.callid);
+},
+
+unlink: function(callid)
+{
+ if (this.req)
+ this.req = null;
+
+ if (this.scrpt[callid])
+ {
+ if (!(document.all && String(navigator.userAgent).indexOf('MSIE 5.0') > 0))
+ document.body.removeChild(this.scrpt[callid]);
+ this.scrpt[callid] = null;
+ }
+
+ this.busy = false;
+} /* NO COMMA */
+
+}
+
+
+// static properties
+it_http.instances = 0;
+
+// static methods
+it_http.get_instance = function()
+{
+ var inst;
+ for (var i=0; i < it_http.instances; i++)
+ if ((inst = it_http['__inst'+i]) && inst.pub && !inst.busy)
+ return inst;
+
+ inst = new it_http();
+ inst.pub = true;
+ return inst;
+}
+
+/* send GET request and trigger callback */
+it_http.get = function(url, callback)
+{
+ var inst = it_http.get_instance();
+ inst.callback = callback;
+ inst.get(url);
+}
+
+/* send POST request and trigger callback */
+it_http.post = function(url, postdata, callback)
+{
+ var inst = it_http.get_instance();
+ inst.callback = callback;
+ inst.post(url, postdata);
+}
+
diff --git a/devel-utf8/itjs/it.js b/devel-utf8/itjs/it.js
new file mode 100644
index 0000000..54fa5c7
--- /dev/null
+++ b/devel-utf8/itjs/it.js
@@ -0,0 +1,297 @@
+// $Id$
+
+/**
+ * Clear contents of element 'jsdebug'
+ */
+function CED(txt)
+{
+ var element = document.getElementById('jsdebug');
+ if (element)
+ element.innerHTML = txt ? txt : "";
+}
+
+/**
+ * Return string with dump of all arguments
+ */
+function D()
+{
+ var text = "";
+ for (var i = 0; i < arguments.length; i++)
+ {
+ var variable = arguments[i];
+
+ if (typeof variable == "string")
+ variable = variable.replace(/&/g, '&amp;').replace(new RegExp("<", "g"), '&lt;');
+
+ text += (typeof variable) + " " + variable;
+
+ if (typeof variable == "object")
+ {
+ text += ":";
+
+ for (field in variable)
+ {
+ text += field + "=";
+
+ try { text += typeof variable[field] == 'function' ? 'function' : variable[field]; }
+ catch (e) { text += "*" + e + "*"; }
+
+ text += "\n";
+ }
+ text += "\n";
+ }
+
+ text += "\n";
+ }
+ return text;
+}
+
+/**
+ * Add debugging output to element 'jsdebug'
+ */
+function ED()
+{
+ var element;
+
+ if (!(element = document.getElementById('jsdebug')))
+ return; // var element = it_create_element(document.body, 'div', {id:'jsdebug', style:{position:'absolute', left:'100px', top:'10px', opacity:'0.8'}})
+
+ element.innerHTML += '<pre style="background-color:#FEE; margin:0">' + D.apply(this, arguments) + '<' + '/pre>';
+}
+
+/**
+ * Quote HTML special chars
+ * @return Text string with & " < > htmlentities-encoded
+ */
+function Q(value)
+{
+ return typeof value == "undefined" ? "" : value.toString().replace(/&/g, '&amp;').replace(/\"/g, '&quot;').replace(new RegExp("<", "g"), '&lt;').replace(/>/g, '&gt;');
+}
+
+/**
+ * String class: Replaces variables of the form {var} with values from given array
+ * @param values Associative array containing values to fill in (optional)
+ * @return Text string with variables replaced by their values
+ */
+String.prototype.T = function(values)
+{
+ var result = this;
+
+ for (key in values)
+ result = result.replace(new RegExp("{" + key + "}", "g"), values[key]);
+
+ return result;
+}
+
+/**
+ * Insert an event handler on top of chain
+ * @param p.element Element to handle event for
+ * @param p.event Name of event:'focus', 'click', ... (without 'on')
+ * @param p.object Object that contains handler method
+ * @param p.method Method of p.object to call on p.event
+ */
+function it_event(p)
+{
+ var oldhandler = p.element["on" + p.event];
+
+ p.element["on" + p.event] = function(ev)
+ {
+ var pp = arguments.callee.p ? arguments.callee.p : p;
+ var oo = arguments.callee.oldhandler ? arguments.callee.oldhandler : oldhandler;
+
+ var result = pp.object[pp.method](ev ? ev : window.event, pp);
+
+ if (result && oo)
+ result = oo(ev);
+
+ return result;
+ }
+ p.element["on" + p.event].p = p;
+ p.element["on" + p.event].oldhandler = oldhandler;
+}
+
+function it_add_event(p)
+{
+ if (!p.object || !p.method) // not enough arguments
+ return;
+ if (!p.element)
+ p.element = document;
+
+ if (!p.object._it_events)
+ p.object._it_events = [];
+
+ var evt = p.event;
+ var key = p.event + '*' + p.method;
+ var p_closure = p; // Needed for Konqueror 3.4.2 as p is (wrongly) shadowed by global input element named p
+ if (!p.object._it_events[key])
+ p.object._it_events[key] = function(e){ return p_closure.object[p_closure.method](e, p_closure); };
+
+ if (p.element.addEventListener)
+ p.element.addEventListener(evt, p.object._it_events[key], false);
+ else if (p.element.attachEvent)
+ p.element.attachEvent('on'+evt, p.object._it_events[key]);
+ else
+ {
+ p.element['on'+evt] = function(e)
+ {
+ var ret = true;
+ for (var k in p_closure.object._it_events)
+ if (p_closure.object._it_events[k] && k.indexOf(evt) == 0)
+ ret = p_closure.object._it_events[k](e);
+ return ret;
+ };
+ }
+}
+
+function it_remove_event(p)
+{
+ if (!p.element)
+ p.element = document;
+
+ var key = p.event + '*' + p.method;
+ if (p.object && p.object._it_events && p.object._it_events[key]) {
+ if (p.element.removeEventListener)
+ p.element.removeEventListener(p.event, p.object._it_events[key], false);
+ else if (p.element.detachEvent)
+ p.element.detachEvent('on'+p.event, p.object._it_events[key]);
+
+ p.object._it_events[key] = null;
+ }
+}
+
+/**
+ * Prevent event propagation and bubbeling
+ */
+function it_event_void(evt)
+{
+ var e = evt ? evt : window.event;
+ if (e.preventDefault)
+ e.preventDefault();
+ if (e.stopPropagation)
+ e.stopPropagation();
+
+ e.cancelBubble = true;
+ e.returnValue = false;
+ return false;
+}
+
+/* Get object pixel position. Based on quirksmode.org's code */
+function it_get_obj_x(obj)
+{
+ var curleft = 0;
+ if (obj.offsetParent)
+ while (obj)
+ {
+ curleft += obj.offsetLeft;
+ obj = obj.offsetParent;
+ }
+ else if (obj.x)
+ curleft += obj.x;
+ return curleft;
+}
+
+function it_get_obj_y(obj)
+{
+ var curtop = 0;
+ if (obj.offsetParent)
+ while (obj)
+ {
+ curtop += obj.offsetTop;
+ obj = obj.offsetParent;
+ }
+ else if (obj.y)
+ curtop += obj.y;
+ return curtop;
+}
+
+/* Common accessor for dom elements */
+function it_find_obj(obj)
+{
+ if (document.getElementById)
+ return document.getElementById(obj);
+ else if (document.all)
+ return document.all[obj];
+ else if (document.layers)
+ return document.layers[obj];
+ return null;
+}
+
+/* Get dom element by ID but always return a valid object */
+function it_element(label)
+{
+ var tmp = it_find_obj(label);
+ return tmp ? tmp : { style:{}, src:"", value:"", isundefined:true };
+}
+
+/* Get an iframe's content document in a compatible way */
+function it_get_iframe_document(iframe)
+{
+ return iframe.contentWindow ? iframe.contentWindow.document : iframe.contentDocument;
+}
+
+/* Create a new dom element and append to doc */
+function it_create_element(doc, type, init)
+{
+ var e = document.createElement(type);
+ it_set(e, init);
+ doc.appendChild(e);
+ return e;
+}
+
+/**
+ * Copy attributes from src to dst in a recursive manner.
+ * @param dst Destination object which gets attributes
+ * @param src Source object containing attributes
+ */
+function it_set(dst, src)
+{
+ if (dst)
+ {
+ for (var i in src)
+ {
+ if (typeof src[i] == 'object')
+ {
+ if (dst[i])
+ it_set(dst[i], src[i]);
+ }
+ else
+ dst[i] = src[i];
+ }
+ }
+}
+
+/**
+ * Return the current timestamp
+ */
+function it_now()
+{
+ return new Date().getTime();
+}
+
+/**
+ * Encodes arbitrary string for use in an url
+ * @param str string to be encoded
+ */
+function it_url_encode(str)
+{
+ var result = window.encodeURIComponent ? encodeURIComponent(str) : escape(str).replace(/\+/g, "%2B");
+
+ return result.replace(/%20/gi, "+").replace(/%2C/gi, ",").replace(/%3B/gi, ";").replace(/%28/gi, "(").replace(/%29/gi, ")");
+}
+
+/**
+ * Patch PNG transparency for IE 5.5-6 on the given image
+ */
+function it_pngfix(img, w, h, mode)
+{
+ var old_IE = navigator.platform == "Win32" && String(navigator.userAgent).match(/MSIE ((5\.5)|6)/);
+ if (img.src && img.src.match(/\.png($|\?)/) && old_IE) {
+ img.style.width = (w || img.width) + 'px';
+ img.style.height = (h || img.height) + 'px';
+ img.runtimeStyle.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+img.src+"',sizingMethod='"+(mode ? mode : 'crop')+"')";
+ img.src = '/images/0.gif';
+ }
+ else if (img && old_IE)
+ img.style.filter = 'none';
+}
+
diff --git a/devel-utf8/itjs/loader.js b/devel-utf8/itjs/loader.js
new file mode 100644
index 0000000..9fdb9a8
--- /dev/null
+++ b/devel-utf8/itjs/loader.js
@@ -0,0 +1,141 @@
+/**
+ * Create loader to request data from server
+ * Uses it_http class for communication
+ *
+ * @param handler Object providing clear()/render() function when data arrives
+ */
+function it_loader(handler)
+{
+ /* Clear cache etc. if completely new data */
+ this.http = null;
+ this.handler = handler;
+ this.callback = { object:this, method:'dataReady', errorhandler:'onerror' };
+ 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 };
+
+ 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;
+
+ this.stop();
+
+ while ((num > 0) && (typeof this.entry[pos] != "undefined"))
+ {
+ pos++;
+ num--;
+ }
+
+ if (this.attr.eof)
+ num = Math.min(num, this.end - pos);
+
+ if (num > 0)
+ {
+ this.retry = retry;
+ this.http = it_http.get_instance();
+ this.http.get(baseurl + (baseurl.match(/\?/) ? "&" : "?") + "pos=" + pos + "&num=" + num + (retry ? "&retry=" + retry : "") + (query_volatile ? query_volatile : ""), this.callback);
+ }
+ else
+ this.handler.render(this);
+
+ return true;
+},
+
+/* deprecated: use it_http::post() instead */
+post: function(baseurl, data)
+{
+ this.clear();
+ this.http = it_http.get_instance();
+ this.http.post(baseurl, data, this.callback);
+},
+
+retryload: function(p)
+{
+ this.load(p.baseurl, p.pos, p.num, p.query_volatile, p.retry);
+},
+
+dataReady: function(data)
+{
+ if ((typeof data == "object"))
+ {
+ this.attr = {};
+
+ 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.http = null;
+ }
+},
+
+onerror: function(response)
+{
+ 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(response);
+},
+
+stop: function()
+{
+ if (this.http)
+ this.http.stop();
+} /* NO COMMA */
+
+}
+
+// static properties
+it_loader.sequence = "";
diff --git a/devel-utf8/itjs/state.html b/devel-utf8/itjs/state.html
new file mode 100644
index 0000000..36f36c0
--- /dev/null
+++ b/devel-utf8/itjs/state.html
@@ -0,0 +1,31 @@
+<?php header("Cache-Control: max-age=3600");
+return <<<EOF
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
+<html>
+<head>
+<title></title>
+<script type="text/javascript">
+var state_load_attempts = 0;
+function state_onload()
+{
+ if (state_load_attempts < 30)
+ {
+ state_load_attempts++;
+ if (parent.it_state && parent.it_state.ready)
+ parent.setTimeout(parent.it_state_restore_history, 1);
+ else
+ window.setTimeout(state_onload, 90);
+ }
+ window[(document.all?'onbeforeunload':'onunload')] = state_onbeforeunload;
+}
+function state_onbeforeunload()
+{
+ if (parent.it_state && !parent.it_state.it_state_saved)
+ parent.it_state.store_state();
+}
+</script>
+</head>
+<body onload="state_onload()"><form action="/itjs/state.html" method="get"><input type="hidden" id="state" name="s" value=""></form></body>
+</html>
+EOF
+?>
diff --git a/devel-utf8/itjs/state.js b/devel-utf8/itjs/state.js
new file mode 100644
index 0000000..e5e7c97
--- /dev/null
+++ b/devel-utf8/itjs/state.js
@@ -0,0 +1,120 @@
+/**
+ * Generic state object (singleton), for supporting Ajax browser history
+ *
+ * $Id$
+ *
+ */
+var it_state =
+{
+it_iframe: null,
+it_history_field: null,
+it_state_saved: false,
+it_store_handlers: [],
+it_restore_handlers: [],
+
+/**
+ * Register a handler that gets called before creating a history entry
+ * @param p.object Object that contains handler method
+ * @param p.method Method of p.object to call
+ */
+register_store_handler: function(p)
+{
+ this.it_store_handlers[this.it_store_handlers.length] = p;
+},
+
+
+/**
+ * Register a handler that gets called after restoring a history entry
+ * @param p.object Object that contains handler method
+ * @param p.method Method of p.object to call
+ * @param p.initial optional flag: if true, handler is called with initial empty state
+ */
+register_restore_handler: function(p)
+{
+ this.it_restore_handlers[this.it_restore_handlers.length] = p;
+
+ // If we already have state data, call registered handler immediately. Yup this _is_ needed!
+ if (this.it_history_field && this.it_history_field.value)
+ p.object[p.method]();
+},
+
+
+/**
+ * Create a new history entry, saving all values of it_state (asynchronously)
+ * Users must call this without parameter!
+ */
+new_history_entry: function(p)
+{
+ this.store_state();
+ this.it_state_saved = true;
+
+ if (!this.it_iframe && !(this.it_iframe = document.getElementById('it_state')))
+ ED('it_state::new_history_entry(): it_state object not found!');
+
+ var idoc;
+ if ((idoc = it_get_iframe_document(this.it_iframe)))
+ {
+ idoc.title = document.title;
+ idoc.forms[0].submit();
+ }
+ this.it_history_field = null;
+},
+
+
+/**
+ * Restore state from history, called from iframe's onload handler but in main window's context
+ */
+restore_history: function()
+{
+ if (!this.it_iframe && !(this.it_iframe = document.getElementById('it_state')))
+ ED('it_state::restore_history(): it_state object not found!');
+
+ var idoc = it_get_iframe_document(this.it_iframe);
+ this.it_history_field = idoc ? idoc.getElementById('state') : {}; // Work-around IE5 not returning iframe document
+ this.it_state_saved = false;
+
+ if (this.it_history_field.value)
+ {
+ var res = eval('({' + this.it_history_field.value + '})');
+ for (var key in res)
+ this[key] = res[key];
+ }
+
+ for (var i in this.it_restore_handlers)
+ {
+ if (this.it_history_field.value || (this.it_restore_handlers[i].initial && (!idoc || !idoc.location.href.match(/s=/))))
+ this.it_restore_handlers[i].object[this.it_restore_handlers[i].method]();
+ }
+},
+
+
+/**
+ * Call all store handlers and store state in it_history_field
+ */
+store_state: function()
+{
+ if (!this.it_iframe && !(this.it_iframe = document.getElementById('it_state')))
+ ED('it_state::store_state(): it_state object not found!');
+
+ var idoc = it_get_iframe_document(this.it_iframe);
+ this.it_history_field = idoc ? idoc.getElementById('state') : {}; // Work-around IE5 not returning iframe document
+
+ for (var i in this.it_store_handlers)
+ this.it_store_handlers[i].object[this.it_store_handlers[i].method]();
+
+ var ser = [];
+ for (var key in this)
+ {
+ var value = this[key], type = typeof(value);
+ if (!key.match(/^it_/) && type.match(/boolean|number|string/))
+ ser[ser.length] = key + ':' + ((type == 'string') ? "'" + value.replace(/([\\'])/g, '\\\1') + "'" : value);
+ }
+
+ this.it_history_field.value = ser.join(',');
+} /* NO COMMA */
+}
+
+function it_state_restore_history()
+{
+ it_state.restore_history();
+}
diff --git a/devel-utf8/itjs/timer.js b/devel-utf8/itjs/timer.js
new file mode 100644
index 0000000..ee04cbb
--- /dev/null
+++ b/devel-utf8/itjs/timer.js
@@ -0,0 +1,64 @@
+/**
+ * Start new timer
+ * Example: timer = new it_timer({ object:this, method:"timer", timeout:100});
+ *
+ * @param p.object Object to call method in when timer fires
+ * @param p.method String with method name to call in object
+ * @param p.timeout Timeout in milliseconds
+ * @param p.continuous One-shot or continuous timer, default is one-shot
+ * @return timer id (deprecated, use method stop() instead)
+ */
+function it_timer(p)
+{
+ this.func = p.continuous ? "Interval" : "Timeout";
+ return this.timer = window["set" + this.func](function() { p.object[p.method](p) }, p.timeout);
+}
+
+it_timer.prototype =
+{
+
+stop: function()
+{
+ if (this.timer)
+ {
+ window["clear" + this.func](this.timer);
+ this.timer = null;
+ }
+} /* NO COMMA */
+
+}
+
+/**
+ * Global helper function to benchmark javascript
+ * @parameter label Message label like "start" or "end"
+ * @paramter print Whether to output timerlog via