/***************************************************************************************************
*
*-- Form validation script by Peter Bailey, Copyright 2001-2002
*  Version 3.14b
*  Updated on September 26, 2002
*  www.peterbailey.net
*  me@peterbailey.net
*
*  IF YOU USE THIS SCRIPT, GIVE ME CREDIT PLEASE =)
*
*  Visit www.peterbailey.net/fValidate/ for more info
*
*  Please contact me with any questions, comments, problems, or suggestions
*  This script has only been validated on various versions of Windows with IE4+
*
*******************************************************************************************************/
var aa = String.fromCharCode(225);
var ea = String.fromCharCode(233);
var ia = String.fromCharCode(237);
var oa = String.fromCharCode(243);
var ua = String.fromCharCode(250);

var Aa = String.fromCharCode(193);
var Ea = String.fromCharCode(201);
var Ia = String.fromCharCode(205);
var Oa = String.fromCharCode(211);
var Ua = String.fromCharCode(218);

var nt = String.fromCharCode(241);
var Nt = String.fromCharCode(209);

var uu = String.fromCharCode(252);
var Uu = String.fromCharCode(220);

function validateForm(Frm, bConfirm, bDisable, bDisableR, groupError) {
  var testOk = false;
  if (groupError && fv['groupErrors'] < fv['switchToEbyE']) {
    fv['groupError'] = 1;
    errorData = new Array();
    }
  else
    fv['groupError'] = 0;

  for (var i=0; i<Frm.elements.length; i++) { // Loops through all the form's elements
    if (Frm.elements[i].getAttribute(fv['code'])) { // Gets the validator attribute, if exists thus starting the validation
      var validateType = Frm.elements[i].getAttribute(fv['code']);
      var validateObj = Frm.elements[i];
      testOk = false;      
      var params = validateType.split("|"); // Separates validation string into parameters
      if (params[0] == 'money') { // Sets flags for money syntax
        var dollarsign  = (params[1].indexOf('$') != -1);
        var grouping  = (params[1].indexOf(',') != -1);
        var decimal    = (params[1].indexOf('.') != -1);
        }

      if (params[params.length-1] == 'bok') // Sets flag if field is allowed to be blank
        fv['bok'] = true;

      switch (params[0]) { // Calls appropriate validation function based on type
        case 'blank'  : if (validateBlank(validateObj)) testOk = true; break;
        case 'equalto'  : if (validateEqualTo(validateObj, params[1], Frm)) testOk = true; break;
        case 'length'  : if (validateLength(validateObj, params[1],params[2] )) testOk = true; break;
        case 'number'  : if (validateNumber(validateObj)) testOk = true; break;
        case 'numberl'  : if (validateNumberL(validateObj, params[1])) testOk = true; break;
        case 'numberr'  : if (validateNumberR(validateObj, params[1], params[2] )) testOk = true; break;
        case 'time'    : if (validateTime(validateObj, params[1])) testOk = true; break;
        case 'date'    : if (validateDate(validateObj, params[1], params[2])) testOk = true; break;
        case 'alnum'  : if (validateAlnum(validateObj, params[1], params[2], params[3], params[4], params[5] )) testOk = true; break;        
        case 'decimal'  : if (validateDecimal(validateObj, params[1], params[2] )) testOk = true; break;
        case 'decimalr'  : if (validateDecimalR(validateObj, params[1], params[2], params[3], params[4] )) testOk = true; break;        
        case 'decimalran'  : if (validateDecimalRange(validateObj, params[1], params[2], params[3], params[4] )) testOk = true; break;
        case 'decimalrran'  : if (validateDecimalRRange(validateObj, params[1], params[2], params[3], params[4], params[5], params[6] )) testOk = true; break;
        case 'regexp'  : if (validateRegexp(validateObj, params[1])) testOk = true; break;
        case 'ip'    : if (validateIP(validateObj, params[1], params[2])) testOk = true; break;
        case 'ssn'    : if (validateSSN(validateObj)) testOk = true; break;
        case 'money'  : if (validateMoney(validateObj, dollarsign, grouping, decimal)) testOk = true; break;
        case 'zip'    : if (validateZip(validateObj, params[1])) testOk = true; break;
        case 'cazip'  : if (validateCAzip(validateObj)) testOk = true; break;
        case 'phone'  : if (validatePhone(validateObj)) testOk = true; break;
        case 'phone1'  : if (validatePhone1(validateObj)) testOk = true; break;	
        case 'RFC'  : if (validateRFC(validateObj)) testOk = true; break;
        case 'AWB'  : if (validateAWB(validateObj)) testOk = true; break;
        case 'email'  : if (validateEmail(validateObj)) testOk = true; break;
        case 'cc'    : if (validateCC(validateObj)) testOk = true; break;
        case 'select'  : if (validateSelect(validateObj)) testOk = true; break;
        case 'selectm'  : if (validateSelectM(validateObj, params[1], params[2])) testOk = true; break;
        case 'selecti'  : if (validateSelectI(validateObj, params[1])) testOk = true; break;
        case 'checkbox'  : if (validateCheckbox(validateObj, Frm.name, validateObj.name, params[1], params[2])) testOk = true; break;
        case 'radio'  : if (validateRadio(validateObj, Frm.name, validateObj.name)) testOk = true; break;
        case 'eitheror'  : if (validateEitherOr(validateObj, params[1], params[2])) testOk = true; break;
        case 'custom'  : if (validateCustom(validateObj)) testOk = true; break;
        // Add additional cases here
        default      : alert('Tipo de validaci'+ oa +'n no encontrada');
        }
      if (!testOk && !fv['groupError']) return false;
      }
    }
  if (fv['groupError']) {
    fv['groupErrors']++;
    var alertStr = "Los campos listados contienen datos erroneos o necesitan llenarse.\n\n";
    for (var i in errorData) {
      fv['revertClass'] = errorData[i].className;
      if (typeof errorData[i].type != 'undefined'  && typeof errorData[i].name != 'undefined') { 
        errorData[i].className = fv['errorClass'];
        alertStr += " -" + formatName(errorData[i]) + "\n";
        }
      else {
        var temp = errorData[i];
        temp[0].className = fv['errorClass'];
        alertStr += " -" + formatName(temp[0]) + "\n";
        }
      errorProcess(errorData[0],0,1);
      }
    if (errorData.length > 0) {
      errorData[0].focus();
      alert(alertStr);
      return false;
      }       
    }
/*******************************************************
*  Any special conditions you have can be added here
********************************************************/
    
  if (typeof bConfirm == 'undefined') bConfirm = 0;        // Checks for submission flags
  if (typeof bDisable == 'undefined') bDisable = 0;
  if (typeof bDisableR == 'undefined') bDisableR = 0;
  if (bConfirm)
    {
    if(!confirm(fv['confirmMsg']))
      {
      if (fv['confirmAbortMsg'] != '') alert(fv['confirmAbortMsg']);    // Displays confim if requested
      return false;
      }
    }
  if (bDisable) Frm.elements[fv['submitButton']].disabled=true;      // Disables submit if requested
  if (bDisableR) Frm.elements[fv['resetButton']].disabled=true;      // Disables reset if requested  
  return true;                          // Form has been validated
  }

/***************************************************************************/
function validateBlank(formObj) {
  var objName = formatName(formObj);
  if (formObj.value == "") {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : 'Por favor introduzca un valor en '+objName);    
    errorProcess(formObj,0,1);
    return false;
    }
  var regex = new RegExp(/\S/);
  if (!regex.test(formObj.value)) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : 'Por favor introduzca un valor en '+objName);
    errorProcess(formObj,1,1);
    return false;      
    }
  return true;
  }
/***************************************************************************/
// Special function used for bok
function checkBlank(formObj) {
  if (formObj.value == "")
    return true;
  var regex = new RegExp(/\S/);
  if (!regex.test(formObj.value))
    return true;      
  return false;
  }
    
/***************************************************************************/
function validateEqualTo(formObj, otherObjName, Frm) {
  var objName = formatName(formObj);
  var equalToValue = Frm.elements[otherObjName].value;

  if (formObj.value != equalToValue) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : otherObjName+' debe ser igual que '+objName+'.\nAseg'+ ua+'rese que los datos coincidan.');
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
  
/***************************************************************************/
function validateLength(formObj,len,max) {
  var objName = formatName(formObj);  
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  
  if (formObj.value.length < parseInt(len)) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : objName+' debe tener al menos '+len+' caracteres');
    errorProcess(formObj,1,1);
    return false;
  }
	if (formObj.value.length > parseInt(max)) {
		alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : objName+' debe tener m'+aa+'ximo '+max+' caracteres');
    errorProcess(formObj,1,1);
    return false;
	}
  return true;
  }
  
/***************************************************************************/
function validateNumber(formObj) {
  var objName = formatName(formObj);
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  
  numReg = "^[0-9]+$"
  var regex = new RegExp(numReg);
  if (!regex.test(formObj.value)) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : 'Solo es posible tener valores num'+ea+'ricos para '+objName);
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
/***************************************************************************/
function validateNumberL(formObj, len) {
  var objName = formatName(formObj);
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  
  numReg = "^[0-9]{"+parseInt(len)+",}$"
  var regex = new RegExp(numReg);
  if (!regex.test(formObj.value)) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : 'Un n'+ua+'mero m'+ia+'nimo de '+len+' valores num'+ea+'ricos son necesarios para '+objName);
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
/***************************************************************************/
function validateNumberR(formObj, lb, ub) {
  var objName = formatName(formObj);
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  var num = parseInt(formObj.value);
  numReg = "^\-?[0-9]+$"
  if (lb == 'none') lb = -999999999999999999;
  if (ub == 'none') ub = 999999999999999999;
  var regex = new RegExp(numReg);
  if (!regex.test(num) || num < lb || num > ub ) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : objName+" debe ser un valor entero entre "+lb+" y "+ub);
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
/***************************************************************************/
function validateTime(formObj, format) {
  var objName = formatName(formObj);
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }

  if (format == 'hh:mm:ss tt') timeReg = "^[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2} (am|pm|AM|PM)$";
  if (format == 'hh:mm:ss') timeReg = "^[0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2}$";
  if (format == 'hh:mm tt') timeReg = "^[0-9]{1,2}:[0-9]{1,2} (am|pm|AM|PM)$";
  if (format == 'hh:mm') timeReg = "^[0-9]{1,2}:[0-9]{1,2}$";
  var regex = new RegExp(timeReg);
  if (!regex.test(formObj.value)) {
    if (fv['groupError']) { addError(formObj); return true; }
    window.alert("Los datos ("+formObj.value+") no cumplen con el formato para "+objName);    
    errorProcess(formObj,1,1);
    return false;
    }

  separator = /[: ]/
  var data = formObj.value.split(separator);
  hour = data[0];
  minute = data[1];
  second = 00;
  ampm = '';
  if (format == 'hh:mm:ss tt') {
    second = data[2];
    ampm =  data[3];
    }
  if (format == 'hh:mm:ss') {
    second = data[2];
    }
  if (format == 'hh:mm tt') {
    ampm =  data[3];
    }

  var hasErrors = false;

  if(ampm != '' && hour > 12) hasErrors = true;
  if(ampm == '' && hour > 24) hasErrors = true;
  if(minute > 60 || second > 60) hasErrors = true;
  if (hasErrors) {
    if (fv['groupError']) { addError(formObj); return true; }
    window.alert('Hora inv'+aa+'lida para '+objName);
    errorProcess(formObj,1,1);
    return false;
    }

  return true;
  }
/***************************************************************************/
function validateDate(formObj, format, separator) {
  var objName = formatName(formObj);
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }

  var hasErrors = false;

  if (separator == '*') {
    regex = /[-.\/]/
  } else {
    regex = separator;
  }
  var data = formObj.value.split(regex);
  if (data.length !=3) {
    hasErrors = true;
    }

  var day = 'day';
  var month = 'month';
  var year = 'year';
  switch (format) {
    case 'dmy'  :
      day = parseInt(data[0],10);
      month = parseInt(data[1],10);
      year = parseInt(data[2],10);
      break;
    case 'mdy'  :
      month = parseInt(data[0],10);
      day = parseInt(data[1],10);
      year = parseInt(data[2],10);
      break;
    case 'ymd'  :
      year = parseInt(data[0],10);
      day = parseInt(data[1],10);
      month = parseInt(data[2],10);
      break;
    default  : alert('Formato de fecha no soportado');
    }
  if (isNaN(day) || isNaN(month) || isNaN(year)) {
    hasErrors = true;
  } else {
    month_days = new Array(0,31,28,31,30,31,30,31,31,30,31,30,31);
    if(year < 100) year = year + 2000;
    if ( day < 1 || month > 12 || month < 1 || year < 1800 || (day > month_days[month] && month != 2)) {
      hasErrors = true;
    } else {
      if (month == 2) { // lap year
        lap_year = false;
        (year%4 == 0)?   lap_year = true: lap_year = false;
        (year%100 == 0)?  lap_year = false: lap_year = lap_year;
        (year%400 == 0)?  lap_year = true: lap_year = lap_year;
        if ((lap_year && day > 29) || (!lap_year && day > 28)) {
          hasErrors = true;
        }
      }
    }
  }
  if (hasErrors) {
    if (fv['groupError']) { addError(formObj); return true; }
    window.alert('Fecha inv'+aa+'lida para '+objName);
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
/***************************************************************************/
function validateAlnum(formObj, minLen, tCase, numbers, spaces, puncs) {
  var objName = formatName(formObj);
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  var arrE = new Array();
  arrE[0] = (minLen == "*") ? "None" : minLen;
  var okChars = "";
  switch (tCase.toUpperCase()) {
    case 'U'  :  okChars = "A-Z"+Aa+Ea+Ia+Oa+Ua+Nt+Uu; arrE[1] = "UPPER"; break
    case 'L'  :  okChars = "a-z"+aa+ea+ia+oa+ua+nt+uu; arrE[1] = "lower"; break;
    case 'C'  :  okChars = "A-Z"+Aa+Ea+Ia+Oa+Ua+Nt+Uu+"][a-z"+aa+ea+ia+oa+ua+nt+uu; if (minLen != "*") minLen--; arrE[1]="Inicial en may"+ua+"sculas"; break;
    default   :  okChars = "a-zA-Z"+Aa+Ea+Ia+Oa+Ua+Nt+Uu+aa+ea+ia+oa+ua+nt+uu; arrE[1]="Cualquiera"; break;
    }
  if (parseInt(numbers)) { okChars += "0-9"; arrE[2] = "Si"; } else arrE[2] = "No";
  if (parseInt(spaces)) { okChars += " "; arrE[3] = "Si"; } else arrE[3] = "No";
  if (puncs == "all") { okChars += puncStr("!@#$%^&*()_+-={}|[]:\";'<\\>?,.?~`"); arrE[4] = "Todos"; }
  else if (puncs == "none") arrE[4] = "Ninguno";
  else { okChars += puncStr(puncs); arrE[4] =  puncStr(puncs).replace(/\\/g,""); }
  var length = (minLen == "*") ? "+" : "{"+minLen+",}";
  var alnumReg = "^["+okChars+"]"+length+"$";
  var regex = new RegExp(alnumReg);
  if (!regex.test(formObj.value) ) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : "Los datos registrados ("+formObj.value+") no cumplen con el formato requerido para "+objName+"\nLongitud m"+ia+"nima: "+arrE[0]+"\nCase: "+arrE[1]+"\nN"+ua+"meros permitidos: "+arrE[2]+"\nEspacios permitidos: "+arrE[3]+"\nSignos de puntuaci"+oa+"n permitidos: "+arrE[4]);    
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }  
/***************************************************************************/
function validateDecimal(formObj, lval, rval) {
  var objName = formatName(formObj);
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  
  (lval == '*')? lval = '*': lval = parseInt(lval);
  (rval == '*')? rval = '*': rval = parseInt(rval);
  var decReg = "";
  if (lval == 0)
    decReg = "^\\.[0-9]{"+rval+"}$";  
  else if (lval == '*' && rval != '*')
    decReg = "^[0-9]"+lval+"\\.[0-9]{"+rval+"}$";
  else if (rval == '*' && lval != '*')
    decReg = "^[0-9]{"+lval+"}\\.[0-9]"+rval+"$";
  else if (lval == '*' && rval == '*')
    decReg = "^[0-9]"+lval+"\\.[0-9]"+rval+"$";
  else
    decReg = "^[0-9]{"+lval+"}\\.[0-9]{"+rval+"}$";
  var regex = new RegExp(decReg);
  if (!regex.test(formObj.value)) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : formObj.value+' no es un tipo v'+aa+'lido para '+objName);
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
  
/***************************************************************************/
function validateDecimalR(formObj, lmin, lmax, rmin, rmax) {
  var objName = formatName(formObj);
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  
  (lmin == '*')? lmin = 0: lmin = parseInt(lmin);
  (lmax == '*')? lmax = '': lmax = parseInt(lmax);
  (rmin == '*')? rmin = 0: rmin = parseInt(rmin);
  (rmax == '*')? rmax = '': rmax = parseInt(rmax);
  var  decReg = "^[0-9]{"+lmin+","+lmax+"}\\.[0-9]{"+rmin+","+rmax+"}$"
  var regex = new RegExp(decReg);
  if (!regex.test(formObj.value)) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : formObj.value+' no es un tipo v'+aa+'lido para '+objName);
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
/***************************************************************************/
function validateDecimalRange(formObj, lval, rval, lb, ub) {
  var objName = formatName(formObj);
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  
  (lval == '*')? lval = '*': lval = parseInt(lval);
  (rval == '*')? rval = '*': rval = parseInt(rval);
  var decReg = "";
  if (lval == 0)
    decReg = "^\\.[0-9]{"+rval+"}$";  
  else if (lval == '*')
    decReg = "^[0-9]"+lval+"\\.[0-9]{"+rval+"}$";
  else if (rval == '*')
    decReg = "^[0-9]{"+lval+"}\\.[0-9]"+rval+"$";
  else
    decReg = "^[0-9]{"+lval+"}\\.[0-9]{"+rval+"}$";
  var regex = new RegExp(decReg);
  if (!regex.test(formObj.value)) {
    if (fv['groupError']) { addError(formObj); return true; }
    window.alert(formObj.value+' no es un tipo v'+aa+'lido para '+objName+'\nEnteros: '+lval+'\nDecimales: '+rval);
    errorProcess(formObj,1,1);
    return false;
    }
  num = parseFloat(formObj.value)
  if (num < lb || num > ub ) {
    if (fv['groupError']) { addError(formObj); return true; }
    window.alert(objName+" debe ser un decimal entre "+lb+" y "+ub);
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
/***************************************************************************/
function validateDecimalRRange(formObj, lmin, lmax, rmin, rmax, lb, ub) {
  var objName = formatName(formObj);
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  
  (lmin == '*')? lmin = 0: lmin = parseInt(lmin);
  (lmax == '*')? lmax = '': lmax = parseInt(lmax);
  (rmin == '*')? rmin = 0: rmin = parseInt(rmin);
  (rmax == '*')? rmax = '': rmax = parseInt(rmax);
  var  decReg = "^[0-9]{"+lmin+","+lmax+"}\\.[0-9]{"+rmin+","+rmax+"}$"
  var regex = new RegExp(decReg);
  if (!regex.test(formObj.value)) {
    if (fv['groupError']) { addError(formObj); return true; }
    window.alert(formObj.value+' no es un tipo v'+aa+'lido para '+objName+'\nEnteros: de '+lmin+' a '+lmax+'\nDecimales: de '+rmin+' a '+rmax);
    errorProcess(formObj,1,1);
    return false;
    }

  num = parseFloat(formObj.value)
  if (num < lb || num > ub ) {
    if (fv['groupError']) { addError(formObj); return true; }
    window.alert(objName+" debe ser un decimal entre "+lb+" y "+ub);
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
/***************************************************************************/
function validateRegexp(formObj, Reg) {
  var objName = formatName(formObj);
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }

  (Reg == '')? Reg = "^.*$": Reg = Reg;
  var regex = new RegExp(Reg);
  if (!regex.test(formObj.value)) {
    if (fv['groupError']) { addError(formObj); return true; }
    window.alert(formObj.value+' no cumple con el formato requerido para '+objName+'.');
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
/***************************************************************************/
function validateIP(formObj, portMin, portMax) {
  var objName = formatName(formObj);  
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  if (typeof portMin == 'undefined') portMin = 0;
  if (typeof portMax == 'undefined') portMax = 99999;
  var portOk = true;
  var ipReg = "^((?:([2]{1}[0-5]{2})|([2]{1}[0-4]{1}[0-9]{1})|([1]?[0-9]{2})|([0-9]{1}))[\\.]){3}(?:([2]{1}[0-5]{2})|([2]{1}[0-4]{1}[0-9]{1})|([1]?[0-9]{2})|([0-9]{1}))(\\:[0-9]{1,5})?$"
  var portLoc = formObj.value.indexOf(":");
  if (portLoc != -1) {
     var port = parseInt(formObj.value.substring(portLoc+1));
     if (port < portMin || port > portMax) portOk = false;    
     }
  var regex = new RegExp(ipReg);
  if (!regex.test(formObj.value) || !portOk) {
    if (fv['groupError']) { addError(formObj); return true; }
    if (regex.test(formObj.value) && !portOk)
      window.alert("El puerto especificado , "+port+", est"+aa+" fuera de rango.\nDebe estar entre "+portMin+" y "+portMax);
    else      
      alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : formObj.value+' no es una IP v'+aa+'lida');
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
/***************************************************************************/
function validateSSN(formObj) {
  var objName = formatName(formObj);  
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }

  var regex = new RegExp(/^\d{3}\-\d{2}\-\d{4}$/);
  if (!regex.test(formObj.value)) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : formObj.value+' no es un N'+ua+'mero de Seguridad Social v'+aa+'lido.\nSu NSS debe teclearse con el formato \'XXX-XX-XXXX\'.');
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
/***************************************************************************/
function validateMoney(formObj, ds, grp, dml) {
  var objName = formatName(formObj);  
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  
  var moneySyntax;
  if (ds && grp && dml)    // Dollar sign, grouping, and decimal
    { moneyReg = "^\\$(?:(?:[0-9]{1,3},)(?:[0-9]{3},)*[0-9]{3}|[0-9]{1,3})(\\.[0-9]{2})$";  moneySyntax = "$XX,XXX.XX"; }
  if (ds && grp && !dml)    // Dollar sign and grouping
    { moneyReg="^\\$(?:(?:[0-9]{1,3},)(?:[0-9]{3},)*[0-9]{3}|[0-9]{1,3})$"; moneySyntax="$XX,XXX"; }
  if (ds && !grp && dml)    // Dollar sign and decimal
    { moneyReg="^\\$[0-9]*(\\.[0-9]{2})$"; moneySyntax="$XXXXX.XX"; }
  if (!ds && grp && dml)    // Grouping and decimal
    { moneyReg="^(?:(?:[0-9]{1,3},)(?:[0-9]{3},)*[0-9]{3}|[0-9]{1,3})(\\.[0-9]{2})?$"; moneySyntax="XX,XXX.XX"; }
  if (ds && !grp && !dml)    // Dollar sign only
    { moneyReg="^\\$[0-9]*$"; moneySyntax="$XXXXX"; }
  if (!ds && grp && !dml)    // Grouping only
    { moneyReg="^(?:(?:[0-9]{1,3},)(?:[0-9]{3},)*[0-9]{3}|[0-9]{1,3})$"; moneySyntax="XX,XXX"; }
  if (!ds && !grp && dml)    // Decimal only
    { moneyReg="^[0-9]*(\\.[0-9]{2})$"; moneySyntax="XXXXX.XX"; }
  if (!ds && !grp && !dml)  // No params set, all special chars become optional
    { moneyReg="^\\$?(?:(?:[0-9]{1,3},?)(?:[0-9]{3},?)*[0-9]{3}|[0-9]{1,3})(\\.[0-9]{2})?$"; moneySyntax="[$]XX[,]XXX[.XX]"; }
  var regex = new RegExp(moneyReg);
  if (!regex.test(formObj.value)) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : formObj.value+' no cumple con el formato '+moneySyntax+' para '+objName+'.');
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }

/***************************************************************************/
function validateSelect(formObj) {
  var objName = formatName(formObj);
  if (formObj.selectedIndex == 0) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : 'Por favor seleccione '+objName);
    errorProcess(formObj,0,1);
    return false;
    }
  return true;
  }
  
/***************************************************************************/
function validateSelectM(formObj, minS, maxS) {
  var objName = formatName(formObj);
  var selectCount = 0;
  if (maxS == 999) maxS = formObj.length;
  for (var i=0; i<formObj.length; i++)
    {
    if (formObj.options[i].selected)
      selectCount++; 
    }
  if (selectCount < minS || selectCount > maxS) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : 'Por favor seleccione entre '+minS+' y '+maxS+' '+objName+'.\nActualmente ha seleccionado '+selectCount);
    errorProcess(formObj,0,1);
    return false;
    }
  return true;
  }
  
/***************************************************************************/
function validateSelectI(formObj, indexes) {
  var objName = formatName(formObj);
  var arrIndexes =indexes.split(/[,]/);
  var selectOK = true;
  for (var i=0; i<arrIndexes.length; i++)
    {
    if (formObj.selectedIndex == arrIndexes[i])
      selectOK = false;
    }

  if (!selectOK) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : 'Seleccione una opci'+oa+'n v'+aa+'lida para '+objName);
    errorProcess(formObj,0,1);
    return false;
    }
  return true;
  }
    
/***************************************************************************/
function validateZip(formObj, sep) {
  if (typeof sep == 'undefined')
    sep = "- ";
  var objName = formatName(formObj);  
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  zipReg = "^[0-9]{5}(|["+puncStr(sep)+"]?[0-9]{4})$"
  var regex = new RegExp(zipReg);
  if (!regex.test(formObj.value)) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : "Inserte un c"+oa+"digo postal v"+aa+"lido de 5 "+oa+" 9 d"+ia+"gitos.");
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
  
/***************************************************************************/
function validateCAzip(formObj) {
  var objName = formatName(formObj);  
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  
  zipReg = "^[A-Z][0-9][A-Z] [0-9][A-Z][0-9]$"
  var regex = new RegExp(zipReg);
  if (!regex.test(formObj.value)) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : "Inserte un c"+oa+"digo postal v"+aa+"lido.");
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
  
/***************************************************************************/
function validateEmail(formObj)  {  
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }

  var emailStr = formObj.value;
  var emailReg1 = /(@.*@)|(\.\.)|(@\.)|(\.@)|(^\.)/; // not valid
  var emailReg2 = /^.+\@(\[?)[a-zA-Z0-9\-\.]+\.([a-zA-Z]{2,3}|[0-9]{1,3})(\]?)$/; // valid
  if (!emailReg1.test(emailStr) && emailReg2.test(emailStr)) {// if syntax is valid
    return true;
    }
  else {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : "Inserte una direcci"+oa+"n de Email v"+aa+"lida.");
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
/***************************************************************************/
function validatePhone(formObj)  {
  var objName = formatName(formObj);  
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  
  //phoneReg = "^(?:[\(][0-9]{3}[\)]|[0-9]{3})[-. ]?[0-9]{3}[-. ]?[0-9]{4}$";
  phoneReg = "^([\(][0-9]{1,3}[\)]|[0-9]{1,3})?[-. ]?[0-9]{3,4}[-. ]?[0-9]{4}$";
  var regex = new RegExp(phoneReg);
  if (regex.test(formObj.value)) {
    return true;
    }
  else {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : "Inserte un n"+ua+"mero de tel"+ea+"fono v"+aa+"lido con LADA.");
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
/********************      marco          *********************************/
function validatePhone1(formObj)  {
  var objName = formatName(formObj);  
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  
  //phoneReg = "^(?:[\(][0-9]{3}[\)]|[0-9]{3})[-. ]?[0-9]{3}[-. ]?[0-9]{4}$";
  //phoneReg = "^([\(][0-9]{1,3}[\)]|[0-9]{1,3})?[-. ]?[0-9]{3,4}[-. ]?[0-9]{4}$";
  phoneReg = "^([\(][0-9]{1,3}[\)]|[0-9]{1,3})?[-. ]?[0-9]{3,4}[-. ]?[0-9]{4}|([A-Za-z\:\.]{3,4}?[0-9]{1,4})?$";

  
  var regex = new RegExp(phoneReg);
  if (regex.test(formObj.value)) {
    return true;
    }
  else {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : "Inserte un n"+ua+"mero de tel"+ea+"fono v"+aa+"lido con LADA.");
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
  
/***************************************************************************/
function validateRFC(formObj)  {
  var objName = formatName(formObj);  
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  
  rfcReg = "^[a-zA-Z]{3,4}[0-9]{6}[a-zA-Z0-9]{3}$";
  var regex = new RegExp(rfcReg);
  if (regex.test(formObj.value)) {
    return true;
    }
  else {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : "Ingrese un RFC v"+aa+"lido.");
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
/***************************************************************************/
function validateAWB(formObj)  {
  var objName = formatName(formObj);  
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  
  awbOK = false;
  awbReg = "[0-9]{6}";
  var regex = new RegExp(awbReg);
  if (regex.test(formObj.value)) {
    awbReg2 = "^(MPKSA|MPKMA|EE)"
    var regex2 = new RegExp(awbReg2);
    if (!regex2.test(formObj.value))
      awbOK = true;
    }
  if(!awbOK) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : "Por favor tecle un n"+ua+"mero v"+aa+"lido de gu"+ia+"a.");
    errorProcess(formObj,1,1);
    return false;
    }
  return true;
  }
/***************************************************************************/
function validateCheckbox(formObj, FRM, chkbxName, minC, maxC) {
  var formObj = eval(FRM+'.'+chkbxName);
  var objName = chkbxName;
  var checkTotal = eval(FRM+'.'+chkbxName+'.length');
  var checkCount = 0;
  if (maxC == 999) maxC = checkTotal;
  for (var i=0; i<checkTotal; i++) {
    if (formObj[i].checked) checkCount++;
    }
  if (checkCount < minC || checkCount > maxC) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : 'Seleccione entre '+minC+' y '+maxC+' opciones para '+objName+'.\nTiene seleccionadas '+checkCount+' opciones');
    errorProcess(formObj[0],0,1);
    return false;
    }
  return true;
  }

/***************************************************************************/  
function validateRadio(formObj, FRM, radioName) {  
  var radioLength = eval(FRM+'.'+radioName+'.length');
  var objName = formatName(formObj);
  var selectTotal = 0;
  for (i=0; i<radioLength; i++) {
    if (eval(FRM+'.'+radioName+'['+i+'].checked'))
      selectTotal++;  
    }
  if (selectTotal != 1) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : 'Seleccione una opci'+oa+'n para '+objName);
    errorProcess(formObj,0,1);
    return false;
    }    
  return true;
  }
/***************************************************************************/    
function validateEitherOr(formObj, del, fields) {
  var f = formObj.form;
  var arrF = fields.split(del);
  var nbCount = 0;
  var list = "";
  for (var i=0; i<arrF.length; i++) {
    list += " -"+formatName(f.elements[arrF[i]])+"\n";
    if (!checkBlank(f.elements[arrF[i]]))
      nbCount++;
    }
  if (nbCount != 1) {
    if (fv['groupError']) { addError(f.elements[arrF[0]]); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : "Solo uno de los siguientes campos puede llenarse:\n"+list);
    for (var i=0; i<arrF.length; i++)
      errorProcess(f.elements[arrF[i]],0,0);
    return false;
    }
  return true;
  }
/***************************************************************************/    
function validateCustom(formObj) {
  var objName = formatName(formObj);  
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  
  var regex = new RegExp(formObj.getAttribute(fv['pattern']));
  if (!regex.test(formObj.value)) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert((formObj.getAttribute(fv['emsg'])) ? formObj.getAttribute(fv['emsg']) : objName+" es inv"+aa+"lido.");
    errorProcess(formObj,1,1);
    return false;
    }    
  return true;
  }
/****************************************************************************
*  Here are all the ancillary functions
****************************************************************************/
function addError(o) {
  errorData[errorData.length] = o;  
  }
/***************************************************************************/
function formatName(o) {
  var wStr = (o.name) ? o.name : o.id;
  wStr = wStr.replace(/_/g," ");
  return wStr;
  }
/***************************************************************************/  
function errorProcess(o, sel, foc) {
  fv['revertClass'] = o.className;
  o.className = fv['errorClass'];
  if (sel) o.select();
  if (foc) o.focus();
  }
/***************************************************************************/
function clearStyle(o) {
  if (o.className == fv['errorClass']) o.className = fv['revertClass'];
  }
/***************************************************************************/  
function puncStr(str) {
  str = str.replace("pipe", "|");
  return str.replace(/([\\\|\(\)\[\{\^\$\*\+\?\.])/g,"\\$1");
//  return str.replace(/([\!\@\#\$\%\^\&\*\(\)\_\+\-\=\{\}\|\[\]\\\:\"\;\'\<\>\?\,\.\/])/g,"\\$1");
  }
/*****************************************************************************************************  
*  CREDIT CARD FUNCTIONS
*
*********** WARNING: DO NOT EDIT BELOW THIS LINE UNLESS YOU KNOW WHAT YOU ARE DOING! ****************/  

function cleanupCCNum(ccNum) {
  return ccNum.replace(/\D/g,'');
  }  
/***************************************************************************/  
function validateCC(formObj) {
  var objName = formatName(formObj);  
  if (fv['bok'] && checkBlank(formObj))
    { fv['bok']=false; return true; }
  
  switch (eval(fv['ccTypeObj']).value) {
    case 'VISA'    : var ccReg = new RegExp(/^4\d{12}(\d{3})?$/); break;
    case 'MC'    : var ccReg = new RegExp(/^5[1-5]\d{14}$/); break;
    case 'DISC'    : var ccReg = new RegExp(/^6011\d{12}$/); break;
    case 'AMEX'    : var ccReg = new RegExp(/^6011\d{12}$/); break;    
    case 'DINERS'  : var ccReg = new RegExp(/^3[0|6|8]\d{12}$/); break;
    case 'ENROUTE'  : var ccReg = new RegExp(/^2[014|149]\d{11}$/); break;
    case 'JCB'    : var ccReg = new RegExp(/^3[088|096|112|158|337|528]\d{12}$/); break;
    // Add additonal card types here
    default      : if (!fv['groupError']) alert('Error! Typo de tarjeta no encontrado!'); return false;
    }
  var formatOK = ccReg.test(formObj.value);
  var luhnOK = validateLUHN(formObj.value);  
  if (!formatOK || !luhnOK) {
    if (fv['groupError']) { addError(formObj); return true; }
    alert(objName+' no es v'+aa+'lido');
    errorProcess(formObj,1,1);
    return false;
    }    
  return true;
  }
/***************************************************************************/  
function validateLUHN(ccString) {
  var odds = "";
  var evens = "";
  var i=1;
  for (i=0; i<ccString.length; i=i+2) {
    var digit = parseInt(ccString.charAt(i)) * 2;
    odds += digit+"";
    }
  for (i=1; i<ccString.length; i=i+2)
    evens += ccString.charAt(i);
  var luhnStr = odds + evens;
  var checkSum = 0;
  for (i=0; i<luhnStr.length; i++)
    checkSum += parseInt(luhnStr.charAt(i));
  return (checkSum % 10 == 0);
  }
  
