/**
 * @fileoverview Esta clase sirve para validar entradas de formularios
 * creados con HTML. 
 *
 * @author Gilberto Leon leon.gilberto@gmail.com
 * @version 1.3
 */
 
/**
 * Construye un nuevo objeto validadorDeFormas.
 * @class La clase se compone de varios métodos que sirven para validar
 * diversos tipos de entradas en un formulario.
 * @constructor
 */
function validadorDeFormas(id)
{
	this.forma=id;
	this.listaDeErrores = new Array;
	this.cadenaAlfabetica= /^[a-zA-ZáÁéÉíÍóÓúÚñÑ]+[.]?([ |-]?[a-zA-ZáÁéÉíÍóÓúÚñÑ]+[.]?)*$/;
	this.cadenaAlfaNumerica=/^[0-9a-zA-ZáÁéÉíÍóÓúÚñÑ]+[.]?([ |-]?[0-9a-zA-ZáÁéÉíÍóÓúÚñÑ]+[.]?)*$/;
	this.cadenaEmail=/^([a-zA-Z0-9])+([.a-zA-Z0-9_-])*@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-]+)+/;
	this.cadenaTelefonica=/^[0-9\s\(\)\+\-]+$/;
	this.cadenaNumerica=/^[0-9]+$/;
	this.numeroEntero=/^[-]?[0-9]+$/;
	this.numeroEnteroPositivo=/^[0-9]+$/;
	this.numeroFlotante=/^[-]?[0-9]*[.]?[0-9]+$/;
	this.numeroFlotantePositivo=/^[0-9]*[.]?[0-9]+$/;
	this.mensajeCadenaAlfabeticaNoValida='Sólo acepta letras, espacios, guiones y guiones bajos.';
	this.mensajeCadenaVacia='No puede quedar vacío.';
	this.mensajeCadenaAlfaNumericaNoValida='Sólo acepta letras, números, espacios, guiones y guines bajos.';
	this.mensajeCadenaEmailNoValida='Sólo acepta direcciones de correo electrónico válidas.';
	this.mensajeCadenaTelefonicaNoValida='Sólo acepta números telefónicos válidos.';
	this.mensajeCadenaNumericaNoValida='Sólo acepta números.';
	this.mensajeCadenaEnteroNoValida='Sólo acepta números enteros.';
	this.mensajeCadenaEnteroPositivoNoValida='Sólo acepta números enteros mayores a cero.';
	this.mensajeCadenaFlotanteNoValida='Sólo acepta números con un punto decimal.';
	this.mensajeCadenaFlotantePositivoNoValida='Sólo acepta números positivos con un punto decimal.';
	this.mensajeCadenaRangoNoValido='Sólo acepta valores entre {min} y {max}.';
	this.mensajeCadenaLargoNoValido='Sólo acepta entre {min} y {max} caracteres.';
	this.mensajeNoHaElegido='No ha elegido una opción.'
	this.limpiaErrores=limpiaErrores;
	this.agregaError=agregaError;
	this.esAlfabetico = esAlfabetico;
	this.estaVacio = estaVacio;
	this.esAlfaNumerico = esAlfaNumerico;
	this.esEmail = esEmail;
	this.esTelefonico=esTelefonico;
	this.esNumero = esNumero;
	this.esNumerico=esNumerico;
	this.esEntero=esEntero;
	this.esEnteroPositivo=esEnteroPositivo;
	this.esOpcion=esOpcion;
	this.esFlotante=esFlotante;
	this.esFlotantePositivo=esFlotantePositivo;
	this.estaDentroDelRango = estaDentroDelRango;
	this.esDeLargo=esDeLargo;
	this.numeroDeErrores = numeroDeErrores;
	this.hayErrores=hayErrores;
	this.despliegaErrores = despliegaErrores;
	this.agregaErrorInterno=agregaErrorInterno;
	this.muestraErrores=muestraErrores;
	this.esHora=esHora;
	this.mensajeHoraNoValida='No es una hora válida.';
}
/**
 * Limpia los elementos marcados como error en la página.
 */
function limpiaErrores()
{
	var elementos = document.getElementsByClassName('error');
	for(i=0; i<elementos.length; i++)
		elementos[i].remove();
	var elementos = document.getElementsByClassName('highlight');
	for(i=0; i<elementos.length; i++)
		elementos[i].removeClassName('highlight');
	Behaviour.apply();
}

/**
 * Agrega un mensaje de error al documento.
 * @param (String) nombre El campo sobre el que se reporta el error.
 * @param (String) mensaje Es el mensaje a agregar.
 */

function agregaError(nombre,mensaje)
{
	this.agregaErrorInterno(mensaje);
	campo=$(nombre).parentNode
	var br = document.createElement('br');
	var span = document.createElement('span');
	var mensaje = document.createTextNode(mensaje);
	Element.addClassName(span,'error');
	Element.addClassName(br,'error');
	campo.appendChild(br);
	campo.appendChild(span);
	span.appendChild(mensaje);	
	if (!Element.hasClassName(campo,'highlight'))
		Element.addClassName(campo,'highlight');
	Behaviour.apply();
}

/**
 * Revisa si la entrada en un campo contiene una cadena alfabética.
 * @param (String) nombre Es el nombre del campo del formulario a validar.
 * @param (Bool) requerido Si el campo es obligatorio o no.
 */
function esAlfabetico(nombre,requerido)
{
	if (requerido==null)
		requerido=false;
	else
		requerido=true;
	valor=$F(nombre).strip();
	if (requerido==true)
		this.estaVacio(nombre);
	if (valor!='')
		if(!valor.match(this.cadenaAlfabetica))
				this.agregaError(nombre,this.mensajeCadenaAlfabeticaNoValida);
}

/**
 * Revisa si la entrada en un campo contiene algún valor.
 * @param (String) nombre Es el nombre del campo del formulario a validar.
 */
function estaVacio(nombre)
{
	if ($F(nombre).strip()=="")
		this.agregaError(nombre,this.mensajeCadenaVacia);
}

/**
 * Revisa si la entrada en un campo contiene es una cadena formada por caracteres alfanuméricos.
 * @param (String) nombre Es el nombre del campo del formulario a validar.
 * @param (Bool) requerido Si el campo es obligatorio o no.
 */
function esAlfaNumerico(nombre,requerido)
{
	if (requerido==null)
		requerido=false;
	else
		requerido=true;
	valor=$F(nombre).strip();
	if (requerido==true)
		this.estaVacio(nombre);
	if (valor!='')
		if(!valor.match(this.cadenaAlfaNumerica))
				this.agregaError(nombre,this.mensajeCadenaAlfaNumericaNoValida);
}

/**
 * Revisa si la entrada en un campo contiene una dirección de e-mail válida.
 * @param (String) nombre Es el nombre del campo del formulario a validar.
 * @param (Bool) requerido Si el campo es obligatorio o no.
 */
function esEmail(nombre,requerido)
{
	if (requerido==null)
		requerido=false;
	else
		requerido=true;
	valor=$F(nombre).strip();
	if (requerido==true)
		this.estaVacio(nombre);
	if (valor!='')
		if(!valor.match(this.cadenaEmail))
			this.agregaError(nombre,this.mensajeCadenaEmailNoValida);
}

/**
 * Revisa si la entrada en un campo es un número telefónico válido.
 * @param (String) nombre Es el nombre del campo del formulario a validar.
 * @param (Bool) requerido Si el campo es obligatorio o no.
 */
function esTelefonico(nombre,requerido)
{
	if (requerido==null)
		requerido=false;
	else
		requerido=true;
	valor=$F(nombre).strip();
	if (requerido==true)
		this.estaVacio(nombre);
	if (valor!='')
		if(!valor.match(this.cadenaTelefonica))
			this.agregaError(nombre,this.mensajeCadenaTelefonicaNoValida);
}

/**
 * Revisa si la entrada en un campo contiene un valor numérico.
 * @param (String) nombre Es el nombre del campo del formulario a validar.
 * @param (Bool) requerido Si el campo es obligatorio o no.
 */
function esNumero(nombre,requerido)
{
	if (requerido==null)
		requerido=false;
	else
		requerido=true;
	valor=$F(nombre).strip();
	if (requerido==true)
		this.estaVacio(nombre);
	if (valor!='')
		if (isNaN(val))
			this.agregaError(nombre,this.mensajeCadenaNumericaNoValida);
}


/**
 * Revisa si la entrada en un campo es una cadena numérica válida.
 * @param (String) nombre Es el nombre del campo del formulario a validar.
 * @param (Bool) requerido Si el campo es obligatorio o no.
 */
function esNumerico(nombre,requerido)
{
	if (requerido==null)
		requerido=false;
	else
		requerido=true;
	valor=$F(nombre).strip();
	if (requerido==true)
		this.estaVacio(nombre);
	if (valor!='')		
		if(!valor.match(this.cadenaNumerica))
			this.agregaError(nombre,this.mensajeCadenaNumericaNoValida);
}

/**
 * Revisa si la entrada en un campo es un número entero.
 * @param (String) nombre Es el nombre del campo del formulario a validar.
 * @param (Bool) requerido Si el campo es obligatorio o no.
 */
function esEntero(nombre,requerido)
{
	if (requerido==null)
		requerido=false;
	else
		requerido=true;
	valor=$F(nombre).strip();
	if (requerido==true)
		this.estaVacio(nombre);
	if (valor!='')		
		if(!valor.match(this.numeroEntero))
			this.agregaError(nombre,this.mensajeCadenaEnteroNoValida);
}

/**
 * Revisa si la entrada en un campo es un número entero positivo.
 * @param (String) nombre Es el nombre del campo del formulario a validar.
 * @param (Bool) requerido Si el campo es obligatorio o no.
 */
function esEnteroPositivo(nombre,requerido)
{
	if (requerido==null)
		requerido=false;
	else
		requerido=true;
	valor=$F(nombre).strip();
	if (requerido==true)
		this.estaVacio(nombre);
	if (valor!='')
		if (!valor.match(this.numeroEnteroPositivo))
			this.agregaError(nombre,this.mensajeCadenaEnteroPositivoNoValida);
}

/**
 * Revisa si la entrada en un campo contiene algún valor.
 * @param (String) nombre Es el nombre del campo del formulario a validar.
 */
function esOpcion(nombre)
{
	if ($F(nombre).strip()=="")
		this.agregaError(nombre,this.mensajeNoHaElegido);
}

/**
 * Revisa si la entrada en un campo es un número flotante.
 * @param (String) nombre Es el nombre del campo del formulario a validar.
 * @param (Bool) requerido Si el campo es obligatorio o no.
 */
function esFlotante(nombre,requerido)
{
	if (requerido==null)
		requerido=false;
	else
		requerido=true;
	valor=$F(nombre).strip();
	if (requerido==true)
		this.estaVacio(nombre);
	if (valor!='')
		if(!valor.match(this.numeroFlotante))
			this.agregaError(nombre,this.mensajeCadenaFlotanteNoValida);
}

/**
 * Revisa si la entrada en un campo es un número flotante positivo.
 * @param (String) nombre Es el nombre del campo del formulario a validar.
 * @param (Bool) requerido Si el campo es obligatorio o no.
 */
function esFlotantePositivo(nombre,requerido)
{
	if (requerido==null)
		requerido=false;
	else
		requerido=true;
	valor=$F(nombre).strip();
	if (requerido==true)
		this.estaVacio(nombre);
	if (valor!='')
		if(!valor.match(this.numeroFlotantePositivo))
			this.agregaError(nombre,this.mensajeCadenaFlotantePositivoNoValida);
}

/**
 * Revisa si la entrada en un campo está dentro de un valor mínimo y uno máximo.
 * @param (String) nombre Es el nombre del campo del formulario a validar.
 * @param (int) min Es el valor mínimo al que se compara el campo.
 * @param (int) max Es el valor máximo al que se compara el campo. 
*/
function estaDentroDelRango(nombre, min, max)
{
	valor=$F(nombre).strip();
	if ((valor<min)||(valor>max))
	{
		var mensaje=this.mensajeCadenaRangoNoValido;
		mensaje=mensaje.replace('{min}',min);
		mensaje=mensaje.replace('{max}',max);
		this.agregaError(nombre,mensaje);
	}
}

/**
 * Revisa si la entrada tiene una largo entre un valor mínimo y uno máximo.
 * @param (String) nombre Es el nombre del campo del formulario a validar.
 * @param (int) minimo Es la longitud mínimo del campo.
 * @param (int) maximo Es la longitud máxima del campo. 
*/
function esDeLargo(nombre,minimo,maximo)
{
	valor=$F(nombre).strip();
	if ((valor.length<minimo)||(valor.length>maximo))
	{
		var mensaje=this.mensajeCadenaLargoNoValido;
		mensaje=mensaje.replace('{min}',minimo);
		mensaje=mensaje.replace('{max}',maximo);
		this.agregaError(nombre,mensaje);
	}
}

/**
 * Regresa el número de errores en la lista de errores.
 * Esta función se invoca desde despliegaErrores().
 * @returns El número de errores en la lista de errores.
*/
function numeroDeErrores()
{
	return this.listaDeErrores.length;
}

/**
 * Dice si hay errores o no.
 * @returns true si hay errores, false si no los hay.
*/
function hayErrores()
{
	var flag=false;
	if (this.numeroDeErrores() > 0)
	{
		flag=true;
		var campos=Form.getElements(this.forma);	
		if (campos.length>0)
		{
			var detener=false;
			campos=$A(campos);
			campos.each(function(elemento){if (!detener){if (Element.hasClassName(elemento.parentNode,'highlight')){Form.Element.focus(elemento);detener=true;}}});
		}
	}
	return flag;
}

/**
 * Regresa la lista de errores.
 * Esta función se invoca desde despliegaErrores().
 * @returns Una cadena con los errores en la forma llenada.
*/
function despliegaErrores()
{
	listaerrores="La forma llenada presenta los siguientes errores:\n\n";
	for (x=0; x<this.listaDeErrores.length; x++)
	{
		listaerrores=listaerrores+this.listaDeErrores[x]+"\n";
	}
	listaerrores=listaerrores+"\nPor favor, corríjalos antes de volver a enviarla."
	return (listaerrores);
}

/**
 * Despliega un mensaje de alerta conteniendo la lista de errores.
 * @returns 0 si hay errores, 1 si no los hay.
*/
function muestraErrores()
{
	if (this.numeroDeErrores() > 0)
	{
		alert(this.despliegaErrores());
		return false;
	}
	else
		return true;
}

/**
 * Agrega un mensaje de error a la lista de errores a reportar.
 * @param (String) msg Es el mensaje a agregar a la lista.
 */
function agregaErrorInterno(msg)
{
	this.listaDeErrores[this.listaDeErrores.length] = msg;
}

/**
 * Revisa si la entrada en un campo es una hora válida.
 * @param (String) nombre Es el nombre del campo del formulario a validar.
 * @param (Bool) requerido Si el campo es obligatorio o no.
 */
function esHora(nombre,requerido)
{
	var mensaje=this.mensajeHoraNoValida;
	if (requerido==null)
		requerido=false;
	else
		requerido=true;
	valor=$F(nombre).strip();
	if (requerido==true)
		this.estaVacio(nombre);
	if (valor!='')
	{
		var hora=valor.split(':');
		var error=false;
		if (hora.length==2)
		{
			var h=parseInt(hora[0]);
			var m=parseInt(hora[1]);
			if ((h<0)||(h>24))
				error=true;
			if ((m<0)||(m>59))
				error=true;			
			if (error)
				this.agregaError(nombre,mensaje);
		}
		else
			this.agregaError(nombre,mensaje);		
	}
}
