/* (c) 2007 Nathana�l Mariani pour PMP CONCEPT */


// include des classes requises
if(typeof PMP != "undefined")
{
	PMP.include("event.js");
}



/***********************************************************************


	Classe FromMgr pour la gestion d'un formulaire


Paramètres
	- form : l'id ou l'object formulaire concerné
	- classDefault : le nom de la classe CSS par défaut des éléments du formulaire
	- classFocus : le nom de la classe CSS onFocus des éléments du formulaire
	- classError : le nom de la classe CSS des éléments du formulaire invalides
	- callback : fonction externe appelée lors de la validation de l'élément. Cette fonction doit prendre en paramètre l'obj représentant le champ ainsi qu'un booléen pour son état valide ou non.


***********************************************************************/

PMP.util.FormMgr = function(form, classDefault, classFocus, classError, callback)
{
	var me = this;
	
	this.form = typeof(form)=="string" ? document.getElementById(form) : form;
	
	this.elements = new Array();
	this.classDefault = classDefault;
	this.classFocus = classFocus;
	this.classError = classError;
	this.callback = callback;
	
	this.form.onsubmit = function(evt)
	{
		var pmpEvt = new PMP.util.pmpEvent();
		pmpEvt.getEvent(evt);
		
		if(!me.validate())
		{
			pmpEvt.cancelEvent();
			return;
		}
	}
}


PMP.util.FormMgr.prototype = {
	
	addElement : function (element, type, required, correct, classDefault, classFocus, classError, callback)
	{
		if( typeof(callback)=="undefined" )
			var callback = this.callback;
		
		if( typeof(classDefault)=="undefined" )
			var classDefault = this.classDefault;
		
		if( typeof(classFocus)=="undefined" )
			var classFocus = this.classFocus;
		
		if( typeof(classError)=="undefined" )
			var classError = this.classError;
		
		
		element = typeof(element)=="string" ? document.getElementById(element) : element;
		if( !PMP.common.isObject(element) )
			return false;
		
		var elem = new PMP.util.FormElement(element, type, required, correct, callback, classDefault, classFocus, classError);
		
		this.elements[this.elements.length] = elem;
	},
	
	
	getElement : function (element)
	{
		element = typeof(element)=="string" ? document.getElementById(element) : element;
		if( !PMP.common.isObject(element) )
			return false;
		
		for(var i=0; i<this.elements.length; i++)
		{
			if( PMP.common.isObject(this.elements[i].element) && this.elements[i].element == element )
				return this.elements[i];
		}
		return false;
	},
	
	
	validate : function ()
	{
		var isValid = true;
		for(var i=0; i<this.elements.length; i++)
		{
			if( PMP.common.isObject(this.elements[i].element) )
				isValid &= this.elements[i].validate();
			//if(isValid ==false)
			//	alert(this.elements[i].element.name + ", " + isValid);
		}
		
		return isValid;
	}
}



/***********************************************************************


	Classe RegExpInputValidator pour la validation d'un champ de saisie


Paramètres
	- input : l'id ou l'object représentant le champ de saisie à gérer
	- type : le type d'information attendue (email, telephone, heure, entier, entier pos, ...)
	- required : champ obligatoire ou non
	- correct : correction automatique du champs si la saisie est invalide
	- callback : fonction externe appelée lors de la validation de l'élément. Cette fonction doit prendre en paramètre l'obj représentant le champ ainsi qu'un booléen pour son état valide ou non.


************************************************************************/


PMP.util.RegExpInputValidator = function(input, type, required, correct, callback, classDefault, classError)
{
	this.alpha 			= /^[a-zA-Z\.\-_]$/;		// format alpha : lettre exclusivement
	this.alphanum		= /^\w$/;					// format alphanumerique
	this.int 			= /^[\+\-\d]$/;				// format nombre entier
	this.uint 			= /^\d$/;					// format nombre entier positif
	this.dec 			= /^[\+\-\d\.]$/;			// format décimal
	this.udec 			= /^[\d\.]$/;				// format décimal positif
	this.hour			= /^[\d\:]$/;				// format heure
	this.mail			= /^[\w-_\.\@]$/;			// format adresse mail
	this.phone			= /^[\d\.\s\-]$/;			// format téléphone
	this.password		= /^[\w\.]$/;				// format mot de passe
	this.alphanum_ext	= /^[\w\s\.\-\'\¨\^ç-ù]$/;	// format alphanumerique étendu
	
	this.control = /^[\x08\x09\x7F\x25\x27\ca\cr]$/i;		// touche autorisée pour la saisie : backspace, del, fleche gauche, fleche droite	AC / AE
	this.valid = /^[\cv\x0D]$/i;				// touches considérées comme une validation du champ: entrée, CTRL-V ou POMME-V
	
	this.input = null;
	this.type = "";
	this.required = false;
	this.correct = false;
	this.callback = null;
	this.onkeypress = "";
	this.onkeyup = "";
	this.onblur = "";
	
	var me = this;
	
	this.setInput = function setInput(input, type, required, correct, callback, classDefault, classError)
	{
		if(typeof(input)=="string")
		{
			input = document.getElementById(input);
		}
		
		if(!input)
		{
			this.input = null;
			this.type = "";
			this.required = false;
			this.correct = false;
			this.callback = null;
			this.classDefault = null;
			this.classError = null;
			return false;
		}
		
		if(this.input!=null && this.input)
		{
			this.input.onkeypress= this.onkeypress;
			this.input.onkeyup = this.onkeyup;
			this.input.onblur = this.onblur;
		}
		
		this.input = input;
		input.validator = this;
		this.type = type;
		this.required = required;
		this.correct = typeof(correct)!="undefined" && (correct==true || correct==false) ? correct : false;
		this.callback = callback;
		this.classDefault = classDefault;
		this.classError = classError;
			
		var self = this;
		
		// sauvegarde des actions affectées au champ input
		this.onkeypress = input.onkeypress;
		this.onkeyup = input.onkeyup;
		this.onblur = input.onblur;
		
		/*if (input.addEventListener)
		{
			input.addEventListener("keypress", self.input_keypress, false);
			input.addEventListener("keyup", self.input_keyup, false);
			input.addEventListener("change", self.input_change, false);
		}
		else if (input.attachEvent)
		{
			input.attachEvent("onkeypress", self.input_keypress);
			//input.attachEvent("onkeyup", self.input_keyup);
			//input.attachEvent("onchange", self.input_change);
		}
		else*/
		{
			input.onkeypress= this.input_keypress.bind(this);
			input.onkeyup = this.input_keyup.bind(this);
			input.onblur = this.input_blur.bind(this);
		}
		
		
		//addEventListener(input, "keypress", "input_keypress");
		//addEventListener(input, "keyup", "input_keyup");
		//addEventListener(input, "change", "input_change");
		
	}
	
	
	
	this.getExpression = function getExpression(type)
	{
		switch(type)
		{
			case "alpha":
				return this.alpha;
				break;
				
			case "alphanum":
				return this.alphanum;
				break;
				
			case "entier":
				return this.int;
				break;
				
			case "entierpos":
				return this.uint;
				break;
				
			case "decimal":
				return this.dec;
				break;
			
			case "decimalpos":
				return this.udec;
				break;
			
			case "email":
				return this.mail;
				break;
			
			case "heure":
				return this.hour;
				break;
			
			case "telephoneFR":
				return this.phone;
				break;
			
			case "telephone":
				return this.phone;
				break;
			
			case "password" :
				return this.password
				break;
			
			case "alphanum_ext" :
				return this.alphanum_ext;
				break;
				
			default:
				return this.defaut;
				break;
		}
		
		return false;
	}
	
	
	this.validateEntry = function validateEntry(evt, type)
	{
		var code;
	
		var pmpEvt = new PMP.util.pmpEvent();
		pmpEvt.getEvent(evt);
		
		
		//alert(pmpEvt.event.ctrlKey);
		
		if (pmpEvt.event.keyCode) code = pmpEvt.event.keyCode;
		else if (pmpEvt.event.which) code = pmpEvt.event.which;
		
		var caractere = String.fromCharCode(code);
		
		var verif = this.validateChar(caractere, type);
		
		//document.getElementById('debug').innerHTML = code + ", " + caractere + ", " + caractere.charCodeAt(0) + ", " + verif;
		
		if(verif==false)
		{
			/*verif = this.valid.test(caractere);
			if(verif)
			{
				this.validateString(evt.target.value, type);
				return;
			}
			*/
		
			verif = this.control.test(caractere) || this.valid.test(caractere);
			if(verif==false)
			{	
				pmpEvt.cancelEvent();
			}
		}	
	}
	
	
	this.validateInput = function validateInput(obj, type, required, correct, callback, classDefault, classError)
	{
		var isValid = false;
		
		var value = typeof(obj.value)!="undefined" ? obj.value : obj.innerHTML;
		
		if(obj && !PMP.common.isUndefined(value) && !PMP.common.isNull(value) )
		{
			isValid = this.validateString(value, type, required);
			
			if(!isValid && typeof(correct)!="undefined" && correct==true)
			{
				var string = value;
				var correctedString = "";
				for(i=0; i<string.length; i++)
				{
					if( this.validateChar(string.charAt(i),type) )
					{
						correctedString += string.charAt(i);
					}
				}
				
				if( typeof(obj.value)!="undefined" )
					obj.value = correctedString;
				else
					obj.innerHTML = correctedString;
			}
		}
		
		if(callback && typeof(callback)=="function")
		{	
			var thisp = arguments[1];
			callback.call(thisp, obj, isValid, classDefault, classError);
		}
		
		var pmpEvt = new PMP.util.pmpEvent("Events", isValid ? "valide" : "invalide", true, false);
		
		//obj.dispatchEvent(pmpEvt.event);
		pmpEvt.dispatchEvent(obj);
		
		return isValid;
	}
	
	
	this.validate = function validate()
	{
		return this.validateInput(this.input, this.type, this.required, this.correct, this.callback, this.classDefault, this.classError);
	}
	
	
	this.validateChar = function validateChar(char, type)
	{
		var expression = new RegExp();
		
		expression = this.getExpression(type);
		
		if(!expression)
			return false;
			
		return expression.test(char);
		
	}
	
	
	this.validateString = function validateString(string, type, required)
	{
		var isValid = false;
		
		var validator = new PMP.util.RegExpValidator();
		
		isValid = validator.validate(string, type, required);
		
		return isValid;
	}
	
	
	this.checkValidation = function checkValidation(evt, type, required, correct, callback, classDefault, classError)
	{
		if (!evt) var evt = window.event;
		
		var code;
		if (evt.keyCode) code = evt.keyCode;
		else if (evt.which) code = evt.which;
		
		var caractere = String.fromCharCode(code);
		
		// vérifie si le caractère entré est coinsidéré comme validant le champ
		var verif = this.valid.test(caractere);
		
		if(verif)
		{
			return this.validateInput(evt.target, type, required, correct, callback, classDefault, classError)
		}
		
		return true;
	}
	
	
	this.input_keypress = function input_keypress(evt)
	{
		var pmpEvt = new PMP.util.pmpEvent();
		pmpEvt.getEvent(evt);
		
		/*if(this.validator)
			this.validator.validateEntry(evt,this.validator.type);
		else*/
			this.validateEntry(pmpEvt.event,this.type);
	}
	
	this.input_keyup = function input_keyup(evt)
	{
		var pmpEvt = new PMP.util.pmpEvent();
		pmpEvt.getEvent(evt);
		
		/*if(this.validator)
			this.validator.checkValidation(evt,this.validator.type);
		else*/
		if(!this.checkValidation(pmpEvt.event, this.type, this.required, this.correct, this.callback));
		{
			//alert("erreur");
		}
	}
	
	this.input_blur = function input_blur(evt)
	{
		var pmpEvt = new PMP.util.pmpEvent();
		pmpEvt.getEvent(evt);
		
		var isValid = false;
		/*if(this.validator)
			isValid = this.validator.validateInput(this.validator.input, this.validator.type, this.validator.correct);
		else*/
	
		isValid = this.validate();
		
		if(PMP.common.isFunction(this.onblur))
		{
			this.onblur.apply(this.input);
		}
	}
	
	
	/***************** initialisation de l'instance *****************/
	
	this.setInput(input, type, required, correct, callback, classDefault, classError);
		
}




/***********************************************************************


	Classe RegExpValidator pour la validation d'une chaine


Paramètres
	

Méthodes
	- validate : valide une chaine selon une expression régulière représentant le type d'information attendu


***********************************************************************/


PMP.util.RegExpValidator = function()
{
	this.alpha 			= /^[a-zA-Z\.\-]+$/;
	this.alphanum		= /^\w+$/;
	this.int 			= /^[\+\-]?\d+$/;
	this.uint 			= /^\d+$/;
	this.dec 			= /^[\+\-]?\d+(\.\d+)?$/;
	this.udec 			= /^\d+(\.\d+)?$/;
	this.hour			= /^[\d]{2}:[\d]{2}(:[\d]{2})?$/;
	this.mail			= /^[\w-_\.]+\@[\w-_\.]+\.[a-z]{2,4}$/;
	this.phoneFR		= /^(\d{2}[\.\s\-]?){5}$/;
	this.password		= /^[\w\.]+$/;
	this.alphanum_ext	= /^[\w\s\'\.\-ç-ù]+$/;
	
	this.defaut			= /^.+$/;
	
	
	this.getExpression = function getExpression(type)
	{
		switch(type)
		{
			case "alpha":
				return this.alpha;
				break;
				
			case "alphanum":
				return this.alphanum;
				break;
				
			case "entier":
				return this.int;
				break;
				
			case "entierpos":
				return this.uint;
				break;
				
			case "decimal":
				return this.dec;
				break;
			
			case "decimalpos":
				return this.udec;
				break;
			
			case "email":
				return this.mail;
				break;
			
			case "heure":
				return this.hour;
				break;
			
			case "telephoneFR":
				return this.phoneFR;
				break;
			
			case "telephone":
				return this.phoneFR;
				break;
			
			case "password" :
				return this.password
				break;
			
			case "alphanum_ext" :
				return this.alphanum_ext;
				break;
			
			default:
				return this.defaut;
				break;
		}
		
		return false;
	}
	
	
	this.validate = function validate(string, expression, required)
	{
		if(required==false && string.length==0)
			return true;
		
		if(typeof(expression)=="string")
			expression = this.getExpression(expression);
		
		if(expression)
		{
			var validExp = expression;
		
			return validExp.test(string);
		}
		
		return false;
	}
}




/***********************************************************************


	Classe FormElement pour la gestion d'un élément de formulaire


Paramètres
	- element : l'id ou l'object représentant l'élément concerné
	- type : le type d'information attendue (email, telephone, heure, entier, entier pos, ...)
	- required : champ obligatoire ou non
	- correct : correction automatique du champs si la saisie est invalide
	- callback : fonction externe appelée lors de la validation de l'élément. Cette fonction doit prendre en paramètre l'obj représentant le champ ainsi qu'un booléen pour son état valide ou non.
	- classDefault : le nom de la classe CSS par défaut de l'élément
	- classFocus : le nom de la classe CSS onFocus de l'élément
	- classError : le nom de la classe CSS de l'élément lorsqu'il est invalide
	
	
***********************************************************************/


PMP.util.FormElement = function(element, type, required, correct, callback, classDefault, classFocus, classError)
{
	var me = this;
	
	this.setElement = function setElement(element, type,  classDefault, classFocus, classError, required, correct, callback)
	{
		this.element = typeof(element)=="string" ? document.getElementById(element) : (element ? element : false);
		this.type = type;
		this.required = required;
		this.correct = correct;
		this.callback = callback;
		this.onblur = false;

		//if( PMP.common.isUndefined(this.element) || PMP.common.isNull(this.element) || (PMP.common.isBoolean(this.element) && !this.element) )
		if( !PMP.common.isObject(this.element) )
		{
			// element non défini	
			return false;
		}

		
		// sauvegarde de l'action affecté à l'évenement onblur
		this.onblur = this.element.onblur;
		
		this.classDefault = classDefault;
		this.classFocus = classFocus ;
		this.classError = classError ;
		
		
		/****************** gestion des styles ******************/
		
		if(typeof(this.classDefault)!="undefined" && this.classDefault!=null && this.classDefault!="")
			this.element.className = this.classDefault;
		
		
		
		this.element.onfocus = function()
		{
			if(typeof(me.classFocus)!="undefined" && me.classFocus!=null && me.classFocus!="")
				this.className = me.classFocus;	
		}
		
		this.element.onblur = function()
		{
			if(this.className==me.classFocus)
			{
				if(typeof(me.classDefault)!="undefined" && me.classDefault!=null && me.classDefault!="")
					this.className = me.classDefault;
			}
			
				
			if(PMP.common.isFunction(me.onblur))
			{
				me.onblur.apply(this);
			}
		}
		
		
		/***************** gestion de la saisie *****************/
		
		this.validator = new PMP.util.RegExpInputValidator(this.element, this.type, this.required, this.correct, this.callback, this.classDefault, this.classError);
		
		var pmpEvt = new PMP.util.pmpEvent();
		
		pmpEvt.addEventListener(this.element, "valide", me._onValide);
		pmpEvt.addEventListener(this.element, "invalide", me._onInvalide);
	}
	
	
	this.setRequired = function setRequired(val)
	{
		this.required = val;
		
		if(PMP.common.isObject(this.element))
		{
			this.validator.required = val;
		}
	}
	
	
	this.validate = function validate()
	{
		if(PMP.common.isObject(this.element))
			return this.validator.validate();
		
		return true;
	}
	
	
	this._onInvalide = function _onInvalide()
	{
		return;

		if(typeof(me.classError)!="undefined" && me.classError!=null && me.classError!="")
			this.className = me.classError;	
	}
	
	
	this._onValide = function _onValide()
	{
		if(typeof(me.classDefault)!="undefined" && me.classDefault!=null && me.classDefault!="")
			this.className = me.classDefault;	
	}
	
	
	/***************** initialisation de l'instance *****************/
	
	this.setElement(element, type,  classDefault, classFocus, classError, required, correct, callback);

}




/***************************************************************************************************************************************************/
	

	
// déclaration d'une instance

var inputVal = new PMP.util.RegExpInputValidator();

