  header  ='Se requiere corregir lo siguiente para continuar:\n\n';
  prefix  ='• [';
  postfix =']: ';
  eDesc   = new Array();
  eDesc['invEmail']='Dirección de correo incorrecta.\n';
  eDesc['required']='El elemento es requerido.\n';
  eDesc['atLeast'] ='Cantidad mínima de elementos: ';
  eDesc['atMost']  ='Cantidad máxima de elementos: ';
  eDesc['invText'] ='Formato de texto incorrecto.\n';
  eDesc['invNum']  ='Formato de número incorrecto (ej. 12344)\n';
  eDesc['invDate'] ='Formato de fecha incorrecto (ej. 2002-12-31)\n';
  eDesc['invCur']  ='Formato de moneda incorrecto (ej. 1234.00)\n';
  eDesc['minLen']  ='Requiere longitud mínima de: ';
  eDesc['invRange']='Requiere número dentro del rango: ';
////////////////////////////////////////////////////////////////////////////////
  field = new Object(); // contiene cada elemento.
  var field_name;       // nombre campo original.
  var error="";         // acumula errores.
////////////////////////////////////////////////////////////////////////////////
  function validateForm(f)
  {
    error=""; //limpiamos
    for(var i=0; i<f.elements.length; i++)
    {  
       field=f.elements[i];
       e=field.name.split(':');
       if(!e[1])continue; //si no tiene nada...
       field_name=e[0];
       a=e[1].split('|');
       for(var j=0; j<a.length; j++)
         (a[j].indexOf('(')>-1)?eval(a[j]):eval(a[j]+'()'); //checamos cada atributo.
    }
    (error!="")?alert(header+error):restore_names(f);      
    return (error=="");
  }
////////////////////////////////////////////////////////////////////////////////
  function restore_names(f) // limpia los nombres de la forma. fuera :'s!!!
  {
    for(var i=0; i<f.elements.length; i++)
    {
      p=f.elements[i].name.split(':');
      if(f.elements[i].name)f.elements[i].name=p[0];
    }
  }
////////////////////////////////////////////////////////////////////////////////
  function req()
  {
    if((field.type=='select-one')?(field.selectedIndex==0):(!field.value))
      error+=prefix+field_name+postfix+eDesc['required'];  
  }
////////////////////////////////////////////////////////////////////////////////
  function dep(n, val)
  {
    f=field.form.elements;
    for(var i=0;i<f.length;i++){
      e=f[i].name.split(':');
      if (e[0]==n&&f[i].options[f[i].selectedIndex].value==val)
        req();
    }
  }
////////////////////////////////////////////////////////////////////////////////
  function email()
  {
    var objRegExp = /^([a-z0-9]([a-z0-9_\-\.]*)@([a-z0-9_\-\.]*)(\.[a-z]{2,3}(\.[a-z]{2}){0,2}))*$/i;
    if (!objRegExp.test(field.value)) 
      error+=prefix+field_name+postfix+eDesc['invEmail'];
  }
////////////////////////////////////////////////////////////////////////////////
  function mul(m1, m2)
  {
    for(c=0,i=0;i<field.options.length;i++)
      if(field.options[i].selected)c++;
    m2?(mi=m1,ma=m2):(mi=c,ma=m1);//un sólo parámetro significa máximo.
    if(c<mi) error+=prefix+field_name+postfix+eDesc['atLeast']+mi+'\n';
    if(c>ma) error+=prefix+field_name+postfix+eDesc['atMost']+ma+'\n';
  }
////////////////////////////////////////////////////////////////////////////////
  function text(len)
  {
    var objRegExp = /^[a-zñáéíóú\s\:\.\,]*$/i;
    if(!objRegExp.test(field.value))
      error+=prefix+field_name+postfix+eDesc['invText'];
    else
      if (len&&field.value&&field.value.length<len)
        error+=prefix+field_name+postfix+eDesc['minLen']+len+'\n';
  }
////////////////////////////////////////////////////////////////////////////////
  function num(mi, ma)
  {
    var objRegExp = /(^-?\d*)$/;
    if(!objRegExp.test(field.value))
      error+=prefix+field_name+postfix+eDesc['invNum'];
    else  
      if((mi&&ma&&field.value)&&(field.value<mi||field.value>ma))
        error+=prefix+field_name+postfix+eDesc['invRange']+mi+'-'+ma+'\n';
  }
////////////////////////////////////////////////////////////////////////////////
  function date() // el formato es: YYYY-MM-DD como en el mysql.
  {
    var e=false; // variable de error.
    var objRegExp = /^((\d{4})\-(0[1-9]|1[0-2])\-(0[1-9]|[1-2][0-9]|3[0-1]))?$/;
    if (objRegExp.test(field.value)){
      var dM=new Array(31,28,31,30,31,30,31,31,30,31,30,31);
      d=field.value.split('-');
      var days=(d[1]!=02)?dM[d[1]-1]:((d[0]%4==0&&d[0]%100!=0||d[0]%400==0)?29:28);
      e=((d[2]<=days)||!field.value);
    }
    if(!e)error+=prefix+field_name+postfix+eDesc['invDate'];
  }
////////////////////////////////////////////////////////////////////////////////
  function cur(mi,ma)
  {
    var objRegExp = /(^-?(\d*(\.\d{2})?)?$)/;
    if(!objRegExp.test(field.value))
      error+=prefix+field_name+postfix+eDesc['invCur'];
    else  
      if((mi&&ma&&field.value)&&(field.value<mi||field.value>ma))
        error+=prefix+field_name+postfix+eDesc['invRange']+mi+'-'+ma+'\n';
  }
////////////////////////////////////////////////////////////////////////////////
  function up()
  {
    field.value=field.value.toUpperCase();
  }
////////////////////////////////////////////////////////////////////////////////
  function lo()
  {
    field.value=field.value.toLowerCase();
  }
////////////////////////////////////////////////////////////////////////////////
