//variable globale
var _global = this;
_global.xhrCount = Math.random();

//window.document.designMode = "on";

//Objet de gestion des requêtes Javascript
function requestManager ()
	{
	this.xhr; //Objet de la requête
	try
		{ this.xhr = new ActiveXObject("Microsoft.XMLHTTP"); }
	catch (e)
			{ this.xhr = new XMLHttpRequest(); }
	this.get = new Array(); //Tableau associatif des variables GET
	this.post = new Array(); //Tableau associatif des variables POST
	this.async = true; //Flag synchrone ou non
	this.xhrHeaders = new Array(); //Tableau Associatif des headers
	this.count = _global.xhrCount++; //Compteur de requêtes (en cas de mise en cache)
	this.keepInCash = false; //Désactivation du counter
	}

requestManager.prototype = 
	{
	send : function (uri)
		{
		this.uri = uri + "?";
		//construction des variables en GET suivant le tableau
		for (name in this.get) this.uri += name + "=" + escape(this.get[name]) + "&";
		//attribution du compteur de requêtes en GET
		(!this.keepInCash) ? this.uri += "idReq=" + this.count : false;
		//contsruction des variables en POST suivant le tableau
		this.strPost = "";
		for (name in this.post) this.strPost += name + "=" + escape(this.post[name]) + "&";
		//Détection de la méthode à utiliser
		(this.strPost != "") ? this.method = "POST" : this.method = "GET";
		(this.strPost == "") ? this.strPost = null : false;
		this.xhr.open(this.method, this.uri, this.async);
		//génération des headers suivant le tableau
		if (this.method == "POST")
			for (name in this.xhrHeaders) this.xhr.setRequestHeader(name, this.xhrHeaders[name]);
		var tmpThis = this;
		//gestion du changement d'état
		this.xhr.onreadystatechange = function ()
			{
			//si le serveur répond ok
			if(tmpThis.xhr.readyState == 4 && tmpThis.xhr.status == 200)
				tmpThis.action(tmpThis.xhr);
			else
				try
					{ tmpThis.loader(tmpThis.xhr.readyState); }
				catch (e) {}
			};
		this.xhr.send(this.strPost);
		},
	// fonction à paramétrer pour l'action
	action : function () {},
	// fonction à paramétrer pour la chargement
	loader : function () {}
	};

//Objet ParseurXML (Tableau, XSLT process)
function XMLParser (xml)
	{ this.xml = this.clean(xml.documentElement); }

XMLParser.prototype = 
	{
	// Node cleaner	
	clean : function (d)
		{
		var bal=d.getElementsByTagName('*');
		for(i=0;i<bal.length;i++)
			{
			a=bal[i].previousSibling;
			if(a && a.nodeType==3)
				this.go(a);
			b=bal[i].nextSibling;
			if(b && b.nodeType==3)
				this.go(b);
			}
		return d;
		},
	go : function (c)
		{
		if(!c.data.replace(/\s/g,''))
			c.parentNode.removeChild(c);
		},
	// appel d'un fichier XSL
	getXsl : function (xslUri) 
		{
		this.xsl;
		// ActiveX pour Internet Explorer
		if (navigator.appName == "Microsoft Internet Explorer")
			{
			try
				{ this.xsl = new ActiveXObject('Msxml2.XMLDOM'); }
			catch (e)
				{ this.xsl = new ActiveXObject('Microsoft.XMLDOM'); }
			this.xsl.async = false;
			this.xsl.load(xslUri);
			}
		// navigateur basé sur Gecko
		else if (document.implementation && document.implementation.createDocument)
			{
			this.xsl = document.implementation.createDocument('', '', null);
			this.xsl.async = false;
			try
				{ this.xsl.load(xslUri); }
			catch (e)
				{
				// navigateur basé sur Netscape à l'aide de lobjet XMLHTTPRequest
				this.xsl = new XMLHttpRequest();
				this.xsl.overrideMimeType('text/xml');
				this.xsl.open('GET', xslUri, false);
				this.xsl.send(null);
				(this.xsl.readyState == 4) ? this.xsl = this.xsl.responseXML : false;
				}
			}
		//Sortie du xsl au format text
		this.outputXSL;
		if(navigator.appName == "Microsoft Internet Explorer")
			this.outputXSL = this.xml.transformNode(this.xsl);
		else
			{
			var Cpu = new XSLTProcessor();
			Cpu.importStylesheet(this.xsl);
			this.outputXSL = Cpu.transformToFragment(this.xml, document);
			var serializer = new XMLSerializer();
			this.outputXSL = serializer.serializeToString(this.outputXSL);
			}
		return this.outputXSL;
		},
	getXMLTab : function ()
		{ return this.xml2tab(this.xml); },
	//Make XML2TAB TODO : Prendre en compte les attributs de la première balise.
	xml2tab : function (xml)
		{
		//Initialisation du tableau à retourner
		var tmpRefNodeTab = new Array();
		//Début du scrutage du noeud Parent
		if (xml.firstChild)
			{
			var niv = xml.childNodes;
			//Départ de la boucle de traitements des noeuds enfants
			for ( var i=0; i<niv.length; i++)
				{
				//Début de détection des attributs pour chaque noeud enfant
				//Initialisation du FLAG si attributs à faux.
				var isAttr = false;
				//Vérification de la présence d'attributs.
				if (niv[i].attributes) isAttr = true;
				
				//Si des la présence est avérée,
				if (isAttr)
					{
					//si le nombre d'attributs est supperieur à 0,
					if (niv[i].attributes.length > 0)
						{
						//Initialisation du tableau contenant les attributs.
						var attTmpTab = new Array();

						//Départ des boucles de traitement des attributs du noeud
						//pour chaques attributs,
						for ( var j=0; j<niv[i].attributes.length; j++)
							{
							//insérer sa val dans le tableau des attributs à la case de son nom. 
							try
								{ attTmpTab[niv[i].attributes[j].name] = niv[i].getAttribute(niv[i].attributes[j].name) }
							catch (e) {  }
							}//Fin des boucles de traitement des attributs.
						}
					}//Fin de vérification des attributs du noeud enfant.

				//Début de la vérification du type de noeud enfant.
				//Si le noeud enfant contient d'autres noeud
				if (niv[i].firstChild)
					{ 
					//Initialisation du tableau contenant les autres noeuds.
					var tmpEnglobTab = new Array();
					
					//si le contenu n'est pas un tableau xhtml
					if (niv[i].nodeName != "table")
						{
						//Affectation des noeuds inferieur à tmpEnglobTab
						//(la fonction s'appel elle même.)
						tmpEnglobTab["c"] = this.xml2tab(niv[i]);
						}
					else
						{
						//sinon affecter le tableau à tmpEnglobTab
						tmpEnglobTab["c"] = niv[i];
						}
					
					//Affectation attTmpTab à tmpEnglobTab si il contient des attributs.
					if (isAttr){ tmpEnglobTab["a"] = attTmpTab; }
					
					//Si le nom du noeud à déjà été référencé,
					if (tmpRefNodeTab[niv[i].nodeName])
						//affectation de tmpEnglobTab au tableau à retourner.
						{ tmpRefNodeTab[niv[i].nodeName].push(tmpEnglobTab); }
					//Sinon,
					else
						{
						//créer un tableau globale dans le noeud au nom de balise,
						var tmpCountNodeTab = new Array;
						//affecter tmpEnglobTab à la première place de tmpCountNodeTab,
						tmpCountNodeTab[0] = tmpEnglobTab;
						//affecter tmpCountNodeTab au tableau de retour.
						tmpRefNodeTab[niv[i].nodeName] = tmpCountNodeTab;
						}
					}
				//Si il ne contient pas d'autres noeuds
				else
					{  
					//Si il contient une valeure on retourne la valeure
					if (niv[i].nodeValue != null){ return niv[i].nodeValue; }
					//Si le noeud parent contient un noeud d'attributs 
					else
						{
						//Si référencé
						if (tmpRefNodeTab[niv[i].nodeName])
							{ 
							//affectation du noeud d'attributs au tableau de retour
							if (isAttr){ tmpRefNodeTab[niv[i].nodeName].push(attTmpTab); }
							else{ tmpRefNodeTab[niv[i].nodeName].push("empty attribute node"); }
							}
						//Sinon
						else
							{ 
							//Référencement et affectation du noeud d'attributs au tableau de retour 
							var tmpCountNodeAttTab = new Array; 
							
							if (isAttr){ tmpCountNodeAttTab[0] = attTmpTab; }
							else { tmpCountNodeAttTab[0] = "empty attribute node"; }
							
							tmpRefNodeTab[niv[i].nodeName] = tmpCountNodeAttTab;
							}
						}
					}
				}
			//retour du tableau
			return tmpRefNodeTab;
			}
		}
	};
