/**
* Objet FormValidator
*
* Permet de g?rer la validation de formulaire
*
* Mettre onsubmit="return validator.check(this);" dans la balise <form>
*
* Utilisation :
* 	validator.addRules("id_du_champ","contraintes","nom du champ");
*
* Contraintes est une liste avec l'espace comme separateur
* les valeurs peuvent etre :
*		champ obligatoire 		=> required (marche aussi pour le select)
*		taille mini				=> minlength=X
*		taille maxi 			=> maxlength=X
*		champ numerique			=> numeric
*		nombre de decimales 	=> decimals=X
*		email					=> mail
*		liste d'email (;)		=> mails
*		entre 2 nombres			=> between=min|max
*		egal a un autre			=> equal=idAutreChamp
*       expression reguli?re	=> regexp=[a-zA-Z0-9]§
*									ATTENTION IL FAUT FINIR SA REGEXP PAR §
*
* Gestion des boutons radios :
*
*		Mettre radio=nom_des_radios au lieu de l'id et required en contrainte.
*		Possibilite de preciser newline.
*
* Gestion des checkboxs :
*		Mettre check=id_check1|id_check2 ...
*		Regles possibles : minlength= maxlength=
*		Possibilite de preciser newline.
*
* Gestion des dates :
*
*		Mettre les 3 id des champs en les separant par des '|'
*		et dans l'ordre jour mois annee, puis mettre la contrainte 'date'.
*		Exemple : 
*			validator.addRules("idjour|idmois|idannee","date required","Date de naissance");
*
*		Pour verifier qu'une date est bien superieure a une autre :
*		Mettre les 3 id des champs de la deuxieme en les separant par des '|'
*		puis mettre dans les contraintes after=id_jour_date1|id_mois_date1|id_annee_date1
*		Il faut aussi passer les deux labels en les separant par des '|' en mettant
*		celui correspondant a la date qui doit etre superieure en premier.
*		
* Gestion des pièces d'identité :
*
*		carte identité 	: mettre id_du_champ et cni et delivrance=id_mois_delivrance|id_annee_delivrance en contrainte
*		passeport		: mettre id_du_champ et passeport en regle
*
*
* Utilisation de fonction(s) de validation externe :
*
*		Mettre function=nom_fonction ou function=nom_fonction1|nom_fonction2
*		Exemples :
*			validator.addRules("idduchamp","function=testDept","Champ");
*			validator.addRules("idduchamp","function=testDept|testAnnee","Champ");
*			validator.addRules("idduchamp","function=testDept required","Champ");
*
*		Les fonctions appelées prennent un argument qui correspond au champ et doivent retourner un
*		résultat de type ValidatorResult.
*		Exemple :
*			function testDept(field){
*				if(document.getElementById('un_autre_champ').value == 100 && field.value == 99)
*					return new ValidatorResult(true,null);
*				else
*					return new ValidatorResult(false,'Incoh&eacute;rence d&eacute;partement / pays');
*			}
*		
*
* Cette version fonctionne avec un formulaire se trouvant dans une table HTML.
* Par defaut, il rajoute une cellule apres le champ a valider.
* Si on veut que le leMessage soit sur une nouvelle ligne,
* il suffit de mettre 'newline' dans les contraintes.
*
* Ne pas mettre d 'espace entre = et la valeur
* decimals peut etre mis a 0 pour un entier
*
* Exemple : validator.addRules("Description","maxlength=3 minlength=1 required","Description");
*
*/

function FormValidator()
{
	this.rules 	= new Array();
	this.isGood	= true;
	this.focused = false;
	this.firstPass = true;
	this.incohIds = new Array();
	
	this.changeRuleField = function(oldField, newField){
		for(fieldId in this.rules){
			if(oldField == fieldId){
				var temp = this.rules[fieldId];
				this.removeRules(oldField);
				this.addRules(newField,temp.rules,temp.label);
				break;
			}
		}
	}
	
	this.removeRules = function(ruleName){
		var temp = this.rules;
		this.rules 	= new Array();
		var isNl = false;
		for(key in temp){
			if(key != ruleName)
				this.rules[key] = temp[key];
			else
				isNl = temp[key].rules.indexOf("newline") != -1;
		}
		if(this.inTable){
			if(!isNl && document.getElementById("formValidatorTd"+ruleName))
				document.getElementById("formValidatorTd"+ruleName).parentNode.removeChild(document.getElementById("formValidatorTd"+ruleName));
			if(isNl && document.getElementById("formValidatorTr"+ruleName))
				document.getElementById("formValidatorTr"+ruleName).parentNode.removeChild(document.getElementById("formValidatorTr"+ruleName));
		}else{
			if(document.getElementById("erreur"+ruleName))
				document.getElementById("erreur"+ruleName).parentNode.removeChild(document.getElementById("erreur"+ruleName));
		}
	}
	
	this.removeAll = function(){

		for(ruleName in this.rules){
			if(this.inTable){
				var isNl = this.rules[ruleName].rules.indexOf("newline") != -1;
						
				if(!isNl && document.getElementById("formValidatorTd"+ruleName))
					document.getElementById("formValidatorTd"+ruleName).parentNode.removeChild(document.getElementById("formValidatorTd"+ruleName));
				if(isNl && document.getElementById("formValidatorTr"+ruleName))
					document.getElementById("formValidatorTr"+ruleName).parentNode.removeChild(document.getElementById("formValidatorTr"+ruleName));
			}else{
				if(document.getElementById("erreur"+ruleName))
					document.getElementById("erreur"+ruleName).parentNode.removeChild(document.getElementById("erreur"+ruleName));
			}
		}
		this.rules 	= new Array();
	}
	
	this.addRules = function(fieldId,rules,label,decalage,decalageT,leMessage){
		
		var par = null;
		suiv = null;
		var cell = null;
		var di;
		di = document.getElementById("erreur"+fieldId);
		if (di == null) di = document.createElement("div");
		di.id	= "erreur"+fieldId;
		di.className = "erreurFormulaire";
		var ecart = 0;
		if(decalage != null)
			ecart = decalage;
		var ecartT = 0;
		if(decalageT != null)
			ecartT = decalageT;
		
		
		if(this.inTable){
			
				var td = document.createElement("td");  
				td.id = "formValidatorTd"+fieldId;
						
				td.appendChild(di);
				
				if(fieldId.indexOf("|") != -1 && fieldId.indexOf("check") == -1){
					var ids = fieldId.split("|");
					par = this.getRow(document.getElementById(ids[1]));
				}
				else if(fieldId.indexOf("radio") != -1 ){
					deb 	= fieldId.indexOf('radio')+6;
					val 	= fieldId.substring(deb);	
					var rads = document.getElementsByName(val);
					par = this.getRow(rads[rads.length-1]);
				}else if(fieldId.indexOf("check") != -1 ){
					deb 	= fieldId.indexOf('check')+6;
					val 	= fieldId.substring(deb);	
					if(val.indexOf("|") != -1){
						vals 	= val.split("|");
						par 	= this.getRow(document.getElementById(vals[vals.length-1]));
					}else
						par 	= this.getRow(document.getElementById(val));
				}
				else{
					par = this.getRow(document.getElementById(fieldId));
				}
			
				if(rules.indexOf('newline') == -1){
					par.appendChild(td);
				}
				else{
					var colsval = par.getElementsByTagName("td").length + par.getElementsByTagName("th").length;
					var nl = document.createElement("tr");
		
					td.colSpan=colsval;
					nl.appendChild(td);
					nl.id = "formValidatorTr"+fieldId;
					if(par.nextSibling)
						par.parentNode.insertBefore(nl,par.nextSibling);
					else
						par.parentNode.appendChild(nl);
						
				}
			
		}
		else{
		
			if(fieldId.indexOf("|") != -1 && fieldId.indexOf("check") == -1){
				var ids = fieldId.split("|");
				par = document.getElementById(ids[1]).parentNode;
				suiv = document.getElementById(ids[1]).nextSibling;
			}
			else if(fieldId.indexOf("radio") != -1 ){
				deb 		= fieldId.indexOf('radio')+6;
				val 		= fieldId.substring(deb);	
				var rads 	= document.getElementsByName(val);
				par 		= rads[rads.length-1].parentNode;
				suiv 		= rads[rads.length-1].nextSibling;
				lastid		= rads[rads.length-1].id;
				if(suiv != null && 
					(suiv.nodeName.toLowerCase() == "label" && suiv.getAttributeNode('for').value == lastid))
					suiv = suiv.nextSibling;
				
					
			}else if(fieldId.indexOf("check") != -1 ){
				deb 	= fieldId.indexOf('check')+6;
				val 	= fieldId.substring(deb);	
				if(val.indexOf("|") != -1){
					vals 	= val.split("|");
					par 	= document.getElementById(vals[vals.length-1]).parentNode;
					suiv 	= document.getElementById(vals[vals.length-1]).nextSibling;
					lastid	= vals[vals.length-1];
				}else{
					par 	= document.getElementById(val).parentNode;
					suiv 	= document.getElementById(val).nextSibling;
					lastid	= val;
				}
				if(suiv != null && (suiv.nodeName.toLowerCase() == "label" && suiv.getAttributeNode('for').value == lastid))
					suiv = suiv.nextSibling;
			}
			else{
				par = document.getElementById(fieldId).parentNode;
				suiv = document.getElementById(fieldId).nextSibling;
			}
							
			if(rules.indexOf('newline') != -1){
				temp = document.createElement("br");	
				suiv2 = suiv.nextSibling;
				if(suiv2 == null)
					par.appendChild(temp);
				else
					par.insertBefore(temp,suiv2);
				suiv = temp.nextSibling;	
			}
			
			if(suiv && suiv.nodeName != "#text"){
			    par.insertBefore(di,suiv);
			}
			else{
			    
			    if(suiv == null){
					temp = document.createTextNode("");				
					par.appendChild(temp);
					suiv = temp;
				}
				else
					suiv = suiv.nextSibling;
			    
			    par.insertBefore(di,suiv);
			}
		}
		
		this.rules[fieldId] = {rules:rules, label:label, cell: null, leMessage:leMessage};
		if(this.inTable)
			this.rules[fieldId].cell = par;
		else{
			var x,y,w;
			
			if(fieldId.indexOf("radio") != -1){
				if(!document.all){
					x = calculeOffsetLeft(par);
					y = calculeOffsetTop(par);
					w = par.offsetWidth;
				}else{	
					var spl = fieldId.split("=");
					var compRName = spl[spl.length-1];
					var rads = document.getElementsByName(compRName);
					var r = rads[rads.length-1];
					x = calculeOffsetLeft(r);
					y = calculeOffsetTop(r);
					w = 50;
				}
			}
			else if(fieldId.indexOf("check") != -1){
				if(!document.all){
					x = calculeOffsetLeft(par);
					y = calculeOffsetTop(par);
					w = par.offsetWidth;
				}else{
					var spl = fieldId.split("=");
					var compRName = spl[spl.length-1];
					var rads = compRName.split("|");
					var r = rads[rads.length-1];
					x = calculeOffsetLeft(r);
					y = calculeOffsetTop(r);
					w = 50;
				}
			}else{
				//debugger;
				x = calculeOffsetLeft(document.getElementById(fieldId));
				y = calculeOffsetTop(document.getElementById(fieldId));
				w = document.getElementById(fieldId).offsetWidth;
			}
			di.style.position = "absolute";

			if(undefined == window.noPlace || noPlace == false)
			{				
				YAHOO.util.Dom.setY(di,y+ecartT);	
				YAHOO.util.Dom.setX(di,x+parseInt(w)+30+ecart);
			}
			
			YAHOO.util.Dom.setStyle("erreur"+fieldId,"opacity","0");
		}
		
		if(rules.indexOf('numeric') != -1)
		{
			document.getElementById(fieldId).onkeypress = function(e){
				var keyCode;
				
				if(!e){
					e = window.event;	
					keyCode = e.keyCode
				}
				else{
					keyCode = e.charCode;
					if(keyCode == 0)
						return;
				}
				
				if(!(keyCode >= 48 && keyCode <=57))
				{					
					
					dec = true;
					if(rules.indexOf('decimals') != -1)
					{
						deb 	= rules.indexOf('decimals')+9;
						space 	= rules.indexOf(' ',deb);
						val 	= space == -1 ? rules.substring(deb) : rules.substring(deb,space);	
						dec 	= parseInt(val) != 0;
					}
					else
						dec = false;
					switch(keyCode)
					{
						case 44:	
							if((this.value.indexOf('.') == -1 && dec)){
								if(document.all)
									e.keyCode = 46;
								else{
									this.value += ".";
									validator.stopKeyPress(e);
								}
							}
							else
								validator.stopKeyPress(e);
							break;
						case 46:
							if(this.value.indexOf('.') != -1 || !dec)
								validator.stopKeyPress(e);
							break;
						default:
							validator.stopKeyPress(e);
					}
				}
				else
				{
					if(rules.indexOf('decimals') != -1)
					{
						deb 	= rules.indexOf('decimals')+9;
						space 	= rules.indexOf(' ',deb);
						val 	= space == -1 ? rules.substring(deb) : rules.substring(deb,space);
						if(this.value.indexOf('.') != -1)
						{
							if(this.value.length - this.value.indexOf('.') - 1 == parseInt(val))
								validator.stopKeyPress(e);
						}
					}
				}
			}
		}
		
		if(leMessage != null)
		{
			
		}
	}
	
	
	/**
	* Méthode qui arrête la propagation de l'évènement
	* @param Event L'évènement
	* @private
	*/
	this.stopKeyPress = function(e){
		if(!document.all)
			e.preventDefault();
		 else
			 e.keyCode = 0;
		 return false;
	}
	
	
	/**
	* Verification d'email
	* @param	String L'email
	* @return 	boolean
	* @type 	boolean
	* @private
	*/ 
	this.isMail = function(string) {
		if (string.search(/^([0-9a-zA-Z]([-.\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\w]*[0-9a-zA-Z]\.)+[a-zA-Z]{2,6})$/) != -1)
			return true;
		else
			return false;
	}
	
	/**
	* Vérifie que le jour est bien compris entre 1 et 31
	* @param String La valeur du jour
	* @return 	boolean
	* @type 	boolean
	* @private
	*/
	this.checkDay = function(val){
		return ( val.length==2 && (!isNaN(val) && (parseInt(val,10) > 0 && parseInt(val,10) < 32)));
	}
	
	/**
	* Vérifie que le mois est bien compris entre 1 et 12
	* @param String La valeur du mois
	* @return 	boolean
	* @type 	boolean
	* @private
	*/
	this.checkMonth = function(val){
		return ( val.length==2 && (!isNaN(val) && (parseInt(val,10) > 0 && parseInt(val,10) < 13)));
	}
	
	/**
	* Vérifie que l'année est bien comprise entre 1850 et 2050
	* @param String La valeur de l'année
	* @return 	boolean
	* @type 	boolean
	* @private
	*/
	this.checkYear = function(val){
		return ( val.length==4 && (!isNaN(val) && (parseInt(val,10) > 1849 && parseInt(val,10) < 2051)));
	}
	
	/**
	* Vérifie que l'objet reçu comporte bien une date complète
	* @param DateObj Un objet retourné par getDateObj()
	* @return 	boolean
	* @type 	boolean
	* @private
	* @see DateObj
	* @see #getDateObj
	*/
	this.checkDateIsFull = function(o){
		if( (trim(o.day) && (!trim(o.month) || !trim(o.year)))
				|| (trim(o.year) && (!trim(o.month) || !trim(o.day)))
				|| (trim(o.month) && (!trim(o.day) || !trim(o.year))))
			return false;
		return true;
	}
	
	/**
	* Vérifie que l'objet reçu comporte bien une date non vide
	* @param DateObj Un objet retourné par getDateObj()
	* @return 	booleen
	* @type 	boolean
	* @private
	* @see DateObj
	* @see #getDateObj
	*/
	this.checkDateIsEmpty = function(o){
		if( !trim(o.day) && !trim(o.month) && !trim(o.year))
			return true;
		return false;
	}
	
	/**
	* Permet de créer un objet DateObj
	* Ce type d'objet contient 3 attributs : day, month et year
	* @param String Une liste d'id séparés par des | dans l'ordre j m a
	* @return DateObj - Un DateObj
	* @type DateObj
	* @see DateObj
	*/
	this.getDateObj = function(id){
		var ids = id.split("|");
		var j1 = document.getElementById(ids[0]).value;
		var m1 = document.getElementById(ids[1]).value;
		var a1 = document.getElementById(ids[2]).value;
		return new DateObj(j1,m1,a1);
	}
	
	/**
	* Vérification d'une date
	* @param String Une liste d'id séparés par des | dans l'ordre j m a
	* @param boolean Indique si la date est requise ou peut être vide
	* @return boolean
	* @type boolean
	*/
	this.checkDate = function(id,isRequired){
		
		var dGood 	= true;
		dObj = this.getDateObj(id);
		if(isRequired){
			dGood = (this.checkDateIsFull(dObj) && 
					(this.checkDay(dObj.day) && this.checkMonth(dObj.month)
							&& this.checkYear(dObj.year)) );
		}
		else{
			if(!this.checkDateIsFull(dObj) && !this.checkDateIsEmpty(dObj))
				dGood = false;
			else{
				dGood = this.checkDay(dObj.day) && this.checkMonth(dObj.month)
							&& this.checkYear(dObj.year);
			}
		}
			
		return dGood;
	}
	
		this.getRow = function(elem){
		var row = elem;
	
		do{
			row =  row.parentNode;
		}while(row.parentNode != null && row.nodeName.toLowerCase() != "tr");
		
		if(row.nodeName.toLowerCase() == "tr")
			return row;
		else
			return false;
	}
	
	/**
	* Permet de forcer un leMessage (uniquement sur controle required pour l'instant)
	* @param leMessage
	* @param complement, le complément est ajouté si le leMessage n'est pas forcé
	* @return leMessage
	*/
	this.getMessage = function(msg, complement){
		if(msg.indexOf("full:") != -1)
			return msg.substr(5, msg.length - 5);
		else
			return msg + complement;
	}
	
	/**
	* Verifie le formulaire
	* 
	* @param	Form	Le formulaire
	* @return	boolean 
	* @type boolean
	*/
	this.check = function(){

		this.isGood = true;		
		for(id in this.rules)
		{
			if(id != "indexOf"){
				rules	= this.rules[id].rules;
				label	= this.rules[id].label;
				leMessage = this.rules[id].leMessage;
				this.setErrMess(id,"");
				
				if(id.indexOf("|") != -1){
							
					if(rules.indexOf("date") != -1){
						if(!this.checkDate(id,label,rules.indexOf("required") != -1))
							this.setErrMess(id,"Date non valide");
					}
					
					if(rules.indexOf("after") != -1){
						deb 	= rules.indexOf('after')+6;
						space 	= rules.indexOf(' ',deb);
						val 	= space == -1 ? rules.substring(deb) : rules.substring(deb,space);
						
						var labs = label.split("|");
						var d0 = this.getDateObj(id);
						var d1 = this.getDateObj(val);
						
						if( (this.checkDateIsFull(d0) && this.checkDateIsFull(d1))
							&& (this.checkDate(id,labs[0],false) && this.checkDate(val,labs[1],false) )){
							var cGood = true;
							if(parseInt(d0.year,10) < parseInt(d1.year,10)){
								cGood = false;
							}
							else if((parseInt(d0.year,10) == parseInt(d1.year,10)) && (parseInt(d0.month,10) < parseInt(d1.month,10))){
								cGood = false;
							}
							else if((parseInt(d0.year,10) == parseInt(d1.year,10)) && 
								    (parseInt(d0.month,10) == parseInt(d1.month,10)) &&
								    (parseInt(d0.day,10) <= parseInt(d1.day,10))){
								cGood = false;
							}
								
							if(!cGood)
								this.setErrMess(id,labs[1]+" doit pr&eacute;c&eacute;der "+labs[0]);		
						}	
						else					
							this.setErrMess(id,labs[1]+" doit pr&eacute;c&eacute;der "+labs[0]);		
					}
					
					if(id.indexOf("check") != -1){
						if(rules.indexOf('minlength') != -1){
							deb 	= rules.indexOf('minlength')+10;
							space 	= rules.indexOf(' ',deb);
			
							val 	= space == -1 ? rules.substring(deb) : rules.substring(deb,space);
							
							deb 	= id.indexOf('check')+6;
							idc 	= id.substring(deb);
							idcs	= idc.split("|");
							
							var cmptc = 0;
							for(var i=0;i<idcs.length;i++){
								var curc = document.getElementById(idcs[i]);
								if(curc.checked)
									cmptc++;
							}
							
							if(cmptc < val){
								if(leMessage != null)
									this.setErrMess(id,label + leMessage);
								else
									this.setErrMess(id,"Il doit y avoir au moins "+val+" "+label);	
							}
						}
						if(rules.indexOf('maxlength') != -1){
							deb 	= rules.indexOf('maxlength')+10;
							space 	= rules.indexOf(' ',deb);
			
							val 	= space == -1 ? rules.substring(deb) : rules.substring(deb,space);
							
							deb 	= id.indexOf('check')+6;
							idc 	= id.substring(deb);
							idcs	= idc.split("|");
							
							var cmptc = 0;
							for(var i=0;i<idcs.length;i++){
								var curc = document.getElementById(idcs[i]);
								if(curc.checked)
									cmptc++;
							}
							
							if(cmptc > val){
								if(leMessage != null)
									this.setErrMess(id,label + leMessage);
								else
									this.setErrMess(id,"Il doit y avoir au maximum "+val+" "+label);	
							}
						}
					}
				} 
				else if(id.indexOf("radio") != -1){
				
					deb 		= id.indexOf('radio')+6;
					val 		= id.substring(deb);	
					var rads 	= document.getElementsByName(val);
					var checked = false;
					var cmpt	= 0;
					while(cmpt < rads.length && !checked){
						checked = rads[cmpt].checked;
						cmpt++;
					}
					if(!checked)
						this.setErrMess(id,label+" est incomplet");		
						
				}else if(id.indexOf("check") != -1){
					if(rules.indexOf('minlength') != -1)
					{
						deb 	= rules.indexOf('minlength')+10;
						space 	= rules.indexOf(' ',deb);
		
						val 	= space == -1 ? rules.substring(deb) : rules.substring(deb,space);
						
						deb 	= id.indexOf('check')+6;
						idc 	= id.substring(deb);
						
						if(val > 1 || (val <=1 && !document.getElementById(idc).checked) ){
							if(leMessage != null)
								this.setErrMess(id,label + leMessage);
							else
								this.setErrMess(id,"Il doit y avoir au moins "+val+" "+label);	
						}
					}
					
				}else{
					field 	= document.getElementById(id);
					if(rules.indexOf('required') != -1)	{
						if((field.type == "text" || field.type == "password"
						|| field.type == "hidden" || field.type == "file" || 
							field.nodeName.toLowerCase() == "textarea")
								&& !trim(field.value)){
							if(leMessage != null)
								var msg = this.getMessage(label, leMessage);
							else
								var msg = this.getMessage(label, " est incomplet.");
							this.setErrMess(id,msg);		
						}else if(field.nodeName.toLowerCase() == "select" && (
							field.options[field.selectedIndex].value == "-1" ||
							field.options[field.selectedIndex].value == "" 
							)){
							if(leMessage != null)
								var msg = this.getMessage(label, leMessage);
							else
								var msg = this.getMessage(label, " est incomplet.");
							this.setErrMess(id,msg);		
						}else if(field.type == "checkbox" && !field.checked){
							if(leMessage != null)
								var msg = this.getMessage(label, leMessage);
							else
								var msg = this.getMessage(label, " est incomplet.");
							this.setErrMess(id,msg);		
						}
					}
					
					if(rules.indexOf("cni") != -1){
						
						var ci 	= document.getElementById(id);
						var num = ci.value;
											
						if(trim(num)){	
							if(num.length == 12){
							
								deb 	= rules.indexOf('delivrance')+11;
								space 	= rules.indexOf(' ',deb);
								val 	= space == -1 ? rules.substring(deb) : rules.substring(deb,space);
								var deli = val.split("|");
								var mois = document.getElementById(deli[0]).value;
								var an 	 = document.getElementById(deli[1]).value.substring(2,4);
								var dptf  = document.getElementById(deli[2]);
								var dpt;
								if(dptf.nodeName.toLowerCase() == "select")
									dpt = dptf.options[dptf.selectedIndex].value;
								else
									dpt = dptf.value;
								
								if(num.substring(0,2) != an || num.substring(2,4) != mois || num.toLowerCase().substring(4,6) != dpt.toLowerCase())
									this.setErrMess(id,"Incoh&eacute;rence avec la date de d&eacute;livrance ou le d&eacute;partement");
							}
							else{
							
								this.setErrMess(id,"Num&eacute;ro non coh&eacute;rent");
							}
						}
					}
					
					if(rules.indexOf("function") != -1){
						field		= document.getElementById(id);
						deb 		= rules.indexOf('function')+9;
						space 		= rules.indexOf(' ',deb);
						val 		= space == -1 ? rules.substring(deb) : rules.substring(deb,space);
						var foncs 	= val.split("|");
	
						for(var i=0;i<foncs.length;i++){
							var fname = foncs[i];
							var res = eval(fname).call(null,field);
							if(!res.valid)
								this.setErrMess(id,res.errMess);
						}
					}
					
					if(rules.indexOf('equal') != -1)
					{
						deb 	= rules.indexOf('equal')+6;
						space 	= rules.indexOf(' ',deb);
						val 	= space == -1 ? rules.substring(deb) : rules.substring(deb,space);
						if(field.value != document.getElementById(val).value)
							this.setErrMess(id,label+" doivent &ecirc;tre identiques.");	
						
					}
					
					
					if(rules.indexOf('numeric') != -1)
					{
						if((field.type == "text")
								&& trim(field.value)){
							field.value = field.value.replace(",",".");
							if(isNaN(field.value))
								if(leMessage != null)
									this.setErrMess(id,label + leMessage);
								else
									this.setErrMess(id,label+" est num&eacute;rique.");
							else if(rules.indexOf("decimals") != -1){
									if(field.value.indexOf(".") != -1){
										deb 	= rules.indexOf('decimals')+9;
										space 	= rules.indexOf(' ',deb);
										val 	= space == -1 ? rules.substring(deb) : rules.substring(deb,space);
										if((field.value.length - field.value.indexOf('.') - 1) > parseInt(val))
											if(leMessage != null)
												this.setErrMess(id,label + leMessage);
											else
												this.setErrMess(id,"Pas plus de "+val+" d&eacute;cimales pour "+label);
									}
							}
							else{
								if(field.value.indexOf(".") != -1)
									if(leMessage != null)
										this.setErrMess(id,label + leMessage);
									else
										this.setErrMess(id,"Pas de d&eacute;cimales pour "+label);
							}
							if(!isNaN(field.value) && rules.indexOf("between")){
								deb 	= rules.indexOf('between')+8;
								space 	= rules.indexOf(' ',deb);
								val 	= space == -1 ? rules.substring(deb) : rules.substring(deb,space);
								bornes 	= val.split("|");
								var fval = parseFloat(field.value);
								var bmin = parseFloat(bornes[0]);
								var bmax = parseFloat(bornes[1]);
								if(fval < bmin || fval > bmax)
									if(leMessage != null)
										this.setErrMess(id,label + leMessage);
									else
										this.setErrMess(id,label+" doit &ecirc;tre entre "+bmin+" et "+bmax);
							}
						}
		
					}
					
					if(rules.indexOf('maxlength') != -1)
					{
						deb 	= rules.indexOf('maxlength')+10;
						space 	= rules.indexOf(' ',deb);
						val 	= space == -1 ? rules.substring(deb) : rules.substring(deb,space);
		
						if((field.type == "text" || field.type == "password" || field.nodeName.toLowerCase() == "textarea")
								&& ! (trim(field.value).length <= val) )
							if(leMessage != null)
								this.setErrMess(id,label + leMessage);
							else
								this.setErrMess(id,"Pas plus de "+val+" caract&egrave;res pour "+ label);
		
						if(field.nodeName.toLowerCase() == "select" && field.multiple)
						{
							cmptsel = 0;
		
							for (j = 0; j < field.options.length; j++)
							    if (field.options.options[j].selected)
									cmptsel++;
		
							if(cmptsel > val)
								if(leMessage != null)
									this.setErrMess(id,label + leMessage);
								else
									this.setErrMess(id,"Pas plus de "+val+" &eacute;l&eacute;ments dans "+label);	
						}
					}
		
					if(rules.indexOf('minlength') != -1)
					{
						deb 	= rules.indexOf('minlength')+10;
						space 	= rules.indexOf(' ',deb);
		
						val 	= space == -1 ? rules.substring(deb) : rules.substring(deb,space);
		
						if((field.type == "text" || field.type == "password" || field.nodeName.toLowerCase() == "textarea")){
							if(!(field.value.length >= val) && (trim(field.value).length > 0)) 
							{
								if(leMessage != null)
									this.setErrMess(id,label + leMessage);
								else
									this.setErrMess(id,"Pas moins de "+val+" caract&egrave;res pour "+ label);
							}
						}
		
						if(field.nodeName.toLowerCase() == "select" && field.multiple)
						{
							cmptsel = 0;
							for (j = 0; j < field.options.length; j++)
							    if (field.options.options[j].selected)
									cmptsel++;
		
							if(cmptsel < val)
								if(leMessage != null)
									this.setErrMess(id,label + leMessage);
								else
									this.setErrMess(id,"Pas moins de "+val+" &eacute;l&eacute;ments dans "+label);	
						}
					}
					
					if(rules.indexOf('regexp') != -1)
					{
						deb 	= rules.indexOf('regexp')+7;
						space 	= rules.indexOf('§',deb);
						val 	= space == -1 ? rules.substring(deb) : rules.substring(deb,space);
		
						if((field.type == "text" || field.type == "password" || field.nodeName.toLowerCase() == "textarea")){
							var reg = new RegExp(val,"");
							if(!reg.test(field.value))
								this.setErrMess(id,label + " est incorrect");
						}
					}
					
					if(rules.indexOf('mail') != -1 && rules.indexOf('mails') == -1)
					{
					
						if(trim(field.value))
							if(!this.isMail(field.value))
								this.setErrMess(id,"Adresse mail invalide");
					}
					
					if(rules.indexOf('mails') != -1)
					{
						if(trim(field.value)){
							var mails = field.value;
							var mailsTab = mails.split(";");
							for(var i=0;i<mailsTab.length;i++)
								if(!this.isMail(mailsTab[i])){
									this.setErrMess(id,"Adresse mail invalide");
									break;
								}
						}
					}
				}
			}
		}
		this.focused = false;
		return this.isGood;
	}
		
	/**
	*	Affecte le leMessage d'erreur ou les images, couleurs ....
	*	@param String id du champ
	*	@param String le leMessage 
	*/
	this.setErrMess = function(fieldId,leMessage){
		sp	= document.getElementById("erreur"+fieldId);
		 YAHOO.util.Dom.setStyle("erreur"+fieldId,"opacity","0");
		if(this.borderColor != null && this.inTable)
			this.rules[fieldId].cell.style.border = "";		
		if(this.bgColor != null && this.inTable)
			this.rules[fieldId].cell.style.backgroundColor = "";		
		
		if(fieldId.indexOf("=") == -1)
			document.getElementById(fieldId).style.backgroundColor = "";
		else{
			if(fieldId.indexOf("radio") != -1){
					var spl = fieldId.split("=");
					var compRName = spl[spl.length-1];
					var rads = document.getElementsByName(compRName);
					for(i=0;i<rads.length;i++)
						rads[i].style.backgroundColor = "";
			}
			else{
				var sp = fieldId.split("=");
				document.getElementById(sp[1]).style.backgroundColor = "";
			}
		}

		if(this.imgOk != null && this.imgKo != null){
			img		= document.createElement("img");
			imb		= document.createElement("img");
			img.src = this.imgOk;
			imb.src = this.imgKo;
			img.alt = "Champ ok";
			imb.alt = "Champ invalide";
		}
		
		if(leMessage != "*" && leMessage != "")
			this.isGood = false;
		
		messErr = document.createElement("span");

		if(leMessage != "*" && leMessage != "")
			messErr.innerHTML = leMessage;	
		else{
			messErr.innerHTML = "";	
		}

		if(sp != null && sp.childNodes.length != 0){
			while(sp.childNodes.length > 0){
				sp.removeChild(sp.firstChild);
			}
		}
	if(!this.isGood){
			sp.appendChild(messErr);
			var fadeIn = new YAHOO.util.Anim("erreur"+fieldId, { opacity: { to: 1 } }, 1.5);
			fadeIn.animate();
		}
	
		if(leMessage != "*" && leMessage != ""){	
			if(!this.isGood){
				if(this.imgOk != null && this.imgKo != null){
					if(this.displayText)
						sp.insertBefore(imb,sp.firstChild);
					else
						sp.replaceChild(imb,sp.firstChild);
				}
				if(this.borderColor != null && this.inTable)
					this.rules[fieldId].cell.style.border = "1px "+this.borderColor+" solid";		
				if(this.bgColor != null && this.inTable)
					this.rules[fieldId].cell.style.backgroundColor = this.bgColor;			
			}
			if(!this.focused){
			
				if(fieldId.indexOf("|") != -1){
					var spl = fieldId.split("|");
					document.getElementById(spl[spl.length-1]).focus();		
				}
				else if(fieldId.indexOf("radio") != -1){
					var spl = fieldId.split("=");
					var compRName = spl[spl.length-1];
					document.getElementsByName(compRName)[0].focus();		
				}
				else if(fieldId.indexOf("=") != -1){
					var spl = fieldId.split("=");
					document.getElementById(spl[spl.length-1]).focus();		
				}
				else{
					if(document.getElementById(fieldId).type != "hidden")
						if(document.getElementById(fieldId).style.visibility != "hidden") 
							document.getElementById(fieldId).focus();
					}
				this.focused = true;
			}
			if(!this.isGood && this.bgColor != null){
				if(fieldId.indexOf("=") == -1)
					document.getElementById(fieldId).style.backgroundColor = "#FDA975";
				else{
					if(fieldId.indexOf("radio") != -1){
						var spl = fieldId.split("=");
						var compRName = spl[spl.length-1];
						var rads = document.getElementsByName(compRName);
						for(i=0;i<rads.length;i++)
							rads[i].style.backgroundColor = "#FDA975";
					}
					else{
						var sp = fieldId.split("=");
						document.getElementById(sp[1]).style.backgroundColor = "#FDA975";
					}
				}
				
			}			
		}
		
		
	}
}

/**
* @param String Le jour
* @param String Le mois
* @param String Le year
*
* @class <p>Objet DateObj<p>
*
* Utilisé pour manipuler des dates dans le FormValidator <p>
*
* @author François Dussert
* @version 1.0
* @see FormValidator
*/
function DateObj(d,m,y){
	/**
	*	Le jour
	*	@type String
	*/
	this.day 		= d;
	
	/**
	*	Le mois
	*	@type String
	*/
	this.month 		= m;
	
	/**
	*	L'année
	*	@type String
	*/
	this.year 		= y;
}


/**
* @param boolean Indique si la validation est ok
* @param String Message d'erreur en cas de non validation
* @class <p> Objet ValidatorResult <p> 
*	Est utilisé en retour des functions de validation externes.<p>
* @author François Dussert
* @version 1.0
* @see FormValidator
*/
function ValidatorResult(bool,label){

	/**
	*	Indique si la validation est ok
	*	@type boolean
	*/
	this.valid 		= bool;
	
	/**
	*	Message d'erreur en cas de non validation
	*	@type String
	*/
	this.errMess 	= label;
}

var validator = new FormValidator();
validator.inTable = false;
validator.displayText = true;
