// Body onload utility (supports multiple onload functions)
function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      oldonload();
      func();
    }
  }
}


// Begin validator code

var myValidators = {
		rango_seleccion : function (fieldID,min,max) {
			var elems = document.forms.item(2).elements[fieldID];
			var count=0;
			// Count number of elements checked
			if (elems.length) {
				// There's a collection of elements
				for (var i=0; i<elems.length; i++) {
					if (elems[i].type == "radio" || elems[i].type == "checkbox") {
						if (elems[i].checked)
							count++;
					}
				}
			} else {
				// There's just 1 element
				if (elems.type == "radio" || elems.type == "checkbox") {
					if (elems.checked) count++;
				}
			}
			// Then we answer the question
			if (isUndefined(max)) {
				if (count >= min) {
					return { result:true, problem: "", solution: ""};
				} else {
					if (min == 1)
						return { result:false, problem: "No se ha alcanzado el número mínimo de respuestas", solution: "Debes seleccionar como mínimo %1 opción", args: [min,max,fieldID]};
					else
						return { result:false, problem: "No se ha alcanzado el número mínimo de respuestas", solution: "Debes seleccionar como mínimo %1 opciones", args: [min,max,fieldID]};
				}
			} else {
				if ((count <= max) && (count >= min)) {
					return { result:true, problem: "", solution: ""};
				} else if (count > max) {
					if (max == 1)
						return { result:false, problem: "Se ha superado el número máximo de respuestas", solution: "Debes seleccionar como máximo %2 opción", args: [min,max,fieldID]};
					else
						return { result:false, problem: "Se ha superado el número máximo de respuestas", solution: "Debes seleccionar como máximo %2 opciones", args: [min,max,fieldID]};
				} else if (count < min) {
					if (min == 1)
						return { result:false, problem: "No se ha alcanzado el número mínimo de respuestas", solution: "Debes seleccionar como mínimo %1 opción", args: [min,max,fieldID]};
					else
						return { result:false, problem: "No se ha alcanzado el número mínimo de respuestas", solution: "Debes seleccionar como mínimo %1 opciones", args: [min,max,fieldID]};
				}
			}
			return { result:true, problem: "rango_seleccion", solution: "rango_seleccion"};
		}
		,
		es_psw : function (fieldID, min, max) {
			if (isUndefined(min))
				min = 0;
			var elem = document.forms.item(2).elements.namedItem(fieldID);
			if (elem.value.length < min) {
				if (min == 1)
					return { result:false, problem: "El campo está vacío", solution: "Por favor, introduce algún valor en este campo", args: [min,max,fieldID]};
				else
					return { result:false, problem: "Longitud mínima no alcanzada", solution: "Este campo debe contener un mínimo de %1 caracteres", args: [min,max,fieldID]};
			}
			if (!isUndefined(max)) {
				if (elem.value.length > max) {
					return { result:false, problem: "Longitud máxima sobrepasada", solution: "Por favor, retira %4 caracteres del campo", args: [min,max,fieldID,(elem.value.length-max)]};
				}
			}
			if(elem.value != document.forms.item(2).fpass.value){
				return { result:false, problem: "Contraseña incorrecta", solution: "Por favor, introduce la confirmación de la contraseña", args: [min,max,fieldID]};
                         }
                    
			return { result:true, problem: "", solution: "", args: [fieldID]};
		}
		,
		es_num : function (fieldID, min, max, except) {
			if (isUndefined(min))
				min = 0;
			if (isUndefined(except) || isUndefined(except.length)) {
				except = new Array();
			}
			var elem = document.forms.item(2).elements.namedItem(fieldID);
			var len = elem.value.length;
			for (var i=0; i<len; i++) {
				if (isNaN(elem.value.charAt(i)) && (!except.has(elem.value.charAt(i)))) {
					return { result:false, problem: "Se encontraron letras", solution: "Este campo tan sólo puede contener números. Por favor, retira las letras o signos", args: [min,max,fieldID]};
				}
			}
			if (elem.value.length < min) {
				if (min == 1)
					return { result:false, problem: "El campo está vacío", solution: "Por favor, introduce algún valor en este campo", args: [min,max,fieldID]};
				else
					return { result:false, problem: "Longitud mínima no alcanzada", solution: "Este campo debe contener un mínimo de %1 dígitos", args: [min,max,fieldID]};
			}
			if (!isUndefined(max)) {
				if (elem.value.length > max) {
					return { result:false, problem: "Longitud máxima sobrepasada", solution: "Por favor, retira %4 dígitos del campo", args: [min,max,fieldID,(elem.value.length-max)]};
				}
			}
			return { result:true, problem: "", solution: "", args: [fieldID]};
		}
		,
		es_alfa : function (fieldID, min, max) {
			if (isUndefined(min))
				min = 0;
			var elem = document.forms.item(2).elements.namedItem(fieldID);
			var len = elem.value.length;
			for (var i=0; i<len; i++) {
				if (!isNaN(elem.value.charAt(i)) && elem.value.charAt(i) != " ") {
					return { result:false, problem: "Se encontraron números", solution: "Este campo tan sólo puede contener letras. Por favor, retira los números", args: [min,max,fieldID]};
				}
			}
			if (elem.value.length < min) {
				if (min == 1)
					return { result:false, problem: "El campo está vacío", solution: "Por favor, introduce algún valor en este campo", args: [min,max,fieldID]};
				else
					return { result:false, problem: "Longitud mínima no alcanzada", solution: "Este campo debe contener un mínimo de %1 letras", args: [min,max,fieldID]};
			}
			if (!isUndefined(max)) {
				if (elem.value.length > max) {
					return { result:false, problem: "Longitud máxima sobrepasada", solution: "Por favor, retira %4 letras del campo", args: [min,max,fieldID,(elem.value.length-max)]};
				}
			}
			return { result:true, problem: "", solution: "", args: [fieldID]};
		}
		,
		es_alfa2num : function (fieldID, min, max) {
			if (isUndefined(min))
				min = 0;
			var elem = document.forms.item(2).elements.namedItem(fieldID);
			if (elem.value.length < min) {
				if (min == 1)
					return { result:false, problem: "El campo está vacío", solution: "Por favor, introduce algún valor en este campo", args: [min,max,fieldID]};
				else
					return { result:false, problem: "Longitud mínima no alcanzada", solution: "Este campo debe contener un mínimo de %1 caracteres", args: [min,max,fieldID]};
			}
			if (!isUndefined(max)) {
				if (elem.value.length > max) {
					return { result:false, problem: "Longitud máxima sobrepasada", solution: "Por favor, retira %4 caracteres del campo", args: [min,max,fieldID,(elem.value.length-max)]};
				}
			}
			return { result:true, problem: "", solution: "", args: [fieldID]};
		}
		,
		es_alfanum : function (fieldID, min, max) {
			if (isUndefined(min))
				min = 0;
			var elem = document.forms.item(2).elements.namedItem(fieldID);
			if (elem.value.length < min) {
				if (min == 1)
					return { result:false, problem: "El campo está vacío", solution: "Por favor, introduce algún valor en este campo", args: [min,max,fieldID]};
				else
					return { result:false, problem: "Longitud mínima no alcanzada", solution: "nada", args: [min,max,fieldID]};
			}
			if (!isUndefined(max)) {
				if (elem.value.length > max) {
					return { result:false, problem: "Longitud máxima sobrepasada", solution: "nada", args: [min,max,fieldID,(elem.value.length-max)]};
				}
			}
			return { result:true, problem: "", solution: "", args: [fieldID]};
		}
		,
		es_nif : function (fieldID, min, max) {
			var elem = document.forms.item(2).elements.namedItem(fieldID);
			if (elem.value.length == 9) {
				var nums = elem.value.substr(0,8);
				var lletra = elem.value.substr(8,9);
				lletra = lletra.toUpperCase();
				if (!isNaN(nums) && isNaN(lletra)){
					var resto,letra_ok;
					var letras = new Array('T','R','W','A','G',
						'M','Y','F','P','D','X','B','N','J','Z','S','Q','V','H',
						'L','C','K','E','T');	
					resto = nums % 23;
					letra_ok = letras[resto];
					if (letra_ok == lletra) {
						return { result:true, problem: "", solution: "", args: [fieldID]};
					} else {
						return { result:false, problem: "NIF incorrecto", solution: "La letra introducida es incorrecta", args: [fieldID]};
					}
				} else {
					return { result:false, problem: "NIF incorrecto", solution: "El NIF se compone de 9 caracteres: 8 dígitos y su letra correspondiente", args: [fieldID]};
				}
			} else {
				if(elem.value.length == 10 && elem.value.indexOf('-')) {
					return { result:false, problem: "NIF incorrecto", solution: "El NIF se compone de 9 caracteres: 8 dígitos y su letra correspondiente, sin guión", args: [fieldID]};
				} else {
					return { result:false, problem: "NIF incorrecto", solution: "El NIF se compone de 9 caracteres: 8 dígitos y su letra correspondiente", args: [fieldID]};
				}
			}
		}
		,
		es_cif : function (fieldID, min, max) {
			var elem = document.forms.item(2).elements.namedItem(fieldID);
			if (elem.value.length == 9) {
				var nums = elem.value.substr(1,9);
				var lletra = elem.value.substr(0,1);
				lletra = lletra.toUpperCase();
				if (!isNaN(nums) && isNaN(lletra)){
					var resto,letra_ok;
					var letras = new Array('T','R','W','A','G',
						'M','Y','F','P','D','X','B','N','J','Z','S','Q','V','H',
						'L','C','K','E','T');	
					resto = nums % 23;
					letra_ok = letras[resto];
					if (letra_ok == lletra) {
						return { result:true, problem: "", solution: "", args: [fieldID]};
					} else {
						return { result:false, problem: "CIF incorrecto", solution: "La letra introducida es incorrecta", args: [fieldID]};
					}
				} else {
					return { result:false, problem: "CIF incorrecto", solution: "El CIF se compone de 9 caracteres: Su letra correspondiente seguidos de 8 dígitos", args: [fieldID]};
				}
			} else {
				if(elem.value.length == 10 && elem.value.indexOf('-')) {
					return { result:false, problem: "CIF incorrecto", solution: "El CIF se compone de 9 caracteres: Su letra correspondiente seguidos de 8 dígitos, sin guión", args: [fieldID]};
				} else {
					return { result:false, problem: "CIF incorrecto", solution: "El CIF se compone de 9 caracteres: Su letra correspondiente seguidos de 8 dígitos", args: [fieldID]};
				}
			}
		}
		,
		es_email : function (fieldID) {
			var elem = document.forms.item(2).elements.namedItem(fieldID);
			var emailStr = elem.value;
			var checkTLD=1;
			var knownDomsPat=/^(com|net|org|edu|int|mil|gov|arpa|biz|aero|name|coop|info|pro|museum)$/;
			var emailPat=/^(.+)@(.+)$/;
			var specialChars="\\(\\)><@,;:\\\\\\\"\\.\\[\\]";
			var validChars="\[^\\s" + specialChars + "\]";
			var quotedUser="(\"[^\"]*\")";
			var ipDomainPat=/^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/;
			var atom=validChars + '+';
			var word="(" + atom + "|" + quotedUser + ")";
			var userPat=new RegExp("^" + word + "(\\." + word + ")*$");
			var domainPat=new RegExp("^" + atom + "(\\." + atom +")*$");
			var matchArray=emailStr.match(emailPat);
			
			if (matchArray==null) {
				return {result: false, problem: "La dirección introducida no parece válida", solution: "Comprueba la @ y los puntos", args: [fieldID]};
			}
			var user=matchArray[1];
			var domain=matchArray[2];
			
			for (i=0; i<user.length; i++) {
				if (user.charCodeAt(i)>127) {
					return {result: false, problem: "La dirección introducida no parece válida", solution: "Comprueba el nombre de usuario (el fragmento anterior a la @)", args: [fieldID]};
				}
			}
			for (i=0; i<domain.length; i++) {
				if (domain.charCodeAt(i)>127) {
					return {result: false, problem: "La dirección introducida no parece válida", solution: "Comprueba el nombre de dominio (el fragmento posterior a la @)", args: [fieldID]};
				}
			}
			if (user.match(userPat)==null) {
				return {result: false, problem: "La dirección introducida no parece válida", solution: "Comprueba el nombre de usuario (el fragmento anterior a la @)", args: [fieldID]};
			}
			var IPArray=domain.match(ipDomainPat);
			if (IPArray!=null) {
				for (var i=1;i<=4;i++) {
					if (IPArray[i]>255) {
						return {result: false, problem: "La dirección introducida no parece válida", solution: "Comprueba la dirección IP introducida", args: [fieldID]};
					}
				}
				return true;
			}
			var atomPat=new RegExp("^" + atom + "$");
			var domArr=domain.split(".");
			var len=domArr.length;
			for (i=0;i<len;i++) {
				if (domArr[i].search(atomPat)==-1) {
					return {result: false, problem: "La dirección introducida no parece válida", solution: "Comprueba el nombre de usuario (el fragmento anterior a la @)", args: [fieldID]};
				}
			}
			if (checkTLD && domArr[domArr.length-1].length!=2 && 
			domArr[domArr.length-1].search(knownDomsPat)==-1) {
				return {result: false, problem: "La dirección introducida no parece válida", solution: "Comprueba el nombre de dominio (el fragmento posterior a la @)", args: [fieldID]};
			}
			if (len<2) {
				return {result: false, problem: "La dirección introducida no parece válida", solution: "Comprueba el nombre de dominio (el fragmento posterior a la @)", args: [fieldID]};
			}
			return {result: true, problem: "", solution: "", args: [fieldID]};
		}
		,
		select_no_es : function (fieldID,needle) {
			var elems = document.forms.item(2).elements[fieldID];
			var count=0;
			if (elems.nodeName != "SELECT") {
				alert("Error! El elemento "+fieldID+" no es un SELECT y no puede ser validado contra la función 'select_no_es'");
				return {result: false, problem: "developer error", solution: "element is not a SELECT", args: [fieldID,needle]};
			}
			if (elems.options.item(elems.selectedIndex).text == needle) {
				return {result: false, problem: "No se ha seleccionado ningún valor", solution: "Por favor, selecciona un valor de la lista", args: [fieldID,needle]};
			} else {
				return {result: true, problem: "", solution: "", args: [fieldID,needle]};
			}
		}
};

// Dummy link to real validator.validate()
function validate() {
	if (!isUndefined(top.validator)) {
		return top.validator.validate();
	} else {
		return true;
	}
}

// Window.onload callback
function validatorGenesis(ev) {

	if (isUndefined(ev) && !isUndefined(window.event)) {
		ev = window.event;
	} else if (isUndefined(ev)) {
		//return false;
	}
	if (isUndefined(validatorLangCode)) {
		validatorLangCode = "es_ES";
	}
	if (isUndefined(top.validator)) {
		top.validator = new IWSValidator(myValidators, validatorLangCode);
	}
	document.forms.item(2).onsubmit = function () {return validate();}
}

// Method to blink informed parents

function blinkInformedNodes(firstBlink) {
	var styleshit;
	var len = document.styleSheets.length;
	for (var i=0; i<len; i++) {
		if (document.styleSheets.item(i).title == "Validacio") {
			styleshit = document.styleSheets.item(i);
			break;
		}
	}
	var rule;
	if (isUndefined(styleshit.cssRules)) {
		var len = styleshit.rules.length;
		for (var i=0; i<len; i++) {
			if (styleshit.rules.item(i).selectorText == "."+top.validator.informClassName) {
				rule = styleshit.rules.item(i);
				break;
			}
		}
	} else {
		var len = styleshit.cssRules.length;
		for (var i=0; i<len; i++) {
			if (styleshit.cssRules.item(i).selectorText == "."+(top.validator.informClassName)) {
				rule = styleshit.cssRules.item(i);
				break;
			}
		}
	}
	if (isUndefined(rule.style.setProperty)) {
		if (top.validator.blinking) {
			rule.style.backgroundColor = "rgb(255,240,229)";
			top.validator.blinking = false;
		} else {
			rule.style.backgroundColor = "rgb(255,255,255)";
			top.validator.blinking = true;
		}
	} else {
		if (top.validator.blinking) {
			rule.style.setProperty("background-color", "rgb(255,240,229)",null);
			top.validator.blinking = false;
		} else {
			rule.style.setProperty("background-color", "rgb(255,255,255)",null);
			top.validator.blinking = true;
		}
	}
	if (!isUndefined(firstBlink)) {
		window.setTimeout("blinkInformedNodes()", 150);
		window.setTimeout("blinkInformedNodes()", 300);
		window.setTimeout("blinkInformedNodes()", 450);
	}
}







function IWSValidator(validators, lang) {
	this.validators = new Array();
	this.elementos = new Array();
	this.i18n = {
		es_ES : {
			        "nada" :
						"",
				"Este campo necesita correcciones" :
						"Este campo necesita correcciones",
				"No se ha alcanzado el número mínimo de respuestas" :
						"No se ha alcanzado el número mínimo de respuestas",
				"Debes seleccionar como mínimo %1 opción" :
						"Debes seleccionar como mínimo %1 opción",
				"Debes seleccionar como mínimo %1 opciones" :
						"Debes seleccionar como mínimo %1 opciones",
				"Se ha superado el número máximo de respuestas" :
						"Se ha superado el número máximo de respuestas",
				"Debes seleccionar como máximo %2 opción" :
						"Debes seleccionar como máximo %2 opción",
				"Debes seleccionar como máximo %2 opciones" :
						"Debes seleccionar como máximo %2 opciones",
				"Se encontraron letras" :
						"Se encontraron letras",
				"Este campo tan sólo puede contener números. Por favor, retira las letras o signos" :
						"Este campo tan sólo puede contener números. Por favor, retira las letras o signos",
				"El campo está vacío" :
						"El campo está vacío",
				"Por favor, introduce algún valor en este campo" :
						"Por favor, introduce algún valor en este campo",
				"Longitud mínima no alcanzada" :
						"Este campo es obligatorio",
				"Este campo debe contener un mínimo de %1 dígitos" :
						"Este campo debe contener un mínimo de %1 dígitos",
				"Longitud máxima sobrepasada" :
						"",
				"Por favor, retira %4 dígitos del campo" :
						"Por favor, retira %4 dígitos del campo",
				"Se encontraron números" :
						"Se encontraron números",
				"Este campo tan sólo puede contener letras. Por favor, retira los números" :
						"Este campo tan sólo puede contener letras. Por favor, retira los números",
				"Este campo debe contener un mínimo de %1 letras" :
						"Este campo debe contener un mínimo de %1 letras",
				"Por favor, retira %4 letras del campo" :
						"Por favor, retira %4 letras del campo",
				"Este campo debe contener un mínimo de %1 caracteres" :
						"Este campo debe contener un mínimo de %1 caracteres",
				"Por favor, retira %4 caracteres del campo" :
						"Por favor, retira %4 caracteres del campo",
				"La dirección introducida no parece válida" :
						"La dirección introducida no parece válida",
				"Comprueba la @ y los puntos" :
						"",
				"Comprueba el nombre de usuario (el fragmento anterior a la @)" :
						"",
				"Comprueba el nombre de dominio (el fragmento posterior a la @)" :
						"",
				"Comprueba la dirección IP introducida" :
						"",
				"No se ha seleccionado ningún valor" :
						"No se ha seleccionado ningún valor",
				"Por favor, selecciona un valor de la lista" :
						"Por favor, selecciona un valor de la lista",
				"NIF incorrecto" :
						"NIF incorrecto",
				"La letra introducida es incorrecta" :
						"La letra introducida es incorrecta",
				"El NIF se compone de 8 dígitos seguidos de su letra correspondiente" :
						"El NIF se compone de 8 dígitos seguidos de su letra correspondiente",
				"El NIF se compone de 8 dígitos seguidos de su letra correspondiente, sin guión" :
						"El NIF se compone de 8 dígitos seguidos de su letra correspondiente, sin guión",
				"El NIF se compone de 9 caracteres: 8 dígitos seguidos de su letra correspondiente" :
						"El NIF se compone de 9 caracteres: 8 dígitos seguidos de su letra correspondiente",
				"CIF incorrecto" :
						"CIF incorrecto",
				"La letra introducida es incorrecta" :
						"La letra introducida es incorrecta",
				"El CIF se compone de 9 caracteres: Su letra correspondiente seguidos de 8 dígitos" :
						"El CIF se compone de 9 caracteres: Su letra correspondiente seguidos de 8 dígitos",
				"El CIF se compone de 9 caracteres: Su letra correspondiente seguidos de 8 dígitos, sin guión" :
						"El CIF se compone de 9 caracteres: Su letra correspondiente seguidos de 8 dígitos, sin guión",
				"El CIF se compone de 9 caracteres: Su letra correspondiente seguidos de 8 dígitos" :
						"El CIF se compone de 9 caracteres: Su letra correspondiente seguidos de 8 dígitos",
				"Contraseña incorrecta" :
						"Contraseña incorrecta",
				"Se encontraron errores en el formulario. Porfavor, revise los valores introducidos" :
						"Se encontraron errores en el formulario. Por favor, revise los valores introducidos",
				"Por favor, introduce la confirmación de la contraseña" :
						"Por favor, introduce correctamente la confirmación de la contraseña"
			},
		ca_ES : {
			        "nada" :
						"", 
				"Este campo necesita correcciones" :
						"Aquest camp necessita correccions",
				"No se ha alcanzado el número mínimo de respuestas" :
						"No s'ha arribat al nombre mínim de respostes",
				"Debes seleccionar como mínimo %1 opción" :
						"Has de seleccionar com a mínim %1 opció",
				"Debes seleccionar como mínimo %1 opciones" :
						"Has de seleccionar un mínim de %1 opcions",
				"Se ha superado el número máximo de respuestas" :
						"S'ha superat el nombre màxim de respostes",
				"Debes seleccionar como máximo %2 opción" :
						"Pots seleccionar com a màxim %2 opció",
				"Debes seleccionar como máximo %2 opciones" :
						"Pots seleccionar un màxim de %2 opcions",
				"Se encontraron letras" :
						"S'han trobat lletres",
				"Este campo tan sólo puede contener números. Por favor, retira las letras o signos" :
						"Aquest camp només pot contenir nombres. Si et plau, retira qualsevol lletra o signe",
				"El campo está vacío" :
						"El camp és buit",
				"Por favor, introduce algún valor en este campo" :
						"Si et plau, introdueix algun valor en aquest camp",
				"Longitud mínima no alcanzada" :
						"Aquest camp és obligatori",
				"Este campo debe contener un mínimo de %1 dígitos" :
						"Aquest camp ha de contindre un mínim de %1 dígits",
				"Longitud máxima sobrepasada" :
						"",
				"Por favor, retira %4 dígitos del campo" :
						"",
				"Se encontraron números" :
						"S'han trobat nombres",
				"Este campo tan sólo puede contener letras. Por favor, retira los números" :
						"Aquest camp només pot contenir lletres. Si et plau, retira els nombres",
				"Este campo debe contener un mínimo de %1 letras" :
						"",
				"Por favor, retira %4 letras del campo" :
						"",
				"Este campo debe contener un mínimo de %1 caracteres" :
						"Aquest camp ha de contindre un mínim de %1 caràcters",
				"Por favor, retira %4 caracteres del campo" :
						"",
				"La dirección introducida no parece válida" :
						"L'adreça introduïda no sembla vàlida",
				"Comprueba la @ y los puntos" :
						"",
				"Comprueba el nombre de usuario (el fragmento anterior a la @)" :
						"",
				"Comprueba el nombre de dominio (el fragmento posterior a la @)" :
						"",
				"Comprueba la dirección IP introducida" :
						"Comprova l'adreça IP introduïda",
				"No se ha seleccionado ningún valor" :
						"No s'ha seleccionat cap valor",
				"Por favor, selecciona un valor de la lista" :
						"Si et plau, selecciona un valor de la llista",
				"NIF incorrecto" :
						"NIF incorrecte",
				"La letra introducida es incorrecta" :
						"La lletra introduïda és incorrecta",
				"El NIF se compone de 8 dígitos seguidos de su letra correspondiente" :
						"El NIF es composa de 8 dígits seguits de la seva lletra corresponent",
				"El NIF se compone de 8 dígitos seguidos de su letra correspondiente, sin guión" :
						"El NIF es composa de 8 dígits seguits de la seva lletra corresponent, sense guió",
				"El NIF se compone de 9 caracteres: 8 dígitos seguidos de su letra correspondiente" :
						"El NIF es composa de 9 caràcters: 8 dígits seguits de la seva lletra corresponent",
				"CIF incorrecto" :
						"CIF incorrecto",
				"La letra introducida es incorrecta" :
						"La lletra introduïda és incorrecta",
				"El CIF se compone de 9 caracteres: Su letra correspondiente seguidos de 8 dígitos" :
						"El CIF es composa de 9 caràcters: La seva lletra corresponent seguida de 8 dígits",
				"El CIF se compone de 9 caracteres: Su letra correspondiente seguidos de 8 dígitos, sin guión" :
						"El CIF es composa de 9 caràcters: La seva lletra corresponent seguida de 8 dígits, sense guió",
				"El CIF se compone de 9 caracteres: Su letra correspondiente seguidos de 8 dígitos" :
						"El CIF es composa de 9 caràcters: La seva lletra corresponent seguida de 8 dígits",
				"Contraseña incorrecta" :
						"Contrasenya incorrecta",
				"Se encontraron errores en el formulario. Porfavor, revise los valores introducidos" :
						"S'han trobat errors al formulari. Si us plau, reviseu els valors introduïts",
				"Por favor, introduce la confirmación de la contraseña" :
						"Si us plau, introdueixi correctament la confirmació de la contrasenya"
			},
		en_ES : {
               "Este campo necesita correcciones" :
                       "Please, check this value",
               "No se ha alcanzado el número mínimo de respuestas" :
                       "Minimum number of answers not reached",
               "Debes seleccionar como mínimo %1 opción" :
                       "You should select at least %1 option",
               "Debes seleccionar como mínimo %1 opciones" :
                       "You should select at least %1 options",
               "Se ha superado el número máximo de respuestas" :
                       "Maximum number of answers surpassed",
               "Debes seleccionar como máximo %2 opción" :
                       "You should select at last %2 option",
               "Debes seleccionar como máximo %2 opciones" :
                       "You should select at last %2 options",
               "Se encontraron letras" :
                       "Letters were found",
               "Este campo tan sólo puede contener números. Por favor, retira las letras o signos" :
                       "This field can only contain numbers. Please, remove any letter or sign",
               "El campo está vacío" :
                       "The value is empty",
               "Por favor, introduce algún valor en este campo" :
                       "Please, input any value in this field",
               "Longitud mínima no alcanzada" :
                       "Minimum length not reached",
               "Este campo debe contener un mínimo de %1 dígitos" :
                       "This field should contain at last %1 digits",
               "Longitud máxima sobrepasada" :
                       "Maximum length surpassed",
               "Por favor, retira %4 dígitos del campo" :
                       "Please, remove %4 digits of the value",
               "Se encontraron números" :
                       "Numbers were found",
               "Este campo tan sólo puede contener letras. Por favor, retira los números" :
                       "This field can only contain letters. Please, remove any number",
               "Este campo debe contener un mínimo de %1 letras" :
                       "This field should contain at least %1 letters",
               "Por favor, retira %4 letras del campo" :
                       "Please, remove %4 letters of the value",
               "Este campo debe contener un mínimo de %1 caracteres" :
                       "This field should contain at least %1 characters",
               "Por favor, retira %4 caracteres del campo" :
                       "Please, remove %4 characters of the value",
               "La dirección introducida no parece válida" :
                       "The address doesn't seem valid",
               "Comprueba la @ y los puntos" :
                       "Check the @ and the dots",
               "Comprueba el nombre de usuario (el fragmento anterior a la @)" :
                       "Check the user name (the word just before the @)",
               "Comprueba el nombre de dominio (el fragmento posterior a la @)" :
                       "Check the host name (the word after the @)",
               "Comprueba la dirección IP introducida" :
                       "Check the IP address",
               "No se ha seleccionado ningún valor" :
                       "You haven't selected any value",
							"Se encontraron errores en el formulario. Porfavor, revise los valores introducidos" :
									"Some errors detected in the form. Please, double-check the values",
               "Por favor, selecciona un valor de la lista" :
                       "Please, select any value from the list"
           }

	};
	this.init(validators, lang);
}

// Public properties
IWSValidator.prototype.validationAttributeName = "validacio";
IWSValidator.prototype.informClassName = "nonvalid";
IWSValidator.prototype.labelClassName = "errorLabel";
IWSValidator.prototype.iconNonValidPath = "iconvalidar.gif";
IWSValidator.prototype.validators;
IWSValidator.prototype.elementos;
IWSValidator.prototype.i18n;
IWSValidator.prototype.i18n_code = "es_ES";
IWSValidator.prototype.matchRegExp;
IWSValidator.prototype.blinking;
		
IWSValidator.prototype.init = function(validators, lang) {
	if (!isUndefined(lang) && !isUndefined(this.i18n[lang])) {
		this.i18n_code = lang;
	}
	if (!isUndefined(validators)) {
		for (var i in validators) {
			this.validators[i] = validators[i];
		}
	}
	// preload inform icon
	var tempImg = new Image();
	tempImg.src = this.iconNonValidPath;
	
	this.blinking = false;
	this.matchRegExp = /informa\d+/;
	
	var elems = document.getElementsByTagName("INPUT");
	var len = elems.length;
	for (var i=0; i<len; i++) {
		var attrib = elems.item(i).getAttribute(this.validationAttributeName);
		var name = elems.item(i).getAttribute("name");
		var repeatFlag = 0;
		if (!isUndefined(attrib)) {
			for (var j=0; j<this.elementos.length; j++) {
				if (name == this.elementos[j].__element.getAttribute("name"))
					repeatFlag = 1;
			}
			if (!repeatFlag)
				this.elementos.push(new ValidatedInput(elems.item(i), this));
		}
	}
	var elems = document.getElementsByTagName("SELECT");
	var len = elems.length;
	for (var i=0; i<len; i++) {
		var attrib = elems.item(i).getAttribute(this.validationAttributeName);
		var name = elems.item(i).getAttribute("name");
		var repeatFlag = 0;
		if (!isUndefined(attrib)) {
			for (var j=0; j<this.elementos.length; j++) {
				if (name == this.elementos[j].__element.getAttribute("name"))
					repeatFlag = 1;
			}
			if (!repeatFlag)
				this.elementos.push(new ValidatedInput(elems.item(i), this));
		}
	}
}

IWSValidator.prototype.getI18nString = function(strcode) {
	if (!isUndefined(this.i18n[this.i18n_code][strcode]))
		return this.i18n[this.i18n_code][strcode];
	else
		return "Undefined i18n string: "+strcode;
}

IWSValidator.prototype.validate = function() {
	var len = this.elementos.length;
	var result = new Array();
	for (var i=0; i<len; i++) {
		var accio = this.elementos[i].validate();
		if (accio.result !== true) {
			result.push(false);
			accio.problem = this.getI18nString(accio.problem);
			accio.solution = this.getI18nString(accio.solution);
			for (var j=0; j<accio.args.length; j++) {
				accio.problem = accio.problem.replace("%"+(j+1),accio.args[j]);
				accio.solution = accio.solution.replace("%"+(j+1),accio.args[j]);
			}
			this.elementos[i].showInvalid( accio.problem, accio.solution );
		} else {
			result.push(true);
			this.elementos[i].showValid( accio.problem, accio.solution );
		}
	}
	if (result.has(false)) {
		var parseURL = window.location.href;
		parseURL = parseURL.substring(0,parseURL.indexOf('#'));
		var elemAnchor = this.elementos[result.find(false)].__elementAnchor;
		if (isUndefined(elemAnchor.scrollIntoView)) {
			if (parseURL != window.location.href) {
				window.location.href = parseURL+"#"+this.elementos[result.find(false)].__defaultClass;
			} else {
				window.location.href = parseURL;
				window.location.href = parseURL+"#"+this.elementos[result.find(false)].__defaultClass;
			}
		} else {
			elemAnchor.scrollIntoView(1);
		}
		window.setTimeout("blinkInformedNodes(1)", 150);
        window.setTimeout("window.alert(\""+this.getI18nString("Se encontraron errores en el formulario. Porfavor, revise los valores introducidos")+"\")", 300);
		return false;
	} else {
		var len = document.forms.item(2).elements.length;
		for (var i=0; i<len; i++) {
			if (document.forms.item(2).elements.item(i).type.toLowerCase() == "submit") {
				document.forms.item(2).elements.item(i).value = document.forms.item(2).elements.item(i).value+"...";
				document.forms.item(2).elements.item(i).disabled = true;
			}
		}
		
		return true;
	}
}

		function ValidatedInput(elem,parent) {
			if (isUndefined(elem)) {
				return false;
			}
			var elemName = elem.getAttribute("name");
			this.__element = elem;
			this.__parent = parent;
			this.__validation = elem.getAttribute(parent.validationAttributeName);
			this.__validationMethodName = this.__validation.substring(0, this.__validation.indexOf('('));
			var tempArgs = this.__validation.substring(this.__validation.indexOf('(')+1);
			if ((tempArgs == ")") || (tempArgs == ");"))
				this.__validationMethodArgs = "('"+elemName+"')";
			else
				this.__validationMethodArgs = "('"+elemName+"',"+tempArgs.substring(0,tempArgs.indexOf(')'))+")";
			this.__informedParents = new Array();
			this.init();
		}
		
		// Private properties
		ValidatedInput.prototype.__defaultValue;
		ValidatedInput.prototype.__defaultClass;
		ValidatedInput.prototype.__element;
		ValidatedInput.prototype.__elementAnchor;
		ValidatedInput.prototype.__parent;
		ValidatedInput.prototype.__validation;
		ValidatedInput.prototype.__validationMethodName;
		ValidatedInput.prototype.__validationMethodArgs;
		ValidatedInput.prototype.__lastValidationState;
		ValidatedInput.prototype.__informedParents;
		
		// Private Methods
		ValidatedInput.prototype.init = function() {
			// Get parent with id starting with validatedBoxPrefix
			var parent = this.__element.parentNode;
			while (!isUndefined(parent)) {
				if ((parent.className != "") && !isUndefined(parent.className)) {
					if (parent.className.match(this.__parent.matchRegExp)) {
						break;
					}
				}
				parent = parent.parentNode;
			}
			if (isUndefined(parent)) {
				// Have no informedParent; default error printing? maybe another day...
				return;
			}
			// Now I got my defaultClass, store it
			this.__defaultClass = parent.className;
			
			// I got my first informed parent, now get the others
			var elems = getElementsByClass(parent.className, "TR");
			var len = elems.length;
			for (var i=0; i<len; i++) {
				this.__informedParents.push(elems[i]);
			}
			var elems = getElementsByClass(parent.className, "TD");
			var len = elems.length;
			for (var i=0; i<len; i++) {
				this.__informedParents.push(elems[i]);
			}
			var elems = getElementsByClass(parent.className, "DIV");
			var len = elems.length;
			for (var i=0; i<len; i++) {
				this.__informedParents.push(elems[i]);
			}
			// And then, pick my anchor
			var elems = document.getElementsByTagName("A");
			var len = elems.length;
			for (var i=0; i<len; i++) {
				var name = elems.item(i).getAttribute("name");
				if (this.__defaultClass == name) {
					this.__elementAnchor = elems.item(i);
				}
			}
		}

		ValidatedInput.prototype.validate = function() {
			if (isUndefined(this.__validation)) {
				// validates by default!
				return { result:this.__defaultValue, problem: "", solution: ""};
			} else {
				if (isUndefined(this.__parent.validators[this.__validationMethodName])){
					return { result:this.__defaultValue, problem: "", solution: ""};
				}
				return eval("this.__parent.validators['"+this.__validationMethodName+"']"+this.__validationMethodArgs);
			}
		}
		
		ValidatedInput.prototype.showInvalid = function(problem, solution) {
			var len = this.__informedParents.length;
			//alert("setting as non valid "+len+" p: "+problem+" s: "+solution);
			for (var i=0; i<len; i++) {
				if (!hasClass(this.__informedParents[i],this.__parent.informClassName)) {
					this.__informedParents[i].className += " "+(this.__parent.informClassName);
				}
			}
			// Now insert the HTML content for invalid fields
			// If the canvas is a TD, then pick it's containing TR
			var tableObj = this.__informedParents[this.__informedParents.length-1];
			if (tableObj.nodeName == "TD") {
				tableObj = tableObj.parentNode;
			}
			var oldTdObj;
			// Now let's pick our error printing canvas cell
			// But take care: if it was originally a TD, look for its defaultClass
			var len = tableObj.childNodes.length;
			if (this.__informedParents[this.__informedParents.length-1].nodeName == "TD") {
				for (var i=0; i<len; i++) {
					if ((tableObj.childNodes.item(i).nodeName == "TD") && (hasClass(tableObj.childNodes.item(i),this.__defaultClass))) {
						oldTdObj = tableObj.childNodes.item(i);
						break;
					}
				}
			} else {
				for (var i=0; i<len; i++) {
					if (tableObj.childNodes.item(i).nodeName == "TD") {
						oldTdObj = tableObj.childNodes.item(i);
						break;
					}
				}
			}
			var tdObj = document.createElement("TD");
			// Copy all old TD's attributes to the new one
			if (isUndefined(tdObj.mergeAttributes)) { // ie-only method, so take care
				for (var i=0; i<oldTdObj.attributes.length; i++) {
					tdObj.setAttribute(oldTdObj.attributes.item(i).nodeName, oldTdObj.attributes.item(i).nodeValue);
				}
			} else {
				tdObj.mergeAttributes(oldTdObj);
			}
			var pObj = document.createElement("P");
			pObj.className = "errorLabel";
			var imgObj = document.createElement("IMG");
			imgObj.setAttribute("src", "iconvalidar.gif");
			imgObj.setAttribute("align", "middle");
			imgObj.setAttribute("alt", this.__parent.getI18nString("Este campo necesita correcciones"));
			var smallObj = document.createElement("SMALL");
			var smallObjTxt = document.createTextNode(problem);
			smallObj.appendChild(smallObjTxt);
			var brObj = document.createElement("BR");
			var spanObj = document.createElement("SPAN");
			var spanObjTxt = document.createTextNode(solution);
			spanObj.appendChild(spanObjTxt);
			pObj.appendChild(imgObj);
			pObj.appendChild(smallObj);
			pObj.appendChild(brObj);
			pObj.appendChild(spanObj);
			tdObj.appendChild(pObj);

			tableObj.replaceChild(tdObj,oldTdObj);
			this.__lastValidationState = false;

			// If informedParent was a TD, put the newly created one inside its collection
			if (this.__informedParents[this.__informedParents.length-1].nodeName == "TD") {
				this.__informedParents[this.__informedParents.length-1] = tdObj;
			}
		}
		
		ValidatedInput.prototype.showValid = function(problem, solution) {
			// Delete the HTML content for invalid fields!
			var tableObj = this.__informedParents[this.__informedParents.length-1];
			if (tableObj.nodeName == "TD") {
				tableObj = tableObj.parentNode;
			}
			var oldTdObj;
			// Now let's pick our error printing canvas cell
			// But take care: if it was originally a TD, look for its defaultClass
			var len = tableObj.childNodes.length;
			if (this.__informedParents[this.__informedParents.length-1].nodeName == "TD") {
				for (var i=0; i<len; i++) {
					if ((tableObj.childNodes.item(i).nodeName == "TD") && (hasClass(tableObj.childNodes.item(i),this.__defaultClass))) {
						oldTdObj = tableObj.childNodes.item(i);
						break;
					}
				}
			} else {
				for (var i=0; i<len; i++) {
					if (tableObj.childNodes.item(i).nodeName == "TD") {
						oldTdObj = tableObj.childNodes.item(i);
						break;
					}
				}
			}
			var tdObj = document.createElement("TD");
			// Copy all old TD's attributes to the new one
			if (isUndefined(tdObj.mergeAttributes)) { // ie-only method, so take care
				for (var i=0; i<oldTdObj.attributes.length; i++) {
					tdObj.setAttribute(oldTdObj.attributes.item(i).nodeName, oldTdObj.attributes.item(i).nodeValue);
				}
			} else {
				tdObj.mergeAttributes(oldTdObj);
			}
			
			tableObj.replaceChild(tdObj,oldTdObj);
			this.__lastValidationState = true;

			// If infdParent was a TD, put the newly created one inside its collection
			if (this.__informedParents[this.__informedParents.length-1].nodeName == "TD") {
				this.__informedParents[this.__informedParents.length-1] = tdObj;
			}

			var len = this.__informedParents.length;
			for (var i=0; i<len; i++) {
				if (hasClass(this.__informedParents[i],this.__parent.informClassName)) {
					this.__informedParents[i].className = this.__informedParents[i].className.replace(" "+ (this.__parent.informClassName), "");
				}
			}
		}



addLoadEvent(validatorGenesis);



// ARRAY EXTENSIONS

if (!Array.prototype.push) Array.prototype.push = function() {
    for (var i=0; i<arguments.length; i++) this[this.length] = arguments[i];
    return this.length;
}

Array.prototype.find = function(value, start) {
    start = start || 0;
    for (var i=start; i<this.length; i++)
        if (this[i]==value)
            return i;
    return -1;
}

Array.prototype.has = function(value) {
    return this.find(value)!==-1;
}

// FUNCTIONAL

function map(list, func) {
    var result = [];
    func = func || function(v) {return v};
    for (var i=0; i < list.length; i++) result.push(func(list[i], i, list));
    return result;
}

function filter(list, func) {
    var result = [];
    func = func || function(v) {return v};
    map(list, function(v) { if (func(v)) result.push(v) } );
    return result;
}

// DOM Extensions

function getElem(elem) {
    if (document.getElementById) {
        if (typeof elem == "string") {
            elem = document.getElementById(elem);
            if (elem===null) throw 'cannot get element: element does not exist';
        } else if (typeof elem != "object") {
            throw 'cannot get element: invalid datatype';
        }
    } else throw 'cannot get element: unsupported DOM';
    return elem;
}

function hasClass(elem, className) {
    return getElem(elem).className.split(' ').has(className);
}

function getElementsByClass(className, tagName, parentNode) {
    parentNode = !isUndefined(parentNode)? getElem(parentNode) : document;
    if (isUndefined(tagName)) tagName = '*';
    return filter(parentNode.getElementsByTagName(tagName),
        function(elem) { return hasClass(elem, className) });
}

function isUndefined(v) {
    if (v === null)
			return true;
		var undef;
    return v===undef;
}



