//UN FICHIER JAVASCRIPT GENERIQUE POUR TRAITER UN FORMULAIRE
//AUTEUR: Yiping Wu (yiping@be-poles.com)
//DATE DE FINITION: 06/08/2007
//Olivier Huet ET Rémi Gérard-Marchant ONT DONNE LEURS PROPOSITIONS


//              VERSION 1.1 - 01/02/2008 - RGM
// - ajout du cas <label><span class="uneclasse">*</span> champ obligatoire</label>
// - attention, le bloc-type est de la forme 
//   <div id="parent_id_error_field"><p id="id_error_field">les messages</p></div>
//   =>le message d'erreur est affiché dans un bloc, mais ce bloc est dans un bloc parent 
//   qu'on affiche (display:block) en cas d'erreur.
//   =>par défaut le parent est display:none

//              VERSION 1.2 - 25/02/2008 - RGM
// - nouveau fonctionnement : ajax_submit_form(id_form, url, lang, id_error_field, err_num)
// - ajout d'une table d'en-tête de message d'errreur
//   

//              VERSION 1.3 - 10/03/2008 - RGM
// - correction bug : affichage du label sans l'espace dans les cas où <span>* </span>CHAMP
//




/********************INSTRUCTIONS POUR ECRIRE LE CODE HTML LORS DE L'UTILISATION DE CE FICHIER ************************/
/*
 * POUR NOMMER L'id D'UN ELEMENT CONCERNE, PLUSIEURS MOTS-CLES SONT A RESPECTER POUR INDIQUER A CE JAVASCRIPT
 *  QUE DES REGLES DOIVENT ETRE APPLIQUEES A CET ELEMENT. VOILA LA LISTE DES MOTS-CLES:
 *	---------------------------------------------------------------------------------------------------------
 *	| MOT-CLE	|	SIGNIFICATION	|	INSTRUCTION															|
 *	|-------------------------------------------------------------------------------------------------------|
 *	| ob 		|	OBLIGATOIRE		|	" *" (UN ESPACE ET UN "*") EST SUPPRIME AUTOMATIQUEMENT				|
 *	|			|					|	DANS L'AFFICHAGE DE MESSAGE D'ERREUR S'IL EXISTE.					|
 *	|-------------------------------------------------------------------------------------------------------|
 *	| int		|	ENTIER			|	--																	|
 *	|-------------------------------------------------------------------------------------------------------|
 *	| float		|	REEL			|	SEULEMENT LE POINT EST VALIDE ET NON LE VIRGULE.					|
 *	|-------------------------------------------------------------------------------------------------------|
 *	| mail		|	MAIL			|	L'ADRESSE IP N'EST PAS VALIDE COMME NOM DE DOMAINE					|
 *	|-------------------------------------------------------------------------------------------------------|
 *	| date		|	DATE			|	JJ/MM/AAAA															|
 *	|-------------------------------------------------------------------------------------------------------|
 *	| verif		|	VERIFICATION	|	CE MOT VERIFIE SI DEUX CHAMPS ONT LA MEME SAISIE. LES DEUX CHAMPS	|
 *	|			|					|	(BALISE "input" DE TYPE "text") DOIVENT SE TROUVER DANS UN MEME		|
 *	|			|					|	FIELDSET QUI NE CONTIENNE QUE LES DEUX "input". CE MOT-CLE EST		|
 *	|			|					|	UNIQUEMENT POUR L'id DU PREMIER ELEMENT "input".					|
 *	|-------------------------------------------------------------------------------------------------------|
 *	| long		|	LONGEUR			|	CE MOT CONTROLE LA LONGEUR D'UN CHAMPS SAISI. IL DOIT ETRE SUIVI	|
 *	|			|					|	PAR LA LONGEUR MINIMALE ET CELLE DE MAXIMALE: UN EXEMPLE: long_5_10	|
 *	|			|					|	 EXIGE QUE LE CHAMPS SOIT ENTRE 5 ET 10 CARACTERES (5 ET 10 INCLUS)	|
 *	|-------------------------------------------------------------------------------------------------------|
 *	| alphanum	|	ALPHANUMERIQUE	|	"_" NON COMPRIS														|
 *	---------------------------------------------------------------------------------------------------------
 *
 * ON PEUT CONBIMER LES MOTS-CLES A SA VOLONTE SAUF QUE POUR LES BIEN SEPARER UN SOULIGNEMENT EST NECESSAIRE
 * AVANT CHAQUE MOT-CLE. UN EXEMPLE: ctx_age_int_ob_long_1_3 DEMANDE AU JAVASCRIPT DE VERIFIER QUE LE CHAMPS
 * CONTIENNE OBLIGATOIREMENT UN ENTIER DE LOGNEUR DE 1 A 3 CHIFFRES. "ctx_age" N'EST LA QUE POUR LE SENS
 * SEMANTIQUE. PLUS D'EXEMPLES:
 *			ctx_age_int_ob_long_1_3			BON (CONSEILLE)
 *			_int_long_1_3_ob				BON
 *			ctx_long_1_3_ob					MAUVAIS (PAS DE SOULIGNEMENT AVANT "int")
 *			ctx_intage_long_1_3				BON
 *			ctx_ageint_ob					MAUVAIS (PAS DE SOULIGNEMENT AVANT "int")
 *
 * LE MESSAGE D'ERREUR UTILISE LE TEXTE DE LA BALISE "label" LIEE COMME INFORMATION.
 *
 * L'ATTRIBUTE "id" ET "name" D'UN ELEMENT DOIVENT ETRE IDENTIQUE SAUF "CHECKBOX" ET "RADIO", SINON
 * LE SCRIPT RISQUE DE NE PAS FONCTIONNER. LE PROGRAMMEUR PHP RECUPERER LES DONNEES D'APRES L'ATTRIBUTE
 * "name" DONC LE TRAITEMENT DES DONNEES PAR CE SCRIPT EST TRANSPARENT. 
 *
 */


/********************LA PARTIE SUIVANTE CONTIENS LES VARIABLES GLOBALES************************/
//L'OBJET XMLHTTPREQUEST
var xmlHttp=false;

//LES MESSAGES DE DIFFERENTES LANGUES D'ERREUR A AFFICHER
var tab_message_fr = new Array(	'Vous devez saisir "',
								'Le champs suivant doit être un entier "',
								'Le champs suivant doit être un nombre réel "',
								'Le format de mail n\'est pas valide pour "',
								'Le format de date n\'est pas valide pour le champs "',
								'Vous devez avoir la même saisie dans les deux champs "',
								//"MIN" ET "MAX" SONT A REMPLACER APRES
								'Le champs suivant doit comporter entre MIN et MAX caractères "',
								'Le champs suivant ne doit comporter que les caractères alphanumérique "');

var tab_message_en = new Array(	'You must fill the following field "',
								'The following field must be an integer "',
								'The following field must be a real number "',
								'The format of mail is not valid for the field "',
								'The format of date is not valid for the fields "',
								'You must fill the same data in the field "',
								//"MIN" ET "MAX" SONT A REMPLACER APRES
								'The following field must be between MIN and MAX characters long "',
								'The following field must contain only the alphanumeric characters "');

var tab_customheader_erreur_fr = new Array(
								"<strong>Attention</strong><br/>"
								,"<strong>Pour vous connecter</strong><br/>"
								,"<strong>Pour un envoi valide&nbsp;:</strong><br/>"
								,"<strong>Pour une modification valide&nbsp;:</strong><br/>"
								,"<strong>Pour vous inscrire&nbsp;:</strong><br/>"
							);

var tab_customheader_erreur_en = new Array(
								"<strong>Warning</strong><br/>"
								,"<strong><strong>To login</strong><br/>"
								,"<strong>For a correct message&nbsp;:</strong><br/>"
								,"<strong>For a valid modification&nbsp;:</strong><br/>"
								,"<strong>To subscribe&nbsp;:</strong><br/>"
							);

/********************FONCTIONS CONCERNANT AJAX ************************/
//INITIALISER UN OBJET XMLHTTPREQUEST
function initialize_xmlhttprequest() {
    if(window.XMLHttpRequest){
        xmlHttp = new XMLHttpRequest();
    }else if(window.ActiveXObject){
        try{
            xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
        }
        catch(e){
            try{
                xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
            }
            catch(e){}
        }
    }
}

//SI LES DONNEES SAISIES PASSENT LA VALIDATION, ON LES ENVOIE AU SERVEUR
function send_data(tab_name, tab_value, url, id_error_field) {
	//xmlHttp = initialize_xmlhttprequest();
	initialize_xmlhttprequest();
	// for(var i=0;i<xmlHttp.length;i++) alert(xmlHttp[i]);
	if (xmlHttp != false) {
		xmlHttp.open("POST", url, true);
		xmlHttp.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		var data = '';
		var reg = new RegExp('[|]{1}', 'g');

		for(var i=0;i<tab_name.length;i++) {
			//SI ON DOIT DESERIALISER LA CHAINE NE LA RENDANT EN UN TABLEAU
			if(tab_value[i].indexOf('|') != -1) {
				//SUPPRESSION DU DERNIER "|"
				tab_value[i] = tab_value[i].substring(0, tab_value[i].length-1);
				tab_choice = tab_value[i].split(reg);
				for(var j=0;j<tab_choice.length;j++)
					data += tab_name[i]+'['+j+']'+'='+tab_choice[j]+'&';
			}
			else
				data += tab_name[i]+'='+tab_value[i]+'&';
		}
		
		//SUPPRESSION DU DERNIER "&"
		data = data.substring(0, data.length-1);
		xmlHttp.send(data);
		xmlHttp.onreadystatechange=function()
     	{
        	if (xmlHttp.readyState == 4  &&  xmlHttp.status == 200)
        		document.getElementById(id_error_field).innerHTML=xmlHttp.responseText.split(' ("').join('"');
     	}
	}
	else {
		alert("toto");
	}
}

/********************FONCTIONS POUR L'AFFICHAGE DES MESSAGES D'ERREUR ************************/

//CES FONCTIONS SERVENT A CONSTRUIRE LE MESSAGE D'ERREUR D'APRES LA SEMANTIQUE ET LA LANGUE
//ET RETOURNE LE MESSAGE QUI S'EST AJOUTE DE NOUVELLES INFORMATIONS

//AFFICHAGE D'UN MESSAGE DE TEL FORMAT: VOUS DEVEZ ... LE CHAMPS SUIVANT: NOM_DU_CHAMPS (TEXTE DANS LA BALISE "label")
function error_message_normal(error_message, seman, lang, index) {
	switch(lang) {
		case 'fr': var base = tab_message_fr[index];break;
		case 'en': var base = tab_message_en[index];break;
		default: var base = tab_message_fr[index];
	}
	// error_message += base + seman.substr(0,seman.length-2) + "\"\n";
	error_message += base + seman + "\"\n";
	return error_message;
}

//CETTE FONCTION SE BASE SUR LA FONCTION error_message_normal ET NE FAIT QU'UN APRS-TRAITEMENT
//POUR REMPLACER DES CHAINES DE CARACTERES
function error_message_length(error_message, seman, lang, index, length_min, length_max) {
	//L'APPEL DE LA FONCTION error_message_normal
	var error_message = error_message_normal(error_message, seman, lang, index);

	var reg_min = new RegExp('MIN', 'g');
	var reg_max = new RegExp('MAX', 'g');
	
	error_message = error_message.replace(reg_min, length_min);
	error_message = error_message.replace(reg_max, length_max);
	
	return error_message;
}

/********************FONCTIONS POUR VERIFIER LES SAISIES DE L'UTILISATEUR************************/

//VERIFIER SI AU MOINS UN CHAMPS DANS UN GROUP DE RADIO OU DE CHECKBOX A ETE BIEN COCHE.
function verify_choice(element) {
	var fieldset = element.parentNode;
	//tab_input CONTIENT TOUS LES ELEMENTS FRERE DE L'element TRANSFERE PAR LE PARAMETRE
	var tab_input = fieldset.getElementsByTagName('input');
	for(var i=0;i<tab_input.length;i++) {
		if(tab_input[i].checked == true) 
			return true;
	}
	return false;
}

//VERIFIER SI LA VALUE DE L'element EN PARAMETRE EST BIEN UN ENTIER
function verify_integer(element) {
	//SI LA VALEUR EST VIDE, ON NE CONTINUE PLUS.
	if (element.value.length == 0)
		return true;

	if(isNaN(element.value))
		return false;
	//SI UN NOMBRE CONTIENT ".", IL DOIT ETRE UN REEL.
	else if(element.value.indexOf('.') != -1)
		return false;
	else
		return true;
}

//VERIFIER SI LA VALUE DE L'element EN PARAMETRE EST BIEN UN REEL
function verify_float(element) {
	//SI LA VALEUR EST VIDE, ON NE CONTINUE PLUS.
	if (element.value.length == 0)
		return true;

	if(isNaN(element.value))
		return false;
	else
		return true;
}

//VERIFIER SI LA VALUE DE L'element EN PARAMETRE CORRESPOND A UN BON FORMAT DE MAIL
function verify_mail(element) {
	//SI LA VALEUR EST VIDE, ON NE CONTINUE PLUS.
	if (element.value.length == 0)
		return true;

	var reg = new RegExp('^[a-zA-Z0-9\-_]+[a-zA-Z0-9\.\-_]*@[a-zA-Z0-9\-_]+\.[a-zA-Z\.\-_]{1,}[a-zA-Z\-_]+', 'g');
	return reg.test(element.value);
}

//VERIFIER SI LA VALUE DE L'element EN PARAMETRE CORRESPOND A UN BON FORMAT DE DATE
function verify_date(element) {
	//SI LA VALEUR EST VIDE, ON NE CONTINUE PLUS.
	if (element.value.length == 0)
		return true;

	var reg = new RegExp('^[0-9]{2}\/[0-9]{2}\/[0-9]{4}$', 'g');
	return reg.test(element.value);
}

//CETTE FONCTION TROUVE LE TYPE CORRESPONDANT DE L'element. LE TYPE SERA UTILISE POUR
//DES TRAITEMENTS DIFFERENTS. POUR L'INSTANT ON NE DISTINGUE QUE "checkbox" ET "radio",
//LES AUTRES TYPES ("text", "texterea", "selectunique", etc) ETANT RESERVES POUR LE FUTUR.
function find_type(element) {
	//alert(element.tagName);
	var tag = element.tagName.toLowerCase();
	if(tag == 'input')
		return element.type;
		
	if(tag == 'textarea')
		return 'textarea';

	//DISTINCTION ENTRE LE CHOIX MULTIPLE ET CELUI D'UNIQUE POUR LE BALISE SELECT
	if(tag == 'select')
		if(element.multiple == true)
			return 'selectmultiple';
		else
			return 'selectunique';
}

/********************LA FONCTION PRINCIPALE ************************/

//LA FONCTION PRINCIPALE VERIFIE LES CHAMPS DU FORMULAIRE (id_form), GENERE UN
//MESSAGE D'ERREUR D'APRES LA LANGUE (lang) EVENTUELLEMENT ET ENVOYE LES DONNEES
//SAISIES A UN URL (url) S'IL N'Y A PAS D'ERREUR EN UTILISANT AJAX.
function ajax_submit_form(id_form, url, lang, id_error_field, err_num) {
	var error_message = '';
	var tab_name = new Array();
	var tab_value = new Array();
	var form = document.getElementById(id_form);

	//POUR AFFICHER LE BON EN-TÊTE CUSTOMISÉ DE MESSAGE D'ERREUR
	if (!err_num) {err_num=0;}
	switch(lang) {
		case 'fr': var customheader_erreur = tab_customheader_erreur_fr[err_num];break;
		case 'en': var customheader_erreur = tab_customheader_erreur_en[err_num];break;
		default: var customheader_erreur = tab_customheader_erreur_fr[err_num];
	}
	//CETTE VARIABLE EVITE D'AFFICHER LE MEME MESSAGE D'ERREUR PLUSIEURS FOIS
	//POUR UN GROUPE DE "INPUT" DE TYPE RADIO OU CHECKBOX
	var name_choice = '';

	//ON PARCOURT TOUS LES ELEMENTS "label" DU FORMULAIRE
	var tab_label = form.getElementsByTagName('label');
	for(var i=0;i<tab_label.length;i++) {
		var tab_legend = tab_label[i].parentNode.getElementsByTagName('legend');
		//LE CAS POUR RADIO OU CHECKBOX OU L'ELEMENT legend SE TROUVE A COTE
		if(tab_legend.length == 1) 
			var semantic = tab_legend[0].firstChild.nodeValue;
		//LES AUTRES CAS OU IL N'Y A PAS D'ELEMENT legend
		else
			var semantic = tab_label[i].lastChild.nodeValue;
// alert('semantic : '+semantic+' indice : '+ tab_label[i].lastChild);
		//SUPPRESSION DE " *" POUR LES CHAMPS OBLIGATOIRES S'IL Y A UN " *"
		//semantic S'AFFICHE EVENTUELLEMENT DANS LE MESSAGE D'ERREUR
		if(semantic.indexOf('*') != -1) //semantic = semantic.split('*')[0];
			semantic = semantic.substr(2, semantic.length);
		if(semantic.indexOf(' ') != -1) //semantic = semantic.split('*')[0];
			semantic = semantic.substr(1, semantic.length);

		var element = document.getElementById(tab_label[i].htmlFor);
		var type = find_type(element);

		//TRAITEMENT POUR LES CHAMPS OBLIGATOIRES
		if(element.id.indexOf('_ob') != -1) {		
			if(type == 'checkbox' || type == 'radio') {
				//EVITER D'AFFICHER LE MEME MESSAGE D'ERREUR PLUSIEUR FOIS
				if(!verify_choice(element) && name_choice != element.name) {
					name_choice = element.name;
					error_message = error_message_normal(error_message, semantic, lang, 0);
				}
			}
			else {
				if(element.value.length == 0)
					error_message = error_message_normal(error_message, semantic, lang, 0);
			}
		}
	
		//TRAITEMENT POUR DES CHAMPS DE SAISIE QUI DOIVENT ETRE UN ENTIER
		if(element.id.indexOf('_int') != -1 && !verify_integer(element))
			error_message = error_message_normal(error_message, semantic, lang, 1);
			
		//TRAITEMENT POUR DES CHAMPS DE SAISIE QUI DOIVENT ETRE UN REEL
		if(element.id.indexOf('_float') != -1 && !verify_float(element))
			error_message = error_message_normal(error_message, semantic, lang, 2);
			
		//TRAITEMENT POUR DES CHAMPS DE SAISIE QUI DOIVENT ETRE UN MAIL
		if(element.id.indexOf('_mail') != -1 && !verify_mail(element))
			error_message = error_message_normal(error_message, semantic, lang, 3);
			
		//TRAITEMENT POUR DES CHAMPS DE SAISIE QUI DOIVENT ETRE UNE DATE
		if(element.id.indexOf('_date') != -1 && !verify_date(element))
			error_message = error_message_normal(error_message, semantic, lang, 4);

		//TRAITEMENT POUR DEUX CHAMPS DE SAISIE QUI DOIVENT SE CORRESPONDRE
		if(element.id.indexOf('_verif') != -1) {
			var tab_verif = element.parentNode.getElementsByTagName('input');
			if(tab_verif[0].value.length == 0 && tab_verif[1].value.length == 0)
				continue;
			//SI LES DEUX MOTS DE PASSE NE SE CORRESPONDENT PAS
			if(tab_verif[0].value != tab_verif[1].value)
				error_message = error_message_normal(error_message, semantic, lang, 5);
		}

		//TRAITEMENT POUR DES CHAMPS DE SAISIE AYANT UNE CONTAINTE DE LONGUEUR
		if(element.id.indexOf('_long') != -1) {
			if(element.value.length == 0)
				continue;
			//TROUVER LA LONGEUR MINIMALE ET CELLE DE MAXIMALE DANS L'ID
			var reg = new RegExp('[0-9]+', 'g');
			length_min = reg.exec(element.id);
			length_max = reg.exec(element.id);

			if(element.value.length<length_min || element.value.length<length_min 
				|| element.value.length>length_max || element.value.length>length_max)
				error_message = error_message_length(error_message, semantic, lang, 6, length_min, length_max);
		}

		//TRAITEMENT POUR DES CHAMPS DE SAISIE NE CONTENANT QUE LES CARACTERES ALPHABETANUMERIQUE
		if(element.id.indexOf('_alphanum') != -1) {
			if(element.value.length == 0)
				continue;

			//SEULEMENT LES CARACTERES ALPHABETANUMERIQUE SONT AUTORISES
			var reg = new RegExp('^[0-9a-zA-Z]+$', 'g');
			if(reg.test(element.value) == false)
				error_message = error_message_normal(error_message, semantic, lang, 7);
		}

		//REMPLISSAGE POUR LES DEUX TABLEAUX DE DONNEES QUI SERONT ENVOYEES VERS LE SERVEUR
		//SI C'EST UN "CHECKBOX"
		if(type == 'checkbox') {
			if(element.checked == false)
				continue;
			else {
				var tab_checkbox = document.getElementsByName(element.name);
				var value = '';
				for(var j=0;j<tab_checkbox.length;j++)
					if(tab_checkbox[j].checked == true)
						value += tab_checkbox[j].value + '|';
				tab_name.push(element.name);
				tab_value.push(value);
			}
		}
		//SI C'EST UN "RADIO"
		else if(type == 'radio') {
			if(element.checked == false)
				continue;
			else {
				var tab_radio = document.getElementsByName(element.name);
				var value = '';
				for(var j=0;j<tab_radio.length;j++)
					if(tab_radio[j].checked == true)
						value = tab_radio[j].value;
				tab_name.push(element.name);
				tab_value.push(value);
			}
		}
		//SI C'EST UNE LISTE DEROULANTE MULTIPLE
		else if(type == 'selectmultiple') {
			var tab_option = element.getElementsByTagName('option');
			var value = '';
			for(var j=0;j<tab_option.length;j++)
				if(tab_option[j].selected == true)
					value += tab_option[j].value + '|';

			if(value != '') {
				tab_name.push(element.name);
				tab_value.push(value);
			}
		}
		//LES AUTRES CAS
		else if(element.value != '') {
			tab_name.push(element.name);
			tab_value.push(element.value);
		}
	}
	//SI LES DONNEES SONT TOUTES VALIDES
	if(error_message.length == 0) {
		//alert('no error');
		var reponse='';
		if(url!='') send_data(tab_name, tab_value, url, id_error_field);
		else return true;
		if(document.getElementById(id_error_field)) {
			//document.getElementById(id_error_field).innerHTML=reponse;
			document.getElementById(id_error_field).style.display='block';
		}
		else {
			alert(reponse);
		}
	}
	//SINON
	else {
		//alert('error');
		if(document.getElementById(id_error_field)) {
			document.getElementById(id_error_field).innerHTML=
				customheader_erreur +
				error_message.split("\n").join("<br/>\n");
			document.getElementById(id_error_field).parentNode.style.display='block';
		}
		else {
			alert(error_message);
		}
	}
	return false;
}
