/**********
* $FWn : objet de parcours du DOM, facile. Les fonctions ne font que les nodes HTML
***********/
var $FWn = {
	/* 	hasAttributes : retourne true si l'element passe en parametre correspond a tous les attributs passes, on peut aussi donner des attributs que l'on ne veut pas, afin de filtrer tous les &eacute;lements
		ex : if (hasAttributes(div, {nodeName:"div", className:"foobar"), {className:"idontwant"} ) doStuff();
		ici on recherche tous les DIV qui on la classe "foobar", mais on ne prend pas ceux qui ont la classe "idontwant" ex : <div class="foobar idontwant"> ne sera pas recupere.
	*/
	hasAttr : function(n, a, not) {
		var re, at;
		if (n.nodeType!=1) return false;
		function check(attr) {
			for (var i in attr) {
				at = (typeof n[i]) !="undefined" ? n[i] : n.getAttribute(i);
				re = attr[i] instanceof RegExp ? re : new RegExp("\\b" + attr[i] + "\\b","i");
				if (!at || !re.test(at)) 
					return false;
			}
			return true;
		};
		if (not && check(not))	return false;
		if (check(a)) return true;
		return false;
	},
	/* getByTagName : equivalent a element.getElementsByTagName, mais compatible avec IE5 et IE5.5 pour l'histoire du "*" */
	getByTagName : function(n, tag) {
		return  (tag=="*") ? (n.all ? n.all : n.getElementsByTagName("*")) : n.getElementsByTagName(tag);
	},
	/* fonction qui retourne le premier element correspondant aux attributs donnes */
	node : function(n, a, not) {
		return $FWn.nodes(n, a, not, true);
	},
	/* fonction qui retourne tous les elements correspondant selon "a" */
	nodes : function(n, a, not, oneNode, arrElms) {
		var aRetElms=[];
		if (!a) a = {};
		if (typeof a == "string") a = {nodeName:a}; //si une chaine de caract&egrave;res pass&eacute;e en param&egrave;tre, cela signifie qu'on ne veut que r&eacute;cup&eacute;rer des tags
		if (a.nodeName && a.nodeName=="*") delete a.nodeName;
		var elms = arrElms || $FWn.getByTagName(n, (a.nodeName || "*"));
		for (var i=0; i<elms.length; i++) {
			var x = elms[i];
			if ($FWn.hasAttr(x, a, not)) {
				if (oneNode) return x;
				else aRetElms.push(x);
			}
		}
		if (oneNode) return null;
		return aRetElms;
	},
	/* childs : retourne tous les noeuds enfants de l'element  */
	childs : function(n, a, not) {
		return $FWn.nodes(n, a, not, false, n.childNodes);
	},
	firstChild : function(n, a, not) {
		return $FWn.nodes(n, a, not, true, n.childNodes);
	},
	lastChild : function(n, a, not) {
		var node = $FWn.nodes(n, a, not, false, n.childNodes);
		return node[node.length-1];
	},
	move : function(n, a, not, action) {
		while (n) {
			if ($FWn.hasAttr(n, a, not)) return n;
			n = n[action];
		}
		return null;
	},
	after : function(n, a, not) { 
		return $FWn.move(n, a, not, "nextSibling");
	},
	before : function(n, a, not) {
		return $FWn.move(n, a, not, "previousSibling");
	},
	parent : function(n, a, not) {
		return $FWn.move(n, a, not, "parentNode");
	}
}
/* fonctions raccourcis */
var getNode = $FWn.node,
	getNodes = $FWn.nodes,
	getChildNodes = $FWn.childs,
	getNextSibling = $FWn.after,
	getPreviousSibling = $FWn.before,
	getParent = $FWn.parent,
	hasAttributes = $FWn.hasAttr,
	getElementsByTagName = $FWn.getByTagName;


/****************
* Validation de formulaires
******************/
var formval={

	defaultErrorMessage:"Ce champ est erron\u00E9",
	defaultPosition:"beforefield",
	globalErrorMsg : [],
	callbackfunctions : function() {
		//fixColumns();
		//if (popLayer.pop) popLayer.resize();
	},
	lineInput : {nodeName:"(div|p|li|span)"},
	validationFunc:{
		required:function(field) {
			var returnMessage=true;
			switch(field.type) {
				case "text":
				case "file":
				case "password":
				case "textarea":
					if (field.value=="") returnMessage="text";
					break;
				case "checkbox":
				case "radio":
					var sameElt = formval.getSameElements(field);
					var onecheck=false;
					for (var i=0; i<sameElt.length; i++) {
						if (sameElt[i].checked)
							onecheck=true;
					}
					if (!onecheck) returnMessage=field.type;
					break;
				case "select-one":
				case "select-multiple":
					if(field.selectedIndex==0) 
						returnMessage="select";
					break;
			}
			return returnMessage;
		},
		email:function(field) {return (field.value=="" || !!field.value.match(/^[a-z0-9._-]+@[a-z0-9.-]{2,}[.][a-z]{2,3}$/));},
		name:function(field) {return (field.value=="" || !!field.value.match(/^([a-zA-Z]|\s|\'|\.|\-)+$/));},
		pseudo:function(field) {return !!field.value.match(/^[a-zA-Z0-9_\-]{3,20}$/);},
		image:function(field) {return (field.value=="" || !!field.value.match(/^.+\.(gif|jpe?g|png)$/));},
		codepostal:function(field){return !!field.value.match(/\d{5}/);},
		cpordep:function(field){if (field.value=="") return true; return !!field.value.match(/\d{2}(\d{3})?/);},
		phonenumber:function(field){if (field.value=="") return true; return !!field.value.match(/^\d{10}$/);},
		length4:function(field){if (field.value=="") return true; return field.value.length>=4},
		phonenumber2:function(field){
			var val = field.value;
			if (val=="") return true; 
			var cleanNum = val.match(/(\+)?\d+/g)
			if (!cleanNum) return false;
			cleanNum = cleanNum.join(""); //on recupere le numero de telephone en version nettoyee.
			if (!cleanNum.match(/^\+?(33|033|0033)?0?[1-9]\d{8}$/)) return false; //on checke reelement le numero de telephone
			return !!val.match(/^(\d|\s|-|\.|\\|\/|_|\+)+$/); //on check si des caract&egrave;res autres que chiffes,-,+,.,_,/,\  sont pr&eacute;sents
		},
		numbers:function(field){if (field.value=="") return true; return !!field.value.match(/^\d+$/);},
		decimal:function(field){if (field.value=="") return true; return !!field.value.match(/^\d+([.,]\d+)?$/);},
		equalsto:function(field) {
			var equalsFieldId = field.getAttribute("equalsto");
			var equalsField = document.getElementById(equalsFieldId);
			return (field.value==equalsField.value);
		},
		minimum:function(field) {
			if (field.nodeName!="FIELDSET") return true;
			var minNum = field.getAttribute("minimum_num") || 1;
			var properties = field.getAttribute("minimum_field") || "text,femail";
			var properties = properties.split(/,/g);
			var inputs = field.getElementsByTagName("input");
			var counter = 0;
			for (var i=0; i<inputs.length; i++) {
				var x=inputs[i];
				if (x.type==properties[0] && new RegExp(properties[1]).test(x.name) && x.offsetHeight>0) {
					if (formval.validationFunc["required"](x)===true) {
						counter++;
					}
				}
			}
			return counter<minNum ? ([false,minNum]) : true;
		},
		requiredexclusif:function(field) {
			var reqExclusifField = document.getElementById(field.getAttribute("reqexclusiffield"));
			if (!reqExclusifField) {
				alert("Vous n'avez pas associe le bon champ, verifiez l'attribut reqexclusif");
				return false;
			}
			if (field.getAttribute("requiredexclusifcondition")) {
				if (field.getAttribute("requiredexclusifcondition")=="noempty") {
					if (field.value!="" || reqExclusifField.value!="") return true;
					else return false;
				}
			} else 
				if ((field.value=="" && reqExclusifField.value=="") || (field.value!="" && reqExclusifField.value!="") ) return false;
		}
	},
	errorMessages:{
		required:{
			checkbox:"Cette case doit \u00EAtre coch\u00E9e",
			radio:"Vous devez s\u00E9lectionner une de ces options",
			text:"Attention, ce champ est obligatoire",
			select:"Vous devez s\u00E9lectionner l\u0027objet de votre demande"
			
		},
		requiredoptional:this.required,
		email:"Veuillez saisir un e-mail valide",
		name:"Ce champ ne doit comporter que des lettres, et les caract&egrave;res suivants : '-",
		numbers:"Ce champ ne doit comporter que des chiffres",
		decimal:"Ce champ ne doit comporter que des chiffres",
		phonenumber:"Ce champ ne doit comporter que des chiffres",
		phonenumber2:"Veuillez v\u00E9rifier votre num\u00E9ro de t\u00E9l\u00E9phone",
		equalsto:"La saisie doit etre identique au champ ci-dessus",
		codepostal:"Ce code postal est erron\u00E9",
		cpordep:"Vous ne pouvez mettre qu'un num\u00E9ro de d\u00E9partement ou un code portal",
		pseudo:'Attention, votre pseudo doit contenir uniquement 20 caract&egrave;res, des lettres et des num\u00E9ros et les signes "_" et "-"',
		image:"Votre fichier n'est pas au bon format",
		minimum:"Vous devez remplir au moins ## champ",
		requiredexclusif:"Vous devez remplir au moins un des champs",
		cgu:"Vous devez accepter les conditions g\u00E9n\u00E9rales d'utilisation pour valider votre inscription",
		length4:"Au moins 4 caractères"
	},
	getMessagePosition:function(field){
		var element=field;
		var position="";
		if (field.getAttribute("position")) {
			var position = field.getAttribute("position");
			if (!position.match(/^(before|after)(label|parentnode|field)$/)) {
			 	position = formval.defaultPosition;
			}
			var arrPos = position.match(/^(before|after)(label|parentnode|field)$/);
			switch(arrPos[2]) {
				case "label" : 
					var node = field;
					while(node.nodeName!="LABEL") {
						node=node.previousSibling;
					}
					if (node.nodeName=="LABEL") element=node;
					break;
				case "parentnode" : 
					var parentPos = field.getAttribute("parentnode_pos") ? parseInt(field.getAttribute("parentnode_pos")) : 1;
					var element=field;
					for (var i=0; i<parentPos; i++) {
						element=element.parentNode;
					}					
					break;
			}
			return [arrPos[1],element];
		} else {
			return [formval.defaultPosition.match(/(before|after)(label|parentnode|field)/)[1],element]
		}
	},
	getSameElements:function(field) { //return an array of elements in form who have same nodeName, name and type
		var aReturnElements=[];
		var elt=field.form.elements;
		for (var i=0; i<elt.length; i++) {
			if (elt[i].nodeName==field.nodeName && elt[i].name==field.name && elt[i].type==field.type) {
				aReturnElements.push(elt[i]);
			}
		}
		return aReturnElements;
	},
	check:function(theForm, showOnlyOneMessage, otherReturnValues) {
		formval.globalErrorMsg = [];
		var scrollTop = document.body.scrollTop;
		var finalErrorMessage = "";
		var hasError = false;
		var elm = theForm.elements;
		var globalErrorMessage = '';
		
		
		
		for (var i = 0, iCount = elm.length; i < iCount; i++) {
			var x = elm[i];
			if (x.getAttribute("validation") && x.offsetHeight && x.offsetHeight > 0 && !x.disabled) {
				var validOptions = x.getAttribute("validation").split(/\s+/g);
				finalErrorMessage="";
				for (var j = validOptions.length - 1; j >= 0; j--) {
					if (typeof(formval.validationFunc[validOptions[j]]) == "function") {
						var returnMessage = formval.validationFunc[validOptions[j]](x);
						var quantity = typeof(returnMessage)=="object" && returnMessage.length ? returnMessage[1] : 0;
						returnMessage = typeof(returnMessage)=="object" && returnMessage.length ? returnMessage[0] : returnMessage;
						if (returnMessage == false || typeof(returnMessage) == "string") { //si message erreur ou index de tableau associatif
							hasError = true;
							if (x.getAttribute(validOptions[j]+"_em") != null) { //si le champ possede un message personnalis&eacute; pour l'erreur alors on affihce
								finalErrorMessage = x.getAttribute(validOptions[j] + "_em");
							}
							else { //sinon
								if (typeof(returnMessage) == "string") { //si le message d'erreur est un index de tableau associatif
									finalErrorMessage=formval.errorMessages[validOptions[j]][returnMessage]; //on va chercher le message associ&eacute; &agrave; cet index
								}
								else {
									if (formval.errorMessages[validOptions[j]] && typeof(formval.errorMessages[validOptions[j]])=="string") { //si le message d'error est false
										finalErrorMessage=formval.errorMessages[validOptions[j]]; //alors on retourne le message d'erreur associ&eacute;
										if (quantity>0) finalErrorMessage=finalErrorMessage.replace(/\#\#/g,quantity);
									}
									else finalErrorMessage=formval.defaultErrorMessage; //sinon on affiche le message d'erreur par d&eacute;faut pour tout champ
								}
							}
						}
						else {
							formval.clearMessage(x);
						}						
					}
				}
				
				if (finalErrorMessage != ""){
					//console.log(finalErrorMessage);
					globalErrorMessage = 'Les champs en rouge sont invalides ou manquants';

					if (x.id.match(/\bemail\b/)){
						globalErrorMessage += ',&nbsp;<span>Entrez une adresse email valide</span>';
					}
					if (x.id.match(/\bdomportable\b/)){
						globalErrorMessage += ',&nbsp;<span>Entrez un num&eacute;ro valide</span>';
					}
					if (x.name.match(/\bagence\b/)){
						globalErrorMessage = '<span>Vous devez s&eacute;lectionner une agence</span>';
					}
					if (x.name.match(/\bprojet\b/)){
						globalErrorMessage = '<span>Vous devez s&eacute;lectionner un projet ou un produit</span>';
					}
					if (x.name.match(/\boptin\b/)){
						globalErrorMessage = '<span>Vous devez s&eacute;lectionner une de ces options</span>';
					}
					formval.showMessage(x, finalErrorMessage);
				}
			}
		}
		document.body.scrollTop=scrollTop;
		var secondErrorValue = false;
		if (otherReturnValues != null) {
			if(typeof(otherReturnValues) == "boolean") {
				secondErrorValue = !otherReturnValues;
			}
			else {
				for (var i = 0, iCount = otherReturnValues.length; i < iCount; i++) {
					if (!otherReturnValues[i]) {
						secondErrorValue = true;
					}
				}
			}
		}
		
		hasError = hasError || secondErrorValue;
		
		//showing only one generic error message!
		if (showOnlyOneMessage && hasError) {
			if(document.getElementsByName('agence').length != 0){
				//show messages msg box
				var errorMsgBox = document.getElementById('showOnlyOneMsg');
				errorMsgBox.innerHTML = '<span class="genericErrmsg">' + globalErrorMessage + '</span>'
				errorMsgBox.style.display = 'block';
				errorMsgBox.style.left = '380px';
				errorMsgBox.style.bottom = '110px';
			}
			else if(document.getElementsByName('projet').length != 0 || document.getElementsByName('produit').length != 0){
				//show messages msg box
				var errorMsgBox = document.getElementById('showOnlyOneMsg');
				errorMsgBox.innerHTML = '<span class="genericErrmsg">' + globalErrorMessage + '</span>'
				errorMsgBox.style.display = 'block';
				errorMsgBox.style.left = '100px';
				errorMsgBox.style.bottom = '15px';
			}
			else if(document.getElementsByName('optin').length != 0){
				var errorMsgBox = document.getElementById('showOnlyOneMsg');
				errorMsgBox.innerHTML = '<span class="genericErrmsg">' + globalErrorMessage + '</span>'
				errorMsgBox.style.display = 'block';
				errorMsgBox.style.left = '20px';
				errorMsgBox.style.bottom = '25px';
			}
			else {
				//show messages msg box
				var errorMsgBox = document.getElementById('showOnlyOneMsg');
				errorMsgBox.innerHTML = '<span class="genericErrmsg">' + globalErrorMessage + '</span>'
				errorMsgBox.style.display = 'block';
			}
		}
		else{
			//show messages msg box
			var errorMsgBox = document.getElementById('showOnlyOneMsg');
			errorMsgBox.innerHTML = '<span class="genericErrmsg">' + globalErrorMessage + '</span>'
			errorMsgBox.style.display = 'block';
		}
		
		formval.callbackfunctions();
		//popLayer.fixSize();
		//console
		return (!hasError); //return true si aucune erreur sinon false;
		
	},
	checkIfErrorMessageBefore:function(field) {
		var node = field;
		var i=0;
		while(node.previousSibling && i<=2) {
			if (node.nodeType==1 && node.className.match(/\berrormsg\b/))
				return node;
			node=node.previousSibling;
			i++;
		}
		return null;
	},//si les champs ont été corrigés clearMessage efface les signaux ou messages d'ereurs
	clearMessage:function(field) {
	
		if (field.getAttribute("typemessage") && field.getAttribute("typemessage")=="aspect") {
			if (field.getAttribute("rel") && field.getAttribute("rel")!="") {
				var elm = document.getElementById(field.getAttribute("rel"));
				elm.className = elm.className.replace(/\berror\b/g,"");
			}
		} else if (field.getAttribute("typemessage") && field.getAttribute("typemessage")=="self") {

			
			var parentField = getParent(field, formval.lineInput);
			parentField.className = parentField.className.replace(/\error\b/g,"");
			
		} else {
			if (field.associatedErrorMessage) {
				field.associatedErrorMessage.style.display="none";
			}
		}
	},
	insertAfter:function(parent, nodeToInsert, nodeInDom) {
		var node = parent.insertBefore(nodeToInsert, nodeInDom);
		parent.insertBefore(nodeInDom, nodeToInsert);
		return nodeToInsert;
	},//si ou ou plusiers champs présentent des erreurs showMessage affiche le message selon le mode d'affichage choisi "self", "aspect", etc...
	showMessage:function(field, msg) {
		formval.globalErrorMsg.push(msg);
		if (field.getAttribute("typemessage") && field.getAttribute("typemessage")=="aspect") {
			if (field.getAttribute("rel") && field.getAttribute("rel")!="") {
				var elm = document.getElementById(field.getAttribute("rel"));
				elm.className+=" error";
			}
		}//le message d'erreur est positionné sur le node parent du champ
		else if (field.getAttribute("typemessage") && field.getAttribute("typemessage")=="self"  && field.getAttribute("type")!="radio" ) {
			//console.log(field.getAttribute("type"));
			var parentField = getParent(field, formval.lineInput);
			parentField.className+=" error";

		} else if(field.getAttribute("typemessage") && field.getAttribute("typemessage")=="self" && field.getAttribute("type")=="radio"){
			//console.log(field.getAttribute("type"));
			var parentField = getParent(field, formval.lineInput);
			parentField.className+=" errorAlter";
			
		} else {
			if (!field.associatedErrorMessage) {
				if (!formval.checkIfErrorMessageBefore(field)) {
					var pos = formval.getMessagePosition(field);
					
					var parentField = getParent(field, formval.lineInput);
					var label = getNode(parentField, {nodeName:"label"});
					if (pos){
						switch(pos[0]){
							case 'before':
								
								var span = document.createElement("span")
								var msgField = pos[1].parentNode.appendChild(span);
								
								break
							case 'after':
								var msgField = formval.insertAfter(pos[1].parentNode, document.createElement("span"),pos[1]);
								break
						}
					}else if (label)
						var msgField = formval.insertAfter(label.parentNode, document.createElement("span"),label);
					else 
						var msgField = formval.insertAfter(parentField.parentNode, document.createElement("span"),parentField);
					msgField.className="errormsg";
					field.associatedErrorMessage=msgField;
				} else {
					field.associatedErrorMessage = formval.checkIfErrorMessageBefore(field);
				}
			}
			field.associatedErrorMessage.innerHTML=msg;
			field.associatedErrorMessage.style.display="";	
			//<span class="errormsg">Attention, ce champ est obligatoire</span>
		}
	}
}