/**
 * @author Fernando Reig Aparicio
 * @copyright 2006
*/
var validaciones_js = true;

/**
 * Se utiliza junto con la funcion existeRefresco() en el servidor
 * en cada submit voluntario que se quiera hacer se deveria llamar 
 * a esta funcion que asignara un valor distinto para la cookie de 
 * sesión "lastsubmit
 */
function prevenirRefresco(){
	document.cookie='lastsubmit='+Math.random()+' '+new Date().getTime()+';path=/';
}

/**
 * Devuelve true si detecta algun cambio realizado por el usuario 
 * en el formulario o false en caso contrario
 * @param HTMLFormElement formu Referencia del formulario a analizar
 * @param bool bMarcarCambios si se quiere que se marquen los campos que han sufrido cambios
 * @return bool
 */
function cambiosFormulario(formu, bMarcarCambios){
	var i,j,e,epadre, cambios = false, haycambios = false, aux;
	for(i = 0; i<formu.elements.length; i++){
		e = formu.elements[i];
		
		switch (e.type){
		case "radio":
		case "checkbox":
			if (e.checked != e.defaultChecked){
				//alert(e.name);
				cambios = true;
				break;
			}
			break;
		case "select-one":
		case "select-multiple":
			j = e.selectedIndex;
			if (j<0)
				break;
			if (e.options[j].selected!=e.options[j].defaultSelected){
				aux = false; //no hay defaultSelected
				for (j=0; j<e.options.length; j++){
					if (e.options[j].defaultSelected){
						aux = true;//hay defaultSelected
						break;
					}
				}
				if (!aux)
					break;
				//alert(e.name);
				//alert(j+"="+e.selectedIndex);
				cambios = true;
				break;
			}
			break;
		case "file":
		case "text":
		case "textarea":
		case "password":
			if (e.value!=e.defaultValue){
				//alert(e.name);
				cambios = true;
				break;
			}
			break;
		}//switch

		if (cambios){
			//break;

			if (bMarcarCambios){
				if (e.parentNode.className!="cambios"){
					epadre = document.createElement("span");
					epadre.className = 'cambios';
					epadre.style.backgroundColor = "red";
					epadre.style.padding = "2px";
					e.parentNode.insertBefore(epadre,e);
					var auxChecked = e.checked; //para IExplorer

					epadre.appendChild(e);
					e.checked = auxChecked;
				}
			}
			cambios = false;
			haycambios = true;
		}else{
			if (bMarcarCambios){
				epadre = e.parentNode;
				if (epadre.className=="cambios"){
					epadre.parentNode.replaceChild(e, epadre);
				}
			}
		
		}

	}//for
	//if (cambios){ e.style.backgroundColor = "red";	}
	
	return haycambios; //no se han detectado cambios realizados por el usuario
}

/**
 * Dice si existe una opcion con el valor indicado en el elemento Select
 * @param HTMLSelectElement eSelect
 * @param String sValor
 * @return bool
 */
function existeOpcion(eSelect, sValor){
	if (!eSelect)
		return false;
		
	var v = eSelect.options;
	for (var i=0; i<v.length; i++){
		if (v[i].value==sValor)
			return true;
	}
	return false;
}

/**
 * Dice si un precio es válido o no
 * @param double precio
 * @return bool
 */
function validarPrecio(precio){
	if (validarReal(precio)){
		if (precio==0){
			alert("¡¡ATENCION!! El precio introducido es 0.");
		}
		return true;
	}
	return false;
}

/**
 * Dice si un email es valido o no
 * @param String email
 * @return bool
 */
function validarEmail(email){
	return /^[a-zA-Z0-9_\-]+(\.[a-zA-Z0-9_\-]+)*@[a-zA-Z0-9_\-]+(\.[a-zA-Z0-9_\-]+)+$/.test(email);
}

/**
 * Dice si el numero indicado es un entero o no
 * @param Number num
 * @return bool
 */
function validarEntero(num){
	return /^[0-9]+$/.test(new String(num));
}

/**
 * Dice si el numero indicado es un real
 * @param Number num
 * @return bool
 */
function validarReal(num){
	return /^\-?[0-9]+(\.[0-9]+)?$/.test(new String(num));
}

/**
 * Dice si la fecha especificada se encuentra en formato europeo (dd-MM-aaaa)
 * @param String fecha
 * @return bool
 */
function validarFecha(fecha){
	return /^[0-9]{2}\-[0-9]{2}\-[0-9]{4}$/.test(fecha);
}

/**
 * Dado un número de cuenta nos dice si la cuenta es válida o no (comprobando su DC) 
 * @param String cuenta
 * @return bool
 */
function validarCuentaBancaria(cuenta){
	var r = /([0-9]{4})[^0-9]?([0-9]{4})[^0-9]?([0-9]{2})[^0-9]?([0-9]{10})/;

	if (r.test(cuenta)){
		r.exec();
		var IentOfi = ""+RegExp.$1+""+RegExp.$2;
		var InumCta = RegExp.$4;
		var dc = (RegExp.$3);
	}else
		return false;

	var APesos =  [1,2,4,8,5,10,9,7,3,6]; // Array de "pesos"
	var DC1=0;
	var DC2=0;
	var x=8;
	var digito;
	while(x>0) {
		digito=IentOfi.charAt(x-1);
		DC1=DC1+(APesos[x+2-1]*parseInt(digito));
		x--;
	}
	var Resto = DC1%11;
	DC1=11-Resto;
	if (DC1==10) DC1=1;
	if (DC1==11) DC1=0;              // Dígito control Entidad-Oficina

	x=10;
	while(x>0) {
		digito=InumCta.charAt(x-1);
		DC2=DC2+(APesos[x-1]*parseInt(digito));
		x--;
	}
	Resto = DC2%11;
	DC2=11-Resto;
	if (DC2==10) DC1=1;
	if (DC2==11) DC1=0;  // Dígito Control C/C

	var DigControl=(DC1)+""+(DC2);   // los 2 números del D.C.

	return (DigControl == dc);	
}

/**
 * Dice si hay algun checkbox seleccionado de una lista de checkbox
 * @param String nombre
 * @return bool
 */
function haySeleccionados(nombre){
	var v = document.getElementsByName(nombre);
	for (var i=0; i<v.length; i++){
		if (v[i].type=="checkbox" && v[i].checked)
			return true;
	}//for
	return false;
}

/**
 * Dice si la cadena es vacia o no
 * @param String cadena
 * @return bool
 */
function esCadenaVacia(cadena){
	if (cadena==null || cadena=="")
		return true;
		
	var c;
	for (var i=0; i<cadena.length; i++){
		c = cadena.charAt(i);
		if (c!=" " && c!="\t" && c!="\r" && c!="\n")
			return false;
	}//for

	return true;
}

/**
 * Si se llama en un evento onkeyup no deja introducir caracteres que no sean numeros
 * @param HTMLInputElement campo
 */
function filtrarEntero(campo){
	campo.value = campo.value.replace(/[^0-9]/g,"");
}

/**
 * Si se llama en un evento onkeyup no deja introducir caracteres que no sean numeros o el punto
 * @param HTMLInputElement campo
 */
function filtrarReal(campo){
	campo.value = campo.value.replace(/\,+/g,".").replace(/[^0-9\.]/g,"");
}

/**
 * Si se llama en un evento onkeyup no deja introducir caracteres que no sean numeros o el guion
 * @param HTMLInputElement campo
 */
function filtrarFecha(campo){
	campo.value = campo.value.replace(/[\/\-]+/g,'-').replace(/[^0-9\-]/g,'');
	//campo.value = /[0-9]{2}\-[0-9]{1,2}\-[0-9]{1,4}|[0-9]{2}\-[0-9]{1,2}\-|[0-9]{2}\-[0-9]{1,2}|[0-9]{2}\-|[0-9]{1,2}/.exec(campo.value);
}

/**
 * Comprueba que se hayan insertado los campos indicados en el vector vsRequeridos. 
 * Este vector debe tener el formato: Object(campo1=>etiqueta1, ... , campo3=>etiqueta3)
 * @param HTMLFormElement form
 * @param Object vsRequeridos
 * @return bool
 */
function validarRequeridos(formu, vsRequeridos){
	ok = true;
	for(campo in vsRequeridos){
		if (is_numeric(campo))
			valor = formu.elements[etiqueta].value;
		else
			valor = formu.elements[campo].value;

		if (esCadenaVacia(valor)){
			ok = false;
			alert("ERROR: El campo 'etiqueta' debe tener valor.");
		}
	}
	return ok;
}

/**
 * Dice si la hora hora tiene el formato correcto o no
 * @param String hora
 * @return bool
 */
function validarHora(hora){
	var r = new RegExp("^([0-9]+)\\:([0-9]+)(\\:([0-9]+))?$");
	var regs = null;

	if (!(regs = r.exec(hora)))
		return false;
	h = parseInt(regs[1]);
	m = parseInt(regs[2]);
	s = 0;
	if (!isNaN(parseInt(regs[4])))
		s = parseInt(regs[4]);

	return ((h>=0 && h<24) && (m>=0 && m<60) && (s>=0 && s<60));
}

/**
 * Dice si es una fecha formada por dia-mes-ano es una fecha valida
 * @param Number dia
 * @param Number mes
 * @param Number ano
 * @return bool
 */
function checkdate(dia, mes, ano){
	var d = new Date(ano, mes, dia);
	return (d.getDate()==dia);
}

/**
 * Dice si la fecha introducida esta en el formato europero. 
 * Devuelve false si es incorrecta o un timestamp si s? lo es.
 * Si se indica un valor de cifras_ano el a?o de la fecha debe 
 * tener ese numero de cifras (2 o 4 tipicamente)
 * @param String fecha
 * @param Number cifras_ano
 * @return bool
 */
function validarFechaEuropa(fecha, cifras_ano){
	var d;
	var regs = new RegExp("^([0-9]+)[\/\-]([0-9]+)[\/\-]([0-9]+)$").exec(fecha);
	if (!regs)
		return false;

	dia = regs[1];
	mes = regs[2] - 1; //para formar una fecha con Date, el mes va de 0..11
	ano = regs[3];
	if (ano<100)
		ano=parseInt(ano)+
			parseInt(new String(new Date().getFullYear()).substring(0,2))*100; //suma 2000, 2100, 2200 segun el seglo qn el que nos encontremos

	if (checkdate(dia,mes,ano) && (cifras_ano==undefined || new String(ano).length == cifras_ano)){
		d = new Date(ano, mes, dia);
		d.setHours(0,0,0,0); //pone las horas, min, sec y ms a 0
		return (d.getTime());
	}else
		return false;
	
}

/**
 * Dice si la fecha introducida se encuentra en formto americano
 * @param String fecha
 * @param Number cifras_ano
 * @return bool
 */
function validarFechaUSA(fecha, cifras_ano){
	var d;
	var regs = new RegExp("^([0-9]+)[\/\-]([0-9]+)[\/\-]([0-9]+)$").exec(fecha);
	if (!regs)
		return false;

	dia = regs[2];
	mes = regs[1] - 1; //para formar una fecha con Date, el mes va de 0..11
	ano = regs[3];
	if (ano<100)
		ano=parseInt(ano)+
			parseInt(new String(new Date().getFullYear()).substring(0,2))*100; //suma 2000, 2100, 2200 segun el seglo qn el que nos encontremos

	if (checkdate(dia,mes,ano) && (cifras_ano==undefined || new String(ano).length == cifras_ano)){
		d = new Date(ano, mes, dia);
		d.setHours(0,0,0,0); //pone las horas, min, sec y ms a 0
		return (d.getTime());
	}else
		return false;
	
}

/**
 * Dice si la fecha introducida se encuentra en formato ISO
 * @param String fecha
 * @param Number cifras_ano
 * @return bool
 */ 
function validarFechaISO(fecha, cifras_ano){
	var d;
	var regs = new RegExp("^([0-9]+)[\/\-]([0-9]+)[\/\-]([0-9]+)$").exec(fecha);
	if (!regs)
		return false;

	dia = regs[3];
	mes = regs[2] - 1; //para formar una fecha con Date, el mes va de 0..11
	ano = regs[1];
	if (ano<100)
		ano=parseInt(ano)+
			parseInt(new String(new Date().getFullYear()).substring(0,2))*100; //suma 2000, 2100, 2200 segun el seglo qn el que nos encontremos

	if (checkdate(dia,mes,ano) && (cifras_ano==undefined || new String(ano).length == cifras_ano)){
		d = new Date(ano, mes, dia);
		d.setHours(0,0,0,0); //pone las horas, min, sec y ms a 0
		return (d.getTime());
	}else
		return false;
	
}

/**
 * Dice si un NIF determinado es válido
 * @param String sNIF NIF a validar
 * @return bool
 */
function validarNIF(sNIF){
	var r = new RegExp("^[ ]*([0-9]{8})[\\-]?([a-z])[ ]*$", "i");
	var regs = null;
	
	sNIF = new String(sNIF).toUpperCase();
	if (!(regs = r.exec(sNIF))){
		//alert("El NIF no tiene el formato correcto.");
		return false;	
	}
	var letras = "TRWAGMYFPDXBNJZSQVHLCKE";
	
	var numero = parseInt(regs[1]*1);
	var letra = regs[2];
	
	if (letras.charAt(numero%23)==letra)
		return true;
		
	//alert("La letra del NIF es incorrecta.");
	return false;	
}

/**
 * Dice si el CIF especificado es valido
 * @param string sCIF
 * @return bool
 */
function validarCIF(sCIF){
	var letras_tipo_organizacion = "ABCDEFGHKLMNPQS";
	/*
    *  A - Sociedad An?nima.
    * B - Sociedad de responsabilidad limitada.
    * C - Sociedad colectiva.
    * D - Sociedad comanditaria.
    * E - Comunidad de bienes.
    * F - Sociedad cooperativa.
    * G - Asociación.
    * H - Comunidad de propietarios.
    * K - Formato antiguo.
    * L - Formato antiguo.
    * M - Formato antiguo.
    * N - Formato antiguo.
    * P - Corporación local.
    * Q - Organismo aut?nomo
    * S - Organo de la administración.
	 * */
	
	var letras_digito_control = "JABCDEFGHI";
	var regs = null;
	var r = new RegExp("^(["+letras_tipo_organizacion+"])[\\-]?([0-9]{7})[\\-]?([0-9"+letras_digito_control+"])$","i");
	if (!(regs = r.exec(sCIF))){
		//alert("El CIF no tiene el formato correcto.");
		return false;
	}

	var letra_tipo_organizacion = regs[1];
	var numero = regs[2];
	var digito_control = regs[3]; 
	
	//Las operaciones para calcular el dígito de control se realizan sobre los siete dígitos centrales
	//Sumar los dígitos de la posiciones pares (empezando en 1) pos2+pos4+pos6
	var sNumero = new String(numero);
	var sumapares = 
		parseInt(sNumero.charAt(1))+
		parseInt(sNumero.charAt(3))+
		parseInt(sNumero.charAt(5));

	//Para cada uno de los dígitos de la posiciones impares, multiplicarlo por 2 y sumar los dígitos del resultado.
	//Acumular el resultado
	var sumaimpares = 0;
	var aux, sAux;
	for(var i=0;i<sNumero.length;i+=2){
		aux = parseInt(sNumero.charAt(i))*2;
		if (aux>9){ //si tiene dos digitos el resultado
			sAux = new String(aux);
			sumaimpares+= 
				(parseInt(sAux.charAt(0))+
				 parseInt(sAux.charAt(1)));
		}else
			sumaimpares+= aux;
	}

	//Sumar sumapares + sumaimpares
	var suma = sumapares+sumaimpares;
	
	//Tomar sólo el dígito de las unidades de suma y restárselo a 10
	var sSuma = new String(suma);
	var resta = 10-parseInt(sSuma.charAt(sSuma.length-1));

	//A partir de éste (resta) ya se obtiene el dígito de control. 
	//Si ha de ser numérico es éste (resta) y si se trata de una letra se corresponde con la relación:
	//J = 0, A = 1, B = 2, C = 3, D = 4, E = 5, F = 6, G = 7, H = 8, I = 9
	if ((digito_control!=resta) && (digito_control!=letras_digito_control[resta])){
		//alert("El dígito control no es correcto.");
		return false;
	}
	
	return true;
}

/**
 * Valida IPs (v4) (Dice si son correctas o no)
 * 
 */
function validarIP(sIP){
	var r = new RegExp("^([0-9]+)\\.([0-9]+)\\.([0-9]+)\\.([0-9]+)$");
	var regs = null;
	if (!(regs = r.exec(sIP))){
		//alert("Formato de IP incorrecto.");
		return false;
	}
	var a = parseInt(regs[1]);
	var b = parseInt(regs[2]);
	var c = parseInt(regs[3]);
	var d = parseInt(regs[4]);
	
	if ((a>=0) && (a<=255) && 
		(b>=0) && (b<=255) && 
		(c>=0) && (c<=255) && 
		(d>=0) && (d<=255)){
		return true;	
	}
	//alert('Algún octeto no es correcto.');
	return false;
}

/**
 * class Param
 * @access public
 */
function Param(key, value){
	this.key = key;
	this.value = value;
}

function buildMessage(sText /*, voParams*/){
	var voParams = arguments;
	
	if (voParams.shift)
		voParams.shift(); //quitamos el primer elemento que es el argumento sText
	var j = 1;
	var oParam = null;
	for(var i = 0; i<voParams.length; i++){
		oParam = voParams[i];
		if (typeof(oParam)=="string")
			sText = sText.replace(new RegExp("\\{"+j+"\\}"), oParam);
		else
			sText = sText.replace(new RegExp("\\{"+oParam.key+"\\}"), oParam.value);
		j++;
	}
	return sText.replace(/'/g,"\\'");
}

/**************************************************************************/
/**************************************************************************/
/*
INTERFACE:
	function setCampos(campos);

	function validarCampoVSValor(campo1, valor, comparacion=IGUAL, tipo=null);
	function validarCampoVSCampo(campo1, campo2, comparacion=IGUAL, tipo=null);
	function validarCampoVSRangoValores(campo1, linf, lsup, tipo = null);
	function validarCampoVSRangoCampos(campo1, campolinf, campolsup, tipo = null);
	function validarCampoVSListaValores(campo1, valores);
	function validarCampoVSListaCampos(campo1, campos);
	function validarCampoVSExpresion(campos, exp);
	function validarLongitudCampos(campos, longitud);	
	function validarTipoCampos(campos, tipo);
	function validarRequeridos(campos);
	function validarRequeridosOR(campos);
	function validarRequeridosXOR(campos);

	function mostrarAlert();
	function mostrarTexto();

*/


/**
 * class Validador -- constuctor
 * @param HTMLFormElement formelem Referencia del formulario HTML a validar
 * @access public
 */
function Validador(formelem){
	if (!window.utiles_js)
		//throw new Error
		throw new Error("SE REQUIERE EL ARCHIVO utiles.js");

	if (formelem.form)
		formelem = formelem.form;
	
	if (!formelem){
		//throw new Error
		alert("No se ha especificado el formulario para el objeto Validador.");
	}else{
		this.m_formu = formelem;
	}
	
	this.m_vsCamposError = new Array(); 
	this.m_vsCamposWarning = new Array();
	this.m_asCampos = new Object(); 
	this.m_vsErrores = new Array();
	this.m_vsWarnings = new Array();
	this.m_bOK = true;	
	
}

/**
 * Referencia del formulario a validar
 * @var HTMLInputElement
 * @access protected
 */
Validador.prototype.m_formu = null; 

/**
 * Campos en los que ha ocurrido algun error
 * @var Array
 * @access protected
 */ 
Validador.prototype.m_vsCamposError = new Array(); 

/**
 * Campos en los que ha saltado algún warning
 * @var Array
 * @access protected
 */ 
Validador.prototype.m_vsCamposWarning = new Array();

/**
 * Un array que contiene la relacion entre nombres de campo 
 * y etiquetas de los mismos. Formato: Object(nombre1=>etiqueta1, ... , nombreN=>etiquetaN)
 * @var Object
 * @access protected
 */ 
Validador.prototype.m_asCampos = new Object(); 

/**
 * Lista de errores ocurridos
 * @var Array
 * @access protected
 */ 
Validador.prototype.m_vsErrores = new Array();

/** 
 * Lista de warnigs ocurridos
 * @var Array
 * @access protected
 */ 
Validador.prototype.m_vsWarnings = new Array();

/**
 * Indica si todo ha ido bien o ha ocurrido algún error
 * @param bool 
 * @access protected
 */ 
Validador.prototype.m_bOK = true;

/**
 * Establece el vector de campos con sus nombres
 * @param Object campos  
 * @access public
 */	
Validador.prototype.setCampos = 
function(campos){
	var vargs = this.setCampos.arguments;
	
	if (vargs.length==1){ //se presupone que le ha entrado un array asociativo con los nombres de los campos asociados con sus etiquetas
		this.m_asCampos = campos;
		//for(var i in campos) alert(i+"="+campos[i]);
	}else
	if (vargs.length>1){ //si no se supone que le  habran entrado los argumentos del siguiente modo: nom1, etiq1, nom2, etiq2...
		this.m_asCampos = new Object();
		for (var i=0; i<vargs.length; i+=2){
			this.m_asCampos[vargs[i]] = vargs[i+1];
		}
	}else
		return false;
}


/** 
 * Añade un nuevo error a la lista
 * @param String mens
 * @param String campo
 * @param int tipError
 * @access private
 */
Validador.prototype.agregarError = 
function(mens, campo, tipoError){
	if (!this.m_formu.elements[campo])
		if (this.m_formu.elements[campo+"[]"])
			campo = campo+"[]";
	
	//if (this.m_formu[campo]==null) //solo se agrega el error si el campo existe
	//	return false;
	if (tipoError==Validador.WARNING){
		this.m_vsWarnings.push(mens);
		if (campo!=null && campo!=undefined && campo!=""){
			this.m_vsCamposWarning.push(campo);
		}
	}else{
		if (campo!=null && campo!=undefined && campo!=""){
			this.m_vsCamposError.push(campo);
		}
		this.m_vsErrores.push(mens);
		if (this.m_bOK)
			this.m_bOK = false;
	}//else
}

/**
 * Devuelve la etiqueta del campo si se ha definido o el nombre si no
 * @param String campo
 * @access private
 */
Validador.prototype.nombreCampo = 
function(campo){
	if (campo.push){ //si se trata de un array
		s = "";
		for (var i=0; i<campo.length; i++){
			s+=this.nombreCampo(campo[i]);
			if (i<(campo.length-1)) 
			if (i==(campo.length-2))
				s+=" y ";
			else
				s+=", ";
		}
		return s;
	}
	campo = this.nameCampo(campo);
	if (this.m_asCampos[campo]!=undefined)
		return "\""+this.m_asCampos[campo]+"\"";
	return '"'+campo+'"';
}

/**
 * Devuelve el nombre (nombre en el formulario html o name) del campo 
 * @param String campo
 * @access private
 */
Validador.prototype.nameCampo = 
function(campo){
	return campo.replace(/\[[0-9]+\]/,"");
}

/**
 * Devuelve el nombre (nombre en el formulario html o name) del campo 
 * @param String campo
 * @access private
 */
Validador.prototype.getCampo = 
function(campo){
	var e;
	var r = /\[([0-9]+)\]/;
	var i = -1;
	if (r.test(campo))
	{
		r.exec(campo);
		i = RegExp.$1;
		campo = this.nameCampo(campo);
		
		e = document.getElementsByName(campo);
		if (e)
			return e[i];
	}
	e = this.m_formu.elements[campo];

	if (e == undefined){
		e = this.m_formu.elements[campo+"[]"];
		if (e==undefined)
			return null;
	}
	
	if (i>=0){
		e = e[i];
		if (e==undefined)
			return null;
	}
	return e;
}

/**
 * Obtiene el valor de un campo
 * @param String campo Nombre(name) del campo del que se quiere obtener el valor
 * @access private
 */
Validador.prototype.valorCampo = 
function(campo){
	var i, aux;

	var e = this.getCampo(campo);
	if (e==null) 
		return false;
	//if (e.push){alert(campo+" es un array");}
		
	if (e.type=="select-one") //select-one
		return e.options[e.selectedIndex].value;
	else
	if (e.type=="select-multiple"){ //select-multiple
		aux = new Array();
		for (i=0; i<e.options.length; i++){
			if (e.options[i].selected)
				aux.push(e.options[i].value);
		}//for
		return aux;
	}else
	if (e.type=="checkbox"){
		if (e.checked)
			return e.value;
		return false;
	}else
	if (e.type==undefined){//lista de campos (tipicamente radiobuttons o checkboxes)
		if (e[0].type=="radio"){//se devolvera el valor del redio button seleccionado
			for(i=0; i<e.length; i++){
				if (e[i].checked)
					return e[i].value;
			}//for
		}else{ //se devuelve la lista de valores seleccionados
			aux = new Array();
			for(i=0; i<e.length; i++){
				if (((e[i].type!="radio") && (e[i].type!="checkbox")) || e[i].checked)
					aux.push(e[i].value);
			}//for
			return aux;
		}//else
	}else //el resto de elementos de formulario
		return e.value;
}

/**
 * Dice si un campo determinado existe en el formulario
 * @return bool
 * @access public
 */
Validador.prototype.existeCampo = 
function(campo){
	return (this.getCampo(campo)!=null);
}

/** 
 * Dice si la variable <code>valor</code> tiene valor "no vacio"
 * @param Object valor
 * @access public
 */
Validador.prototype.tieneValor = 
function(valor){
	var i;
		
	switch(typeof(valor)){
	case "object": //un conjunto de valores
		for(i=0;i<valor.length;i++){
			if (!esCadenaVacia(valor[i]))
				return true;
		}
		/*for (i=0; i<valor.length; i++)
			if (!esCadenaVacia(valor[i])) //si alguno de los valores no es cadena vacia se devuelve true (se considera que tiene valor)
				return true;
		return false;*/
		return false;
	default: //un unico valor
		return (!esCadenaVacia(valor));
	}
	return false;
}

/**
 * Obtiene el nombre dado el codigo de una comparaciopn
 * @param int comparacion
 * @param int tipo
 * @access private
 */
Validador.prototype.nombreComparacion = 
function(comparacion, tipo){
	switch (tipo){
	case Validador.TIPO_FECHA_EUROPA:
	case Validador.TIPO_FECHA_USA:
	case Validador.TIPO_FECHA_ISO:
	case Validador.TIPO_FECHA:
		switch (comparacion){
		case Validador.IGUAL: return "igual a";		
		case Validador.MENOR: return "anterior a";		
		case Validador.MENORIGUAL: return "anterior o igual a";		
		case Validador.MAYOR: return "posterior a";		
		case Validador.MAYORIGUAL: return "posterior o igual a";
		case Validador.DISTINTO: return "diferente a";
		}
		break;
	default:
		switch (comparacion){
		case Validador.IGUAL: return "igual a";		
		case Validador.MENOR: return "menor que";		
		case Validador.MENORIGUAL: return "menor o igual que";		
		case Validador.MAYOR: return "mayor que";		
		case Validador.MAYORIGUAL: return "mayor o igual que";
		case Validador.DISTINTO: return "diferente a";
		}
	}
	return false;
}
	
/**
* Obtiene la fecha/hora actual
* @return Date
* @access private
*/
Validador.prototype.hoy = function(){
	var d = new Date();
	d.setHours(0,0,0,0); //pone las horas, minutos, segundos y milisegundos a 0
	return d;
}

/**
 * Dado un codigo de comoparacion, realiza esta misma 
 * entre dos valores valor1 y valor2
 * @param Object valor1
 * @param Object valor2
 * @param int comparacion Codigo de la comparacion a realizar Validador.MAYOR...
 * @param int tipo Codigo del tipo de los datos a comparar Validador.TIPO_ENTERO....
 * @access private
 */
Validador.prototype.comparar = 
function(valor1, valor2, comparacion, tipo){

	if (comparacion == undefined) 
		comparacion = Validador.IGUAL; //valor por defecto
		
	switch(tipo){
	case Validador.TIPO_FECHA:
		valor1 = Date.makeDate(valor1);
		valor2 = Date.makeDate(valor2);
		//alert(valor1+"="+valor2);
		break;
	case Validador.TIPO_FECHA_EUROPA:
		if (valor2 == Validador.HOY){
			if (!(valor1 = validarFechaEuropa(valor1)))
				return false;
			valor2 = this.hoy();
		}else
		if (!(valor1 = validarFechaEuropa(valor1)) || 
			!(valor2 = validarFechaEuropa(valor2)))
			return false;
		break;
	case Validador.TIPO_FECHA_USA:
		if (valor2 == Validador.HOY){
			if (!(valor1 = validarFechaUSA(valor1)))
				return false;
			valor2 = this.hoy();
		}else
		if (!(valor1 = validarFechaUSA(valor1)) || 
			!(valor2 = validarFechaUSA(valor2)))
			return false;
		break;
	case Validador.TIPO_FECHA_ISO:
		if (valor2 == Validador.HOY){
			if (!(valor1 = validarFechaISO(valor1)))
				return false;
			valor2 = this.hoy();
		}else
		if (!(valor1 = validarFechaISO(valor1)) || 
			!(valor2 = validarFechaISO(valor2)))
			return false;
		break;
	case Validador.TIPO_HORA:
		valor1 = (Date.makeDate('1980-04-01 '+valor1)).getTime();
		valor2 = (Date.makeDate('1980-04-01 '+valor2)).getTime();
		break;
	default:
		//si los dos valores son numeros reales se toman como tales
		if (validarReal(valor1) && validarReal(valor2)){
			valor1 = parseFloat(valor1);
			valor2 = parseFloat(valor2);
		}//if
	}//switch

	switch (comparacion){
	case Validador.IGUAL:	return (valor1 == valor2);
	case Validador.DISTINTO:	return (valor1 != valor2);
	case Validador.MENOR:	return (valor1 < valor2);
	case Validador.MENORIGUAL: return (valor1 <= valor2);
	case Validador.MAYOR:	return (valor1 > valor2);
	case Validador.MAYORIGUAL: return (valor1 >= valor2);
	default:
		myAlert("ERRROR EN EL TIPO DE COMPARACI?N.");
	}//switch	
	return false;
}

/**
 * @param string $s
 * @return string
 * @access protected
 */
Validador.prototype.parseString = 
function(s){
	var regs = new Array();
	var sCampo = "";
	var vCampos = new Array();
	var r = new RegExp("\\{\\#([^\\}]+)\\}","g");
	var valor = null;	
	
	regs = r.exec(s);
	if (!regs)
		return s;
	while(regs){
		vCampos.push(regs[1]);
		regs = r.exec(s);
	}
	//alert(s);	
	for(var i=0; i<vCampos.length; i++){
		sCampo = vCampos[i];
		if (!this.existeCampo(sCampo)){
			alert("ERROR en la validación. El campo "+sCampo+" no existe.");
			continue;
		}
		r = new RegExp("\\{\\#"+sCampo+"\\}",'g');
		valor = this.valorCampo(sCampo);
		if (!validarReal(valor))
			valor = '"'+valor+'"';
		s = s.replace(r, valor);
	}
	//alert("2 "+s);
	return s;
}

/**
 * Valida la expresion 'expresion' solo en caso de que se cumpla la precondicion 'precondicion'.
 * Si no se cumple la precondicion se devuelve true, en caso contrario se evalua la 'expresion'
 * y si no se cumple (se evalúa a false) se añade el mensaje de error $sError a la cola de mensajes.
 * Las cadenas dentro de la expresion o precondicion de la forma {#nombre_campo} se traducen por el
 * valor que tenga el campo "nombre_campo".
 * En este último caso, si además se ha indicado el campo de error se marcará este como erróneo 
 * (con un asterisco por ejemplo) y se le dará el foco 
 * @param string expresion
 * @param string precondicion
 * @param string sError
 * @return bool
 * @access public
 */
 Validador.prototype.validarExpresion = 
 function(expresion, precondicion, sError, sCampoError, tipoError){
		
	expresion = this.parseString(expresion);
	precondicion = this.parseString(precondicion);

	if (precondicion=='' || precondicion==null || eval(precondicion)){ //si se cumple la precondicion se valida la expresion
		if (!eval(expresion)){ //se devuelve el resultado de la expresion
			this.agregarError(sError, sCampoError, tipoError);
			return false;
		}
	}
	return true;
}

/**
 * Compara el valor del campo1 con un valor escalar proporcionado.
 * Devuelve true si se cumple la comparacion o false en caso contrario.
 * En el caso de comparar fechas debe indicarse en el campo tipo (FECHA_EUROPA o FECHA_USA o FECHA_ISO).
 * @param String campo1
 * @param String valor
 * @param int comparacion
 * @param int tipo
 * @param int tipoError
 * @param String sMens
 * @return bool
 * @access public
 */	
Validador.prototype.validarCampoVSValor = 
function(campo1, valor, comparacion, tipo, tipoError, sMens){
	var valor1;
	valor1 = this.valorCampo(campo1);

	if (!this.tieneValor(valor1)) //si no tiene valor el campo1 no se realiza la comprobacion
		return true;	

	if (comparacion == undefined) 
		comparacion = Validador.IGUAL; //valor por defecto

	if (this.comparar(valor1, valor, comparacion, tipo))
		return true;

	if (sMens==undefined) var sMens = "";
	if (sMens=="")
		sMens = "El campo {campo} debería ser {comparacion} {valor}.";

	this.agregarError(buildMessage(sMens,
		new Param("campo", this.nombreCampo(campo1)),
		new Param("comparacion",this.nombreComparacion(comparacion, tipo)),
		new Param("valor", valor)), campo1, tipoError);
		
	return false;
}

/**
 * Compara el valor del campo1 con el valor del campo2
 * Devuelve true si se cumple la comparacion o false en caso contrario.
 * En el caso de comparar fechas debe indicarse en el campo tipo (FECHA_EUROPA o FECHA_USA o FECHA_ISO).
 * @param String campo1
 * @param String campo2
 * @param int comparacion Codigo de la comparacion a realizar Validador.MAYOR, Validador.MENOR... del parametro1 con respecto al parametro2 (por defecto IGUAL)
 * @param int tipo Tipo de los datos a comparar (del campo1 y campo2)
 * @param int tipoError Tipo de error que se generara en caso de no evaluarse la comparacion (Validador.ERROR, Validador.WARNING) (por defecto ERROR)
 * @param String sMens Mensaje de error a generar en caso de que no se cumpla la comparacion (Si no se indica se generar? uno por defecto)
 * @return bool
 * @access public
 */	
Validador.prototype.validarCampoVSCampo = 
function(campo1, campo2, comparacion, tipo, tipoError, sMens){
	var valor1, valor2;
	valor1 = this.valorCampo(campo1);	
	
	if (!this.tieneValor(valor1)) //si no tiene valor el campo1 no se realiza la comprobacion
		return true;	
	
	if (comparacion == undefined) 
		comparacion = Validador.IGUAL; //valor por defecto	

	valor2 = this.valorCampo(campo2);
	
	if (this.comparar(valor1, valor2, comparacion, tipo))
		return true;
		
	if (sMens==undefined) var sMens = "";
	if (sMens=="")
		sMens = "El campo {campo1} debe ser {comparacion} el campo {campo2}.";

	this.agregarError(buildMessage(sMens,
		new Param("campo1",this.nombreCampo(campo1)),
		new Param("campo2",this.nombreCampo(campo2)),
		new Param("comparacion",this.nombreComparacion(comparacion, tipo))), campo1, tipoError);
		
	return false;
}

/**
 * Comprueba si el valor del campo1 se encuentra entre los valores linf y lsup
 * Devuelve true si se cumple la comparacion o false en caso contrario.
 * En el caso de comparar fechas debe indicarse en el campo tipo (FECHA_EUROPA o FECHA_USA o FECHA_ISO).
 * @param String campo1
 * @param Object Limite inferior 
 * @param Object Limite superior
 * @param int tipo Tipo de los datos a comparar (del campo1 y las variables linf y lsup)
 * @param int tipoError Tipo de error que se generara en caso de no evaluarse la comparacion (Validador.ERROR, Validador.WARNING) (por defecto ERROR)
 * @param String sMens Mensaje de error a generar en caso de que no se cumpla la comparacion (Si no se indica se generar? uno por defecto)
 * @return bool
 * @access public
 */
Validador.prototype.validarCampoVSRangoValores = 
function (campo1, linf, lsup, tipo, tipoError, sMens){
	var valor1;
	valor1 = this.valorCampo(campo1);
	if (!this.tieneValor(valor1)) //si no tiene valor el campo1 no se realiza la comprobacion
		return true;	

	//si linf y lsup tienen valor y linf>lsup se intercambian los valores
	if (!esCadenaVacia(linf) && !esCadenaVacia(lsup) && linf > lsup){
		var aux = lsup;
		lsup = linf;
		linf = aux;
	}//if	

	if (this.comparar(valor1,linf, Validador.MAYORIGUAL,tipo) && 
		this.comparar(valor1,lsup, Validador.MENORIGUAL,tipo))
		return true;
		
	if (sMens==undefined) var sMens = "";
	if (sMens=="")
		sMens = "El valor del campo {campo} debe estar comprendido entre {linf} y {lsup}.";
		
	this.agregarError(buildMessage(sMens,
		new Param("campo",this.nombreCampo(campo1)),
		new Param("linf",linf),
		new Param("lsup",lsup)), campo1, tipoError);
		
	return false;				
}

/**
 * Comprueba si el valor del campo1 se encuentra entre los valores de los campos campolinf y campolsup
 * Devuelve true si se cumple la comparacion o false en caso contrario.
 * En el caso de comparar fechas debe indicarse en el campo tipo (FECHA_EUROPA o FECHA_USA o FECHA_ISO).
 * @param String campo1
 * @param String campolinf Nombre del campo cuyo valor ser? el limite inferior
 * @param String campolsup Nombre del campo cuyo valor ser? el limite superior
 * @param int tipo Tipo de los datos a comparar (del campo1 y de los campos campolinf y campolsup)
 * @param int tipoError Tipo de error que se generara en caso de no evaluarse la comparacion (Validador.ERROR, Validador.WARNING) (por defecto ERROR)
 * @param String sMens Mensaje de error a generar en caso de que no se cumpla la comparacion (Si no se indica se generar? uno por defecto)
 * @return bool
 * @access public
 */
Validador.prototype.validarCampoVSRangoCampos = 
function (campo1, campolinf, campolsup, tipo, tipoError, sMens){
	var valor1, linf, lsup;
	valor1 = this.valorCampo(campo1);
	
	if (!this.tieneValor(valor1)) //si no tiene valor el campo1 no se realiza la comprobacion
		return true;		
	
	linf = this.valorCampo(campolinf); //limite inferior
	lsup = this.valorCampo(campolsup); //limite superior

	//si linf y lsup tienen valor y linf>lsup se intercambian los valores
	if (!esCadenaVacia(linf) && !esCadenaVacia(lsup) && linf > lsup){
		var aux = lsup;
		lsup = linf;
		linf = aux;
	}//if	
	
	if ((esCadenaVacia(linf) || this.comparar(valor1,linf,Validador.MAYORIGUAL,tipo)) && 
		(esCadenaVacia(lsup) || this.comparar(valor1,lsup,Validador.MENORIGUAL,tipo)))
		return true;
		
	if (sMens==undefined) var sMens = "";
	if (sMens=="")
		sMens = "El valor del campo {campo} debe estar comprendido entre el valor de {campolinf} y {campolsup}.";
		
	this.agregarError(buildMessage(sMens,
		new Param("campo", this.nombreCampo(campo1)),
		new Param("campolinf", this.nombreCampo(campolinf)),
		new Param("campolsup", this.nombreCampo(campolsup))), campo1, tipoError);
		
	return false;				
}

/**
 * Comprueba si el valor del campo1 se encuentra entre los valores valores (un array de valores)
 * Devuelve true si se cumple la comparacion o false en caso contrario.
 * En el caso de comparar fechas debe indicarse en el campo tipo (FECHA_EUROPA o FECHA_USA o FECHA_ISO).
 * 
 * La comparacion funciona asi, si se usa comparacion IGUAL (por defecto) se cumple si el valor del campo1 coincide con 
 * alguno de los valores indicados en el array valores.
 * Si se usa otra comprobacion se comprueba que se cumpla para todos los valores indicados	
 * @param String campo1
 * @param Array valores
 * @param int comparacion Codigo de la comparacion a realizar Validador.MAYOR, Validador.MENOR... del parametro1 con respecto al parametro2 (por defecto IGUAL)
 * @param int tipo Tipo de los datos a comparar (del campo1 y los elementos del vector valores)
 * @param int tipoError Tipo de error que se generara en caso de no evaluarse la comparacion (Validador.ERROR, Validador.WARNING) (por defecto ERROR)
 * @param String sMens Mensaje de error a generar en caso de que no se cumpla la comparacion (Si no se indica se generar? uno por defecto)
 * @return bool
 * @access public
*/
Validador.prototype.validarCampoVSListaValores = 
function (campo1, valores, comparacion, tipo, tipoError, sMens){
	var i, value;
	var valor1 = this.valorCampo(campo1);
	if (esCadenaVacia(valor1))
		return true;

	if (comparacion == undefined) 
		comparacion = Validador.IGUAL; //valor por defecto				
	
	var ok = true;
	if (comparacion == Validador.IGUAL){
		for(i=0; i< valores.length; i++){
			value = valores[i];
			if (this.comparar(valor1,value,comparacion,tipo))
				return true;			
		}//for
	}else{
		for(i=0; i< valores.length; i++){
			value = valores[i];
			if (!this.comparar(valor1,value,comparacion,tipo)){
				ok = false;
				break;
			}
		}//for
		if (ok)
			return true;
	}//else
	
		
	if (sMens==undefined) var sMens = "";
	if (sMens==""){
		sMens = "El valor del campo {campo}";
		if (comparacion == Validador.IGUAL)
			sMens+=" debe tener uno de los siguientes valores: {valores}.";
		else
			sMens+=" debe ser {comparacion} los valores: {valores}.";
	}
	
	this.agregarError(buildMessage(sMens,
		new Param("campo",this.nombreCampo(campo1)),
		new Param("valores",valores),
		new Param("comparacion",this.nombreComparacion(comparacion, tipo))), campo1, tipoError);

	return false;					
}

/**
 * Comprueba si el valor del campo1 se encuentra entre los valores  de los campos campos (un array de nombres de campos)
 * Devuelve true si se cumple la comparacion o false en caso contrario.
 * En el caso de comparar fechas debe indicarse en el campo tipo (FECHA_EUROPA o FECHA_USA o FECHA_ISO).
 * 
 * La comparacion funciona asi, si se usa comparacion IGUAL (por defecto) se cumple si el valor del campo1 coincide con 
 * el valor de alguno de los campos indicados.
 * Si se usa otra comprobacion se comprueba que se cumpla para todos los valores de los campos indicados
 * @param String campo1
 * @param String campos
 * @param int comparacion Codigo de la comparacion a realizar Validador.MAYOR, Validador.MENOR... del parametro1 con respecto al parametro2 (por defecto IGUAL)
 * @param int tipo Tipo de los datos a comparar 
 * @param int tipoError Tipo de error que se generara en caso de no evaluarse la comparacion (Validador.ERROR, Validador.WARNING) (por defecto ERROR)
 * @param String sMens Mensaje de error a generar en caso de que no se cumpla la comparacion (Si no se indica se generar? uno por defecto)
 * @return bool
 * @access public
 */
Validador.prototype.validarCampoVSListaCampos = 
function (campo1, campos, comparacion, tipo, tipoError, sMens){
	var i, value, ok;
	var valor1 = this.valorCampo(campo1);
	if (esCadenaVacia(valor1))
		return true; //si no tiene valor el campo1 no tiene sentido realizar la comparacion
	/*ok = false;
	for(key in campos){ 
		value = this.valorCampo(campos[key]);	
		if (this.tieneValor(value)){
			ok = true;
			break;
		}//if
	}//for
	if (!ok)
		return true;//si ninguno de los campos tiene valor no tiene sentido realizar la comparacion
		*/
	if (comparacion == undefined) 
		comparacion = Validador.IGUAL; //valor por defecto	de la comparacion		
	
	ok = true;
	if (comparacion == Validador.IGUAL){ //si la comparacion es de igualdad
		for(i=0; i< campos.length; i++){
			value = this.valorCampo(campos[i]);
			if (this.comparar(valor1,value,comparacion,tipo))
				return true; //basta con que coincida con uno de los valores de los campos
		}//for
	}else{//para el resto de comparaciones
		for(i=0; i<campos.length; i++){
			value = this.valorCampo(campos[i]); //la comparacion debe cumplirse para todos los campos
			if (!this.tieneValor(value))//si el campo no tiene valor no se compara
				continue;
			if (!this.comparar(valor1,value,comparacion,tipo)){
				ok = false;
				break;
			}//if
		}//for
		if (ok)
			return true;
	}//else
	
	if (sMens==undefined) var sMens = "";
	if (sMens==""){
		sMens = "El valor del campo {campo}";
		if (comparacion == Validador.IGUAL)
			sMens+=" debe ser igual que uno de los siguientes: {campos}.";
		else
			sMens+=" debe ser {comparacion} los valores de : {campos}.";
	}//if
	this.agregarError(buildMessage(sMens,
		new Param("campo",this.nombreCampo(campo1)),
		new Param("campos",this.nombreCampo(campos)),
		new Param("comparacion",this.nombreComparacion(comparacion, tipo))), campo1, tipoError);

	return false;				
}

/**
 * Comprueba que el valor de todos los campos indicados cumplan la expresion regular exp
 * @param String campo1
 * @param String exp Expresion regular
 * @param int tipoError Tipo de error que se generara en caso de no evaluarse la comparacion (Validador.ERROR, Validador.WARNING) (por defecto ERROR)
 * @param String sMens Mensaje de error a generar en caso de que no se cumpla la comparacion (Si no se indica se generar? uno por defecto)
 * @return bool
 * @access public
 */
Validador.prototype.validarCamposVSExpresionRegular = 
function (campos, exp, tipoError, sMens){
	var ok = true;
	var campo, valor;
	var re = new RegExp(exp);
	
	if (sMens==undefined) var sMens = "";
	if (sMens=="")
		sMens = "El campo {campo} no tiene el formato correcto.";			
	
	for(var i=0; i< campos.length; i++){
		campo = campos[i];
		valor = this.valorCampo(campo);
		if (!esCadenaVacia(valor))
		if (!re.test(valor)){
			ok = false;
			this.agregarError(buildMessage(sMens,
				new Param("campo", this.nombreCampo(campo))), campo, tipoError);
		}//if
	}//foreach
			
	return ok;
}

/**
 * Compara la longitud (el numero de caracteres de su valor) de los campos 
 * indicados con <code>longitud</code> y una comparacion <code>comparacion</code>
 * @param Array campo1
 * @param int longitud
 * @param int comparacion Codigo de la comparacion a realizar Validador.MAYOR, Validador.MENOR... del parametro1 con respecto al parametro2 (por defecto IGUAL)
 * @param int tipoError Tipo de error que se generara en caso de no evaluarse la comparacion (Validador.ERROR, Validador.WARNING) (por defecto ERROR)
 * @param String sMens Mensaje de error a generar en caso de que no se cumpla la comparacion (Si no se indica se generar? uno por defecto)
 * @return bool
 * @access public
 */
Validador.prototype.validarLongitudCampos = 
function(campos, longitud, comparacion, tipoError, sMens){
	var ok = true;
		
	if (comparacion == undefined) 
		comparacion = Validador.IGUAL; //valor por defecto	

	if (sMens==undefined) var sMens = "";
	if (sMens=="")
		sMens = "La longitud del campo {campo} debe ser {comparacion} {longitud}.";	
	
	if (typeof(campos)!="object")
		campos = new Array(campos);
	//alert(campos);
	for (var key in campos){
		campo = campos[key];
		valor = this.valorCampo(campo);
		//alert(new String(valor).length);
		if (esCadenaVacia(valor)) //si el campo no tiene valor no se valida
			continue;
		
		if (!this.comparar(new String(valor).length, longitud, comparacion)){
			ok = false;
			
			this.agregarError(buildMessage(sMens,
				new Param("campo",this.nombreCampo(campo)),
				new Param("longitud", longitud),
				new Param("comparacion", this.nombreComparacion(comparacion))), campo, tipoError);
		}//if
	}
	
	return ok;
}

/**
 * Comprueba que los campos indicados sean del tipo indicado
 * @param Array campos
 * @param int tipo Tipo de los datos a comparar (de campo1 y campo2)
 * @param int tipoError Tipo de error que se generara en caso de no evaluarse la comparacion (Validador.ERROR, Validador.WARNING) (por defecto ERROR)
 * @param String sMens Mensaje de error a generar en caso de que no se cumpla la comparacion (Si no se indica se generar? uno por defecto)
 * @return bool
 * @access public
 */	
Validador.prototype.validarTipoCampos = 
function (campos, tipo, tipoError, sMens){
	if (sMens==undefined) var sMens = "";	
	var sMens2 = "";
	var ok = true;
	var campo, i;

	for (var key in campos){
		campo = campos[key];
		valor = this.valorCampo(campo);
		if (!this.tieneValor(valor)) //si el campo no tiene valor no se valida su tipo
			continue;

		switch(tipo){
		case Validador.TIPO_FECHA_EUROPA:
			ok = validarFechaEuropa(valor);
			sMens2 = "El campo {campo} debe contener una fecha válida en formato día-mes-año.";
			break;
		case Validador.TIPO_FECHA_USA:
			ok = validarFechaUSA(valor);
			sMens2 = "El campo {campo} debe contener una fecha válida en formato mes-día-año.";
			break;
		case Validador.TIPO_FECHA_ISO:
			ok = validarFechaISO(valor);
			sMens2 = "El campo {campo} debe contener una fecha válida en formato año-mes-día.";
			break;			
		case Validador.TIPO_HORA:
			ok = validarHora(valor);
			sMens2 = "El campo {campo} debe contener una hora válida.";
			break;			
		case Validador.TIPO_ENTERO:
			ok = validarEntero(valor);
			sMens2 = "El campo {campo} debe contener un número entero.";
			break;
		case Validador.TIPO_DECIMAL:
			ok = validarReal(valor);
			sMens2 = "El campo {campo} debe contener un número real.";	
			break;
		case Validador.TIPO_EMAIL:
			ok = validarEmail(valor);
			sMens2 = "El campo {campo} debe contener una dirección de email válida.";
			break;
		case Validador.TIPO_EMAILS:
			var vEmails = valor.split(/[,]/);
			ok = true;
			for(i=0; i<vEmails.length; i++)
			{
				if (!validarEmail(vEmails[i]))
				{	
					ok = false;
					break;
				}
			}
			sMens2 = "La dirección de email \"" +vEmails[i]+ "\" del campo {campo} no parece correcta.";
			break;
		case Validador.TIPO_NIF:
			ok = validarNIF(valor);
			sMens2 = "El campo {campo} no contiene un NIF válido.";
			break;
		case Validador.TIPO_CIF:
			ok = validarCIF(valor);
			sMens2 = "El campo {campo} no contiene un CIF válido.";
			break;
		case Validador.TIPO_NIF_CIF:
			ok = validarCIF(valor) || validarNIF(valor);
			sMens2 = "El campo {campo} no contiene un CIF/NIF válido.";
			break;
		case Validador.TIPO_IP:
			ok = validarIP(valor);
			sMens2 = "El campo {campo} debe contener una dirección IP válida.";
			break;
		case Validador.TIPO_CP:
			ok = /^[0-9]{5}$/.test(valor);
			sMens2 = "El código postal (CP) no es válido."; 
			break;
		case Validador.TIPO_TELEFONO:
			sMens2 = "El campo {campo} no contiene un teléfono válido.";
			ok = /^[0-9]{9,}$/.test(valor);
			break;
		case Validador.TIPO_MOVIL:
			sMens2 = "El campo {campo} no contiene un teléfono móvil válido.";
			ok = /^6[0-9]{8}$/.test(valor);
			break;			
		case Validador.TIPO_CUENTA_BANCARIA:
			sMens2 = "El campo {campo} no contiene un número de cuenta válido.";
			ok = validarCuentaBancaria(valor);
			break;
		case Validador.TIPO_NOMBRE:
		case Validador.TIPO_MONEDA:
		case Validador.TIPO_URL:
		default:
			alert("EL TIPO INDICADO NO SE ENCUENTRA.");
			return false;
		}//switch
		if (sMens=="")
			sMens = sMens2;
		if (!ok)
			this.agregarError(buildMessage(sMens,
				new Param("campo",this.nombreCampo(campo))),campo, tipoError);
	}
	return ok;
}

/**
 * Todos los campos indicados en el array campos deben tener valor
 * @param Array campos
 * @param int tipoError Tipo de error que se generara en caso de no evaluarse la comparacion (Validador.ERROR, Validador.WARNING) (por defecto ERROR)
 * @param String sMens Mensaje de error a generar en caso de que no se cumpla la comparacion (Si no se indica se generar? uno por defecto)
 * @return bool
 * @access public
 */	 
Validador.prototype.validarCamposRequeridos = 
function (campos, tipoError, sMens){
	var ok = true;
	var campo;
	if (sMens==undefined) var sMens = "";
	if (sMens=="")
		sMens = "El campo {campo} debe tener valor.";			
	for(var i=0;i<campos.length;i++){
		campo = campos[i];
		if (!this.tieneValor(this.valorCampo(campo))){
			ok = false;
			this.agregarError(buildMessage(sMens, 
				new Param("campo",this.nombreCampo(campo))), campo, tipoError);
		}//if
	}//for

	return ok;
}

/**
 * Reliza la siguiente validacion: Alguno de los campos indicados en el array campos debe tener valor
 * @param Array campos
 * @param int tipoError Tipo de error que se generara en caso de no evaluarse la comparacion (Validador.ERROR, Validador.WARNING) (por defecto ERROR)
 * @param String sMens Mensaje de error a generar en caso de que no se cumpla la comparacion (Si no se indica se generar? uno por defecto)
 * @return bool
 * @access public
 */	 
Validador.prototype.validarCamposRequeridosOR = 
function (campos, tipoError, sMens){
	var campo, aux="", mens;
	var todosNombresIguales = true;
	
	if (sMens==undefined) var sMens = "";
	if (sMens=="")
		sMens = "Al menos uno de los siguientes campos debe tener valor: {campos}.";

	for(var i=0;i<campos.length;i++){
		campo = campos[i];
		
		if (this.tieneValor(this.valorCampo(campo)))
			return true;
		if (todosNombresIguales){
			if (aux!=this.nombreCampo(campo) && aux!="")
				todosNombresIguales = false;
			aux = this.nombreCampo(campo);
		}
	}//for
	
	if (todosNombresIguales){
		if (sMens=="")
			sMens = "El campo "+aux+" debe tener valor.";
	}
		
	this.agregarError(buildMessage(sMens, 
		new Param("campos",campos)), campos[0], tipoError);
		
	return false;
}

/**
 * Valida que sólo uno de los campos indicados en el array campos tenga valor
 * @param Array campos
 * @param int tipoError Tipo de error que se generara en caso de no evaluarse la comparacion (Validador.ERROR, Validador.WARNING) (por defecto ERROR)
 * @param String sMens Mensaje de error a generar en caso de que no se cumpla la comparacion (Si no se indica se generar? uno por defecto)
 * @return bool
 * @access public
 */
Validador.prototype.validarCamposRequeridosXOR = 
function(campos, tipoError, sMens){
	
	var num = 0;
	var campo;
	for(var i=0;i<campos.length;i++){
		campo = campos[i];
		if (this.tieneValor(this.valorCampo(campo))){
			num++;
		}//if
	}

	if (sMens==undefined) var sMens = "";

	//segun el numero de campos rellenados:
	switch(num){
	case 1: return true;
	case 0: //no se ha rellenado ningun campo
		if (sMens=="")
			sMens = "Uno de los siguientes campos debe tener valor: {campos}.";
		break;
	default:
		if (sMens=="")
			sMens = "Sólo uno de los siguientes campos debe tener valor: {campos}.";
	}//switch
			
	this.agregarError(buildMessage(sMens,
		new Param("campos",this.nombreCampo(campos))), campos[0], tipoError);

	return false;
}

/**
 *  Muestra una alerta con los errores ocurridos en el 
 * proceso de validación. Situa el foco en el primer campo en 
 * el que haya ocurrido algún error
 * @param String sMens Texto introductorio previo al texto de los errores (por defecto: "Ocurrieron los siguientes errores")
 * @access public
 */	
Validador.prototype.mostrarAlert = 
function(sMens){
	if (this.m_vsErrores.length==0)
		return true;

	if (sMens==undefined) var sMens = "";
	if (sMens=="")
		sMens = "Ocurrieron los siguientes errores:";
	sMens+="\n\r";
	for(var i=0; i<this.m_vsErrores.length; i++){
		sMens+="  - "+this.m_vsErrores[i]+" \n\r";
	}
	myAlert(sMens);
	var e = this.m_formu.elements[this.m_vsCamposError[0]];
	try{e.focus();}catch(ex){} //coloca el foco sobre el primer campo en el que se ha detectado un error
}

/**
 * Valida el formulario y marca los campos donde ha ocurrido un error
 * @access public
 */
Validador.prototype.validar = 
function(){
//return true; //descomentar para probar la validacion en el servidor
	var i, e, capa, txt;
	var sError = "  *";
	var sWarning = " !";

	//quita las marcas de error a todos los campos
	var v = document.getElementsByTagName("span");
	for (i=0; i<v.length; i++){
		if (v[i].className == "capaError")
			v[i].innerHTML = "";
	}//for

	//los campos erroneos los marca con un *
	if (Validador.MarcarCamposErroneos)
	for(i=0;i<this.m_vsCamposError.length;i++){
	
		if (e = document.getElementById('capa'+this.m_vsCamposError[i])){
			e.innerHTML = sError;
		}else{
			e = this.getCampo(this.m_vsCamposError[i]);//elemento del formulario
			if (e==null)
				continue;
			if (e.type==undefined)//si es una lista de nodos (como en el caso de radiobuttons)
				e = e[0];
		
			capa  = document.createElement("span"); //se crea un elemento SPAN
			capa.id = "capa"+this.m_vsCamposError[i];
			capa.className = "capaError";
			capa.style.position = "absolute";
			capa.style.color = "red";
			capa.style.fontWeight = "bold";
			capa.style.fontSize="13px";
			
			txt = document.createTextNode(sError); //se crea un nodo de texto "*" y se mete en el SPAN recien creado
			capa.appendChild(txt);

			//e.parentNode.insertBefore(capa,e); //el "*" se inserta justo delante del elemento del formulario
			e.parentNode.insertBefore(capa,e.nextSibling); //el "*" se inserta justo despues del elemento del formulario
		}//else
	}//for

	//los campos erroneos los marca con un !
	for(i=0;i<this.m_vsCamposWarning.length;i++){
		if (e = document.getElementById('capa'+this.m_vsCamposWarning[i]))
			e.innerHTML = sWarning;
		else
		{
			e = this.getCampo(this.m_vsCamposWarning[i]);//elemento del formulario
			
			capa  = document.createElement("span"); //se crea un elemento SPAN
			capa.id = "capa"+this.m_vsCamposWarning[i];
			capa.className = "capaWarning";
			capa.style.position = "absolute";
			capa.style.color = "red";
			capa.style.fontWeight = "bold";
			//capa.style.fontFamily = "comi";
			capa.style.fontSize="12px";			
			
			txt = document.createTextNode(sWarning); //se crea un nodo de texto "*" y se mete en el SPAN recien creado
			capa.appendChild(txt);
		
			e.parentNode.insertBefore(capa, e.nextSibling); //se inserta justo despues del elemento del formulario
		}//else
	}		
	
	if (this.m_bOK){
		for(i=0;i<this.m_vsWarnings.length;i++){
			if (!myConfirm(this.m_vsWarnings[i]+"\r\n &iquest;Está seguro de continuar?"))
				return false;
		}//for
	}//if
	
	return this.m_bOK;
}

//formatos de fecha
Validador.TIPO_FECHA_EUROPA = 1;
Validador.TIPO_FECHA_USA = 2;
Validador.TIPO_FECHA_ISO = 3;
Validador.TIPO_FECHA = 4; //formato de fecha automatico (intenta detectar el tipo)

//tipos a validar
Validador.TIPO_HORA = 101;
Validador.TIPO_ENTERO = 102;
Validador.TIPO_DECIMAL = 103;
Validador.TIPO_MONEDA = 104;
Validador.TIPO_URL = 105;
Validador.TIPO_EMAIL = 106;
Validador.TIPO_NOMBRE = 107;
Validador.TIPO_NIF = 108;
Validador.TIPO_CIF = 109;
Validador.TIPO_NIF_CIF = 110; //CIF o NIF
Validador.TIPO_IP = 111;
Validador.TIPO_CP = 112;
Validador.TIPO_TELEFONO = 113; //telefono fijo o movil
Validador.TIPO_CUENTA_BANCARIA = 114;
Validador.TIPO_MOVIL = 115; //telefono movil
Validador.TIPO_EMAILS = 116; //lista de emails

//tipos de comparacion
Validador.MENOR = 1;
Validador.MENORIGUAL = 2;
Validador.IGUAL = 3;
Validador.MAYOR = 4;
Validador.MAYORIGUAL = 5;
Validador.DISTINTO = 6;

//fechas predefinidas
Validador.HOY = "la fecha actual";

Validador.ERROR = -1;
Validador.WARNING = 99;

Validador.MarcarCamposErroneos = true;