/**************************************************************************************************
* Classe générale de gestion des requêtes XMLHttpRequest
**************************************************************************************************/
// Constructeur
function xhr ()
{
	this._xhr=null;
	this._busy=false;
	this._url=null;
	this._data=null;
	this._fct='';
	this._fctwait='';
	this._msg=false;
	this._timer=null;
	this._timeout=60000;
	this._async=null;
	this._sendval=null;
	this._starttime=0;
	this._time=0;
	this._responsesize=0;
	this._response='';
	this._ok=(window.XMLHttpRequest || (document.getElementById && window.ActiveXObject)) ? true : false;
}

xhr.prototype=
{
	// Effectue une requete XMLHttpRequest et traite son résultat en fonction des paramètres passés
	//	_method		méthode : GET ou POST
	//	_url		url du fichier à exécuter
	//	_data		données post ou get à transmettre
	//	_fct		fonction qui doit traiter le résultat de la requête.
	//				- S'il n'y a pas d'argument autre que la réponse de la requête, on passe juste le nom de la fonction
	//				- S'il y a d'autres arguments que la réponse de la requête, on la passe sous la forme fonction('arg1','arg2'), avec ou sans la parenthèse fermante
	//	_fctwait	fonction à appeler entre l'appel de la requête et son résultat (par exemple pour afficher un message de chargement en cours)
	//	_sync		1 = synchrone, 0 = asynchrone
	request: function(_method,_url,_data,_fct,_fctwait,_sync)
	{
//		alert(_url + ' et ' + _data);

		if (!this._ok) return false;
		// Si une requête est en cours, on l'annule avant de lancer la nouvelle
		if (this._xhr)
		{
			this.setBusy(false);
			this._xhr.abort();
			this._xhr=null;
		}
		this._sendval=null;
		this._response='';
		this._responsesize=0;
		this._starttime=new Date().getTime();
		this._time=0;

		// Détection du support d'XMLHttpRequest et création d'un objet s'y rapportant
		// Tous navigateurs Gecko et KHTML compatibles (Mozilla 1.4+, Netscape 6.2+, Safari 1.2.1+...)
		if (window.XMLHttpRequest) this._xhr=new XMLHttpRequest();
		// Internet Explorer
		else if (window.ActiveXObject)
		{
			try { this._xhr=new ActiveXObject('Microsoft.XMLHTTP'); }
			catch(e)
			{
				try { this._xhr=new ActiveXObject('Msxml2.XMLHTTP'); }
				catch(e) { this._xhr=new ActiveXObject('Msxml2.XMLHTTP.4.0'); }
			}
		}

		this._async=(typeof _sync == 'undefined' || !_sync) ? true : false; // true si mode asynchrone
		if (typeof _fct == 'undefined') _fct='';
		if (this._xhr && (!this._async || _fct))
		{
			// Ajout d'un paramêtre aléatoire à la liste des paramêtres de l'url appelée pour éviter les poblèmes de cache d'IE et Safari
			_data+=((_data) ? '&' : '') + 'xhrrand=' + Math.random();
			// S'il y a une parenthèse fermante à la fonction passée en paramêtre, on la retire
//			if (_fct.substring(_fct.length-1) == ')') _fct=_fct.substring(0,_fct.length-1);
			// Si la fonction est passée sans arguments, on ajoute la parenthèse d'ouverture, sinon on ajoute une virgule après les arguments
//			_fct+=(_fct.indexOf('(') == -1) ? '(' : ',';
			if (_fct && _fct.indexOf('(') == -1) _fct+='()';

			this._url=_url;
			this._data=_data;
			this._fct=_fct;
			this._fctwait=_fctwait;
			this.setBusy(true);

			if (_method == 'POST')
			{
				this._xhr.open('POST',_url,this._async);
				this._xhr.setRequestHeader('Content-type','application/x-www-form-urlencoded');
				this._sendval=_data;
			}
			else this._xhr.open('GET',_url + '?' + _data,this._async);

			var _xhrtmp=this;
			if (this._async) this._xhr.onreadystatechange=function() { _xhrtmp.response(); };

			// 1 : début du transfert des données, à placer ici car Opera ne l'interprète pas dans la fonction "response"
//			if (this._xhr.readyState == 1 && this._fctwait) eval(this._fctwait);

//			alert('this._xhr.send(' + this._sendval + ')');
			this._xhr.send(this._sendval); // Envoi de la requête
			if (!this._async) this.response();

			return true;
		}
		else return false;
	},

	// Effectue une requête avec la méthode GET
	get: function(_url,_data,_fct,_fctwait,_sync)
	{
		return this.request('GET',_url,_data,_fct,_fctwait,_sync);
	},
	
	// Effectue une requête avec la méthode POST
	post: function(_url,_data,_fct,_fctwait,_sync)
	{
		return this.request('POST',_url,_data,_fct,_fctwait,_sync);
	},

	// Effectue des opérations lorsqu'une requête débute ou se termine
	//	_state		true = requête en cours, false = aucune requête en cours
	setBusy: function(_state)
	{
		// On stocke l'état actuel
		this._busy=_state;

		// Fonction d'attente au début du transfert, se substitue à (this._xhr.readyState == 1)
		if (_state && this._fctwait) eval(this._fctwait);

		// Si un timer tourne, on le stoppe
		if (this._timer) clearTimeout(this._timer);

		// Si la requête est en cours et si elle est asynchrone, on lance le timer de timeout
		var _xhrtmp=this;
		if (this._async && _state && this._timeout) this._timer=setTimeout(function() { _xhrtmp.timedOut(); },this._timeout);
	},

	// Annule une requête (appelé lors d'un timeout)
	timedOut: function()
	{
		this._busy=false;
		this._xhr.abort();
		if (this._fct) eval(this._fct);
//		eval(this._fct + '"")');
	},

	// Traite les différents stades de la requête 
	response: function()
	{
		if (this._busy)
		{
			// 1 : début du transfert des données, Opéra ne l'interprète pas lorsque placé ici
//			if (this._xhr.readyState == 1 && this._fctwait) { alert('wait'); eval(this._fctwait); }
			// 4 : requête terminée
			if (this._xhr.readyState == 4)
			{
				this.setBusy(false);
//				alert(this._xhr.responseText);
				// 200 : code HTTP pour OK
				if (this._xhr.status == 200)
				{
					if (this._xhr.responseText != null)
					{
						this._response=this._xhr.responseText;
						this._responsesize=this._xhr.responseText.length;
					}
 					this.setRequestTime(); // Peut être redéfini après le traitement de la fonction this._fct() au besoin
//					eval(this._fct + '"")');
//					eval(this._fct + '"' + escape(this._xhr.responseText) + '")');
				}
				// Si échec, on appelle la fonction sans texte résultat, la fonction devant interpréter ca comme un échec
//				else eval(this._fct + '"")');
				if (this._fct) eval(this._fct);
			}
		}
	},

	// Calcule la durée de la requête
	setRequestTime: function()
	{
		this._time=new Date().getTime() - this._starttime;
	},

	test: function(_txt) { alert(_txt); }
}
