/*----------------------------------------------------------------------------\
|							Askia AskAjax Objects							  |
|-----------------------------------------------------------------------------|
|                          Created by Askia Company							  |
|							(http://www.askia.com)							  |
|-----------------------------------------------------------------------------|
| Execute the ajax queries													  |
|-----------------------------------------------------------------------------|
|							Copyright Askia © 1994-2007						  |
|-----------------------------------------------------------------------------|
| No dependencies															  |
|-----------------------------------------------------------------------------|
| 2006-12-06 |V 1.0.0														  |
|			 |+	Execute a simple AJAX rooting								  |
|-----------------------------------------------------------------------------|
| Created 2006-12-06 | All changes are in the log above. | Updated 2006-12-06 |
|-----------------------------------------------------------------------------|
|														All rights reserved	  |
| Plug-In - AskAjax - API Version 1.0.0			Copyright Askia © 1994-2007   |
\----------------------------------------------------------------------------*/

//Variable to know if Ajax is supported by the browser
var isAjaxSupported=(window.ActiveXObject || window.XMLHttpRequest);

//Http methods
var eAskAjaxHttpMethod={
		HEAD		: 'HEAD',
		POST		: 'POST',
		GET			: 'GET'
	};
//Header on request
var eAskAjaxRequestHeader={
		CONTENT_TYPE_NAME : 'Content-Type',
		CONTENT_TYPE_VALUE: 'application/x-www-form-urlencoded'
	};
//Ready state of request
var eAskAjaxReadyState={
		NOT_SUPPORTED  :-1,		//Not supported by the browser
		NOT_INITIALIZE : 0,		//Not initialize
		OPEN		   : 1,		//Opening. The method open() is successfully called 
		SENT 		   : 2,		//Sent. The method send()is successfully called 
		TRANSFERING    : 3,		//Transfering. The data are transfering (not ready)
		READY   	   : 4		//The data are loaded
	};
//Http state
var eAskAjaxHttpState={
		CONTINUE			: 100,
		SWITCHING_PROTOCOLS : 101,
		OK					: 200,
		CREATED				: 201,
		ACCEPTED			: 202,
		NON_AUTHORITATIVE_INFORMATION:203,
		NO_CONTENT			: 204,
		RESET_CONTENT		: 205,
		PARTIAL_CONTENT		: 206,
		MULTIPLE_CHOICES	: 300,
		MOVED_PERMANENTLY	: 301,
		FOUND				: 302,
		SEE_OTHER			: 303,
		NOT_MODIFIED		: 304,
		USE_PROXY			: 305,
		UNUSED				: 306,
		TEMPORARY_REDIRECT	: 307,
		BAD_REQUEST			: 400,
		UNAUTHORIZED		: 401,
		PAYMENT_REQUIRED	: 402,
		FORBIDDEN			: 403,
		NOT_FOUND			: 404,
		METHOD_NOT_ALLOWED	: 405,
		NOT_ACCEPTABLE		: 406,
		PROXY_AUTHENTICATION_REQUIRED	: 407,
		REQUEST_TIMEOUT		: 408,
		CONFLICT			: 409,
		GONE				: 410,
		LENGTH_REQUIRED		: 411,
		PRECONDITION_FAILED	: 412,
		REQUEST_ENTITY_TOO_LARGE : 413
	};
//Insert the loadXML method in the method of Document
if (document.implementation && document.implementation.createDocument){
		Document.prototype.loadXML = function (s) {
			// parse the string to a new doc
			var doc = (new DOMParser()).parseFromString(s, "text/xml");

			// remove all initial children
			while (this.hasChildNodes())
				this.removeChild(this.lastChild);

			// insert and import nodes
			for (var i = 0; i < doc.childNodes.length; i++) {
				this.appendChild(this.importNode(doc.childNodes[i], true));
			}
		};
	}
	
//Return the XmlHttpObject
function getXmlHttpObject(){
		//Initialiaze the Ajax request
		var oXmlHttp=null;
		// Mozilla, Opera, Safari, ...
		if (window.XMLHttpRequest)oXmlHttp=new XMLHttpRequest();     
		// IE
		if (!oXmlHttp && window.ActiveXObject)oXmlHttp=new ActiveXObject("Microsoft.XMLHTTP"); 
		if (!oXmlHttp)isAjaxSupported=false;
		return oXmlHttp;
	}
	
//Return the AJAX Request object
function AskAjaxRequest(method,url,data,isAsynch){
		//XmlHttpRequest
		this.request=getXmlHttpObject();	
		//Method to use see eAjaxMethod
		this.method=method || eAskAjaxHttpMethod.HEAD;
		//Url of request
		this.url=url || '';
		//Data on request
		this.data=data || null;
		//Is asynchrone call
		this.isAsynch=true;
		if (isAsynch!=null)this.isAsynch=isAsynch;
		//Result of request in text format
		this.result='';
		
		//State error
		this.stateError=0;
	}
	
//Execute a request
AskAjaxRequest.prototype.execute=function(data){
		if (!isAjaxSupported)return;
		
		//Re-init the request
		this.request=getXmlHttpObject();
				
		var _THIS=this;
		//Manage the event on ready state change
		this.request.onreadystatechange=function() {
				if (_THIS.request.readyState!=eAskAjaxReadyState.READY)return;
				//Manage the state error
				if (_THIS.request.status!=eAskAjaxHttpState.OK){
						_THIS.stateError=_THIS.request.status;
						_THIS.onError();
						return;
					}
				_THIS.result=_THIS.request.responseText;
				_THIS.onLoad();
			};
			
		//Open the request
        this.request.open(this.method,this.url, this.isAsynch);
        //Add header on request
		if (this.method==eAskAjaxHttpMethod.POST)this.request.setRequestHeader(eAskAjaxRequestHeader.CONTENT_TYPE_NAME, eAskAjaxRequestHeader.CONTENT_TYPE_VALUE);
		//Execute the request (with data)
		if (data)this.data=data;
		this.request.send(this.data);
	}
	
//Return the result as XML object
AskAjaxRequest.prototype.getXMLDoc=function(){
		var xmlDoc=null;
		
		if (document.implementation && document.implementation.createDocument){
				xmlDoc= document.implementation.createDocument("", "", null);
				xmlDoc.loadXML(this.result);
			}
		else if (window.ActiveXObject) {
				var xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
				xmlDoc.loadXML(this.result);
 			}
		return xmlDoc;
	}
	
//Events on object	
//Fires on error
AskAjaxRequest.prototype.onError=function(){/* EVENT */}
//Fires on load to obtain the result
AskAjaxRequest.prototype.onLoad=function(){/* EVENT */}

// *** Object to manage the queue of ajax calls *** 
function AjaxQueue(url,maxLength){
        this.url=url;
        this._maxQueueLength=maxLength || -1;
        this._queue=[]; //Array to store the queue
        this._isStart=false;
    }
//Add the element in top of queue
AjaxQueue.prototype.addOnTop=function(param){
        var arr=[];
        arr[0]=param;
        var arrResult=arr.concat(this._queue);
        this._queue=arrResult;
    }
//Add element into the queue
AjaxQueue.prototype.add=function(param){
        this._queue.push(param);
        //Too many queries in queue
        if (this._maxQueueLength!=-1){
                if (this._queue.length>=this._maxQueueLength){
                        this.onMaxSizeReached();
                    }
            }        
    }
//Start to execute the queue
AjaxQueue.prototype.start =function(){
        this._isStart=true;
        this._executeNext();
    }
//Stop to execute the queue
AjaxQueue.prototype.stop=function(){
        this._isStart=false;
    }
//Execute the ajax query
AjaxQueue.prototype.execute=function(param){
        this._isStart=true;
        if (this._queue.length>0){
                //Put the query in queue
                this._queue.push(param);
                //Too many queries in queue
                if (this._maxQueueLength!=-1){
                        if (this._queue.length>=this._maxQueueLength){
                                this.onMaxSizeReached();
                            }
                    }
            }
        else {
                //Execute the query now
                this._executeNow(param);
            }
    }
//Execute the query now
AjaxQueue.prototype._executeNow=function(param){
            this.onExecute();
            var ajaxRequest= new AskAjaxRequest(eAskAjaxHttpMethod.POST,this.url,null,true);
            var _THIS=this;
            //Attach the event
            ajaxRequest.onLoad=function(){
                    _THIS.onCallBack(this.getXMLDoc());
                    _THIS._executeNext(); //Execute the next query in queue
                }
            ajaxRequest.execute(param);
    }
//Execute the next item in pool
AjaxQueue.prototype._executeNext=function(){
            if (!this._isStart)return; //Stop the process
            this.onExecuteNext();
            if (!this._isStart)return; //Verify the state again
            if (this._queue.length==0){
                    this._isStart=false;
                    this.onFinish();
                    return;
                }
            var strParam=this._queue.shift();
            this._executeNow(strParam);
    }
//Event fires when the process is finish (no more item in queue)
AjaxQueue.prototype.onFinish=function(){ /* Event */ }
//Event fires when we execute an ajax query
AjaxQueue.prototype.onExecute=function(){/* Event */}
//Event fires when the result is coming
AjaxQueue.prototype.onCallBack=function(oXmlDoc){/* Event */}
//Event fires when the max size of queue was reached
AjaxQueue.prototype.onMaxSizeReached=function(){/* Event */}
//Event fires when we execute the next item 
AjaxQueue.prototype.onExecuteNext=function(){/* Event */}