/*  Tecknosfera DBNET S.L.
	Element: LIB Form Validation
	Programed by: francisco_javier_martinez@hotmail.com
	To : Tecknosfera DBNET S.L.
*/

/*
	Formato de un campo configurado del formulario
	ID = nombre_del_campo:OB:Tipo_de_dato
*/

/*
	REFERENCIA RAPIDA DE OPCIONES
	
	Opcion		Formato						Caracteres		Tamaño
	number										[0-9]
	text
	CP											[0-9]				5
	email		xxx@xxx.com	
	image		.jpg .gif .jpeg .png
	document	.pdf .dov
	audio		.mp3 .wav
	video		.wmv .mov .avi .mpeg
	jpg			.jpg
	gif			.gif
	png			.png
	pdf			.pdf
	pdf-jpg		.pdf .jpg
	phone										[0-9]				12
	price		xx.xx xx,xx						[0-9][.,]			6
	
*/


// Clase Current Form
function LIB_forms_validation()
{
	// Objeto Público de definición de tipos de datos y sus longitudes
	this.lengthTypes = new Object();
	this.lengthTypes["cp"] = 5;
	this.lengthTypes["phone"] = 12;
	this.lengthTypes["price"] = 6;
	this.lengthTypes["dni"] = 9;

	// Elemento separador de atributos en los campos del formulario
	this.configSeparator = ":";
	
	// Vector donde guardamos los elementos MAL RELLENOS del formulario
	var arrayBadElements = new Array(); // Este objeto consta de: Nombre del campo mal relleno
										//                        Su posición en el formulario
										// 						  El mensaje correspondiente al tipo de dato validado

	// Objeto que define el formato en que se mostrará el error de los campos
	var error = new Object();
	error.type = new Object();
	error.type["makeAlert"] = new Object();
	error.type["makeAlert"].activate = true;

	error.type["remarkFields"] = new Object();
	error.type["remarkFields"].activate = true;
	error.type["remarkFields"].borderFieldSelected = "1px solid #FF0000";
	error.type["remarkFields"].borderInitial = "1px solid #F7E48E";
										
	// variable de control de la cantidad de elementos mal rellenos
	var countBadElements = -1;
		
	// Función para validar los campos del formulario
	this.validateForm = function(formNumber)
	{
		if (!formNumber)
		{
			formNumber = 0;
		}

		// Limpiamos los errores guardados de anteriores ejecuciones
		cleanErrors(formNumber);
		var validate = false;
		for(var contElements = 0;contElements < document.forms[formNumber].length;contElements++)
		{
			validate = false;
			var actualElement = document.forms[formNumber].elements[contElements]
			// Si el elemento que recorremos NO ES UN BOTON
			if(actualElement.type.toLowerCase() != "button" && actualElement.type.toLowerCase() != "submit")
			{
				if (actualElement.type.toLowerCase() == "hidden")
				{
					if (actualElement.id.indexOf(":") != -1)
					{
						validate = true;
					}
				}
				else
				{
					validate = true;
				}
				
				if (validate == true)
				{
					// Si el elemento actual está accesible (visible y enabled)
					if (actualElement.disabled == false)
					{
						// SI el elemento Actual es OBLIGATORIO
						if(actualElement.id.split(LIB_forms_validation.configSeparator)[1] == "OB")
						{
							validateElement(contElements,actualElement.id.split(LIB_forms_validation.configSeparator)[0].replace(/_/g," ") , actualElement.id.split(LIB_forms_validation.configSeparator)[2], actualElement.value);
						}
						else // si no es obligatorio, pero tiene contenido, lo validamos
						{
							if(actualElement.id.split(LIB_forms_validation.configSeparator)[1] == "NO" && actualElement.value != "")
							{
								validateElement(contElements,actualElement.id.split(LIB_forms_validation.configSeparator)[0].replace(/_/g," ") , actualElement.id.split(LIB_forms_validation.configSeparator)[2], actualElement.value);
							}
						}
					}
				}
			}
		}
		
		// Comprobamos si hay errores en el formulario
		if(arrayBadElements.length > -1 && arrayBadElements[0])
		{
			// Mostramos los errores
			showFormErrors(formNumber);
			return(false);
		}
		else
		{
			if (arguments[1])
			{
				document.forms[formNumber].submit();
			}
			else
			{
				return(true);
			}
		}
	}
	
	// Function to clear all form elements values
	this.clearForm = function(objReferer)
	{
		var actualForm = LIB_forms_validation.foundForm(objReferer);
		if (actualForm)
		{
			for(var contElements = 0;contElements < actualForm.length;contElements++)
			{
				var actualElement = actualForm.elements[contElements]
				// Si el elemento que recorremos NO ES UN BOTON
				if(actualElement.type.toLowerCase() != "button" && actualElement.type.toLowerCase() != "submit" && actualElement.type.toLowerCase() != "reset" && actualElement.type.toLowerCase() != "hidden")
				{
					switch (actualElement.type.toLowerCase())
					{
						case "checkbox":
							actualElement.checked = false;
						case "radio":
							actualElement.checked = false;
						case "select-one":
							actualElement.selectedIndex = 0;
						case "select-multiple":
							actualElement.selectedIndex = -1;
						break;
						
						default:
							actualElement.value = "";
					}
				}
			}
		}
	}
	
	// PRIVATE FUNCTIONS
	
	// Función que valida el campo segun su tipo de dato.
	function validateElement(positionInForm, nameElement, typeElement, valueElement)
	{
		var validate = true;
		// Si el elemento pasado como parámetro está vacio...
		if(valueElement == "" || valueElement == -1)
		{
			setError(getContBadElement(nameElement), nameElement, positionInForm, "Rellene el campo");
		}
		else
		{
			try
			{
				if (defaultValues != null && defaultValues != "undefined")
				{
					if (valueElement.toLowerCase() == defaultValues[positionInForm].toLowerCase())
					{
						setError(getContBadElement(nameElement), nameElement, positionInForm, "Rellene el campo");
						validate = false;
					}
				}
			}
			catch (exception)
			{
			
			}
			if (validate == true)
			{
				// Validamos el TIPO del campo
				switch(typeElement.toLowerCase())
				{
					case "cp":
						if(!valueElement.match("([0-9]){1,5}"))
						{
							setError(getContBadElement(nameElement), nameElement, positionInForm, "Mal formato en el campo");
						}
					break;
					case "email":
						if(!valueElement.match("([a-z0-9]){2,}(@)([a-z0-9\-]){2,}(\.)([a-z]){2,}"))
						{
							setError(getContBadElement(nameElement), nameElement, positionInForm, "Formato del e-mail Incorrecto");
						}
					break;
					case "image":
						if (valueElement.toLowerCase().indexOf(".jpg") == -1 && valueElement.toLowerCase().indexOf(".jpeg") == -1 && valueElement.toLowerCase().indexOf(".gif") == -1 && valueElement.toLowerCase().indexOf(".png") == -1)
						{
							setError(getContBadElement(nameElement), nameElement, positionInForm, "Formato de Imagen Incorrecto");
						}
					break;
					case "image-swf":
						if (valueElement.toLowerCase().indexOf(".jpg") == -1 && valueElement.toLowerCase().indexOf(".jpeg") == -1 && valueElement.toLowerCase().indexOf(".gif") == -1 && valueElement.toLowerCase().indexOf(".png") == -1 && valueElement.toLowerCase().indexOf(".swf") == -1)
						{
							setError(getContBadElement(nameElement), nameElement, positionInForm, "Formato de Imagen Incorrecto");
						}
					break;
					case "pdf":
						if (valueElement.toLowerCase().indexOf(".pdf") == -1)
						{
							setError(getContBadElement(nameElement), nameElement, positionInForm, "Formato de Fichero PDF incorrecto");
						}
					break;
					case "jpg":
						if (valueElement.toLowerCase().indexOf(".jpg") == -1)
						{
							setError(getContBadElement(nameElement), nameElement, positionInForm, "Formato de Fichero JPG incorrecto");
						}
					break;
					case "gif":
						if (valueElement.toLowerCase().indexOf(".gif") == -1)
						{
							setError(getContBadElement(nameElement), nameElement, positionInForm, "Formato de Fichero GIF incorrecto");
						}
					break;
					case "png":
						if (valueElement.toLowerCase().indexOf(".png") == -1)
						{
							setError(getContBadElement(nameElement), nameElement, positionInForm, "Formato de Fichero PNG incorrecto");
						}
					break;
					case "pdf-jpg":
						if (valueElement.toLowerCase().indexOf(".jpg") == -1 && valueElement.toLowerCase().indexOf(".pdf") == -1)
						{
							setError(getContBadElement(nameElement), nameElement, positionInForm, "Formato de Fichero PDF-JPG incorrecto");
						}
					break;
					
					case "audio":
						if (valueElement.toLowerCase().indexOf(".mp3") == -1 && valueElement.toLowerCase().indexOf(".wav") == -1)
						{
							setError(getContBadElement(nameElement), nameElement, positionInForm, "Formato de Fichero de audio incorrecto");
						}
					break;
					case "document":
						if (valueElement.toLowerCase().indexOf(".pdf") == -1 && valueElement.toLowerCase().indexOf(".doc") == -1)
						{
							setError(getContBadElement(nameElement), nameElement, positionInForm, "Formato de Fichero de documentación incorrecto");
						}
					break;
					case "pdf-ppt":
						if (valueElement.toLowerCase().indexOf(".pdf") == -1 && valueElement.toLowerCase().indexOf(".ppt") == -1)
						{
							setError(getContBadElement(nameElement), nameElement, positionInForm, "Formato de Fichero incorrecto. Debe ser PDF o PPT");
						}
					break;
					case "video":
						if (valueElement.toLowerCase().indexOf(".wmv") == -1 && valueElement.toLowerCase().indexOf(".mov") == -1 && valueElement.toLowerCase().indexOf(".avi") == -1 && valueElement.toLowerCase().indexOf(".mpeg") == -1)
						{
							setError(getContBadElement(nameElement), nameElement, positionInForm, "Formato de Fichero de video incorrecto");
						}
					break;
				}
			}
		}
	}
	
	// Función que pone el error en la posición que le corresponde del vector
	function setError(posError, nameElementError, positionInForm, menssajeError)
	{
		// Compruebo si NO existe un elemento en esa posición, por lo que crearía uno nuevo...
		if(!arrayBadElements[posError])
		{
			arrayBadElements[posError] = new Object();
		}
		// Pongo los atributos del error correspondiente
		arrayBadElements[posError].nameField = nameElementError;
		arrayBadElements[posError].positionInForm = positionInForm;
		arrayBadElements[posError].menssaje = menssajeError;
	}
	
	// Función que busca en el Vector de elementos mal reyenos que posición ha de tomar el objeto a validar ahora.
	// Si el elemento ya tiene un error asociado, le añadimos mas mensaje a ese elemento
	function getContBadElement(nameBadElement)
	{
		var nexBadPosition = null;
		// Si hay elementos en el array lo recorremos para ver si ESTE está ya dado de alta
		if(arrayBadElements.length > 0)
		{
			var contBad = 0
			var foundedBad = false;
			while(contBad < arrayBadElements.length && foundedBad == false)
			{
				if(arrayBadElements[contBad].nameField == nameBadElement)
				{
					foundedBad = true;
					nexBadPosition = contBad;
				}
				contBad++
			}
			// Si el elemento que estamos validando NO está como error anterior ...
			if(foundedBad == false)
			{
				nexBadPosition = arrayBadElements.length
			}
		}
		else // Si no hay elemento, retornamos la posición siguiente del contador;
		{
			nexBadPosition = countBadElements+1;
		}
		return(nexBadPosition);
	}
	
	// Función que borra el Vector de Errores, de lo que tubiera de otra ejecución
	function cleanErrors(formNumber)
	{
		arrayBadElements = null;
		arrayBadElements = new Array();

		if(error.type["remarkFields"].activate == true)
		{
			// Ponemos las cajas de texto y todos los elementos en su estado inicial
			for(i=0;i<document.forms[formNumber].length;i++)
			{
				if (document.forms[formNumber].elements[i].type.toLowerCase() != "button" && document.forms[formNumber].elements[i].type.toLowerCase() != "hidden" && document.forms[formNumber].elements[i].type.toLowerCase() != "submit" && document.forms[formNumber].elements[i].type.toLowerCase() != "checkbox" && document.forms[formNumber].elements[i].type.toLowerCase() != "radio")
				{
					document.forms[formNumber].elements[i].style.border = error.type["remarkFields"].borderInitial;
				}
			}
		}
	}

	// Función uqe muestra los errores del formulario.
	// El formato de mostrarlos viene configurado en el objeto Formulario
	function showFormErrors(formNumber)
	{
		// Comprobamos el formato de salida del mensaje
		
		// Si es mensaje por ALERTA
		if(error.type["makeAlert"].activate == true)
		{
			var menssajeError = "";
			for(i=0;i<arrayBadElements.length;i++)
			{
				menssajeError += arrayBadElements[i].menssaje + " [" + arrayBadElements[i].nameField + "].\n";
			}
			alert(menssajeError)
		}
		// SI es mensaje RESALTANDO CAMPOS
		if(error.type["remarkFields"].activate == true)
		{
			for(i=0;i<arrayBadElements.length;i++)
			{
				document.forms[formNumber].elements[arrayBadElements[i].positionInForm].style.border = error.type["remarkFields"].borderFieldSelected;
			}
		}
	}
	
	
	// ************************************* FUNCIONES PARA VALIDAR LA ENTRADA DE DATOS POR TECLADO *******************************************
	
	// Validar la entrada de ENTEROS por teclado
	this.isInteger = function(evt)
	{
		// Capturamos el evento producido
		var e = (window.event) ? window.event : evt;
		var codeKey = LIB_navigator.getKeyCode(e);
		// Comprobamos si la tecla pulsada es una de las especiales (borrar, Enter, escape, actualizar...)
		if (codeKey != 8 && codeKey != 13 && codeKey != 9 && codeKey != 0) // teclas permitidas: BACKSPACE, ENTER, TAB
		{
			if (codeKey < 48 || codeKey > 57)
			{
				switch(LIB_navigator.getName())
				{
					case "Microsoft Internet Explorer":
						e.returnValue = false;
					break;
					
					case "Firefox":
						e.preventDefault();
						// TENGO QUE CANCELAR EL EVENTO DE PULSAR LA TECLA
					break;
				}
			}
		}
	}
	
	// Validar la entrada de PRECIOS por teclado
	this.isPrice = function(evt)
	{
		// Capturamos el evento producido
		var e = (window.event) ? window.event : evt;
		var codeKey = LIB_navigator.getKeyCode(e);
		// Comprobamos si la tecla pulsada es una de las especiales (borrar, Enter, escape, actualizar...)
		if (codeKey != 8 && codeKey != 13 && codeKey != 9 && codeKey != 0) // teclas permitidas: BACKSPACE, ENTER, TAB
		{
			if (codeKey < 48 || codeKey > 57)
			{
				if (codeKey != 44 && codeKey != 46) // teclas permitidas: '.', ','
				{
					switch(LIB_navigator.getName())
					{
						case "Microsoft Internet Explorer":
							e.returnValue = false;
						break;
						
						case "Firefox":
							e.preventDefault();
						break;
					}
				}
			}
		}
	}
	
	// Function to found the position in form of referer element
	this.foundPositionInForm = function (objReferer)
	{
		var formNumber = 0;
		if (arguments[1] != null && arguments[1] != "undefined")
		{
			formNumber = arguments[1];
		}
		for(var contElements = 0;contElements < document.forms[formNumber].length;contElements++)
		{
			var actualElement = document.forms[formNumber].elements[contElements]
			// Si el elemento que recorremos NO ES UN BOTON
			if(actualElement.type.toLowerCase() != "button" && actualElement.type.toLowerCase() != "hidden" && actualElement.type.toLowerCase() != "submit")
			{
				// Si el elemento actual está accesible (visible y enabled)
				if (actualElement.disabled == false)
				{
					if (actualElement.id == objReferer.id && actualElement.name == objReferer.name)
					{
						return (contElements);
					}
				}
			}
		}
	}
	
	// Function to found parent form of referer element
	this.foundForm = function (objReferer)
	{
		var formFound = false;
		
		var actualObject = objReferer.parentNode;
		while (actualObject && actualObject.nodeName.toLowerCase() != "form")
		{
			actualObject = actualObject.parentNode;
		}
		
		if (actualObject.nodeName.toLowerCase() == "form")
		{
			formFound = actualObject;
		}
		
		return(formFound);
	}
}

// Instanciamos el objeto de la clase CurrentForm
var LIB_forms_validation = new LIB_forms_validation();

// Añadimos al formulario una nueva función, despues de que todo esté cargado
/*
LIB_events.addDynamicEvent(window, "load", function(evt)
										   {
										   	initForm(evt);
										   });
*/
function initForm(evt)
{
	var contForms = 0;
	for(contForms = 0;contForms<document.forms.length;contForms++)
	{
		document.forms[contForms].validateForm = LIB_forms_validation.validateForm;
		for(i=0;i<document.forms[contForms].elements.length;i++)
		{
			actualElement = document.forms[contForms].elements[i];
			// Verificamos que el elemento actual no esté oculto
//			alert (actualElement.nodeName + " --> " + actualElement.id + " --> " + actualElement.name);
			if(actualElement.type && actualElement.type.toLowerCase() != "hidden")
			{
				// Verificamos que no sea ni un boton de RESET ni un boton de SUBMIT
				if(actualElement.type.toLowerCase() != "button" && actualElement.type.toLowerCase() != "reset")
				{
					// Si el objeto actual tiene ID, y el ID tiene el caracter de separación de validación, lo tratamos
					if (actualElement.id && actualElement.id.indexOf(LIB_forms_validation.configSeparator) != -1)
					{
						var typeElement = actualElement.id.split(LIB_forms_validation.configSeparator)[2].toLowerCase();
						switch(typeElement)
						{
							case "number":
								LIB_events.addDynamicEvent(actualElement, "keypress", function(evt)
																					  {
																					  	LIB_forms_validation.isInteger(evt)
																					  });
							break;
							
							case "price":
								LIB_events.addDynamicEvent(actualElement, "keypress", function(evt)
																					  {
																					  	LIB_forms_validation.isPrice(evt)
																					  });
								actualElement.maxLength = LIB_forms_validation.lengthTypes[typeElement];
							break;
							case "phone":
								LIB_events.addDynamicEvent(actualElement, "keypress", function(evt)
																					  {
																					  	LIB_forms_validation.isInteger(evt)
																					  });
								actualElement.maxLength = LIB_forms_validation.lengthTypes[typeElement];
							break;
							case "dni":
								actualElement.maxLength = LIB_forms_validation.lengthTypes[typeElement];
							break;
							case "cp":
								LIB_events.addDynamicEvent(actualElement, "keypress", function(evt)
																					  {
																					  	LIB_forms_validation.isInteger(evt)
																					  });
								actualElement.maxLength = LIB_forms_validation.lengthTypes[typeElement];
							break;
						}
					}
				}
			}
		}
	}
}