/*
	Source: classbehaviours.ajax.js
	ClassBehaviours is a javascript framework based on class-name parsing.
	Copyright 2011 by Maurice van Creij and published on http://www.woollymittens.nl/
	This work is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.
*/

	// CLASSBEHAVIOURS CLASS
	// create the root classbehaviours object if it doesn't already exist
	if(typeof(classBehaviours)=='undefined') classBehaviours = {};

		// COMMON AJAX FUNCTIONS
		// this implementation of AJAX adds a request queue as a differentiating feature
		if(typeof(classBehaviours.ajax)=='undefined') classBehaviours.ajax = {
			queue : new Array(),
			deserializeHTML : function(text){
				newElement = document.createElement('DIV');
				newElement.innerHTML = text;
				return newElement;
			},
			deserializeXML : function(text){
				if (window.DOMParser){
					parser = new DOMParser();
					xmlDoc = parser.parseFromString(text,"text/xml");
				}else{
					xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
					xmlDoc.async = "false";
					xmlDoc.loadXML(text);
				}
				return xmlDoc;
			},
			defaultProgressHandler : function(progressStatus, progressNode, progressError){
				// fill the refered node with a progress report
				progressNode.innerHTML = (progressStatus>-1) ? 'Loading: ' + Math.round(progressStatus * 100) + '%' : 'Error: ' + progressError ;
			},
			defaultLoadHandler : function(loadXml, loadNode, loadText){
				// fill the refered node with the returned html string
				loadNode.innerHTML = loadText.split('<body>')[1].split('</body>')[0];
			},
			addRequest : function(url, loadHandler, progressHandler, post, referingObject){
				// get the first free slot in the que
				index = this.queue.length;
				// add new request to the end of the que
				this.queue[index] = new this.HttpRequest();
				// set request constants
				this.queue[index].idx			=	index;
				this.queue[index].url			=	url;
				this.queue[index].post			=	post;
				this.queue[index].method		=	(post!=null) ? 'POST' : 'GET' ;
				// request events
				this.queue[index].doOnLoad		=	(loadHandler=='default') ? this.defaultLoadHandler : loadHandler ;
				this.queue[index].doOnProgress	=	(progressHandler=='default') ? this.defaultProgressHandler : progressHandler ;
				this.queue[index].referObject	=	referingObject;
				// request properties
				this.queue[index].time			=	new Date();
				// ask the queue handler to handle the next queued item
				this.handleQueue();
				// return false
				return false;
			},
			makeRequest : function(queued){
				// branch for native XMLHttpRequest object
				if(window.XMLHttpRequest){
					queued.request = new XMLHttpRequest();
					queued.request.onreadystatechange = this.progress;
					queued.request.open(queued.method, queued.url, true);
					if(queued.method == 'POST'){
						queued.request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
						queued.request.setRequestHeader("Content-length", queued.post.length);
						queued.request.setRequestHeader("Connection", "close");
					}
					queued.request.send(queued.post);
				// branch for IE/Windows ActiveX version
				}else if(window.ActiveXObject){
					queued.request = new ActiveXObject("Microsoft.XMLHTTP");
					queued.request.onreadystatechange = this.progress;
					queued.request.open(queued.method, queued.url, true);
					if(queued.method == 'POST'){
						queued.request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
						queued.request.setRequestHeader("Content-length", queued.post.length);
						queued.request.setRequestHeader("Connection", "close");
					}
					queued.request.send(queued.post);
				// if all else fails: load the document in an iFrame
				}else if(window.frames){
					// create an iframe to read the document in
						objIframe = document.createElement("IFRAME");
						objIframe.src = queued.url;
						objIframe.id = "feedimport0";
						objIframe.name = "feedimport0";
						objIframe.style = "visibility : invisible; position : absolute; left : -1600px; top : -1600px;";
						//objIframe.onload = ajax_load; // Doesn't work in Opera
					// append the iframe to the document
						document.body.appendChild(objIframe);
					// wait for the iframe to load
					this.wait();
				}
			},
			handleQueue : function(){
				queue = classBehaviours.ajax.queue;
				// if the first item in the queue is a completed request
				if(queue.length>0){
					if(queue[0].ready==4 /*&& ajax.queue[0].status==200*/){
						// remove the completed request
						queue.reverse();
						queue.length = queue.length - 1;
						queue.reverse();
					}
				}
				// if the first item in the queue isn't allready in progress
				if(queue.length>0){
					if(!(queue[0].ready<4 && queue[0].ready!=null)){
						this.makeRequest(queue[0]);
					}
				}
			},
			progress : function(){
				queued = classBehaviours.ajax.queue[0];
				// remember the readyState
				queued.ready = queued.request.readyState;
				// only if req shows "complete"
				if(queued.request.readyState == 4){
					// remember the status
					queued.status = queued.request.status;
					// only if "OK"
					if(queued.request.status == 200 || queued.request.status == 304){
						// update optional progress indicator code
						if(queued.doOnProgress) queued.doOnProgress(4, queued.referObject, queued.request.status, queued.time);
						// get the imported text
						queued.text = queued.request.responseText;
						// get the imported document
						queued.document = queued.request.responseXML;
						// if the document is empty use a deserialized version of the text instead
						if(queued.document==null) queued.document = classBehaviours.ajax.deserializeHTML(queued.text)
						else if(queued.document.childNodes.length==0) queued.document = classBehaviours.ajax.deserializeHTML(queued.text);
						// trigger the load event
						if(queued.doOnLoad) queued.doOnLoad(queued.document, queued.referObject, queued.text, queued.time);
						// request the next item in the queue to be handled
						classBehaviours.ajax.handleQueue();
					}else{
						// update optional progress indicator code
						if(queued.doOnProgress) queued.doOnProgress(-1, queued.referObject, queued.request.status, queued.time);
					}
				}else{
					// update optional progress indicator code
					if(queued.doOnProgress) queued.doOnProgress(queued.request.readyState, queued.referObject, 200, queued.time);
				}
				// return the status if desired
				return queued.request.readyState;
			},
			wait : function(){
				queued = classBehaviours.ajax.queue[0];
				// if the xml document has loaded in the iframe
				if(window.frames["feedimport0"]){
					// define the xml document object
					queued.document = window.frames["feedimport0"].document;
					queued.text = window.frames["feedimport0"].document.body.innerHTML;
					// what to do after the xml document loads
					queued.doOnLoad(queued.document, queued.referObject, queued.text, queued.time);
				// else try again in a while
				}else{
					setTimeout("ajax.wait()",256);
				}
			},
			HttpRequest : function(){
				// request constants
				this.idx			=	null;
				this.url			=	null;
				this.post			=	null;
				this.method			=	'GET';
				// request events
				this.doOnLoad		=	null;
				this.doOnProgress	=	null;
				this.referObject	=	null;
				// request properties
				this.request		=	null;
				this.document		=	null;
				this.text			=	null;
				this.ready			=	null;
				this.status			=	null;
				this.time			=	null;
			}
		}

