/*****************************************************************************************************************************

	DESCRIPTION	: FICHIER SERVANT À FAIRE DES CALLS AJAX
	PAR 		: DAVID BOISSONNAULT (davidboiss@gmail.com)
	DATE MODIF	: 15 MARS 2007
			
	UTILISATION :
	
		PREMIÈREMENT 
		
			Ajoutez ceci dans le header de vos pages  :	<script type="text/javascript" src="ajax.js"></script>
			
			Ajoutez ensuite les lignes qui parle de divDebug vers la fin du fichier ajax.css dans votre fichier CSS
	
		1: Retourner la réponse ajax dans un objet HTML 
		
		------8<-----------------[DÉBUT]-Coupez-ici--------------------------------------------------------
		
			callAjax('fichier.php',null,document.getElementById('objetHTML'), [ document.getElementById('objetFORM') ] );
			
			// Note : Le dernier paramêtre est optionnel et est utilisé 
			// seulement si on veut envoyé un formulaire en POST.
			
		------8<-----------------[FIN]-Coupez-ici--------------------------------------------------------
	
	
	
		2: Traité le retour dans une fonction javascript.
		
		------8<-----------------[DÉBUT]-Coupez-ici--------------------------------------------------------
			
			// Déclarez premièrement la fonction qui traite le retour comme ceci :
			
			var fonctionDeRetour = function() {
				if (ajaxOk()) {
					
					// faite ce que vous voulez avec le retour
					
					// La réponse se trouve dans objAjax.responseText 
					// ou bien dans objAjax.responseXML (si vous traitez le XML)
					
					alert(objAjax.responseText);
					
					
					killAjax();
				}
			}
			
			// Appelez ensuite la fonction callAjax de cette manière
			
			callAjax('fichier.php',fonctionDeRetour, [ null ], [ document.getElementById('objetFORM') ] );
			
			// Si on n'envoit pas de formulaire avec notre call, on peut 
			// simplement appeler callAjax('fichier.php',fonctionDeRetour);
			// les derniers paramêtre sont facultatifs.
			
			// Notez qu'il faut passé null au 3ième paramêtre si on envoit un formulaire (4ième paramêtre)
			// car sinon le retour ne sera pas traité dans notre fonction
			
			
		------8<------------------[FIN]-Coupez-ici--------------------------------------------------------
		

*****************************************************************************************************************************/

// Paramêtres à modifier pour qu'ils fittent avec vos besoins.


/**************************************************************************
//Paramêtre ajaxEmptyObject :
//
// 		Lorsqu'un call ajax retourne son contenu dans un objet html
//		est-ce qu'au moment du call on veut vider le contenu du call ?
//		
//			Choix de réponse : true ou false
//			
//			Si true 	: 	L'objet du retour sera vider au moment du call, 
//							et sera mit à jour au moment de la réponse
//							
//			Si false 	: 	L'objet du retour restera comme il est au moment 
//							du call et sera mit à jour seulement lorsque la 
//							réponse ajax sera reçu
//							
*/

var ajaxEmtyObject = false;



/*************************************************************************/


/************************************************************************** 
//Paramêtre ajaxEnableDebug :
//
// 		Lorsqu'on effectue un call ajax est-ce qu'on veut logger 
//		toutes les opérations à l'intérieur d'un objet html ?
//		
//		Les opérations qui seront loggés :
//			
//			1 : Tous les call avec les paramêtres reçu
//			
//			2 : Toutes les réponses de retour.
//			
//			3 : Toutes les fois que des calls auront été ajoutés à la queue.
//			
//			4 : Toutes les exécutions de scripts dans les retours
//			
//		
//		Choix de réponse : true ou false
//			
//			Si true 	: 	On loggera les informations des call, des retour, 
//							et d'autres informations utile au déboggage des 
//							traitements ajax...
//							
//			Si false 	: 	On ne loggera rien (Mode production par exemple)
*/			

var ajaxEnableDebug = false;



/*************************************************************************/


/************************************************************************** 
//
//VEUILLEZ NOTER QUE SI VOUS AVEZ DÉFINI : 
//
//var ajaxEnableDebug = false;
//
//LES PROCHAINS PARAMÊTRES SONT INUTILES.
//
**************************************************************************/


/************************************************************************** 
//Paramêtre ajaxDebugID :
//
//		NOTE : Ce paramêtre est requis seulement si ajaxEnableDebug est true.
//
// 		Lorsqu'on effectue un call ajax est-ce qu'on veut logger toutes 
//		les opérations à l'intérieur d'un objet html ?
//		
//			Réponse : 	un string définissant l'id de l'objet HTML ou on ajoute
//						les informations de déboggage
//			
*/			

var ajaxDebugID = 'divDebug';



/*************************************************************************/


/************************************************************************** 
//Paramêtre ajaxShowDebugOnError :
//
// 		Lorsqu'on effectue un call ajax est-ce qu'on veut afficher 
//		la fenêtre de déboggage si une erreur survient ?
//		
//		Erreur possible :
//			
//			1: 	Lorsque le statut de la réponse est différent de 200 (objAjax.status).
//			
//			2: 	Lors du traitement d'une balise script dans le retour, et que ce 
//				traitement retourne une erreur.
//			
//			3: 	Lorsqu'il est impossible d'effectuer un call Ajax avec le browser.
//		
//		Choix de réponse : true ou false
//			
//			Si true 	: 	On affiche la fenêtre de déboggage en cas d'erreur
//							
//			Si false 	: 	On n'affiche pas la fenêtre de déboggage...
*/			


var ajaxShowDebugOnError = false;



/*************************************************************************/



/**************************************************************************

	  VOUS NE DEVRIEZ PAS AVOIR BESOIN DE MODIFIER LE CODE PLUS BAS.

**************************************************************************/


// Variables qui sont utilisées par plusieurs fonctions et qui doivent être déclarées globalement.  
var objAjax=null;
var ajaxQueue=new Array();
var ajaxReturnObject=null;

//sdfsdf
// Fonction qui effectue les call, les explications pour cette fonction sont décrites au début du fichier.
function callAjax(url,returnFunction,returnObject,formToPost,forcePost) {
	//alert('test ajax');
	// déclaration d'un string vide qui servira a garder le contenu 
	// du formulaire à poster, si formulaire à poster il y a.
	var postData = "";
	
	// si l'objet ajax n'est pas présentement en utilisation, on peut y aller avec le call.
	if (objAjax == null) {
		//alert(formToPost);
		// Si on doit poster un formulaire, on apelle la fonction buildPostData 
		// qui construira le string encodé du formulaire à poster.
		if (!('undefined' == typeof formToPost || formToPost == null)) postData = buildPostData(formToPost);
		if(!('undefined' == typeof forcePost || forcePost == null)) postData = forcePost;
		// vérification si on retourne la réponse dans un objet
		// dans ce cas il sera différent de null et n'aura pas un type 'undefined'
		if (!('undefined' == typeof returnObject || returnObject == null)) {
			
			// On garde alors l'objet de retour globalement pour pouvoir l'utiliser dans la fonction ajaxToElement.
			ajaxReturnObject = returnObject;
			
			// Si on doit vider le contenu de l'objet de retour au moment du call, on le vide...
			if (ajaxEmtyObject) ajaxReturnObject.innerHTML = '';
			
			// La fonction de retour sera donc ajaxToElement
			returnFunction = ajaxToElement;
		}
		else ajaxReturnObject = null;
		
		// Ajout de compatibilité pour la majorité des browsers....
		ajaxAddDebug('Tentative de call ajax', 'URL : '+url+((postData != '') ? '<br/>FORMDATA :'+postData : ''));
		if (window.XMLHttpRequest) {
			// Cette méthode sera utilisé pour la majorité des browsers (IE7, Firefox, Safari, Konqueror, etc...)
			objAjax = new XMLHttpRequest();
			
			// Assignation de la fonction de retour...
			objAjax.onreadystatechange = returnFunction;
			
			if (postData != "") {
				// Si on post un formulaire avec le call, on ouvre l'objet en post 
				// et on envoit le contenu du formulaire à l'aide de la fonction send().
				
				objAjax.open("POST",url,true);
				objAjax.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
				objAjax.send(postData);
			}
			else {
				// Sinon on envoit le call en GET, et on envoit null à la fonction send.
				
				// 		Note : 	je ne sais pas pourquoi on envoit null à la fonction send() avec XMLHttpRequest()
				//				alors qu'on ne passe pas ce paramêtre avec ActiveXObject("Microsoft.XMLHTTP")
				//				mais c'est comme ca que l'exemple sur w3schools est décrite.
				
				objAjax.open("GET",url,true);	
				objAjax.send(null);
			}			
		}
		else if (window.ActiveXObject) {
			
			// Même chose que plus haut mais pour MSIE 6 (Et peut-être MSIE 5.5, je ne suis pas très sur...)
			
			objAjax = new ActiveXObject("Microsoft.XMLHTTP");
			objAjax.onreadystatechange = returnFunction;
			if (postData != "") {
				objAjax.open("POST",url,true);
				objAjax.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");
				objAjax.send(postData);
			}
			else {
				objAjax.open("GET",url,true);	
				objAjax.send();
			}
		}
		else {
			// Sinon le call ajax est impossible, aviser l'usager...
			ajaxAddError('Call ajax impossible','Le browser ne comprend ni l\'objet ActiveXObject, ni XMLHttpRequest');
			alert("Browser incompatible avec la technologie du site.");
		}
	}
	
	// Si l'objet ajax était déjà en train d'effectuer un call, 
	// alors on ajoute ce call à la queue, il sera traité dès 
	// que les calls précédents seront terminés.
	else queueAjaxCall(url,returnFunction,returnObject,formToPost);
}

// Fonction qui ajoute un élément dans la queue. 
// Les paramêtre sont les même que la fonction callAjax.
//
// Vous n'aurez pas besoin d'appeler cette fonction
// C'est la fonction callAjax qui s'occupe de l'appeler
// si un call est en traitement.
function queueAjaxCall(url,retfunc,retobj,ftp) {
	var newqueue = new Array();
	newqueue['url'] = url;
	newqueue['retfunc'] = retfunc;
	newqueue['retobj'] = retobj;
	newqueue['ftp'] = ftp;
	ajaxQueue.push(newqueue);
	ajaxAddDebug('Ajout d\'un call ajax à la queue','URL : '+url);
}

// Fonction servant à vérifié le readyState
// il est important d'appeler cette fonction
// et de ne pas vérifier manuellement le readyState
// car cette fonction ajoute le retour dans 
// votre objet de déboggage.
//
// La manière d'utiliser la fonction est décrite 
// dans l'entête du fichier.
function ajaxOk() {
	if (objAjax.readyState == 4) {
		//alert(objAjax.responseText);
		if (objAjax.status == 200) ajaxAddDebug('Réponse reçu',objAjax.responseText);
		else ajaxAddError('Réponse reçu avec un statut différent de 200 ('+objAjax.status+')',objAjax.responseText);
		
		return true;
 	}
	else return false;
}


// Fonction pour envoyer le contenu d'une requete vers un élément HTML.
function ajaxToElement() {
	if (ajaxOk()) {
		
		// Modification de l'objet de retour avec la réponse...
		ajaxReturnObject.innerHTML = objAjax.responseText;
		/*var teststr = objAjax.responseText;
		//alert(teststr);
		var scripts;
		var regexpress = /<script.*>(.*)<\/script>/gmi;
		if (scripts = regexpress.exec(teststr)) {
			alert(scripts[1]);
		}
		// Vérification si on a recu des balises <SCRIPT> dans la réponse et éxécution de ceux-ci.
		*/
		var fs = ajaxReturnObject.getElementsByTagName('script');
		
		for(var x=0;x<fs.length;x++) {
			try { 
				eval(fs[x].innerHTML); 
				ajaxAddDebug('Script exécuté dans la réponse',fs[x].innerHTML);
				
			}
			catch(e) { 
				//alert('Error executing script : '+fs[x].innerHTML);
				ajaxAddError('Un script a retourné une erreur dans la réponse ('+e.description+')',fs[x].innerHTML);
			}
		}
		
		// Destruction de l'objet ajax... 
		killAjax();
	}
}


// Destruction de l'objet ajax.

// À appeler lorsqu'on termine le traitement dans une fonction de retour...
// Vous trouverez un exemple concret dans le header du fichier...
function killAjax() {
	objAjax = null;	
	
	// S'il y a des éléments dans la queue, alors on apelle le premier, puis on l'enleve de la queue...
	if (ajaxQueue.length > 0) {
		callAjax(ajaxQueue[0]['url'],ajaxQueue[0]['retfunc'],ajaxQueue[0]['retobj'],ajaxQueue[0]['ftp'])	
		ajaxQueue.shift();
	}
	
}


// Fonction qui build un string encodé pour poster un formulaire...
function buildPostData(frm) {
	
	// String de retour, on la débute vide...
	var returnData = "";
	
	// Tags html qu'on doit vérifier les valeurs...
	var tags = new Array("input","textarea","select");
	
	// On loop et on cherche chacun des éléments dans le array plus haut...
	for (var k = 0; k < tags.length; ) {
		var ar = frm.getElementsByTagName(tags[k++]);
		var cc = null;
		for (var i = 0; i < ar.length;) {
			cc = ar[i++];
			
			// Si l'objet possède un attribut "name" et n'est pas de type "file"
			// alors on doit l'encoder dans notre string de retour.
			if (cc.name != "" && cc.type != "file") {
				
				// Traitement différent si c'est un checkbox ou un radio... 
				// dans ce cas, seulement si l'attribut checked est différent 
				// de false on doit l'ajouter dans notre string de retour...
				if (cc.getAttribute("type") == 'checkbox' || cc.getAttribute('type') == 'radio') {
					if (cc.checked != false) returnData += (returnData != "") ? "&" + cc.name + "=" + escape(cc.value) : cc.name + "=" + escape(cc.value);
				}
				
				// Sinon, c'est un élément HTML normal, on l'ajoute dans notre string de retour...
				else returnData += (returnData != "") ? "&" + cc.name + "=" + escape(cc.value) : cc.name + "=" + escape(cc.value);					
			}
		}
	}
	
	// On retourne ensuite le string qu'on vient de bâtir...
	return returnData;
}

function ajaxAddDebug(strOperation,strData) {
	// Ajout d'une ligne dans le débug s'il est actif
	if (ajaxEnableDebug) {
		var debugElement = document.createElement('div');
		debugElement.className = 'success';
		var debugInfo = document.createElement('div');
		debugInfo.className = 'operation';
		var txtNode = document.createTextNode(strOperation);
		debugInfo.appendChild(txtNode);
		var debugData = document.createElement('pre');
		debugData.innerHTML = strData.split('<').join('&lt;').split('>').join('&gt;');
		debugElement.appendChild(debugInfo);
		debugElement.appendChild(debugData);
		try{ 
			document.getElementById(ajaxDebugID).appendChild(debugElement); 
			document.getElementById(ajaxDebugID).scrollTop = 99999999;
		}
		catch(e) { alert('L\'objet de déboggage (ID : '+ajaxDebugID+') n\'a pas été trouvé.'); }
	}
	
}

function ajaxAddError(strOperation,strData) {
	// Ajout d'une ligne d'erreur dans le débug s'il est actif et montrer la fenetre si on doit la montrer lors d'une erreur
	if (ajaxEnableDebug) {
		var debugElement = document.createElement('div');
		debugElement.className = 'error';
		var debugInfo = document.createElement('div');
		debugInfo.className = 'operation';
		var txtNode = document.createTextNode(strOperation);
		debugInfo.appendChild(txtNode);
		var debugData = document.createElement('pre');
		debugData.innerHTML = strData.split('<').join('&lt;').split('>').join('&gt;');
		debugElement.appendChild(debugInfo);
		debugElement.appendChild(debugData);
		try{ 
			document.getElementById(ajaxDebugID).appendChild(debugElement); 
			if (ajaxShowDebugOnError) document.getElementById(ajaxDebugID).style.display = 'block';
			document.getElementById(ajaxDebugID).scrollTop = 99999999;
		}
		catch(e) { alert('L\'objet de déboggage (ID : '+ajaxDebugID+') n\'a pas été trouvé.'); }
	}
}

function validForm(frm) {
	
	var tags = new Array('input','textarea','select');
	for (var k=0; k<tags.length; k++){
		if (typeof(frm) != 'undefined') 
			var sfElems = frm.getElementsByTagName(tags[k]);
		else 
			var sfElems = document.getElementsByTagName(tags[k]);
		
		for (var i = 0; i < sfElems.length; i++) {
			if (sfElems[i].value == "" && sfElems[i].getAttribute('obg')=="true") {
				alert(sfElems[i].getAttribute('err'));
				sfElems[i].focus();
				return(false);
			}
			else if (sfElems[i].getAttribute('obg')=="check" && sfElems[i].checked == false) {
				alert(sfElems[i].getAttribute('err'));
				sfElems[i].focus();
				return(false);
			}
			
			switch(sfElems[i].getAttribute("special")){
				
				case null : isValid = true;
							break;
				case "email" : 	isValid = (sfElems[i].getAttribute("obg") != "true" && sfElems[i].value == '') ? true : validMail(sfElems[i].value);
								oComments = "\nEx.: nom@site.com";
								break;
				case "date" :  	isValid = (sfElems[i].getAttribute("obg") != "true" && sfElems[i].value == '') ? true :  validDate(sfElems[i].value);
								oComments = "\nEx.: 1982-03-25";
								break;
				case "nospecial" :  isValid = (sfElems[i].getAttribute("obg") != "true" && sfElems[i].value == '') ? true :  validSpecial(sfElems[i].value);
									oComments = "\nEx.: a-z, A-Z, 0-9";
									break;
				case "numeric" :  	isValid = (sfElems[i].getAttribute("obg") != "true" && sfElems[i].value == '') ? true :  validNumeric(sfElems[i].value);
									oComments = '';
									if (isValid && sfElems[i].getAttribute('minval') != null &&  parseFloat(sfElems[i].value) < parseFloat(sfElems[i].getAttribute('minval'))) {
										isValid=false;	
									}
									if (isValid && sfElems[i].getAttribute('maxval') != null &&  parseFloat(sfElems[i].value) > parseFloat(sfElems[i].getAttribute('maxval'))) {
										isValid=false;	
									}
									
									break;
				case "mustequal" : 
								oComments = '';
								if (sfElems[i].value != document.getElementById(sfElems[i].getAttribute('depend_id')).value) isValid=false;
								else isValid=true;
								break;	
				case "tel" : 	isValid = (sfElems[i].getAttribute("obg") != "true" && sfElems[i].value == '') ? true :  validTel(sfElems[i].value);
								oComments = "\nEx.: 819-379-8614";
								break;
					
			}
			if(!isValid){
				alert(sfElems[i].getAttribute("errorspecial")+oComments);
				sfElems[i].focus();
				return false;
			}
			if (sfElems[i].getAttribute("minlength") != null && sfElems[i].value.length < sfElems[i].getAttribute("minlength")) {
				alert(sfElems[i].getAttribute("errorlength"));
				sfElems[i].focus();
				return false;
			}
			
		}
	}
	return(true);
}

function validDate(dateaaaammjj) {
	var dt=dateaaaammjj.split("-"),date=new Date(dt[0],dt[1]-1,dt[2]);
	return date.getDate()==dt[2]&&date.getMonth()+1==dt[1]&&date.getFullYear()==dt[0]?date:false;
}

function validSpecial(fStr){
	myReg = new RegExp("[A-Za-z0-9]+");
	if(myReg.exec(fStr)!=fStr){return false};
	return true;
}

function validNumeric(fStr){
	myReg = new RegExp("[0-9.]+");
	if(myReg.exec(fStr)!=fStr){return false};
	return true;
}


function checkDependency(obg) {
	if (obg.getAttribute('depend')!="")
	{
		var sfElems = document.getElementsByTagName('input');
		for (var i = 0; i < sfElems.length; i++) {
			if (obg.getAttribute('depend')== sfElems[i].name && obg.value=="" && sfElems[i].checked==true && sfElems[i].value=="1") {
				//alert(obg.getAttribute('err'));
				return(false);
			}
		}
		
	}
	return(true);
}

function validMail(email) {
	var result = false
	var theStr = new String(email)
	var index = theStr.indexOf("@");
	if (index > 0) {
		var pindex = theStr.indexOf(".",index);
		if ((pindex > index+1) && (theStr.length > pindex+1)) result = true;
	}
	return result;
}

function validTel(val) {
	if (val.match(/\(?\d{3}\)?([-\/\.])\d{3}\1\d{4}/) || val.match(/\d{10}/)) return true;
}

function showHasDomain(){
	document.getElementById('ownDomain').style.display='';
	document.getElementById('buyDomain').style.display='none';
	document.getElementById('montant').value = document.getElementById('montant').getAttribute('montant')+'$ (CND)';
}

function showWantDomain(){
	document.getElementById('ownDomain').style.display='none';
	document.getElementById('buyDomain').style.display='';
	document.getElementById('montant').value = (parseInt(document.getElementById('montant').getAttribute('montant'))+15)+'$ (CND)';
}

function checkAvail(domain){
	ret = function(){
		if(ajaxOk()){
					 document.getElementById('resdomain').innerHTML='recherche en cours...';
					 if(objAjax.responseText=='Available'){
						 document.getElementById('resdomain').innerHTML='This domain is available';
						 document.getElementById('resdomain').style.color='#4ae25c';
						 document.getElementById('resdomain').setAttribute('ok','1');
					 }else{
						  document.getElementById('resdomain').innerHTML='This domain is not available';
						  document.getElementById('resdomain').style.color='#e24a4a';
						  document.getElementById('resdomain').setAttribute('ok','0');
					 }
					 killAjax();
					}
	}
	if(domain!=''){
		callAjax('/ajax/availDomain.php?d='+domain,ret);
	}else{
		document.getElementById('resdomain').setAttribute('ok','0');
	}
}

function checkForm(f){
	if(validForm(f)){
		if(document.achat.wantdomain[1].checked){ //achat de domain
			if(document.getElementById('resdomain').getAttribute('ok')==0 || document.getElementById('resdomain').getAttribute('ok')=='0'){
				alert('Select a valid domain name or click on the button \'Validate this domain\' to validate this domain.');
				return(false);
			}
		}else{
			if(document.getElementById('domainname').value==''){
				alert('Enter your domain name');
				return(false);
			}
		}
		return(true);
	}else{
		return(false);
	}
	
}

