/**
 * Versión:        1.1
 * Autor:          Agustín Rodríguez Reina
 * E-mail:         agustin@jfactory.es
 * Ult. Actualiz:  13/12/2006
                   Añadidas funciones para validación de "radiobuttons"

 * Utilidad:       Chequeo de Formulario Web
 */


/* ******************************* GENÉRICOS **************************************** */

function enfocar(componente)
{
    componente.focus();
    // Los "select" (listas) no tienen el método "select" (paradojas de la vida)
    if (componente.type != 'select-one') componente.select();
}


/* Se ha producido un error en un 'componente'. Mostramos el mensaje de error,
situamos el cursor sobre el componente y lo seleccionamos. */
function error (msg, componente)
{
    alert (msg);
    enfocar(componente);

    return (false);
}

function vacio (componente, nomComp)
{
    if (componente.value == "")
    {
      error("Debe escribir un valor en el campo '"+ nomComp + "'", componente);
      return (true);
    }
    return (false);
}

function vacioFile (componente, nomComp)
{
    if (componente.value == "")
    {
      error("Debe poner un fichero en el campo '"+ nomComp + "'", componente);
      return (true);
    }
    return (false);
}



/* ******************************* CARACTERES ********************************* */


/* Solo dev. verdadero o falso pero no muestra ningún error */
function isAlpha (valor)
{
    if (valor == "") return (false);

    for (var i= 0; i < valor.length; i++)
        if (! (("a" <= valor.charAt(i)) && (valor.charAt(i) <= "z")
            || ("A" <= valor.charAt(i)) && (valor.charAt(i) <= "Z")))
            return (false);

    return (true);
}

function soloAlpha (componente, nomComponente)
{
    if (! isAlpha(componente.value))
        return error(nomComponente + " solo admite caracteres alfabéticos", componente);
    return (true);
}

/* Solo permite escribir caracteres del alfabeto sobre el cuadro de texto.
Uso: <.... onkeypress="return soloAlpha_keypress(event)" ...>
Restricción: Solo IE4+  */
function soloAlpha_keypress(e)
{
    if (document.all) // IE
    {
        if (((65 <= e.keyCode) && (e.keyCode <= 90)) 	 // A..Z
         || ((97 <= e.keyCode) && (e.keyCode <= 122))    // a..z
         || (13 == e.keyCode))                           // ENTER
             return (true);
        else
        {
            e.keyCode= 0;
            return (false);
        }
    }
    return (true);  // No IE
}

/* Elimina los espacios en blanco del principio y del final de la cadena */
function trim(s)
{
//  Con expresiones regulares:
//    return s.replace(/^\s*/,'').replace(/\s*$/,'')
//    return s.replace(/^\s+|\s+$/g, ''); 
  
  if ((s == null)||(s.length == 0))
    return s;

  for(var start = 0; s.charCodeAt(start) == 32; start++)
    if (start == s.length-1)
        return '';

  for(var end = s.length-1; s.charCodeAt(end) == 32; end--);

  return s.substring(start, end+1); 
}


// Corrige caracteres conflictivos de Word
// Source: http://www.kevinkorb.com/post/37
function removeMSWordChars(str) 
{
    var myCode, intReplacement;
    var myReplacements= new Array();
    myReplacements[8216]= 39;  // Comilla simple apertura -> '
    myReplacements[8217]= 39;  // Comilla simple cierre -> '
    myReplacements[8220]= 34;  // Comilla doble apertura -> "
    myReplacements[8221]= 34;  // Comilla doble cierre -> '
    myReplacements[8211]= 45;  // Guión corto -> -
    myReplacements[8212]= 45;  // Guión largo -> -
    for(c=0; c<str.length; c++) 
    {
        var myCode = str.charCodeAt(c);
        if(myReplacements[myCode] != undefined) 
        {
            intReplacement= myReplacements[myCode];
            str= str.substr(0,c) + String.fromCharCode(intReplacement) + str.substr(c+1);
        }
    }
    return str;
}

// Corrige el formulario completo de caracteres conflictivos de Word
function fixFrmWord(frm)
{
  var nElems= frm.elements.length;

  for(i=0; i < nElems; i++)
  {
    if ((frm.elements[i].type == "text") ||
        (frm.elements[i].type == "textarea"))
    {
      frm.elements[i].value= removeMSWordChars(frm.elements[i].value);
    }
  }
}


/* ******************************* NÚMEROS ********************************* */


/* Tabaja con sólo un carácter. Dev. true si está entre 0..9 */
function isDigit (c)
{
    return ((c >= "0") && (c <= "9"))
}

/* Dev. el nº de letras numéricas que hay en la cadena */
function countNums (valor)
{
    if (valor == "") return 0;

    var resultado= 0;
    for (i= 0; i < valor.length; i++)
        if (isDigit(valor.charAt(i))) ++resultado;

    return (resultado);
}

/* Solo dev. verdadero o falso pero no muestra ningún error */
function isNum (valor)
{
    if (valor == "") return (false);

    for (i= 0; i < valor.length; i++)
        if ((valor.charAt(i) < "0") || ("9" < valor.charAt(i)))
            return (false);

    return (true);
}

function soloNum (componente, nomComponente)
{
    if (! isNum(componente.value))
        return error(nomComponente + " solo admite números", componente);
    return (true);
}

/* El componente debe tener un valor numérico entre 2 valores */
function numEntre (componente, nomComponente, valorIzq, valorDch)
{
	if (! soloNum(componente, nomComponente)) return (false);

    var valor= parseInt(componente.value);

    if (valorIzq == valorDch)
        if (valor != valorIzq)
            return error(nomComponente + " debe tener el valor " + valorIzq, componente);

    if ((valor < valorIzq) || (valorDch < valor))
            return error(nomComponente + " debe tener un valor entre " + valorIzq + " y " + valorDch, componente);

    return (true);
}

/* Obtiene el contenido de la caja de texto y lo convierte a Int
   Todos los caracteres inválidos los borra.
   NOTA: por defecto no acepta números negativos
   USO:
     Negativos: <.... onkeyup="fixNum(this, true)" ...>
     No neg: <.... onkeyup="fixNum(this)" ...>
   RESTRICCIÓN: Requiere "gnral.js"
*/
function fixNum(componente, aceptaNeg)
{
   if (aceptaNeg == null) aceptaNeg= false; // Por defecto
   var s= componente.value;
   var posCursor= 0;

   if(s == null) s= "";
   else
   {
      s= trim(s);
      var i;
      var tmp= "";

      for (i=0; i < s.length; i++)
      {
        var c= s.charAt(i);

        if ((!isNaN(c)) && (c != " ")) tmp += c;  // Es un nº
        else if (aceptaNeg && (i == 0) && (c == "-")) tmp= "-";
        else if (posCursor == 0) posCursor= i;
      }
	  
      s= tmp;
   }
   
   // Evita que cuando no cambie la cadena se mueva el cursor en IE
   if (s != componente.value)
   {
      componente.value= s;
      setCursorPos(componente, posCursor);
   }
}


/* Solo permite escribir números sobre el cuadro de texto.
Uso: <.... onkeypress= "return soloNum_keypress(event)" ...>
Restricción: Solo IE4+  */
function soloNum_keypress(e)
{
    // e.keyCode = Valor UNICODE (ej: 13 = ENTER)
    if (document.all) // IE
        if (((e.keyCode < 48) && (13 != e.keyCode)) || (57 < e.keyCode))
		    return (false);

    return (true);  // Deja escribir en todos los navegadores
}

/** Comprueba si la cadena contiene un nº real válido 
    NOTA: Si "s == null" dev. "false"
*/
function isFloat(s)
{
   if(s == null) return false;
   
   s= trim(s);
   if (s == "") return false;
   
   var i;
   var dotAppeared= false;
  
   if ((s == "-") || (s == ".") || (s == ",")) return false;

   for (i=0; i < s.length; i++)
   {
	 var c= s.charAt(i);
	
     if (c == "-")
     {
        if (i > 0) return false;
     }
     else if ((c == ".") || (c == ","))
     {
        if (dotAppeared) return false;
        else dotAppeared= true;
     }
     else if (isNaN(c)) return false;
   }
  
   return true;
}


function soloFloat (componente, nomComponente)
{
    if (! isFloat(componente.value))
        return error(nomComponente + " solo admite números reales", componente);
    return (true);
}

/* Obtiene el contenido de la caja de texto y lo convierte a Float
   La ',' la convierte a '.'. Todos los caracteres inválidos los borra.
   NOTA: por defecto no acepta números negativos
   USO:
     Negativos: <.... onkeyup="fixFloat(this, true)" ...>
     No neg: <.... onkeyup="fixFloat(this)" ...>
   RESTRICCIÓN: Requiere "gnral.js"
*/
function fixFloat(componente, aceptaNeg)
{
   if (aceptaNeg == null) aceptaNeg= false; // Por defecto
   var s= componente.value;
   var posCursor= 0;

   if(s == null) s= "";
   else
   {
      s= trim(s);
      var i;
      var dotAppeared= false;
      var tmp= "";

      for (i=0; i < s.length; i++)
      {
        var c= s.charAt(i);
		
        // Corregimos el separador decimal
        if (c == ",") c= ".";
		
        if ((!isNaN(c)) && (c != " ")) tmp += c;  // Es un nº
        else if (aceptaNeg && (i == 0) && (c == "-")) tmp= "-";
        else if ((c == "." ) && (!dotAppeared))
        {
          dotAppeared= true;
          tmp += ".";
        }
        else if (posCursor == 0) posCursor= i;
      }
	  
      s= tmp;
   }
   
   // Evita que cuando no cambie la cadena se mueva el cursor en IE
   if (s != componente.value)
   {
      componente.value= s;
      setCursorPos(componente, posCursor);
   }
}


/* Solo permite escribir números, '-', '.' y ',' sobre el cuadro de texto.
   NOTA: Es posible escribir valores incorrectos como "-", "4.-",...
         Por defecto no acepta números negativos, para que los permita "aceptaNeg= true"
   USO:
    Negativos: <.... onkeypress= "return soloFloat_keypress(event, this.value, true)" onkeyup="fixFloat(this, true)" ...>
    No neg: <.... onkeypress= "return soloFloat_keypress(event, this.value)" onkeyup="fixFloat(this)" ...>
   RESTRICCIÓN: Solo IE4+  */
function soloFloat_keypress(e, cadenaIni, aceptaNeg)
{
    if (document.all) // IE
    {
	    if (aceptaNeg == null) aceptaNeg= false; // Por defecto
	
        if (e.keyCode == 13) return true; // ENTER

        if (cadenaIni == null) cadenaIni= "";
        if (e.keyCode == 44) e.keyCode= 46; // , -> .
		
        if (aceptaNeg && (e.keyCode == 45) && (cadenaIni.indexOf("-") == -1)) return true;
		if ((e.keyCode == 46) && (cadenaIni.indexOf(".") == -1)) return true;
		if ((47 < e.keyCode) && (e.keyCode < 58)) return true;
		  
        return false;
    }

    return true;  // Deja escribir en todos los navegadores
}

/* El componente debe tener un valor float entre 2 valores */
function floatEntre (componente, nomComponente, valorIzq, valorDch)
{
    if (! soloFloat(componente, nomComponente)) return (false);

    var valor= parseFloat(componente.value);

    if (valorIzq == valorDch)
        if (valor != valorIzq)
            return error(nomComponente + " debe tener el valor " + valorIzq, componente);

    if ((valor < valorIzq) || (valorDch < valor))
            return error(nomComponente + " debe tener un valor entre " + valorIzq + " y " + valorDch, componente);

    return (true);
}


/* El componente no puede tener más de 'valor' caracteres */
function hasMaxCars (componente, nomComponente, valor)
{
    if (valor < componente.value.length)
       return ! error(nomComponente + " no debe tener más de " + valor + " caracteres", componente);

    return (false);
}

/* El componente debe tener entre 'valorIzq' y valorDch' caracteres */
function entre (componente, nomComponente, valorIzq, valorDch)
{
    if (valorIzq == valorDch)
        if (componente.value.length != valorIzq)
        {
           if (valorIzq == 1)
             return error(nomComponente + " debe tener sólo un caracter", componente);
           else
             return error(nomComponente + " debe tener " + valorIzq + " caracteres exactos", componente);
        }

    if ((componente.value.length < valorIzq) || (valorDch < componente.value.length))
            return error(nomComponente + " debe tener entre " + valorIzq + " y " + valorDch + " caracteres", componente);

    return (true);
}


/* Solo dev. verdadero o falso pero no muestra ningún error */
function isNumConSpaces (valor)
{
    if (valor == "") return (false);

    for (i= 0; i < valor.length; i++)
        if (((valor.charAt(i) < "0") && (valor.charAt(i) != " ")) || ("9" < valor.charAt(i)))
            return (false);

    return (true);
}

function soloNumYspaces (componente, nomComponente)
{
    if (! isNumConSpaces(componente.value))
        return error(nomComponente + " solo admite números y espacios en blanco", componente);
    return (true);
}

/* Solo permite escribir números y espacios sobre el cuadro de texto.
Uso: <.... onkeypress= "return soloNumYspace_keypress(event)" ...>
Restricción: Solo IE4+  */
function soloNumYspace_keypress(e)
{
    // e.keyCode = Valor UNICODE (ej: 13 = ENTER)
    if (document.all) // IE
        if (((e.keyCode < 48) && (32 != e.keyCode) && (13 != e.keyCode)) || (57 < e.keyCode))
		    return (false);

    return (true);  // Deja escribir en todos los navegadores
}



/* *********************************** AÑO *************************************** */


/* Comprueba si es un año de 4 dígitos correcto */
function anno4_valido (componente)
{
    if (componente.value.length != 4)
        return error("El año debe tener 4 dígitos", componente);

    if (! isNum(componente.value))
        return error("El año solo puede contener dígitos", componente);

    return (true);
}



/* ******************************* CÓDIGO POSTAL ********************************* */


/* Comprueba si es un CP correcto en España */
function cpEsp_valido (componente)
{
    if (componente.value.length == 4)
        componente.value= "0" + componente.value;

    if (componente.value.length != 5)
        return error("El código postal debe tener 4 ó 5 dígitos", componente);

    if (! isNum(componente.value))
        return error("El código postal solo puede contener dígitos", componente);

    return (true);
}



/* ******************************* CIF / NIF ********************************* */


function cif_valido (compLetra, compDigitos)
{
    if (! soloAlpha(compLetra, "Letra del CIF")) return (false);
    if (! entre(compLetra, "Letra del CIF", 1, 1)) return (false);

//    if (! soloNum(compDigitos, "Dígitos del CIF")) return (false);
    if (compDigitos.value.length != 8)
        return error("El CIF debe tener 8 dígitos justos, si el suyo tiene menos inserte ceros delante", compDigitos);

    return (true);
}

function nif_valido (compDigitos, compLetra)
{
	if (! soloNum(compDigitos, "Dígitos del NIF")) return (false);
      if (compDigitos.value.length != 8)
          return error("El NIF debe tener 8 dígitos justos, si el suyo tiene menos inserte ceros delante", compDigitos);

	if (! soloAlpha(compLetra, "Letra del NIF")) return (false);
	if (! entre(compLetra, "Letra del NIF", 1, 1)) return (false);

	// Comprueba si la letra es válida a partir de los dígitos
	var caracteres= 'TRWAGMYFPDXBNJZSQVHLCKET';
	var pos= compDigitos.value % 23;
	var carValido= caracteres.substring(pos, pos + 1);

	if (carValido != compLetra.value.toUpperCase())
           return error("NIF erróneo, asegúrese de que lo tecleo correctamente",compDigitos);

	return (true);
}



/* ******************************* CUENTA BANCARIA ******************************* */


/* Devuelve los dígitos de control (DC) de una cuenta bancaria */
function calculaDC(banco, cuenta)
{
	var pesos= new Array(6,3,7,9,10,5,8,4,2,1);
	var result= "";
	var iTemp= 0;
	var n;

	for (n= 0; n <= 7; n++)
		iTemp  = iTemp + banco.substring(7 - n, 8 - n) * pesos[n];

	result = 11 - iTemp % 11;
	if (result > 9)	result= 1 - result % 10;

	iTemp=0;
	for (n=0; n <= 9; n++)
		iTemp  = iTemp + cuenta.substring(9 - n, 10 - n) * pesos[n];

	iTemp= 11 - (iTemp % 11);
	if (iTemp > 9) iTemp =1-(iTemp % 10);

	result= result*10+iTemp;
	return (result);
}

/* Comprueba la validez de una cuenta bancaria con respecto a su DC */
function cb_valida (entidad, oficina, dc, cuenta)
{
	if (! soloNum(entidad, "Cuenta Bancaria - Entidad")) return (false);
	if (! entre(entidad, "Cuenta Bancaria - Entidad", 4, 4)) return (false);

	if (! soloNum(oficina, "Cuenta Bancaria - Oficina")) return (false);
	if (! entre(oficina, "Cuenta Bancaria - Oficina", 4, 4)) return (false);

	if (! soloNum(dc, "Cuenta Bancaria - DC")) return (false);
	if (! entre(dc, "Cuenta Bancaria - DC", 2, 2)) return (false);

	if (! soloNum(cuenta, "Cuenta Bancaria - Número de Cuenta")) return (false);
	if (! entre(cuenta, "Cuenta Bancaria - Número de Cuenta", 10, 10)) return (false);

	// Comprueba el DC
	var dcCorrecto= calculaDC(entidad.value + oficina.value, cuenta.value);
	if (dcCorrecto != dc.value)
		return error("Número de cuenta erróneo. Asegúrese de escribirlo correctamente", entidad);

      return (true);
}



/* ******************************* e-MAIL ******************************************* */


/* Solo NS4+ o IE4+ */
function cuenta_email_valida(cuenta)
{
	var reCuenta = /^\w+([\.-]?\w+)*$/ ;

    	// Si contiene '@' avisamos del error
	if (cuenta.value.search(/@/) != -1)
         return error("No incluya el carácter '@'", cuenta);

	if (! reCuenta.test(cuenta.value))
		return error("Nombre de cuenta erróneo", cuenta);

      return (true);
}

/* Solo NS4+ o IE4+ */
function servidor_email_valido(servidor)
{
	var reServidor = /^\w+([\.-]?\w+)*(\.\w{2,3})+$/ ;

	if (servidor.value.search(/@/) != -1)
		return error("No incluya el carácter '@'", servidor);


	if (! reServidor.test(servidor.value))
       	return error("Nombre erróneo de servidor", servidor);

      return (true);
}

/* Solo NS4+ o IE4+ */
function email_valido_2cmps(cuenta, servidor)
{
	return ((cuenta_email_valida(cuenta)) &&
	        (servidor_email_valido(servidor)));
}


/* Solo NS4+ o IE4+ */
function email_valido (campo)
{
	var pos= campo.value.indexOf('@',0);

	if(pos < 0)
		return error("E-mail erróneo. Una cuenta de correo debe contener el carácter '@'", 	campo);

	if(campo.value.indexOf('@',pos+1) >= 0)
		return error("E-mail erróneo. El carácter '@' debe aparecer sólo una vez", 	campo);

	var trozos= campo.value.split("@");

	// Comprobamos la cuenta
	var reCuenta = /^\w+([\.-]?\w+)*$/ ;
	if (! reCuenta.test(trozos[0]))
		return error("E-mail erróneo. Nombre de cuenta no válido", campo);

	// Comprobamos el servidor
	var reServidor = /^\w+([\.-]?\w+)*(\.\w{2,3})+$/ ;
	if (! reServidor.test(trozos[1]))
       	return error("E-mail erróneo. Nombre de servidor no válido", campo);

	return(true);
}



/* ******************************* URL ******************************************* */


/* Solo NS4+ o IE4+ */
function urlPag_valido (componente)
{
	var reProtocolo = /^http:\/\// ;
	var reResto = /\S+(\/\S+)*\.(htm|html|jsp|asp|php)$/i ;

      // Si contiene 'http://' lo quitamos
	if (componente.value.search(reProtocolo) != -1)
		componente.value= componente.value.substring(7);

	if (reResto.test(componente.value)) return (true);

	return error("URL erróneo. Asegúrese de escribir la dirección completa a la página principal. El 'http://' no es necesario", componente);
}



/* ******************************* TELÉFONO/FAX ********************************** */


/* Comprueba si es un número de teléfono extranjero */
function telExt_valido (componente)
{
	if (! soloNumYspaces(componente, "Teléfono")) return (false);
	if (! entre(componente, "Teléfono", 9, 20)) return (false);

      return (true);
}

/* Comprueba si es un número de teléfono español */
function telEsp_valido (componente)
{
	if (! soloNumYspaces(componente, "Teléfono")) return (false);
	if (countNums(componente.value) != 9)
		return error("Un número de teléfono español debe tener 9 dígitos", componente);

	return (true);
}

/* Comprueba si es un número de fax extranjero */
function faxExt_valido (componente)
{
	if (! soloNumYspaces(componente, "Fax")) return (false);
	if (! entre(componente, "Fax", 9, 20)) return (false);

	return (true);
}

/* Comprueba si es un número de fax español */
function faxEsp_valido (componente)
{
	if (! soloNumYspaces(componente, "Fax")) return (false);
	if (countNums(componente.value) != 9)
		return error("Un número de fax español debe tener 9 dígitos", componente);

	return (true);
}



/* ******************************* CLAVES **************************************** */


function login_valido(login, nomComponente)
{
        if (! entre(login, nomComponente, 3, 20)) return (false);
        else return (true);
}

function clave_valida(pw, nomComponente)
{
        if (! entre(pw, nomComponente, 6, 20)) return (false);
        else return (true);
}

function cmpClaveConf (pw1, pw2)
{
	if (pw1.value != pw2.value)
	{
		pw1.value= ""; pw2.value= "";
		return error("La contraseña nueva no coincide con su confirmación. Vuelva a escribirlas",
			pw1);
	}
	return (true);
}

function cmpClaveAnt_New(pwAnt, pwNew, pwNewConfirm)
{
	if (pwAnt.value == pwNew.value)
	{
		pwNew.value= ""; pwNewConfirm.value= "";
		return error("Ha escrito la misma contraseña. La nueva debe ser distinta que la anterior",
			pwNew);
	}
	return (true);
}



/* ************************** MONEDA (euros)************************************** */


/* Convierte un real a euro (2 decimales con redondeo si es necesario)
   Corrige el defecto de JavaScript con los reales y además se queda
   solo con 2 decimales */
function formatEuro(real)
{
  return (Math.round(real*100)/100);
}

/* Despues de aplicar el formatEuro convierte a String
   con formato: XXXX.XX */
function formatEuro2string(real)
{
  var s= formatEuro(real) + ''; // convierte a string (imposible que tenga más de 2 decimales)
  s= (s.charAt(0) == '.' ? '0'+s : s); // Primer caracter '.'
  if (s.charAt(s.length - 3) == '.') return s;
  if (s.charAt(s.length - 2) == '.') return s + '0';
  return s + '.00';
}

function presupuesto_valido(componente)
{
     // Quitamos espacios directamente sobre el valor del formulario
     componente.value= trim(componente.value);

     // Compruebo si es un valor numérico
     if (! isFloat(componente.value))
		return error("El presupuesto debe ser un valor numérico\n"
                  + "Se admite el punto o la coma como separador decimal",
                  componente);

     if (componente.value.charAt(0) == '-')
        return error("El presupuesto no puede ser negativo", componente);

     return (true);
}

function precio_valido(componente)
{
     // Quitamos espacios directamente sobre el valor del formulario
     componente.value= trim(componente.value);

     // Compruebo si es un valor numérico
     if (! isFloat(componente.value))
		return error("El precio debe ser un valor numérico\n"
                  + "Se admite el punto o la coma como separador decimal",
                  componente);

     if (componente.value.charAt(0) == '-')
        return error("El precio no puede ser negativo", componente);

     return (true);
}

/* Dev. con múltiples decimales. Aplicar "formatEuro" para reducir a 2 */
function getPrecioMasIVA(baseImponible, tpIVA)
{
    var num1= parseFloat(baseImponible);
    var num2= (tpIVA == null) ? 16 : parseInt(tpIVA);
	
    return num1 * ((100 + num2) / 100);
}

/* Dev. con múltiples decimales. Aplicar "formatEuro" para reducir a 2 */
function getPrecioConDto(valor, dto)
{
    var num1= parseFloat(valor);
    var num2= (dto == null) ? 0 : parseInt(dto);
	
    return num1 * ((100 - num2) / 100);
}

/* Dev. con múltiples decimales. Aplicar "formatEuro" para reducir a 2 */
function getPrecioConDtoMasIVA(baseImponible, dto, tpIVA)
{
	if (dto == null) dto= 0;
	if (tpIVA == null) tpIVA= 16;
	
    return getPrecioMasIVA( getPrecioConDto(baseImponible, dto), tpIVA);
}


/* ******************************* FECHAS **************************************** */

/* Solo permite escribir números y dos puntos sobre el cuadro de texto.
Uso: <.... onkeypress= "return soloNumYspace_keypress(event)" ...>
Restricción: Solo IE4+  */
function soloFecha_keypress(e)
{
    // e.keyCode = Valor UNICODE (ej: 13 = ENTER)
    if (document.all) // IE
        if (((e.keyCode < 48) && (13 != e.keyCode) && (47 != e.keyCode)) || (57 < e.keyCode))
		    return (false);

    return (true);  // Deja escribir en todos los navegadores
}

/* Fecha válida: dd/mm/aaaa (control sobre bisiestos) */
function fecha_valida(componente, nomComponente)
{
    var mal= false;

    var patron= /^(\d{1,2})\/(\d{1,2})\/(\d{1,4})$/;

    // Quitamos espacios directamente sobre el valor del formulario
    componente.value= trim(componente.value);

    var matchArray= componente.value.match(patron);

    if (matchArray == null)
        mal= true;
    else
    {
        var d= matchArray[1];
        var m= matchArray[2];
        var a= matchArray[3];

        if((m < 1) || (m > 12) || (d < 1) || (d > 31))
           mal= true;
        else
        {
          if((a%4 != 0) && (m == 2) && (d > 28))
            mal= true; // Año no bisiesto y es febrero y el dia es mayor a 28
          else
            if ((((m == 4) || (m == 6) || (m == 9) || (m==11)) && (d>30)) || ((m==2) && (d>29)))
            {
               mal= true;
            }
        }
    }

    if (mal)
	     return error("El contenido del campo '"+ nomComponente +"' no es válido.\n"
                    + "Formato correcto: dd/mm/aaaa. La fecha debe existir", componente);
    else
       return (true);
}

/* ******************************* HORAS **************************************** */

/* Solo permite escribir números y dos puntos sobre el cuadro de texto.
Uso: <.... onkeypress= "return soloHora_keypress(event)" ...>
Restricción: Solo IE4+  */
function soloHora_keypress(e)
{
    // e.keyCode = Valor UNICODE (ej: 13 = ENTER)
    if (document.all) // IE
        if (((e.keyCode < 48) && (13 != e.keyCode)) || ((57 < e.keyCode) && (58 != e.keyCode)))
		    return (false);

    return (true);  // Deja escribir en todos los navegadores
}

/* Hora válida: hh:mm o hh:mm:ss (24h) */
function hora_valida(componente, nomComponente)
{
    var patron= /^(\d{1,2}):(\d{2})(:(\d{2}))?$/;

    // Quitamos espacios directamente sobre el valor del formulario
    componente.value= trim(componente.value);

    var matchArray= componente.value.match(patron);

    if (matchArray == null)
        return error("El contenido del campo '"+ nomComponente +"' no es válido.\n"
                   + "Escriba la hora en formato de 24 horas", componente);

    var hora= matchArray[1];
    var minutos= matchArray[2];
    var seg= matchArray[4];

    if (hora < 0  || hora > 23) {
      return error("La hora debe estar entre 0 y 23", componente);
    }

    if (minutos < 0 || minutos > 59) {
      return error("Minutos deben estar entre 0 y 59", componente);
    }

    if (seg=="") { seg = null; }
    if ((seg != null) && (seg < 0 || seg > 59))
      return error("Segundos deben estar entre 0 y 59", componente);

    return true;
}


/* ******************************* LISTAS **************************************** */


/* Comprueba si el elemento seleccionado de una lista es válido.
   Supone que todos los elementos de una lista son válidos menos los que tengan
   el valor "-1". */
function valorSelEnLst_valido (lst, nomLst)
{
    // 22/09/2011: Añadida segunda condición ("")
    if ((lst.options[lst.selectedIndex].value == "-1") ||
        (lst.options[lst.selectedIndex].value == ""))
    {
        return error("Elija un elemento válido de '"+ nomLst +"'", lst);
    }
    return (true);
}

/* Selecciona el elemento indicado del componente de tipo "select-one"
   NOTA: Si no existe no selecciona ninguno
*/
function selLstValue(componente, valor)
{
    for (var i=componente.length-1; i > -1; i--)
    {
        if (componente.options[i].value == valor)
        {
            componente.selectedIndex= i;
        }
    }
}



/* ******************************** CHECK BOX *********************************** */


function checkBoxesVacio (frm, nameComponente, nomCampo)
{
  var nElems= frm.elements.length;

  for(i=0; i < nElems; i++)
  {
    if ((frm.elements[i].type == "checkbox") &&
        (frm.elements[i].name == nameComponente) &&
        (frm.elements[i].checked == true))
    {
	return(false);
    }
  }

  alert ("Debe seleccionar uno de los posibles valores del campo '"+ nomCampo + "'");
  return(true);
}


/* Pone la selección de todos los checkbox del formulario */
function selAll(frm)
{
  var nElems= frm.elements.length;

  for(i=0; i < nElems; i++)
  {
    if (frm.elements[i].type == "checkbox")
        frm.elements[i].checked= true;
  }
}

/* Quita la selección de todos los checkbox del formulario */
function deselAll(frm)
{
  var nElems= frm.elements.length;

  for(i=0; i < nElems; i++)
  {
    if (frm.elements[i].type == "checkbox")
        frm.elements[i].checked= false;
  }
}

/* Selecciona el CheckBox/RadioButton indicado */
function selChBox(nomChBox)
{
  document.getElementById(nomChBox).checked= true;
}

/* Deselecciona el CheckBox/RadioButton indicado */
function deselChBox(nomChBox)
{
  document.getElementById(nomChBox).checked= false;
}

/* Cambia el estado activo/inactivo del Checbox/RadioButton indicado */
function changeSelChBox(idChBox)
{
  var componente= document.getElementById(idChBox);
  componente.checked= componente.checked ? false : true;
}

function changeSelChBoxObj(objChBox)
{
  objChBox.checked= !objChBox.checked;
}




/* ****************************** RADIO BUTTONS ********************************* */


/* Dev. el valor del elemento activo. Si ninguno lo está dev. "null" */
function radioCheckValue(componente)
{
    var cnt = -1;
    for (var i=componente.length-1; i > -1; i--)
    {
        if (componente[i].checked) {cnt= i; i= -1;}
    }
    if (cnt > -1) return componente[cnt].value;
    else return null;
}

function radioVacio (componente, nomComp)
{
	if (radioCheckValue(componente) == null)
	{
		error("Debe seleccionar uno de los posibles valores del campo '"+ nomComp + "'", componente[0]);
		return (true);
	}
	return (false);
}

/* Selecciona el elemento indicado del componente de tipo "RadioButton"
   NOTA: Si no existe no selecciona ninguno
*/
function selRadioValue(componente, valor)
{
    for (var i=componente.length-1; i > -1; i--)
    {
        componente[i].checked= (componente[i].value == valor);
    }
}

/* Quita la selección del grupo de radio buttons.
   NOTA: Al final de este método no habrá ninguna opción seleccionada
*/
function deselRadioGrp(componente)
{
	selRadioValue(componente, null);
}


/* *************************** FORMULARIO COMPLETO **************************** */

/* Muestra un formulario completo. Recibe el ID del formulario 
 * (ej: "formAcceso")
 */
function showFrm(idFrm)
{
	var sAux="";
	var frm = document.getElementById(idFrm);
	for (i=0;i<frm.elements.length;i++)
	{
		sAux += "NOMBRE: '" + frm.elements[i].name + "' ";
		sAux += "TIPO: '" + frm.elements[i].type + "' "; ;
		sAux += "VALOR: '" + frm.elements[i].value + "'\n" ;
	}
	alert(sAux);
}

/* Vacía el contenido de todos los campos cuyo nombre contenga como mínimo los
   caracteres 'txtName'.

   NOTA: Si no se usa el parámetro 'txtName' vaciará todos los 'value' 
         (inclusive botones)
 */
function vaciarFrmValue(frm, txtName)
{
  var nElems= frm.elements.length;

  if (txtName == null) txtName= "";

  for(i=0; i < nElems; i++)
  {
    if (frm.elements[i].name.lastIndexOf(txtName) > -1)
        frm.elements[i].value= "";
  }
}

function habilitarFrm(frm, color, txtName)
{
  var nElems= frm.elements.length;

  if (color == null) color= "#FFFFFF";
  if (txtName == null) txtName= "";

  for(i=0; i < nElems; i++)
  {
    if (frm.elements[i].name.lastIndexOf(txtName) > -1)
    {
        frm.elements[i].disabled= false;
        frm.elements[i].style.backgroundColor= color;
    }
  }
}

function deshabilitarFrm(frm, color, txtName)
{
  var nElems= frm.elements.length;

  if (color == null) color= "#F3F3F3";  // Gris claro
  if (txtName == null) txtName= "";

  for(i=0; i < nElems; i++)
  {
    if (frm.elements[i].name.lastIndexOf(txtName) > -1)
    {
        frm.elements[i].disabled= true;
        frm.elements[i].style.backgroundColor= color;
    }
  }
}

function deshabilitarFrmSalvoBotones(frm, color, txtName)
{
  var nElems= frm.elements.length;

  if (color == null) color= "#F3F3F3";  // Gris claro
  if (txtName == null) txtName= "";

  for(i=0; i < nElems; i++)
  {
    if ((frm.elements[i].name.lastIndexOf(txtName) > -1) &&
        (frm.elements[i].type !=  "button") &&
        (frm.elements[i].type !=  "reset") &&
        (frm.elements[i].type !=  "submit"))
    {
        frm.elements[i].disabled= true;
        frm.elements[i].style.backgroundColor= color;
    }
  }
}

/* Sólo deshabilita el botón o botones SUBMIT */
function deshabilitarSubmit(frm, color, txtName)
{
  var nElems= frm.elements.length;

  if (color == null) color= "#F3F3F3";  // Gris claro
  if (txtName == null) txtName= "";

  for(i=0; i < nElems; i++)
  {
    if ((frm.elements[i].name.lastIndexOf(txtName) > -1) &&
        (frm.elements[i].type ==  "submit"))
    {
        frm.elements[i].disabled= true;
        frm.elements[i].style.backgroundColor= color;
    }
  }
}

/* Envía el formulario deshabilitando el botón o botones submit */ 
function enviarDeshabSubmit(frm)
{
  deshabilitarSubmit(frm);
  frm.submit();
  return false;
}

