/**
 * @author Stéphane
 *
 * Fonction Ajax
 *
 * Utilité :
 * 	Cette fonction permet de gérer l'ensemble des echanges synchrone et asynchrone entre le client et le serveur
 *
 * Utilisation :
 * Exemple 1 (avec la fonction setParam) :
 * ObjAJAX = new Ajax();
 * ObjAJAX.setParam ({
 * url : "http://yoururl/index.html",
 * returnFormat : "txt",
 * method : "POST",
 * data : {
 * test : "11",
 * test1 : "4",
 * test2 : "555"
 * },
 * asynchronus : true,
 * onComplete : function (response) {alert(response)},
 * onFailure : function (errorCode) {alert("Erreur : " + errorCode)}
 * });
 * ObjAJAX.execute();
 *
 * Exemple 2 (avec la fonction setParam) :
 *
 * ObjAJAX = new Ajax();
 * ObjAJAX.setParam ({
 * url : "http://yoururl/index.html",
 * returnFormat : "txt", // OU returnFormat : "xml"
 * method : "POST", // OU method : "GET"
 * data : "valeur1=1&valeur2=2",
 * asynchronus : true, // OU asynchronus : false
 * onComplete : "document.body.innerHTML = response"
 * });
 * ObjAJAX.execute();
 *
 * Exemple 3 (avec la fonction setParamFromForm et setParam) :
 *
 * JS :
 * ObjAJAX = new Ajax();	
 * ObjAJAX.setParamFromForm(0); // OU ObjAJAX.setParamFromForm("form1"); OU ObjAJAX.setParamFromForm(document.forms[0]); OU ObjAJAX.setParamFromForm(document.getElementById("form1_id"));
 * ObjAJAX.setParam({
 * onComplete : "document.body.innerHTML = response"
 * });
 * ObjAJAX.execute();

 * HTML :
 * <form action="http://yoururl/index.html" method="POST" name="form1" id="form1_id">
 * <input type="text" name="valeur1" value="1">
 * <input type="text" name="valeur2" value="2">
 * <input type="button" name="button" value="Envoyer" onclick="fonctionblabla()"> <!-- Contrôle ignorer lors de l'envoie avec ma classe -->
 * </form>
 * Note : Lorsque vous utiliser la fonction setParamFromForm avec un chiffre en paramètre, ce chiffre doit correspondre à ça place dans le document HTML (si c'est le premier dans le document, alors c'est 0, si c'est le deuxième c'est 1 et ainsi de suite).
 * Note 2 : Lorsque vous utiliser la fonction setParam, certains paramètres ont déjà une valeur par défault : asynchronus (true), data (""), method ("GET") et returnFormat ("txt"). Si vous utilisez les valeurs par défaut, il n'est pas obligatoire de les paramètrer. Cependant, il est obligatoire d'avoir un paramètre "url" et "onComplete" pour que évidement le tout fonction comme il le faut.

*/
// Synthaxe : ErreurObj ([String Message]) Objet
// Objet pour la gestion d'erreur
function ErreurObj(txt)
{
	// Variable //
	this.txt = txt;
	this.caller = getCaller(ErreurObj.caller);

	// Fonction //
	this.toString = function ()
	{
	return "Erreur : " + this.txt + " Fonction : " + this.caller;
	}
}

// Synthaxe : isset ([Variable]) Boolean
// Même chose que en PHP
function isset(toTest)
{
	return (typeof toTest != "undefined");
}

// Synthaxe : Array.inArray ([String ChercheQuoi]) Boolean
// Chercher pour une chaine particuliere dans un tableau
function inArray(text)
{
	for (var a = 0; a < this.length; a++)
	{
		if(this[a] == text)
			return true;
	}
}
Array.prototype.inArray = inArray;
// Synthaxe : getCaller ([String fonction.caller]) String
// Retourne le nom de la fonction appartir de l'attribut caller //
function getCaller(rawCaller)
{
	rawCaller = rawCaller.toString();
	if (rawCaller == null)
	return "";
	return rawCaller.substring(rawCaller.indexOf("function ") + 9,rawCaller.indexOf("(")).replace(" ","");
}

// Synthaxe : Ajax () Objet
// Objet centrale de la classe
function ajax()
{
	// Variable //
	this.asyn = true;
	this.data = "";
	this.url = "";
	this.method = "GET";
	this.returnFormat = "txt";
	this.obj;
	this.init();
}

// Synthaxe : httprequest () Objet XMLHttpRequest
// Crée l'objet XMLHttpRequest //
ajax.prototype.init = function()
{
	this.obj = null;
	if (window.XMLHttpRequest)
		this.obj = new XMLHttpRequest();
	else if (window.ActiveXObject) // if IE
	{
		var ieversions = ['Msxml2.XMLHTTP','Microsoft.XMLHTTP','Msxml2.XMLHTTP.5.0','Msxml2.XMLHTTP.4.0','Msxml2.XMLHTTP.3.0'];
		for(var i = 0; !this.obj && i < ieversions.length; i++)
		{
			try
			{
				this.obj = new ActiveXObject(ieversions[i]);
			}
			catch(e) { }
		}
	}
}

// Lorsque la requête ne réussit pas
ajax.prototype.onFailure = function (errorCode)
{
// ...
}

// Lorsque la requête réussit
ajax.prototype.onComplete = function (response)
{
// ...
}

// Synthaxe : setParamFromForm ([HTML Form || String Name || Int Index])
// Ajoute les paramètres et les données d'un formulaire à celui de la requête
ajax.prototype.setParamFromForm = function (obj)
{
	if (!isNaN(obj))
		obj = document.forms[obj];

	if (typeof obj == "string")
		eval("obj = document."+obj);
	
	if (!isset(obj))
		return ErreurObj("Donnée Invalide");
	
	this.method = (isset(obj.method) && (["GET","POST"].inArray(obj.method.toUpperCase()))) ? obj.method.toUpperCase() : this.method;
	this.url = obj.action;

	for (var i = 0; i < obj.elements.length; i++)
	{
		if (["file","button","reset","submit"].inArray(obj.elements[i].type.toLowerCase()))
			continue;

		if (this.data != null)
			this.data += "&";

		this.data += obj.elements[i].name + "=" + escape(obj.elements[i].value);
	}
}

// Synthaxe : setParam ([Array data])
// Ajoute les paramètres à la requête à partir d'un tableau
ajax.prototype.setParam = function (arr)
{
	if (typeof arr != "object" && !isset(arr))
		return ErreurObj("Donnée Invalide");


	for(k in arr)
	{
		switch (k)
		{
			case "url" :
				this.url = arr[k];
			break;
			case "method" :
				this.method = (["GET","POST"].inArray(arr[k].toUpperCase())) ? arr[k].toUpperCase() : this.method;
			break;
			case "data" :
				if (typeof arr[k] == "string")
				{
					if (this.data != "")
						this.data += "&";
					this.data += arr[k];
				}
				else
				{
					if (typeof arr[k] != "object")
					break;

					for (j in arr[k])
					{
						if (this.data != "")
							this.data += "&";
						this.data += j + "=" + escape(arr[k][j]);
					}

				}
			break;
			case "asynchronus" :
				this.asyn = arr[k];
			break;
			case "onComplete" :
				this.onComplete = arr[k];
			break;
			case "onFailure" :
				this.onFailure = arr[k];
			break;
			case "returnFormat" :
				this.returnFormat = arr[k];
			break;
		}
	}
}

// Synthaxe : Function execRequest ()
// Exécute la requête, ainsi que le callback
ajax.prototype.execute = function ()
{
	this.obj.open(this.method,this.url,this.asyn);
	
	if (this.method == "POST")
		this.obj.setRequestHeader('Content-Type','application/x-www-form-urlencoded');

	if (this.asyn)
	{
		_tempAJAX_Reference_ = this; // Crée une copie de l'objet AJAX courant pour pouvoir le récupérer après //
		this.obj.onreadystatechange = function ()
		{
			if (_tempAJAX_Reference_.obj.readyState == 4 && _tempAJAX_Reference_.obj.status == 200)
			{
				if (_tempAJAX_Reference_.returnFormat != "txt")
					response = _tempAJAX_Reference_.obj.responseXML;
				else
					response = _tempAJAX_Reference_.obj.responseText;

			if (typeof _tempAJAX_Reference_.onComplete == "string")
				eval (_tempAJAX_Reference_.onComplete);
			else
				_tempAJAX_Reference_.onComplete(response);
			}
			else if (_tempAJAX_Reference_.obj.readyState == 4)
			{
				errorCode = _tempAJAX_Reference_.obj.status;

				if (typeof _tempAJAX_Reference_.onFailure == "string")
					eval(_tempAJAX_Reference_.onFailure);
				else
					_tempAJAX_Reference_.onFailure(errorCode);
			}
		}
		this.obj.send(this.data);
	}
	else
	{
		this.obj.send(this.data);

		if (this.obj.status == "200")
		{
			if (this.returnFormat != "txt")
				response = this.obj.responseXML;
			else
				response = this.obj.responseText;

			if (typeof this.onComplete == "string")
				eval (this.onComplete);
			else
				this.onComplete(response);
		}
		else
		{
			errorCode = this.obj.status;
			if (typeof this.onFailure == "string")
				eval (this.onFailure);
			else
				this.onFailure(errorCode);
		}
	}
}
