/* ************************************************************************************* *\
 * The MIT License
 * Copyright (c) 2007 Fabio Zendhi Nagao - http://zend.lojcomm.com.br
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this
 * software and associated documentation files (the "Software"), to deal in the Software
 * without restriction, including without limitation the rights to use, copy, modify,
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to the following
 * conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all copies
 * or substantial portions of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 * 
\* ************************************************************************************* */

var fValidator = new Class({
	options: {
		msgContainerTag: "div",
		msgClass: "fValidator-msg",

		styleValid: {"background-color": "#ffffff"},
		styleInvalid: {"background-color": "#ffffff"}, 
		styleNeutral: {"background-color": "#ffffff"},

		required: {type: "required", re: /[^.*]/, msg: "<font color=#FF0000><strong>Campo requerido</strong></font>"},
		login: {type: "login", re: /^[a-z\d_]{6,20}$/i, msg: "<font color=#FF0000><strong>El login no es valido. Debe ser de 6 a 16 caracteres alafanumericos sin espacios. Puede aceptar guiones bajos</strong></font>"},
		rfc:{type: "rfc", re: /^[A-Za-z]{3,4}[-\s]*\d{6}[-\s]*[A-Za-z0-9]{0,3}$/, msg: "<font color=#FF0000><strong>RFC Invalido.</strong></font>"},
		curp:{type: "curp", re: /^[A-Za-z]{4}\d{6}[HMhm]{1}[A-Za-z]{2}[A-Za-z]{3}[A-Za-z0-9]{1}[0-9]{1}$/, msg: "<font color=#FF0000><strong>CURP Invalido.</strong></font>"},
		
//		alpha: {type: "alpha", re: /^[a-zA-Z���������������������� ._-]+$/i, msg: "<font color=#FF0000><strong>Este campo s&oacute;lo acepta caracteres alfab&eacute;ticos.</strong></font>"},
//		alphanum: {type: "alphanum", re: /^[a-zA-Z����������������������0-9 ._-]+$/i, msg: "<font color=#FF0000><strong>Este campo s&oacute;lo acepta caracteres alfanum&eacute;ricos.</strong></font>"},
		alpha: {type: "alpha", re: /^[a-zA-Z������������ ._-]+$/i, msg: "<font color=#FF0000><strong>Este campo s&oacute;lo acepta caracteres alfab&eacute;ticos.</strong></font>"},
		alphanum: {type: "alphanum", re: /^[a-zA-Z������������0-9 ._-]+$/i, msg: "<font color=#FF0000><strong>Este campo s&oacute;lo acepta caracteres alfanum&eacute;ricos.</strong></font>"},

		integer: {type: "integer", re: /^[-+]?\d+$/, msg: "<font color=#FF0000><strong>Ingrese un n&uacute;mero entero v&aacute;lido.</strong></font>"},
		real: {type: "real", re: /^[-+]?\d*\.?\d+$/, msg: "<font color=#FF0000><strong>Ingrese un n&uacute;mero v&aacute;lido.</strong></font>"},
		fecha: {type: "fecha", re: /^((((0[13578])|([13578])|(1[02]))[\/](([1-9])|([0-2][0-9])|(3[01])))|(((0[469])|([469])|(11))[\/](([1-9])|([0-2][0-9])|(30)))|((2|02)[\/](([1-9])|([0-2][0-9]))))[\/]\d{4}$|^\d{4}$/, msg: "<font color=#FF0000><strong>Ingrese la fecha en el siguiente formato: (mm/dd/yyyy).</strong></font>"},
		email: {type: "email", re: /^[a-z0-9._%-]+@[a-z0-9.-]+\.[a-z]{2,4}$/i, msg: "<font color=#FF0000><strong>E-mail inv&aacute;lido.</strong></font>"},
		phone: {type: "phone", re: /^[\d\s ().-]+$/, msg: "<font color=#FF0000><strong>Ingrese un num. de tel. v&aacute;lido.</strong></font>"},
		url: {type: "url", re: /^[a-z0-9\-\.]+\.[a-z]{2,3}(:[a-z0-9]*)?\/?([a-z0-9\-\._\?\,\\/\\\+&amp;%\$#\=~])*$/i, msg: "<font color=#FF0000><strong>Ingrese una url v&aacute;lida.</strong></font>"},
		money: {type: "money", re: /^\$?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/, msg: "<font color=#FF0000><strong>Ingrese una cantidad monetaria v&aacute;lida</strong></font>"},   

		confirm: {type: "confirm", msg: "<font color=#FF0000><strong>La confirmacion de este campo es incorrecta.</strong></font>"},

		onValid: Class.empty,
		onInvalid: Class.empty 
	},

	initialize: function(form, options) {
               
		this.form = $(form);
		this.setOptions(options);

		this.fields = this.form.getElements("*[class^=fValidate]");
		this.validations = [];

		this.fields.each(function(element) 
		{
			if(!this._isChildType(element)) 
				element.setStyles(this.options.styleNeutral);
			
			element.cbErr = 0;
			var classes = element.getProperty("class").split(' ');
			
			classes.each(function(klass) 
			{
				if(klass.match(/^fValidate(\[.+\])$/)) 
				{
					var aFilters = eval(klass.match(/^fValidate(\[.+\])$/)[1]);
					for(var i = 0; i < aFilters.length; i++) 
					{
						if(this.options[aFilters[i]]) 
							this.register(element, this.options[aFilters[i]]);
						if(aFilters[i].charAt(0) == '=') 
							this.register(element, $extend(this.options.confirm, {idField: aFilters[i].substr(1)}));
					}
				}
			}.bind(this));
		}.bind(this));

		this.form.addEvents({
			"submit": this._onSubmit.bind(this),
			"reset": this._onReset.bind(this)
		});
	},

	register: function(field, options) {
		field = $(field);
		this.validations.push([field, options]);
		field.addEvent("blur", function() {
			this._validate(field, options);
		}.bind(this));
	},

	_isChildType: function(el) {
		var elType = el.type.toLowerCase();
		if((elType == "radio") || (elType == "checkbox")) 
			return true;
		return false;
	},

	_validate: function(field, options) {
		switch(options.type) {
			case "confirm":
				if($(options.idField).getValue() == field.getValue()) 
					this._msgRemove(field, options);
				else 
					this._msgInject(field, options);
				break;
			default:
				var vacio;    //				prueba=$(field).getValue();
				campoValue=field.getValue();
//				prueba=this._cadenaIncorrecta(campoValue,"0");
//				alert("con cero: "+ prueba);
				
				if(options.re.test(field.getValue()))  //si el campo es valido
				{
					//verifico no vacios
					
					if (campoValue=="" || this._cadenaIncorrecta(campoValue,"0") || this._cadenaIncorrecta(campoValue," ") ) //con vacios
						this._msgInject(field, options); //mando error
					else //es valido
					
						this._msgRemove(field, options);
				}
				else //si el campo es errone
					this._msgInject(field, options);
		}
	},


	// revisa que el elemento no tenga solamente alg�n caracter considerado como no v�lido (espacio en blanco, ceros, etc)
	_cadenaIncorrecta: function(cad, car) {
		var cadena = cad;
		for (j=0; cad.length > j && cadena.charAt(j) == car; j++);
		if (cad.length != j)
			return 0;
		else
			return 1;
	},



	_validateChild: function(child, options) {
		var nlButtonGroup = this.form[child.getProperty("name")];
		var cbCheckeds = 0;
		var isValid = true;
 		for(var i = 0; i < nlButtonGroup.length; i++) {
			if(nlButtonGroup[i].checked) {
				cbCheckeds++;
				//La siguiente linea revisar. Causa error
				if(!options.re.test(nlButtonGroup[i].getValue())) {
					isValid = false;
					break;
				}
			}
		}
		if(cbCheckeds == 0 && options.type == "required") isValid = false;
		if(isValid)
			this._msgRemove(child, options);
		else 
		this._msgInject(child, options);
	},

	_msgInject: function(owner, options) {
		if(!$(owner.getProperty("id") + options.type +"_msg")) {
			var msgContainer = new Element(this.options.msgContainerTag, {"id": owner.getProperty("id") + options.type +"_msg", "class": this.options.msgClass})
				.setHTML(options.msg)
				.setStyle("opacity", 0)
				.injectAfter(owner) 
				.effect("opacity", {
					duration: 500,
					transition: Fx.Transitions.linear
				}).start(0, 1);
			owner.cbErr++;
			this._chkStatus(owner, options);
		}
	},

	_msgRemove: function(owner, options, isReset) {
		isReset = isReset || false;
		if($(owner.getProperty("id") + options.type +"_msg")) {
			var el = $(owner.getProperty("id") + options.type +"_msg");
			el.effect("opacity", {
				duration: 500,
				transition: Fx.Transitions.linear,
				onComplete: function() {el.remove()}
			}).start(1, 0);
			if(!isReset) {
				owner.cbErr--;
				this._chkStatus(owner, options);
			}
		}
	},

	_chkStatus: function(field, options) {
		if(field.cbErr == 0) {
			field.effects({duration: 500, transition: Fx.Transitions.linear}).start(this.options.styleValid);
			this.fireEvent("onValid", [field, options], 50);
		} else {
			field.effects({duration: 500, transition: Fx.Transitions.linear}).start(this.options.styleInvalid);
			this.fireEvent("onInvalid", [field, options], 50);
		}
	},

	_onSubmit: function(event) {
		event = new Event(event);
		var isValid = true;

		this.validations.each(function(array) {
			if(this._isChildType(array[0])) 
				this._validateChild(array[0], array[1]);
			else 
				this._validate(array[0], array[1]);
			if(array[0].cbErr > 0) 
				isValid = false;
		}.bind(this));

		if(!isValid) event.stop();
		return isValid;
	},

	_checkSubmit: function() {

		var isValid = true;
		var msjinValid = "";
		
		this.validations.each(function(array) {
			if(this._isChildType(array[0])) 
				this._validateChild(array[0], array[1]);
			else 
				this._validate(array[0], array[1]);

			if(array[0].cbErr > 0) 
			{
				isValid = false;
				
			}
		}.bind(this));
		
		return isValid;
	},


	_onReset: function() {
		this.validations.each(function(array) {
			if(!this._isChildType(array[0])) array[0].setStyles(this.options.styleNeutral);
			array[0].cbErr = 0;
			this._msgRemove(array[0], array[1], true);
		}.bind(this));
	}
});
fValidator.implement(new Events); // Implements addEvent(type, fn), fireEvent(type, [args], delay) and removeEvent(type, fn)
fValidator.implement(new Options);// Implements setOptions(defaults, options)



function FC_JS_ValidatorGeneraObjeto(nombreform,mask)
{
	
	if(mask)
	{
		new iMask({
		 onFocus: function(obj) {  
			 obj.setStyles({"background-color":"#ffffff", border:"1px solid #cccccc"});  
		 },  
		
		  onBlur: function(obj) {  
			 obj.setStyles({"background-color":"#ffffff", border:"1px solid #cccccc"});  
		 },  
		
			onValid: function(event, obj) {obj.setStyles({"background-color":"#ffffff", border:"1px solid #cccccc"})},
			onInvalid: function(event, obj) {obj.setStyles({"background-color":"#fccccc", "border":"1px solid #cc0000"})}
		});
	}


	var exValidatorBL = new fValidator(nombreform);	
	return (exValidatorBL)
	
	
}
 
//funcion que hace submit en el formulario
// parametros: 	exValidator:	objeto de la clase fvalidator
//				vmsj: mensaje de confirm antes de hacer submit
//				vaction: action del formulario
//				vtarget: target del formulario (_blank, _self, _parent)
//				vmetjod: metodo del formulario (post, get)
//				vnumvar: numero del elemento del formulario al cual se le colocara el valor de vvalvar
//				vvalvar: valor que tomara el elemento vnumvar; estos dos ultimos parametros sirven para enviar banderas..
//				myvalidator: si llega algun dato a esta variable no se ejecutara la validacion de la funcion validator si no la validacion usada  
//							 en la funccion myvalidator que esta definida en esta pag, esto es usada cuando la pag incluyen campos generados con ajax
//							 los cuales no son validades correctamente x la Fvalidator original

function EnviarForm(exValidator,vmsj,vaction,vtarget,vmethod,vnumvar, vvalvar, myValidator) 
{
	var msjerror="";
	
	//si se require hacer uso de la funcion myValidator
	//la mando llamar y paso a esa funcion
	if(myValidator)
	{
		FL_JS_myValidator(exValidator,vmsj,vaction,vtarget,vmethod,vnumvar, vvalvar);

		return;
	}
	
	
/*	alert("entre");
	msjerror= FC_JS_Tamanio (exValidator.form);		
	alert (msjerror);
*/
	if ( exValidator._checkSubmit( ) ) 
	{

//		alert("entre");
		msjerror= FC_JS_Tamanio (exValidator.form);		
//		alert (msjerror);
		if(msjerror=="")
		{
			if (vmsj)
				if (!confirm(vmsj))
					return false;
	
			if(vnumvar)
				exValidator.form.elements[vnumvar].value=vvalvar;
			if (vaction)
				exValidator.form.action = vaction;
			if (vtarget)
				exValidator.form.target = vtarget;
			if (vmethod)
				exValidator.form.method = vmethod;
					
			exValidator.form.submit();
			 
			for (i=0;  exValidator.form.elements[i]; i++)
				exValidator.form.elements[i].disabled=true;
		} //fin si no hubo error
		else
			alert("No se ha podido enviar la informacion ya que faltan datos\n" + msjerror);
			
	}else {
		alert("No se ha podido enviar la informacion ya que faltan datos\nCorrija porfavor");
	}

}	


// Revisa que el tama�o de los elementos del formulario sea correcto
function FC_JS_Tamanio (formulario) 
{
    var mensaje;   
	mensaje="";   
//	alert("entre2");
    for (i=0; formulario.elements[i]; i++)
	{
		if (formulario.elements[i].getAttribute("tamanio")) 		
		{
			if (formulario.elements[i].value.length < formulario.elements[i].maxLength )
                mensaje += "- " +  formulario.elements[i].title + ": debe ser de tama�o" + formulario.elements[i].maxLength + '\n';
		}
	}
    return mensaje;
	
}


//FUNCION MYVALIDATOR
//esta funcion es una alternativa a la funcion validator, lo que hace es hacer una validacion 
//recorriendo los elementos del formulario (a la antiguita)
//verificando si son requeridos, y si su value corresponde al tipo indicado en la clase fvalidate
//esta funcion se llama si se indica su llamada desde la funcion EnviarForm
function FL_JS_myValidator(exValidator,vmsj,vaction,vtarget,vmethod,vnumvar, vvalvar, retornarmsjerror, errorAdicional, deshabilitar, validaYRetorna)
{
	var msjerror;
	var elementoform;
	msjerror="";

        if(deshabilitar="")
            deshabilitar=true;
		
	//recorro todos los elementos del formulario
	for(i=0;exValidator.form.elements[i]; i++) //Mientras tenga elementos el formulario
	{
		el=exValidator.form.elements[i];
		elclass=el.className; //saco la clase del elemento
		//si tiene clase
		if(elclass){
			//ahora veo si la clase es del tipo fvalidator
			if(elclass.indexOf("fValidate")!=-1){
				//ahora veo si es un campo requerido; si es asi valido que no este vacio
				if(elclass.indexOf("required")!=-1)
				{
					if (el.value=="" || FC_JS_cadenaIncorrecta(el.value,"0") || FC_JS_cadenaIncorrecta(el.value," ") ) //con vacios		
						msjerror+="- "+el.title+" esta vacio\n";
				}		


				if (el.getAttribute("tamanio")) 		
				{
					if (el.value.length < el.maxLength )
                                    msjerror += "- " +  el.title + ": debe ser de tama�o " + el.maxLength + '\n';
				}

				//comienzan los ifs para ver la clase de validacion que necesita el campo
				if(elclass.indexOf("alpha")!=-1)
				{
					//alert(fields[i].id+" , "+fields[i].value);
					if (!(/^[a-zA-Z������������ ._-]+$/.test(el.value)))
						msjerror+="- "+el.title+" debe ser un dato alafabetico\n";
				}
				else if(elclass.indexOf("login")!=-1)
				{
					if (!(/^[a-zA-Z\d_]{6,20}$/.test(el.value)))	
						msjerror+="- "+el.title+" debe ser alfanumerico entre 6 y 16 caracteres y sin espacios\n";
				}
				else if(elclass.indexOf("alphanum")!=-1)
				{
					if (!(/^[a-zA-Z������������0-9 ._-]+$/.test(el.value)))
						msjerror+="- "+el.title+" debe ser un dato alfanumerico\n";
				}
				else if(elclass.indexOf("integer")!=-1)
				{
					if (!(/^[-+]?\d+$/.test(el.value)))
						msjerror+="- "+el.title+" debe ser un dato numerico\n";
				}		
				else if(elclass.indexOf("curp")!=-1)
				{ 
					if (!(/^[A-Za-z]{4}\d{6}[HMhm]{1}[A-Za-z]{2}[A-Za-z]{3}[A-Za-z0-9]{1}[0-9]{1}$/.test(el.value)))				
						msjerror+="- "+el.title+" es un curp no valido consulte la ayuda para corregir\n";
				}				
				else if(elclass.indexOf("rfc")!=-1)
				{
					if (!(/^[A-Za-z]{3,4}[-\s]*\d{6}[-\s]*[A-Za-z0-9]{0,3}$/.test(el.value)))	
						msjerror+="- "+el.title+" no es un RFC  valido\n";
				}	
				else if(elclass.indexOf("email")!=-1)
				{
					if (!(/^[a-z0-9._%-]+@[a-z0-9.-]+\.[a-z]{2,4}$/.test(el.value)))	
						msjerror+="- "+el.title+" no es un email valido\n";
				}
				else if(elclass.indexOf("url")!=-1)
				{
					if (!(/^[a-z0-9\-\.]+\.[a-z]{2,3}(:[a-z0-9]*)?\/?([a-z0-9\-\._\?\,\\/\\\+&amp;%\$#\=~])*$/.test(el.value)))	
						msjerror+="- "+el.title+" no es una URL valido\n";
				}
				
				else if(elclass.indexOf("real")!=-1)
				{
					if (!(/^[-+]?\d*\.?\d+$/.test(el.value)))	
						msjerror+="- "+el.title+" no es un decimal valido\n";
				}
				else if(elclass.indexOf("fecha")!=-1)
				{
					if (!(/^[A-Za-z]{3,4}[-\s]*\d{6}[-\s]*[A-Za-z0-9]{0,3}$/.test(el.value)))	
						msjerror+="- "+el.title+" no es una fecha valida\n";
				}
				else if(elclass.indexOf("phone")!=-1)
				{
					if (!(/^[\d\s ().-]+$/.test(el.value)))	
						msjerror+="- "+el.title+" no es un telefono valido\n";
				}
				else if(elclass.indexOf("money")!=-1)
				{
	/*				if (!( /^\$?([1-9]{1}[0-9]{0,2}(\,[0-9]{3})*(\.[0-9]{0,2})?|[1-9]{1}[0-9]{0,}(\.[0-9]{0,2})?|0(\.[0-9]{0,2})?|(\.[0-9]{1,2})?)$/.test(fields[i].value)))	
						msjerror+="- "+fields[i].title+" no es un RFC valido\n";
	*/					
				}
				
			}	 //fin de si la clase es del tipo validator
		
		} //fin de si tiene clase
		
	} //fin del for que recorre los elementos con clase fvalidator

        //le pego a la cadena del error el error adicional q proviene de los parametros
        
        if(errorAdicional!=undefined && errorAdicional!="")msjerror+=errorAdicional;



        
	//si hubo algun error lo mando
	if(msjerror!="")
	{
		//alert("retornarmsjerror: "+retornarmsjerror);
		if(retornarmsjerror )
			return (msjerror);
		else	
			alert("Error los siguientes datos son incorrectos \n\n"+msjerror);
	}
	else
	{
		if (vmsj)
                    if (!confirm(vmsj))
                        return false;

                if(vnumvar)
                        exValidator.form.elements[vnumvar].value=vvalvar;
                if (vaction)
                        exValidator.form.action = vaction;
                if (vtarget)
                        exValidator.form.target = vtarget;
                if (vmethod)
                        exValidator.form.method = vmethod;

                //alert("validaYRetorna"+validaYRetorna);
                if(validaYRetorna){
                    
                   return true;
                }

                exValidator.form.submit();

                if(deshabilitar){
                    for (i=0; exValidator.form.elements[i]; i++)
                        exValidator.form.elements[i].disabled=true;
                }



                
	}
	

}  //fin de la funcion

// revisa que el elemento no tenga solamente alg�n caracter considerado como no v�lido (espacio en blanco, ceros, etc)
function FC_JS_cadenaIncorrecta(cad, car) 
{
	var cadena = cad;
	for (j=0; cad.length > j && cadena.charAt(j) == car; j++);
		if (cad.length != j)
			return 0;
		else
			return 1;
}

