/***********************************************************************************************
 							formValidator V 2.1.3
																								
 [Descripción]
 - Reglas de validación centralizadas
 - Validación post-submit y en tiempo real
 - Especificación de estilos globales para los errores: 
 	Si no se especifica ninguno utiliza los siguientes estilos 
		- text: textValidateError
		- textArea: textAreaValidateError
		- selectOne: selectOneValidateError
 		- selectMultiple: selectMultipleValidateError
		- radioButton: rbValidateError
		- checkBox: chkValidateError
 - Validación de campos múltiples (telefono[0], telefono[1].....,telefono[n])
	- Valida los siguientes tipos de campos:
		- text
		- radioButtons y RadioButton Areas
		- checkBoxes
		- textArea
		- selects (Multiples y simples)
 - Validación de datos mediante una función externa: 
   Esto permite validaciones más complicadas como campos anidados o máscaras especiales
 - Utiliza expresiones regulares para optimizar la velocidad

 [Ejemplo de validación con función externa]
 	
	formValidator.addRule({
		id:'pax_precio_base',
		validate:'positiveNumber',
		validateMsg: 'Número inválido. Debe ser un número mayor que 0',
		required:true,
		requiredMsg:'Campo obligatorio',
		validateFunction: validarPrecioBase,
		validateFunctionMsg: 'Campo inválido'
		});	
		
	function validarPrecioBase() {
		alert('valido precio base y me dio mal');
		return true;
	}

 [Atributos]
 - preError:	html que va antes de cada error. Sirve para poner alguna imagen detrás
 - summary: id del div donde se mostrará el resumen de errores ej: 'summary'
 - summaryTitle: título del resumen ej: 'Resumen de errores del formulario'
 - styles: Objeto literal con los estilos para cada tipo de validación
				ej: {input:'',textArea:'',select:'', radioButton:'', checkBox:''}
 
 [Correciones]
 - 16/09/2007 Arreglado problema de validación de campos array que no admitian un id del tipo "productos[id_tipo_producto]"
 - 28/02/2008 Arreglado problema de DefaultValue para validaciones de datos
 - 13/03/2008 Agregado validacion positiveNumber para validar que sea un número > 0
 - 13/03/2008 Arreglado problema con validación con función externa
 - 17/03/2008 Se agregó la validación de tarjetas de crédito
 [Mejoras previstas]
 	- Múltiples validaciones por cada campo. Actualmente solo permite combinar campo requerido con cualquier otra validacion de datos
 pero no permite validar el mismo dato contra diferentes reglas de validación
 	- Restricción de datos en tiempo real. Permite restringir que tipos de datos se deben ingresar en un campo. Cada vez que se oprima una tecla
 el validador comprobará si ese campo admite ese caracter
 	- Bug conocidos: Si no encuentra la div de summary en el html el validador tira error por mas que esté especificado que no muestra el sumario de errores
	- Estilos globales y por cada regla: Setea los estilos por cada regla y si no se setean utiliza los globales
*******************************************************************************************************************************************/
var Class = {
        create: function() { return function() { this.initialize.apply(this, arguments); } }
}
 
function getValue(s){return document.getElementById(s).value}
 
var formValidator = Class.create();
formValidator.prototype = {
        
		/*--------------------------------------------------------------------------*/
        initialize:function(){
                // **** Publicas  ****
				this.showSummary = true;				// Indica si se debe mostrar el resumen de errores
				this.shortSummary = true;				// Indica que en el sumario solo se muestre una leyenda y no un resumen de todos los errores
				this.showFieldErrors = true;			// Indica si se debe mostrar o no la validación en cada campo
				this.focusFieldErrors = true;			// Indica si se debe destacar el campo que tenga error
				
				// Layout
				this.summaryTitle = ""; 				// String con el título del div ej: 'Resumen de errores del formulario'
				this.summaryText = '';					// Texto a mostrar en el short summary
				this.summary = "";						// id del div donde se mostrará el resumen de errores ej: 'summary'
				this.preError = ""; 					// HTML que se concatena antes de los mensajes de error del div
				this.errorStyle = "fontValidateError"; 	// Estilo del error a mostrar
				this.styles = {
					error: {text:'fv_text_error', textarea:'fv_textarea_error', select_one:'fv_select-one_error', select_multiple:'fv_select-multiple_error', radio:'fv_radio_error', checkbox:'fv_checkbox_error', file:'fv_file_error'},
					valid: {text:'fv_text_valid', textarea:'fv_textarea_valid', select_one:'fv_select-one_valid', select_multiple:'fv_select-multiple_valid', radio:'fv_radio_valid', checkbox:'fv_checkbox_Valid', file:'fv_file_Valid'}
					}; // Objeto literal de estilos por defecto
				
				// **** Privadas ****
				this.rules_array = [];					// Array con las reglas de los campos
				this.error_array = [];					// Array con el resumen de errores
				this.error_control_array = []; 			// Contiene las posiciones de los errores asociados a su id para poder quitarlos cuando se valida el campo con validateField
				this.pres = 50; 						// Presisión de busqueda de htmlArrays (Cuanto mas grande el numero más presición) 50 default
        
                // **** Dinámicas (específicas) ****
				this.parametros = [];					// Array de parametros cargados (para validacion de formulas de corte)
		},
        /*--------------------------------------------------------------------------*/
        hasValidChars:function(s, characters, caseSensitive){
                function escapeSpecials(s){
                        return s.replace(new RegExp("([\\\\-])", "g"), "\\$1");
                }
                return new RegExp("^[" + escapeSpecials(characters) + "]+$",(!caseSensitive ? "i" : "")).test(s);
        },
        /*--------------------------------------------------------------------------*/
        isSimpleIP:function(ip){
                ipRegExp = /^(([0-2]*[0-9]+[0-9]+)\.([0-2]*[0-9]+[0-9]+)\.([0-2]*[0-9]+[0-9]+)\.([0-2]*[0-9]+[0-9]+))$/
                return ipRegExp.test(ip);
        },
        /*--------------------------------------------------------------------------*/
        isAlphaLatin:function(string){
                alphaRegExp = /^[0-9a-z]+$/i
                return alphaRegExp.test(string);
        },
        /*--------------------------------------------------------------------------*/
        isNotEmpty:function (string){
                return /\S/.test(string);
        },
        /*--------------------------------------------------------------------------*/
        isEmpty:function(s){
                return !/\S/.test(s);
        },
        /*--------------------------------------------------------------------------*/
        isIntegerInRange:function(n,Nmin,Nmax){
                var num = Number(n);
                if(isNaN(num)){
                        return false;
                }
                if(num != Math.round(num)){
                        return false;
                }
                return (num >= Nmin && num <= Nmax);
        },
        /*--------------------------------------------------------------------------*/
        isFloatInRange:function(n,Nmin,Nmax){
				// Convierte a float
				var num = String(n);
				num = num.replace(/[.]/g,'');
				num = num.replace(/[,]/g,'.');
				num = parseFloat(num);
	
				if(isNaN(num) || !this.isFloatWithFormat(num))	
					{
					return false;
					}
				else
					{
					return (num >= Nmin && num <= Nmax);
					}
					
        },
        /*--------------------------------------------------------------------------*/
        isNum:function(number){
                numRegExp = /^[0-9]+$/
                return numRegExp.test(number);
        },
        /*--------------------------------------------------------------------------*/
        isPositiveNum:function(number){
                numRegExp = /^[0-9]+$/
                testeo = numRegExp.test(number);
				if (testeo) {
				 number = parseFloat(number);	
				 if (number >0) { return true;} else { return false; }
				}
        },
        /*--------------------------------------------------------------------------*/
        isEMailAddr:function(string){
				emailRegExp = /^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*(\.([a-zA-Z]){2,4})$/
                return emailRegExp.test(string);
        },
        /*--------------------------------------------------------------------------*/
        isZipCode:function(zipcode,country){
                if(!zipcode) return false;
                if(!country) format = 'US';
                switch(country){
                        case'US': zpcRegExp = /^\d{5}$|^\d{5}-\d{4}$/; break;
                        case'MA': zpcRegExp = /^\d{5}$/; break;
                        case'CA': zpcRegExp = /^[A-Z]\d[A-Z] \d[A-Z]\d$/; break;
                        case'DU': zpcRegExp = /^[1-9][0-9]{3}\s?[a-zA-Z]{2}$/; break;
                        case'FR': zpcRegExp = /^\d{5}$/; break;
                        case'Monaco':zpcRegExp = /^(MC-)\d{5}$/; break;
                }
                return zpcRegExp.test(zipcode);
        },
        /*--------------------------------------------------------------------------*/
        isDate:function(date,format){
                if(!date) return false;
                if(!format) format = 'FR';
                
                switch(format){
                        case'FR': RegExpformat = /^(([0-2]\d|[3][0-1])\/([0]\d|[1][0-2])\/([2][0]|[1][9])\d{2})$/; break;
                        case'US': RegExpformat = /^([2][0]|[1][9])\d{2}\-([0]\d|[1][0-2])\-([0-2]\d|[3][0-1])$/; break;
                        case'SHORTFR': RegExpformat = /^([0-2]\d|[3][0-1])\/([0]\d|[1][0-2])\/\d{2}$/; break;
                        case'SHORTUS': RegExpformat = /^\d{2}\-([0]\d|[1][0-2])\-([0-2]\d|[3][0-1])$/; break;
                        case'dd MMM yyyy':RegExpformat = /^([0-2]\d|[3][0-1])\s(Jan(vier)?|Fév(rier)?|Mars|Avr(il)?|Mai|Juin|Juil(let)?|Aout|Sep(tembre)?|Oct(obre)?|Nov(ember)?|Dec(embre)?)\s([2][0]|[1][19])\d{2}$/; break;
                        case'MMM dd, yyyy':RegExpformat = /^(J(anuary|u(ne|ly))|February|Ma(rch|y)|A(pril|ugust)|(((Sept|Nov|Dec)em)|Octo)ber)\s([0-2]\d|[3][0-1])\,\s([2][0]|[1][9])\d{2}$/; break;
                }
                
                return RegExpformat.test(date);
        },
        /*--------------------------------------------------------------------------*/
        isMD5:function(string){
                if(!string) return false;
                md5RegExp = /^[a-f0-9]{32}$/;
                return md5RegExp.test(string);
        },
        /*--------------------------------------------------------------------------*/
        isURL:function(string){
                if(!string) return false;
                string = string.toLowerCase();
                urlRegExp = /^(((ht|f)tp(s?))\:\/\/)([0-9a-zA-Z\-]+\.)+[a-zA-Z]{2,6}(\:[0-9]+)?(\/\S*)?$/
                return urlRegExp.test(string);
        },
        /*--------------------------------------------------------------------------*/
        isGuid:function(guid){//guid format : xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx or xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
                if(!guid) return false;
                GuidRegExp = /^[{|\(]?[0-9a-fA-F]{8}[-]?([0-9a-fA-F]{4}[-]?){3}[0-9a-fA-F]{12}[\)|}]?$/
                return GuidRegExp.test(guid);
        },
        /*--------------------------------------------------------------------------*/
        isISBN:function(number){
                if(!number) return false;
                ISBNRegExp = /ISBN\x20(?=.{13}$)\d{1,5}([- ])\d{1,7}\1\d{1,6}\1(\d|X)$/
                return ISBNRegExp.test(number);
        },
        /*--------------------------------------------------------------------------*/
        isSSN:function(number){//Social Security Number format : NNN-NN-NNNN
                if(!number) return false;
                ssnRegExp = /^\d{3}-\d{2}-\d{4}$/
                return ssnRegExp.test(number);
        },
        /*--------------------------------------------------------------------------*/
        isPositiveDecimal:function(number){
			// positive 
            if(!number) return false;
			if (!this.isDecimal(number)) return false;
			if (parseFloat(number) > 0) return true;
        },
        /*--------------------------------------------------------------------------*/
        isDecimal:function(number){// positive or negative decimal
                if(!number) return false;
                decimalRegExp = /^-?(0|[1-9]{1}\d{0,})(\.(\d{1}\d{0,}))?$/
                return decimalRegExp.test(number);
        },
        /*--------------------------------------------------------------------------*/
        isplatform:function(platform){
                //win, mac, nix
                if(!platform) return false;
                var os;
                winRegExp = /\win/i
                if(winRegExp.test(window.navigator.platform)) os = 'win';
                
                macRegExp = /\mac/i
                if(macRegExp.test(window.navigator.platform)) os = 'mac';
                
                nixRegExp = /\unix|\linux|\sun/i
                if(nixRegExp.test(window.navigator.platform)) os = 'nix';
                
                if(platform == os) return true;
                else return false;
        },
        /*--------------------------------------------------------------------------*/
        isFloatWithFormat: function(number){
			var malFormed = false;
			number = String(number);
			tmp = number.replace(/[.]/g,"");
			tmp = tmp.replace(/[,]/g,"");
			if (number.indexOf('-') != -1 && number.indexOf('-') != 0 ) malFormed = true;
			tmp = tmp.replace(/[-]/g,"");
			if (malFormed){ return false; } else { return this.isNum(tmp); }
        },
		/*--------------------------------------------------------------------------*/
        isPositiveFloatWithFormat: function(number){
			var malFormed = false;
			number = String(number);
			tmp = number.replace(/[.]/g,"");
			tmp = tmp.replace(/[,]/g,"");
			if (number.indexOf('-') != -1 && number.indexOf('-') != 0 ) malFormed = true;
			tmp = tmp.replace(/[-]/g,"");
			
			if (malFormed){ return false; } else { 
				if( this.isNum(tmp) ) { 
					number = String(number);
					tmp = number.replace(/[.]/g,"");
					tmp = tmp.replace(/[,]/g,".");
					return this.isPositiveDecimal(tmp);
				} else {
					return false;	
				}
			}
        },
        /*--------------------------------------------------------------------------*/
        isIntegerWithFormat: function(number){
			var malFormed = false;
			tmp = number.replace(/[.]/g,"");
			if (number.indexOf('-') != -1 && number.indexOf('-') != 0 ) malFormed = true;
			tmp = tmp.replace(/[-]/g,"");
			if (malFormed){ return false; } else { return this.isNum(tmp); }
        },
        /*--------------------------------------------------------------------------*/
        isFormulaCorte: function(number){
			
			var expresion;
			
			tmp = number.toUpperCase();
			
			tmp = tmp.replace(/[(]/g,"");
			tmp = tmp.replace(/[)]/g,"");
			
			tmp = tmp.replace(/[[]/g,"");
			tmp = tmp.replace(/[]]/g,"");

			tmp = tmp.replace(/[{]/g,"");
			tmp = tmp.replace(/[}]/g,"");

			tmp = tmp.replace(/[+]/g,"");
			tmp = tmp.replace(/[-]/g,"");
			tmp = tmp.replace(/[\/]/g,"");
			tmp = tmp.replace(/[*]/g,"");
			
			tmp = tmp.replace(/[ ]/g,"");
			
			// Parametros cargados	
			//alert("params "+this.parametros.lenght);
			for (x in this.parametros)
				{
				// Ej: expresion = /[A]/g
				expresion = new RegExp("["+this.parametros[x]+"]","g");		
				//alert(expresion);
				tmp = tmp.replace(expresion,"");
				}

			if (tmp != "") { return this.isFloatWithFormat(tmp); } else { return true;}
        },
		/*--------------------------------------------------------------------------*/
		isParametro: function(param){
			
			var letras = ['A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z'];
			var expresion;
			
			tmp = param.replace(/[ ]/g,"");
			
			for (x in letras)
				{
				// Ej: expresion = /[A]/g
				expresion = new RegExp("["+letras[x]+"]","g");				
				tmp = tmp.replace(expresion,"");
				}
			
			if (tmp == "") { return true; } else { return false; }
			
		},
		/*--------------------------------------------------------------------------*/
		isCreditCard: function(numero_tarjeta) {
			var cadena = numero_tarjeta.toString();
			var longitud = cadena.length-1;
			var k = 1;
			var suma = 0;
			var i = 0;

			for (i=longitud; i>=0; i--) {
				if (k%2) {
					cifra = parseInt(cadena.charAt(i));
				} else {
					cifra = parseInt(cadena.charAt(i))*2;
				}

				if (cifra > 9) {
					cifra_cad = cifra.toString();
					cifra = parseInt(cifra_cad.charAt(0)) + parseInt(cifra_cad.charAt(1));
				}

				suma = suma + cifra;
				k++;
			}

			if (((suma % 10) == 0) && suma <=150) {
				return true;
			} else {
				return false;
			}
		},
        /*--------------------------------------------------------------------------*/
        getValue:function(id){
                document.getElementById(id).value;
        },
        /*--------------------------------------------------------------------------*/
        addRule:function(rules){
			   // Código html pre-error
				if (this.preError != "" && typeof(this.preError) != "undefined") 
					{ 
					if (typeof(rules.required) != "undefined") rules.requiredMsg = this.preError + rules.requiredMsg;
					if (typeof(rules.validate) != "undefined") rules.validateMsg = this.preError + rules.validateMsg;
					if (typeof(rules.unique) != "undefined") rules.uniqueMsg = this.preError + rules.uniqueMsg;
					if (typeof(rules.validateFunction) != "undefined") rules.validateFunctionMsg = this.preError + rules.validateFunctionMsg;
					}
					
				// Agrega la regla de validación al array de reglas	
				this.rules_array.push(rules);
        },
		// agregar un metodo quitar regla para utilizar en tiempo real y validaciones dinámicas
        /*--------------------------------------------------------------------------*/
        removeRule:function(rules){
			   // Recorre y busca el id elegido
			   var index = '';
			   for(var i = 0; i < this.rules_array.length; i++) {
			   	if (this.rules_array[i].id == rules.id) {
			   		index = i;
			   	}
			   } 
				// Borra la regla de validación al array de reglas
				if (index != '')	
					this.rules_array.splice(index, 1);
        },
		// agregar un metodo quitar regla para utilizar en tiempo real y validaciones dinámicas
        /*--------------------------------------------------------------------------*/	
		check:function(rules){
				// Flag que controla si ocurrió algun error durante el chequeo de todos los elementos
				var check_error 		= false;  // false = Operación ok | true = Operación con errores
				var tmp_error_control 	= [];
				var tmp_error 			= [];
				
				// ************** RECORRIDO DE REGLAS DE VALIDACION **************
				for(i=0; i<rules.length; i++)
					{
					// Revalidación de uno o varios campos: Vacia todos los errores asociados a este id
					if (this.error_array.length > 0)
						{
						var cont = this.error_array.length;
						for(x=0; x<cont; x++) 
							{
							if (this.error_control_array[x] != rules[i].id) 
								{ 
								tmp_error_control.push(this.error_control_array[x]);
								tmp_error.push(this.error_array[x]);
								//this.error_array.splice(x,1);
								//this.error_control_array.splice(x,1);
								}
							}
						this.error_array 			= tmp_error;
						this.error_control_array 	= tmp_error_control;
						}
						
					// Elemento a analizar
					var field = document.getElementById(rules[i].id);
					
					// Flag que controla si en este elemento ocurrió algún error
					var field_error = false; 
						
						/*---------------------------[VALIDACION DE REQUERIDO]---------------------------*/
							if (typeof(rules[i].required) != "undefined" && rules[i].required) 
							{
							// Tipo de campos
							switch(field.type) 
								{
								
								/*-----------------------------------------------------------------*/
								case "select-one":
									// Comprueba si el valor actual coincide con el valor por default especificado en la regla
									defaultValue = false;
									if (typeof(rules[i].defaultValue) != "undefined") 
										{ 
										for(p=0; p<rules[i].defaultValue.length; p++)
											{
											if (rules[i].defaultValue[p] == field.value) defaultValue = true;
											}
										}
									
									if (field.options[0].selected || defaultValue) {   
										this.error_array.push(rules[i].requiredMsg);
										this.error_control_array.push(rules[i].id);
										field_error = true;
									}
								break;
								/*-----------------------------------------------------------------*/
								case "select-multiple":
									
									// Completar									
									
								break;
								/*-----------------------------------------------------------------*/
								case "radio":
									// Comprueba si tiene algún radio seleccionado
									elem_rb = document.getElementsByName(rules[i].id);
									var gotCheked = false;
									for (x=0;x< elem_rb.length ; x++) { 
										if (elem_rb[x].checked) gotCheked = true;
									} 

									if (!gotCheked) {   
										this.error_array.push(rules[i].requiredMsg);
										this.error_control_array.push(rules[i].id);
										field_error = true;
									}
								break;
								/*-----------------------------------------------------------------*/
								case "checkbox":
									if (!field.checked) {
										this.error_array.push(rules[i].requiredMsg);
										this.error_control_array.push(rules[i].id);
										field_error = true;
										}
								break;
								/*-----------------------------------------------------------------*/
								case "textarea":
									// Comprueba si el valor actual coincide con el valor por default especificado en la regla
									defaultValue = false;
									if (typeof(rules[i].defaultValue) != "undefined") if (rules[i].defaultValue == field.value) defaultValue = true;
									
									if (this.isEmpty(field.value) || defaultValue) {
											this.error_array.push(rules[i].requiredMsg);
											this.error_control_array.push(rules[i].id);
											field_error = true;
									}
								break;
								/*-----------------------------------------------------------------*/
								case "text":
									defaultValue = false;
									
									if (typeof(rules[i].defaultValue) != "undefined") 
										{ 
										for(p=0; p<rules[i].defaultValue.length; p++)
											{
											if (rules[i].defaultValue[p] == field.value) defaultValue = true;
											}
										}

									if (this.isEmpty(field.value) || defaultValue)
										{
										this.error_array.push(rules[i].requiredMsg);
										this.error_control_array.push(rules[i].id);
										field_error = true;
										}
								break;
								/*-----------------------------------------------------------------*/
								case "hidden":
									defaultValue = false;
									
									if (typeof(rules[i].defaultValue) != "undefined") 
										{ 
										for(p=0; p<rules[i].defaultValue.length; p++)
											{
											if (rules[i].defaultValue[p] == field.value) defaultValue = true;
											}
										}

									if (this.isEmpty(field.value) || defaultValue)
										{
										this.error_array.push(rules[i].requiredMsg);
										this.error_control_array.push(rules[i].id);
										field_error = true;
										}
								break;
								} // fin switch

							} // Fin validación de requerido
						/*-------------------------------------------------------------------------------*/
						
						/*------------------------[VALIDACION POR FUNCION EXTERNA]-----------------------*/
							if( typeof(rules[i].validateFunction) != "undefined") { 
								var result = "";
								result = rules[i].validateFunction(field);
								if (result) {
									// si devuelve String, tomo result como mensaje
									if (typeof(result)=='string')
										{ this.error_array.push(result); }
									else
										{ this.error_array.push(rules[i].validateFunctionMsg); }
									this.error_control_array.push(rules[i].id);
									field_error = true;	
								}
								
							}
						/*-------------------------------------------------------------------------------*/
						
						/*-----------------------------[VALIDACION DE CAMPO ÚNICO]---------------------------*/
							if( typeof(rules[i].unique) != "undefined") { 
								var id			= field.id;
								var flagError 	= false;
								
								// Recorro todos los campos del array y compruebo que ninguno tenga el mismo valor que este
								
								// Obtengo el indice del campo
									if (id.lastIndexOf("]") !=  -1) fin = id.lastIndexOf("]");
									if (id.lastIndexOf("[",fin) ) ini = id.lastIndexOf("[",fin);
																						 
									if (fin != null && rules[i].array) 
										{
										index = id.substr(ini+1,(fin - ini)-1); 
										id = id.replace("["+index+"]","");
										}
								
								
								// Multiple formularios (Arrays)
								var cant_fields = 0;
								var actual = 0;
								var last = 0;
								var ids = new Array();
								var values = new Array();
								
								// Búsqueda por presición para obtener la cantidad de campos y los ids correspondientes
								while ( actual - last < this.pres )
									{
									tmpField = document.getElementById(id+'['+actual+']');
									if (tmpField != null) 
										{ 
										ids[cant_fields] = actual;
										values[cant_fields] = tmpField.value;
										
										if (field.value == tmpField.value &&  field.id != tmpField.id )
											{ 
											flagError = true;
											}
										
										// /*DEBUG*/ alert("ID: "+ids[cant_fields]+"| VALUE: "+values[cant_fields]);
										cant_fields++; 
										last = actual; 
										}
									actual++;
									}	
								
								if (flagError) {
									field_error = true;
									this.error_array.push(rules[i].uniqueMsg);
									this.error_control_array.push(rules[i].id);
									}
								}
						/*-------------------------------------------------------------------------------*/
						
						
						/*-----------------------------[VALIDACION POR REGLAS]---------------------------*/
							defaultValue = false;
							if (typeof(rules[i].defaultValue) != "undefined") if (rules[i].defaultValue == field.value) defaultValue = true;
							if( typeof(rules[i].validate) != "undefined" && this.isNotEmpty(field.value) && !defaultValue) {
								// Flag que indica si esta validación especifica da o no algun error	
								var flag_validate = false; 
								
								switch(rules[i].validate) {
									/*--------------------------------------------------------------------------*/
										case'ValidChars':
											if( !this.hasValidChars(field.value, rules[i].chars, false) ) flag_validate = true;
										break;
										/*--------------------------------------------------------------------------*/
										case'AlphaLatin':
											if ( this.isAlphaLatin(field.value) ) flag_validate = true;
										break;
										/*--------------------------------------------------------------------------*/
										case'integerRange':
											if ( !this.isIntegerInRange(field.value, rules[i].Min, rules[i].Max) ) flag_validate = true;
										break;
										/*--------------------------------------------------------------------------*/
										case'floatRange':
											if ( !this.isFloatInRange(field.value, rules[i].Min, rules[i].Max) ) flag_validate = true;
										break;
										/*--------------------------------------------------------------------------*/
										case'Number':
											if ( !this.isNum(field.value) ) flag_validate = true;
										break;
										/*--------------------------------------------------------------------------*/
										case'positiveNumber':
											if ( !this.isPositiveNum(field.value) ) flag_validate = true;
										break;										
										/*--------------------------------------------------------------------------*/
										case'integerWithFormat':
											if ( !this.isIntegerWithFormat(field.value) ) flag_validate = true;
										break;
										/*--------------------------------------------------------------------------*/
										case'notNumber':
											if ( this.isNum(field.value) ) flag_validate = true;
										break;
										/*--------------------------------------------------------------------------*/
										case'email':
											if ( !this.isEMailAddr(field.value) ) flag_validate = true;
										break;
										/*--------------------------------------------------------------------------*/
										case'zipCode':
											if ( !this.isZipCode(field.value,rules[i].country) ) flag_validate = true;
										break;
										/*--------------------------------------------------------------------------*/
										case'date':
											if( !this.isDate(field.value,rules[i].format) ) flag_validate = true;
										break;
										/*--------------------------------------------------------------------------*/
										case'url':
											if( !this.isURL(field.value) ) flag_validate = true;
										break;
										/*--------------------------------------------------------------------------*/
										case'positiveDecimal':
											if( !this.isPositiveDecimal(field.value) ) flag_validate = true;
										break;
										/*--------------------------------------------------------------------------*/
										case'Decimal':
											if( !this.isDecimal(field.value) ) flag_validate = true;
										break;
										/*--------------------------------------------------------------------------*/
										case'floatWithFormat':
											if( !this.isFloatWithFormat(field.value) ) flag_validate = true;
										break;
										/*--------------------------------------------------------------------------*/
										case'positiveFloatWithFormat':
											if( !this.isPositiveFloatWithFormat(field.value) ) flag_validate = true;
										break;
										/*--------------------------------------------------------------------------*/
										case'formulaCorte':
											if( !this.isFormulaCorte(field.value) ) flag_validate = true;
										break;
										/*--------------------------------------------------------------------------*/
										case'parametro':
											if( !this.isParametro(field.value) ) flag_validate = true;
										break;
										/*--------------------------------------------------------------------------*/
										case'creditCard':
										 if( !this.isCreditCard(field.value) ) flag_validate = true;
										break;
									} //fin switch
								
								if (flag_validate)
									{ 
									this.error_array.push(rules[i].validateMsg);
									this.error_control_array.push(rules[i].id);
									field_error = true;
									}
	
							} // fin validacion especifica
						/*-------------------------------------------------------------------------------*/
						
						// Activa o desactiva los mensajes de error para esta campo
						if(this.showFieldErrors || this.focusFieldErrors) this.refreshFieldErrorMsg(field,field_error);
						if(this.showSummary) this.refreshSummary();
						
						// Si algún elemento tiene errores entonces la operación de chequeo devolverá false
						// Si todos los field_error son false entonces check_error será false también y la operacion devolverá true
						if(field_error) check_error = field_error;
					
                	} // Fin del for de reglas de validación
					return check_error;
        },
		/*--------------------------------------------------------------------------*/
		 refreshFieldErrorMsg:function(field,show){
				var id = field.id; // Id del objeto
				var val = document.getElementById(id+'_validator_class_msg'); // Tag con el mensaje de validación
				
				// Crea el <SPAN> si no está creado
				if (val == null)
					{
					// Crea un span junto al objeto
					var span = document.createElement('span');
					span.setAttribute('id',id+'_validator_class_msg');
					span.setAttribute('class',this.errorStyle);
					field.parentNode.appendChild(span);
					}
				// Vuelve a tomar el tag validador una vez que ya fue creado
				val = document.getElementById(id+'_validator_class_msg');

				// Arma el array temporal con los errores del campo especifico
				var tmp_array = [];
				for(y=0; y<this.error_array.length; y++)
					{
					if(this.error_control_array[y] == id) tmp_array.push(this.error_array[y]);
					}
					
				// Muestra u oculta el mensaje de error
				switch(field.type) {
					/*-------------------------------------------------------------------------------*/
					case "text":
						if(show) { 
						 	if (this.focusFieldErrors) field.className = this.styles.error.text;
							if (this.showFieldErrors) val.innerHTML = "<span class='"+this.errorStyle+"' ><br>"  +tmp_array.toString().replace(/\,/gi,"<br/>")+  "</span>"; }
						else{ 
							if (this.focusFieldErrors) field.className = this.styles.valid.text; 
							if (this.showFieldErrors) val.innerHTML = "";
						}
					break;
					/*-------------------------------------------------------------------------------*/
					case "select-one":
						if(show) { 
							if (this.focusFieldErrors) field.className = this.styles.error.select_one; 
							if (this.showFieldErrors) val.innerHTML = "<span class='"+this.errorStyle+"' ><br>"  +tmp_array.toString().replace(/\,/gi,"<br/>")+  "</span>"; }
						else { 
							if (this.focusFieldErrors) field.className = this.styles.valid.select_one; 
							if (this.showFieldErrors) val.innerHTML = ""; 
						}
					break;
					
					/*-------------------------------------------------------------------------------*/
					case "select-multiple":
						if(show) { 
							if (this.focusFieldErrors) field.className = this.styles.error.select_multiple; 
							if (this.showFieldErrors) val.innerHTML = "<span class='"+this.errorStyle+"' ><br>"  +tmp_array.toString().replace(/\,/gi,"<br/>")+  "</span>"; 
						}
						else { 
							if (this.focusFieldErrors) field.className = this.styles.valid.select_multiple; 
							if (this.showFieldErrors) val.innerHTML = ""; 
						}
					break;
					/*-------------------------------------------------------------------------------*/
					case "radio":
						if(show) { 
							if (this.focusFieldErrors) {
							elem_rb = document.getElementsByName(field.id);
							for (x=0;x< elem_rb.length ; x++) elem_rb[x].className = this.styles.error.radio; 
							}
							
							if (this.showFieldErrors) val.innerHTML = "<span class='"+this.errorStyle+"' ><br>"  +tmp_array.toString().replace(/\,/gi,"<br/>")+  "</span>";
						}
						else { 
							
							if (this.focusFieldErrors){
							elem_rb = document.getElementsByName(field.id);
							for (x=0;x< elem_rb.length ; x++) elem_rb[x].className = this.styles.valid.radio;
							}
							
							if (this.showFieldErrors) val.innerHTML = "";
						}
					break;
					/*-------------------------------------------------------------------------------*/
					case "checkbox":
						if(show) { 
							if (this.focusFieldErrors) field.className = this.styles.error.checkbox; 
							if (this.showFieldErrors) val.innerHTML = "<span class='"+this.errorStyle+"' ><br>"  +tmp_array.toString().replace(/\,/gi,"<br/>")+  "</span>"; 
						}
						else { 
							if (this.focusFieldErrors) field.className = this.styles.valid.checkbox; 
							if (this.showFieldErrors) val.innerHTML = ""; 
						}
					break;
					/*-------------------------------------------------------------------------------*/
					case "textarea":
						if(show) { 
							if (this.focusFieldErrors) field.className = this.styles.error.textarea; 
							if (this.showFieldErrors) val.innerHTML = "<span class='"+this.errorStyle+"' ><br>"  +tmp_array.toString().replace(/\,/gi,"<br/>")+  "</span>"; 
							}
						else { 
							if (this.focusFieldErrors) field.className = this.styles.valid.textarea; 
							if (this.showFieldErrors) val.innerHTML = ""; 
						}
					break;
					/*-------------------------------------------------------------------------------*/
					case "file":
						if(show) { 
							if (this.focusFieldErrors) field.className = this.styles.error.file; 
							if (this.showFieldErrors) val.innerHTML = "<span class='"+this.errorStyle+"' ><br>"  +tmp_array.toString().replace(/\,/gi,"<br/>")+  "</span>"; }
						else { 
							if (this.focusFieldErrors) field.className = this.styles.valid.file; 
							if (this.showFieldErrors) val.innerHTML = ""; 
						}
					break;
					/*-------------------------------------------------------------------------------*/
				}
		 },
		/*--------------------------------------------------------------------------*/
		refreshSummary:function() {
			var summ = document.getElementById(this.summary); // Summary object
			
			if (summ != null) {
			
				// Titulo del resumen de errores
				if (this.summaryTitle) { summ.innerHTML = this.summaryTitle; }
				else { summ.innerHTML = ""; }
						
				// Short summary
				if (this.shortSummary) {
					summ.innerHTML = this.summaryText;
				}else {
					// Recumen de errores
					summ.innerHTML = summ.innerHTML + this.error_array.toString().replace(/\,/gi,"<br/>");
				}
							
				// Muestra u oculta el resumen de errores
				if (this.error_array.length != 0) { summ.style.display = ""; } else { summ.style.display = "none"; }
			}
		},
        /*--------------------------------------------------------------------------*/
        validateFields:function(){
			// Revalidación completa: Vacia todos los errores
			this.error_array = [];
			this.error_control_array = [];
			var opState = true;

			for(o=0; o<this.rules_array.length; o++) 
				{ 
				state = this.validateField(this.rules_array[o].id);
				if (!state) opState = false;
				}
			return opState;
        },
        /*--------------------------------------------------------------------------*/
        validateField:function(id){
			var rules 	= new Array;
			var fin 	= null;
			var ini 	= null;
			var index 	= null;
			var pos 	= -1;
			var isArray = false;
			
			
			// Obtiene el id y la posición dentro de las reglas de validación
			if (typeof(id) != "undefined" && typeof(id) == "string" && id != "" ) 
				{
				// Obtiene la posición del campo pasado en el array de reglas siempre y cuando no sea un array
				for(x=0; x<this.rules_array.length; x++) 
					{ 
					if (this.rules_array[x].id == id && typeof(this.rules_array[x].array) == "undefined" ) { pos=x; isArray = false; }
					}
				
				// Si no pudo encontrar concordancia comprueba con arrays
				if (pos == -1)
					{
					// Detecta si es o no array el campo comparando su id quitando el contador de ids del array 
					// ej: si el campo es id_familia[0] comparará con las reglas de id_familia para ver si es array 
					if (id.lastIndexOf("]") !=  -1) fin = id.lastIndexOf("]");
					if (id.lastIndexOf("[",fin) ) ini = id.lastIndexOf("[",fin);
																		 
					if (fin != null) 
						{
						index = id.substr(ini+1,(fin - ini)-1); 
						id = id.replace("["+index+"]","");
						}
					
					// Vuelve a comprobar
					for(x=0; x<this.rules_array.length; x++)
						{
						if (this.rules_array[x].id == id && this.rules_array[x].array) { pos=x; isArray = true; }
						}
					}
				}
			
			if ( pos != -1 ) {
				// Array
				if(isArray) {

				// Multiple formularios (Arrays)
				var cant_fields = 0;
				var actual = 0;
				var last = 0;
				var ids = new Array();
				
				// Búsqueda por presición para obtener la cantidad de campos y los ids correspondientes
				while ( actual - last < this.pres )
					{
					field = document.getElementById(this.rules_array[pos].id+'['+actual+']');
					if (field != null) 
						{ 
						ids[cant_fields] = actual;
						cant_fields++; 
						last = actual; 
						}
					actual++;
					}
				
				// Si index es != null entonces no es una validacion completa
				if (index != null) 
					{
					cant_fields = 1;
					ids[0] = index;
					}
				
				
				// Creación de las reglas adaptadas
				var baseid = this.rules_array[pos].id;
				var newObj = [];

				for(x=0; x<cant_fields; x++) {
					// Clona el objeto y luego acualiza el id
					newObj = new this.cloneObject(this.rules_array[pos]);
					rules.push(newObj);
					rules[x].id = rules[x].id + "["+ids[x]+"]";
					}
					
				} else {
					rules[0] = this.rules_array[pos];
				}
			}
			
			return !this.check(rules);
        },
		/*--------------------------------------------------------------------------*/
		cloneObject:function(what){
			for (i in what) this[i] = what[i];

		},
		/*--------------------------------------------------------------------------*/
		addEvent: function(elmId, evType, fn, useCapture) {
				var elm = document.getElementById(elmId);
				
				if ( elm != null ) {
				
					if (elm.addEventListener) {
						elm.addEventListener(evType, fn, useCapture);
						return true;
					}
					else if (elm.attachEvent) {
						var r = elm.attachEvent('on' + evType, fn);
						return r;
					}
					else {
						elm['on' + evType] = fn;
					}
				}
		}
		
		
}

