/**
  * CSAjax - Cognix Systems Ajax Connect Manager
  * 
  * Cet classe permet de charger une page en Ajax
  * Et de récupérer son contenu directement dans un élément HTML (div, ...)
  *
  * Exemple d'utilisation :
  *  maFonction = function(action, param) {
  *	if(CSAjax.requestLock) return;	
  *	var ajax = new CSAjax(idDiv);
  *	ajax.setVar('action', param);
  *	ajax.setVar('mon_param', param);
  *	ajax.onCompletion = function() {
  *		alert('Mon bloc '+idDiv+' contient le contenu de la page  /index.php?action='+action+'&mon_param='+param+' ('+ajax.response+')');
  *	};
  *	ajax.run();
  * }
  *
  * @author Loïc DIRINGER
  * @version 20070717
  */
function CSAjax(HTMLElement) {

	/** XHR */
	this.xmlhttp = null;

	/** 
	  * private void buildData()
	  * Construit les données
	  */
	this.buildData = function() {
		// get ou post
		this.method = 'GET';
		// ?var=valeur
  		this.queryStringSeparator = '?';
		// ?var=valeur&vor=voleur&vur=vuleur
		this.argumentSeparator = '&';
		// La query string
		this.URLString = '';
		// La query string encodée
		this.encodeURIString = true;
		//
  		this.element = null;
		//
		this.elementObj = null;
		// Le fichier destinataire (obligatoire en POST)
		this.requestFile = 'index.php';
		//
		this.execute = false;
		// Les variables/valeur à lister dans la query string
		this.vars = new Object();
		// Le statut de réponse de la requete
		this.responseStatus = new Array(2);
		// Le bloc qui va contenir le responseText
		this.HTMLElement = HTMLElement;
		// Le verrou
		CSAjax.requestLock = false;
		// Les verrous de div (si on demande de charger qqch dans une div verouillée alors on appelle la fonction associée)
		if(CSAjax.locks==null) {
			CSAjax.locks = new Array();
		}
		// La classe css que prend le HTMLElement lors du chargement
		this.loadingCssClass = 'loading';
  	};
	
	/**
	   * public void lock(HTMLElement div_id, string code)	
	   * Pose le verrou sur div_id
	   */
	CSAjax.lock = function(div_id, code) {
		CSAjax.locks[div_id] = code;
	}
	
	/**
	   * public void unlock(HTMLElement div_id)	
	   * Enleve le verrou sur div_id
	   */
	CSAjax.unlock = function(div_id) {
		delete CSAjax.locks[div_id];
	}
	
	/**
	   * public boolean isLocked(HTMLElement div_id)	
	   * Retourne si le div_id est verouillé ou non
	   */
	CSAjax.isLocked = function(div_id) {
		for(i in CSAjax.locks) {
			if(i==div_id) return true;
		}
		return false;
	}
	
	/**
	   * public string getLockCode(HTMLElement div_id)
	   * Retourne le code à renvoyer si div_id est verouillé
	   */
	CSAjax.getLockCode = function(div_id) {
		for(i in CSAjax.locks) {
			if(i==div_id) return CSAjax.locks[i];
		}
		return '';
	}
	
	/**
	  * private void buildFunction()
	  * Construit les fonctions d'évènements
	  */ 
	this.buildFunctions = function() {
  		this.onLoading = function() { };
  		this.onLoaded = function() { };
  		this.onInteractive = function() { };
  		this.onCompletion = function() { };
  		this.onError = function() { };
		this.onFail = function() { };
	};

	/**
	  * private void build()
	  * Pseudo-constructeur / Initialiseur
	  */			  
	this.build = function() {
		this.buildFunctions();
		this.buildData();
		this.create();
	};

	/**
	  * private void create()
	  * Crée le XHR
	  */
	this.create = function() {
		try {
			this.xmlhttp = new ActiveXObject('Msxml2.XMLHTTP');
		} catch (e1) {
			try {
				this.xmlhttp = new ActiveXObject('Microsoft.XMLHTTP');
			} catch (e2) {
				this.xmlhttp = null;
			}
		}

		if (!this.xmlhttp) {
			if (typeof XMLHttpRequest != 'undefined') {
				this.xmlhttp = new XMLHttpRequest();
			} else {
				this.failed = true;
			}
		}
	};
	
	/**
	   * public void setRequestFile(string page)
	   * Modifie le 'index.php' par défaut
	   */
	this.setRequestFile = function(page){
		this.requestFile = page;
	}
	
	/**
	  * public void setVar(string name, mixed value)
	  * Ajoute un doublet name/value à la requête AJAX
	  */
	this.setVar = function(name, value){
		this.vars[name] = Array(value, false);
	};

	/**
	  * private [Array/void] void encVar(string name, mixed value, boolean returnvars)
	  * Protège la variable en encodant certains caractères
	  */
	this.encVar = function(name, value, returnvars) {
		if (returnvars) {
			return Array(encodeURIComponent(name), encodeURIComponent(value));
		} else {
			this.vars[encodeURIComponent(name)] = Array(encodeURIComponent(value), true);
		}
	}

	/**
	  * private void processURLString(string string, boolean encode)
	  */
	this.processURLString = function(string, encode) {
		encoded = encodeURIComponent(this.argumentSeparator);
		regexp = new RegExp(this.argumentSeparator + "|" + encoded);
		varArray = string.split(regexp);
		for (i=0; i<varArray.length; i++) {
			urlVars = varArray[i].split("=");
			if (encode) {
				this.encVar(urlVars[0], urlVars[1]);
			} else {
				this.setVar(urlVars[0], urlVars[1]);
			}
		}
	}

	/**
	  * private void createURLString(string urlString)
	  */
	this.createURLString = function(urlString) {
		if (this.encodeURIString && this.URLString.length) {
			this.processURLString(this.URLString, true);
		}

		if (urlString) {
			if (this.URLString.length) {
				this.URLString += this.argumentSeparator + urlString;
			} else {
				this.URLString = urlString;
			}
		}

		// Empêche le systeme de cache client de fonctionner (requête unique à chaque fois)
		this.setVar("cache", new Date().getTime());

		urlstringtemp = new Array();
		for (key in this.vars) {
			if (!this.vars[key][1] && this.encodeURIString) {
				encoded = this.encVar(key, this.vars[key][0], true);
				delete this.vars[key];
				this.vars[encoded[0]] = Array(encoded[1], true);
				key = encoded[0];
			}

			urlstringtemp[urlstringtemp.length] = key + "=" + this.vars[key][0];
		}
		if (urlString){
			this.URLString += this.argumentSeparator + urlstringtemp.join(this.argumentSeparator);
		} else {
			this.URLString += urlstringtemp.join(this.argumentSeparator);
		}
	}

	/**
	  * public void runResponse()
	  */
	this.runResponse = function() {
		eval(this.response);
	}

	/**
	  * public void run()
	  * Execute la requête et gère les évènements
	  */
	this.run = function(urlString) {
	
		if(CSAjax.isLocked(this.HTMLElement)) {
			if(!eval(CSAjax.getLockCode(this.HTMLElement))) return;
		}
	
		if (this.failed) {
			this.onFail();
		} else {
			this.createURLString(urlString);
			if (this.element) {
				this.elementObj = document.getElementById(this.element);
			}
			if (this.xmlhttp) {
				var self = this;
				if (this.method != 'GET') {
					this.xmlhttp.open(this.method, this.requestFile, true);
					try {
						this.xmlhttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded")
					} catch (e) { }
				} else {
					totalurlstring = this.requestFile + this.queryStringSeparator + this.URLString;
					this.xmlhttp.open(this.method, totalurlstring, true);
				}

				this.xmlhttp.onreadystatechange = function() {
					switch (self.xmlhttp.readyState) {
						case 1:
							CSAjax.requestLock = true;
							if(self.HTMLElement && document.getElementById(self.HTMLElement)) {
								document.getElementById(self.HTMLElement).innerHTML = '';
								document.getElementById(self.HTMLElement).className = self.loadingCssClass+' ' + document.getElementById(self.HTMLElement).className;
							}
							self.onLoading();
							break;
						case 2:
							self.onLoaded();
							break;
						case 3:
							self.onInteractive();
							break;
						case 4:
							try {
								self.response = self.xmlhttp.responseText;
								self.responseXML = self.xmlhttp.responseXML;
								self.responseStatus[0] = self.xmlhttp.status;
								self.responseStatus[1] = self.xmlhttp.statusText;
							} catch(exception) {
								self.run(urlString);
							}

							if (self.execute) {
								self.runResponse();
							}

							if (self.elementObj) {
								elemNodeName = self.elementObj.nodeName;
								elemNodeName.toLowerCase();
								if (elemNodeName == "input"	|| elemNodeName == "select"	|| elemNodeName == "option" || elemNodeName == "textarea") {
									self.elementObj.value = self.response;
								} else {
									self.elementObj.innerHTML = self.response;
								}
							}
							if (self.responseStatus[0] == "200") {
								if(self.HTMLElement) {
									document.getElementById(self.HTMLElement).innerHTML = self.response;
									document.getElementById(self.HTMLElement).className = document.getElementById(self.HTMLElement).className.replace(self.loadingCssClass,'');
								}
								CSAjax.requestLock = false;
								self.onCompletion();
							} else {
								if(self.HTMLElement && document.getElementById(self.HTMLElement)) {
									document.getElementById(self.HTMLElement).className = document.getElementById(self.HTMLElement).className.replace(self.loadingCssClass+' ','');
								}
								CSAjax.requestLock = false;
								self.onError();
							}

							self.URLString = "";
							break;
					}
				};

				this.xmlhttp.send(this.URLString);
			}
		}
	};

	// Lance l'initialisation
	this.build();
}

