<!--
/******************************************************/
/*  CUSTOM AJAX CALL                                  */
/******************************************************/

function AjaxRequest(options) {
	//show "action in progress" animation
	if ($('waitanimation')) $('waitanimation').style.visibility = 'visible';
	var _this		= this;												// Save correct scope of "this"
	this.updating	= false;											// Set to true if this object is already working on a request
	this.async		= (options.async == false) ? false : true;			// asynchronous (default: true) or synchronous (false) call
	this.method		= options.method || 'GET';							// GET: fetch data, POST: update data
	this.onSuccess	= options.onSuccess || function () {}				// A post-processing call -- a stub you overwrite
	this.onFailure	= options.onFailure || function () { /*trace('Error loading data.',1);*/ }	// A post-processing call -- a stub you overwrite
	this.isHTML		= options.HTML == true ? true : false;
	
	var timestamp	= new Date();
	options.data	= (options.data || '') + (options.data ? '&': '') + 'timestamp='+(timestamp*1);
	
	this.send = function() {											// Initiates server call.
		if (_this.updating == true) {
			trace('Action in progress.\nPlease try again.',1);
			return false;												// Abort if we're already processing a call
		}
		_this.updating = true;
		var AJAX = null;
		if (window.XMLHttpRequest) {
			AJAX = new XMLHttpRequest();								// Mozilla
		} else {
			AJAX = new ActiveXObject("Microsoft.XMLHTTP");				// IE
		}
		if (AJAX == null) {												// Error initializing Ajax
			trace('This application makes extensive use of AJAX.\nPlease upgrade your browser.',1);
			return false;												// Abort
		} else {
			AJAX.onreadystatechange = function() {
				if (AJAX.readyState == 4) {
					_this.updating = false;
					if ((AJAX.status >= 200) && (AJAX.status < 300)) {	//  If page could be loaded
						if (options.debug) trace('return value: '+AJAX.responseText);
						
						if (_this.isHTML) {
							//convert HTML to DOM tree
							var container	= breakApartDOM(AJAX.responseText);
							var DOMtree	= container.tree;
							var Events	= container.script;
							
						} else {
							var DOMtree	= '';
							var Events	= '';
						}
						
						_this.onSuccess(AJAX.responseText, DOMtree, Events);				//	Pass response and status to callback
					} else {
						var err = 'Error loading data. Please try again.';
						if (_this.isHTML) {
							//convert HTML to DOM tree
							var container	= breakApartDOM(err);
							var DOMtree	= container.tree;
							var Events	= container.script;
							
						} else {
							var DOMtree	= '';
							var Events	= '';
						}
						
						_this.onFailure(err, DOMtree, Events);
					}
					delete AJAX;										//	delete the AJAX object since it's done
					if ($('waitanimation')) $('waitanimation').style.visibility = 'hidden';
				}
			}
			var uri = options.url + (options.url.indexOf('?') == 0 ? '&' : '?') + options.data;
			if (options.debug) trace('uri: '+uri);
			AJAX.open(this.method, uri, this.async);					// Open url
			AJAX.send(null);											// Send request
			return true;
		}
	}
}

/* Example use of AjaxRequest() */
function doRequest() {
	var myRequest = new AjaxRequest({
		url: 'testajax.asp',
		data: '',
		onSuccess: function(myResult) {
			trace("*"+myResult, 0);
		}
	});
	myRequest.send();
}

function appendHTML(source, scripts, target) {
	var obj		= target.append || target.before || target.after;
	var atIndex	= target.index;
	
	//append tree (fragment) to target
	if (target.index && target.append) {
		obj.parentNode.insertBefore(source, obj.parentNode.childNodes[atIndex]);
	} else if (target.before) {
		obj.parentNode.insertBefore(source, obj);
	} else if (target.after) {
		obj.parentNode.insertBefore(source, obj.nextSibling);
	} else {
		obj.appendChild(source);
	}
	
	if (scripts) {
		for (var scr = 0; scr < scripts.length; scr++) {
			var text = scripts[scr];
			text = text.substring(text.indexOf('>')+1, text.lastIndexOf('<'));
			execJS(text);
		}
		//execJS(scripts);
	}
}

function breakApartDOM(source) {
/*
*	source = chunk of html
*/
	var match = source.match(/<body[^>]*>([\s\S]*?)<\/body>/i);
	source = (match) ? match[1] : source;
	var scripts = source.match(/<script[^>]*>([\s\S]*?)<\/script>/gi);
//	trace('scripts: ' + scripts.join('\n'));
/*	if (scripts) {
		tmp_scripts = '';
		for (var scr = 0; scr < scripts.length; scr++) {
			var text = scripts[scr];
			text = text.substring(text.indexOf('>')+1, text.lastIndexOf('<'));
			tmp_scripts = tmp_scripts + text.replace(/&amp;/g, '&');
		}
		scripts = tmp_scripts;
	}
*/	
	var container = document.createDocumentFragment();
	var root = '<root>' + source + '</root>', doc;
	
	if (window.DOMParser){
		doc = new DOMParser().parseFromString(root, 'text/xml');
	} else {
		doc = new ActiveXObject('Microsoft.XMLDOM');
		doc.async = false;
		doc.loadXML(root);
	}
	root = doc.getElementsByTagName('root')[0];
	for (var i = 0; i < root.childNodes.length; i++){
		var child = root.childNodes[i];
		if (child) {
			if (child.nodeName != 'script') container.appendChild(constructNode(child));
		}
	}
	
	return { tree: container, script: scripts };
}

function constructNode(node) {
	var attr = node.attributes;
	var newNode;
	
	if (node.nodeName == 'input') {
		var strNode = '<';
		strNode += node.nodeName;
		for (var j = 0; j < attr.length; j++) {
			strNode += ' ' + attr[j].name.toLowerCase() + '=\'' + attr[j].value + '\'';
		}
		strNode += ' />';
		
		// Try the IE way; this fails on standards-compliant browsers
		try {
			newNode = document.createElement(strNode);
		} catch(e) {}
	}
	
	if (!newNode) {
		newNode = document.createElement(node.nodeName);
	//	var attr = node.attributes;
		
		for (var j = 0; j < attr.length; j++) {
			/*	beware of exceptions:
			*		bgcolor	-> bgColor (in IE)
			*		table	-> requires <tbody> (in IE)
			*		class	-> className
			*		style	-> todo !!
			*		events	-> mousedown, mouseup, click, dblclick, mousemove, mouseover, mouseout, focus, blur
			*				-> mouseenter, mouseleave, contextmenu (IE only)
			*				-> http://www.quirksmode.org/dom/events/index.html
			*				-> DO NOT USE! Use "addEvent"-function
			*/
			var attrName	= attr[j].name.toLowerCase();
			var attrVal		= attr[j].value;
			if (attrName == 'bgcolor') attrName = 'bgColor';
			if (attrName == 'class') newNode.className = attrVal; //attrName = 'classname';
			else if (attrName == 'onmousedown'
				|| attrName == 'onmouseup'
				|| attrName == 'onclick'
				|| attrName == 'ondblclick'
				|| attrName == 'onmousemove'
				|| attrName == 'onmouseover'
				|| attrName == 'onmouseout'
				|| attrName == 'onfocus'
				|| attrName == 'onblur'
				|| attrName == 'onmouseenter'
				|| attrName == 'onmouseleave'
				|| attrName == 'oncontextmenu'
			) {
				if (newNode.addEventListener) {
					/* Add with 'addEvent() {}'
					attrName = attrName.substr(2); //strip 'on'
					//trace(newNode.tagName + ' - ' + attrName + ': ' + attrVal);
					//newNode.addEventListener(attrName, eval(attrVal), false);
					if (attrVal.substr(0,7) == 'return ') {
						trace(attrVal.substr(7));
						newNode.addEventListener(attrName, function(event) { return eval(attrVal.substr(7)) }, false);
						
					} else {
						newNode.addEventListener(attrName, function(event) { eval(attrVal) }, false);
					}
					
					/*	Add as normal attribute (works fine in Mozilla-based browsers)
					* /
					newNode.setAttribute(attrName, attrVal);
				} else if (newNode.attachEvent) {
					/*
					newNode.myHandler = eval(attrVal);
					newNode.attachEvent(attrName, function(e) { newNode[myHandler](e); });
					*/
				}
			} else newNode.setAttribute(attrName, attrVal);
		}
	}
	
	for (var k = 0; k < node.childNodes.length; k++) {
		if (node.childNodes[k].nodeName == '#text') newNode.appendChild(document.createTextNode(node.childNodes[k].nodeValue));
		else if (node.childNodes[k].nodeName != 'script') newNode.appendChild(constructNode(node.childNodes[k]));
		//else newScript.appendChild(nodes.node.childNodes[k]);
	}
	
	return newNode;
}

function execJS(scripttext){
	if (window.execScript){
		window.execScript(scripttext);
	} else {
		var script = document.createElement('script');
		script.setAttribute('type', 'text/javascript');
		script.text = scripttext;
		document.getElementsByTagName('head')[0].appendChild(script);
		document.getElementsByTagName('head')[0].removeChild(script);
	}
	//(window.execScript || self.eval)(scripttext);
}

//-->