/* copyright 2004- Dave McCall - Please do not copy or reuse without author's permission */
function isString(sInput) {
  sInput = String(sInput);
  if (typeof(sInput)=="string")
    return true;
  else
    return false;
}
function isNumeric(sInput) {
  if (isNaN(Number(sInput)) || sInput.length <= 0)
    return false;
  else
    return true;
}
function isWholeNumber(sInput) {
  if (!isNumeric(sInput))
    return false;
  sInput = sInput.replace(/ /g, '');
  for (var i = 0; i < sInput.length; i++) {
    var oneChar = sInput.charAt(i);
    if (oneChar < '0' || oneChar > '9')
      return false;
  }
  if (Number(sInput) < 0)
    return false;
  return true;
}
function isNumberInRange(sInput, nMinValue, nMaxValue, bWholeNumber) {
  if (arguments.length < 4) bWholeNumber = false;
  if (bWholeNumber && !isWholeNumber(sInput)) return false;
  if (!isNumeric(sInput))
    return false;
  if (Number(sInput) < Number(nMinValue) || Number(sInput) > Number(nMaxValue))
    return false;
  else
    return true;
}
function formatNumber(sInput, nDecimals) {
  if (arguments.length < 2)
    nDecimals = 0;
  var nCurrDecimals = 0;
  if (!isNumeric(sInput))
    return sInput;
  sInput = String(Math.round(Number(sInput) * Math.pow(10,nDecimals))/Math.pow(10,nDecimals));
  if (sInput.search(/\./) >= 0)
    nCurrDecimals = sInput.length - 1 - sInput.search(/\./);
  else if (nDecimals > 0)
    sInput += '.';
  for (var x=0; x < (nDecimals-nCurrDecimals); x++)
    sInput += '0';
  return sInput;
}
function digits(sInput, nDigits) {
  if (!isNumeric(sInput)) return sInput;
  if (String(sInput).search(/\./) > 0) {
    var sLeft = String(sInput).substr(0, sInput.search(/\./));
    var sRight = String(sInput).substr(sInput.search(/\./)+1);
    while(nDigits > sLeft.length)
      sLeft = '0'+sLeft;
    return sLeft+'.'+sRight;
  }
  else {
    var sOutput = String(sInput);
    while(nDigits > sOutput.length)
      sOutput = '0'+sOutput;
    return sOutput;
  }
}
function isFull(sInput) {
  if (isNumeric(sInput)) {
    if (sInput != null)
      return true;
    else
      return true;
  }
  if (isString(sInput)) {
    if (sInput.length > 0)
      return true;
    else
      return false;
  }
  return false;
}
function isValidLength(sInput, nMinLength, nMaxLength) {
  if (!isString(sInput))
    return false;
  if (String(sInput).length < nMinLength || String(sInput).length > nMaxLength)
    return false;
  return true;
}
function getMonths() {
  var aMonth = ['January','February','March','April','May','June','July','August','September','October','November','December'];
  return aMonth;
}
function guessMask(sInput) {
  var aMasks = ['MM/DD/YYYY', 'DD/MM/YYYY', 'MM-DD-YYYY', 'DD MON YYYY', 'MON DD YYYY', 'MONTH DD YYYY'];
  for (var nMask=0; nMask<aMasks.length; nMask++)
    if (isDate(sInput, aMasks[nMask])) return aMasks[nMask];
}
function isValidDate(sInput, sMask) {
  // This function exists for backwards compatibility
  return isDate(sInput, sMask);
}
function isDate(sInput, sMask) {
  if (!isFull(sInput))
    return false;
  if (arguments.length < 2) sMask = guessMask(sInput);
  if (sMask == null) return false;
  var aDate, nMonth, sMonth, nDay, nYear;
  var aMonth = getMonths();
  switch (sMask.toUpperCase()) {
    case 'MM/DD/YY':
    case 'MM/DD/YYYY':
      if (sInput.match(/\d{1,2}\/\d{1,2}\/\d{2,4}/) == null) return false;
      aDate = sInput.split('/');
      nMonth = Number(aDate[0]);
      nDay = Number(aDate[1]);
      nYear = Number(aDate[2]);
      break;
    case 'DD/MM/YY':
    case 'DD/MM/YYYY':
      if (sInput.match(/\d{1,2}\/\d{1,2}\/\d{2,4}/) == null) return false;
      aDate = sInput.split('/');
      nDay = Number(aDate[0]);
      nMonth = Number(aDate[1]);
      nYear = Number(aDate[2]);
      break;
    case 'MM-DD-YY':
    case 'MM-DD-YYYY':
      if (sInput.match(/\d{1,2}\-\d{1,2}\-\d{2,4}/) == null) return false;
      aDate = sInput.split('-');
      nMonth = Number(aDate[0]);
      nDay = Number(aDate[1]);
      nYear = Number(aDate[2]);
      break;
    case 'DD MON YY':
    case 'DD MON YYYY':
      if (sInput.match(/\d{1,2} [a-zA-Z]{3} \d{2,4}/) == null) return false;
      aDate = sInput.split(' ');
      nDay = Number(aDate[0]);
      sMonth = aDate[1];
      for (var x=0; x<aMonth.length;x++)
        if (sMonth.toLowerCase() == aMonth[x].toLowerCase().substr(0,3))
          nMonth = x+1;
      if (nMonth == null) return false;
      nYear = Number(aDate[2]);
      break;
    case 'DD MONTH YY':
    case 'DD MONTH YYYY':
      if (sInput.match(/\d{1,2} [a-zA-Z]{3,9} \d{2,4}/) == null) return false;
      aDate = sInput.split(' ');
      nDay = Number(aDate[0]);
      sMonth = aDate[1];
      for (var x=0; x<aMonth.length;x++)
        if (sMonth.toLowerCase() == aMonth[x].toLowerCase())
          nMonth = x+1;
      if (nMonth == null) return false;
      nYear = Number(aDate[2]);
      break;
    case 'MON DD YY':
    case 'MON DD YYYY':
    case 'MON DD, YY':
    case 'MON DD, YYYY':
      if (sInput.match(/[a-zA-Z]{3} \d{1,2},* \d{2,4}/) == null) return false;
      aDate = sInput.split(' ');
      sMonth = aDate[0];
      for (var x=0; x<aMonth.length;x++)
        if (sMonth.toLowerCase() == aMonth[x].toLowerCase().substr(0,3))
          nMonth = x+1;
      if (nMonth == null) return false;
      nDay = Number(aDate[1].replace(',',''));
      nYear = Number(aDate[2]);
      break;
    case 'MONTH DD YY':
    case 'MONTH DD YYYY':
    case 'MONTH DD, YY':
    case 'MONTH DD, YYYY':
      if (sInput.match(/[a-zA-Z]{3,9} \d{1,2},* \d{2,4}/) == null) return false;
      aDate = sInput.split(' ');
      sMonth = aDate[0];
      for (var x=0; x<aMonth.length;x++)
        if (sMonth.toLowerCase() == aMonth[x].toLowerCase())
          nMonth = x+1;
      if (nMonth == null) return false;
      nDay = Number(aDate[1].replace(',',''));
      nYear = Number(aDate[2]);
      break;
  }
  if (!isNumberInRange(nMonth, 1, 12))
    return false;
  if (!isNumberInRange(nDay, 1, 31))
    return false;
  if (!isNumberInRange(nYear, 0, 4000))
    return false;
  var oDateCheck = new Date(nYear, nMonth-1, nDay);
  if (oDateCheck.getMonth() != nMonth-1)
    return false;
  return true;
}
function getDate(sInput, sMask) {
  if (!isDate(sInput)) return false;
  if (arguments.length < 2) sMask = guessMask(sInput);
  if (sMask == null) return false;
  var aDate, nMonth, sMonth, nDay, nYear;
  var aMonth = getMonths();
  switch (sMask.toUpperCase()) {
    case 'MM/DD/YY':
    case 'MM/DD/YYYY':
      aDate = sInput.split('/');
      nMonth = Number(aDate[0]);
      nDay = Number(aDate[1]);
      nYear = Number(aDate[2]);
      break;
    case 'DD/MM/YY':
    case 'DD/MM/YYYY':
      aDate = sInput.split('/');
      nDay = Number(aDate[0]);
      nMonth = Number(aDate[1]);
      nYear = Number(aDate[2]);
      break;
    case 'MM-DD-YY':
    case 'MM-DD-YYYY':
      aDate = sInput.split('-');
      nMonth = Number(aDate[0]);
      nDay = Number(aDate[1]);
      nYear = Number(aDate[2]);
      break;
    case 'DD MON YY':
    case 'DD MON YYYY':
      aDate = sInput.split(' ');
      nDay = Number(aDate[0]);
      sMonth = aDate[1];
      for (var x=0; x<aMonth.length;x++)
        if (sMonth.toLowerCase() == aMonth[x].toLowerCase().substr(0,3))
          nMonth = x+1;
      if (nMonth == null) return false;
      nYear = Number(aDate[2]);
      break;
    case 'DD MONTH YY':
    case 'DD MONTH YYYY':
      aDate = sInput.split(' ');
      nDay = Number(aDate[0]);
      sMonth = aDate[1];
      for (var x=0; x<aMonth.length;x++)
        if (sMonth.toLowerCase() == aMonth[x].toLowerCase())
          nMonth = x+1;
      if (nMonth == null) return false;
      nYear = Number(aDate[2]);
      break;
    case 'MON DD YY':
    case 'MON DD YYYY':
    case 'MON DD, YY':
    case 'MON DD, YYYY':
      aDate = sInput.split(' ');
      sMonth = aDate[0];
      for (var x=0; x<aMonth.length;x++)
        if (sMonth.toLowerCase() == aMonth[x].toLowerCase().substr(0,3))
          nMonth = x+1;
      if (nMonth == null) return false;
      nDay = Number(aDate[1].replace(',',''));
      nYear = Number(aDate[2]);
      break;
    case 'MONTH DD YY':
    case 'MONTH DD YYYY':
    case 'MONTH DD, YY':
    case 'MONTH DD, YYYY':
      aDate = sInput.split(' ');
      sMonth = aDate[0];
      for (var x=0; x<aMonth.length;x++)
        if (sMonth.toLowerCase() == aMonth[x].toLowerCase())
          nMonth = x+1;
      if (nMonth == null) return false;
      nDay = Number(aDate[1].replace(',',''));
      nYear = Number(aDate[2]);
      break;
  }
  if (nYear < 100) {
    var oToday = new Date();
    nYear += 2000;
    if (nYear > oToday.getFullYear()) nYear -= 100;
  }
  var oDateCheck = new Date(nYear, nMonth-1, nDay);
  return oDateCheck;
}
function isValidDateTime(sInput, sDateMask) {
  // This function exists for backwards compatibility
  return isDateTime(sInput, sDateMask);
}
function isDateTime(sInput, sDateMask) {
  var nSpace = sInput.search(' ');
  if (nSpace > 0) {
    var sDate = sInput.substr(0, nSpace);
    var sTime = sInput.substr(nSpace+1);
  }
  else {
    var sDate = sInput;
    var sTime = '';
  }
  if (arguments.length > 1)
    return (isDate(sDate, sDateMask) && (!isFull(sTime) || isTime(sTime)))
  else
    return (isDate(sDate) && (!isFull(sTime) || isTime(sTime)))
}
function isDateInRange(sInput, sMinDate, sMaxDate, sMask) {
  if (!isDate(sInput))
    return false;
  if (arguments.length < 4)
    sMask = 'MM/DD/YYYY';
  if (sInput.search('DD\/MM\/YY') == 0)
    sInput = convertDate(sInput);
  var objInpDate = new Date(sInput);
  if (arguments.length > 1 && isDate(sMinDate, sMask)) {
    if (sMinDate.search('DD\/MM\/YY') == 0)
      sMinDate = convertDate(sMinDate);
    var objMinDate = new Date(sMinDate);
    if (objInpDate < objMinDate)
      return false;
  }
  if (arguments.length > 2 && isDate(sMaxDate, sMask)) {
    if (sMaxDate.search('DD\/MM\/YY') == 0)
      sMaxDate = convertDate(sMaxDate);
    var objMaxDate = new Date(sMaxDate);
    if (objInpDate > objMaxDate)
      return false;
  }
  return true;
}
function convertDate(sInput) {
  if (!isDate(sInput))
    return sInput;
  var aDate = String(sInput).split(/\//);
  return aDate[1]+'\/'+aDate[0]+'\/'+aDate[2];
}
function formatDate(oDate, sMask) {
  if (arguments.length < 2) sMask = 'DD Mon YYYY';
  var aMonth = getMonths();
  sOut = sMask;
  sOut = sOut.replace(/MM/gi, digits(oDate.getMonth()+1,2));
  sOut = sOut.replace(/Month/g, aMonth[oDate.getMonth()]);
  sOut = sOut.replace(/MONTH/g, aMonth[oDate.getMonth()].toUpperCase());
  sOut = sOut.replace(/Mon/g, aMonth[oDate.getMonth()].substr(0,3));
  sOut = sOut.replace(/MON/g, aMonth[oDate.getMonth()].substr(0,3).toUpperCase());
  sOut = sOut.replace(/DD/gi, digits(oDate.getDate(),2));
  var nYear = oDate.getYear();
  if (nYear < 1000) nYear += 1900;
  nYear = String(nYear);
  sOut = sOut.replace(/YYYY/gi, nYear);
  sOut = sOut.replace(/YY/gi, nYear.substr(2,2));
  return sOut;
}
function formatDateTime(oDate, sMask) {
  if (arguments.length < 2) sMask = 'DD Mon YYYY HH:MI:SS AM';
  var aMonth = getMonths();
  sOut = sMask;
  sOut = sOut.replace(/MM/gi, digits(oDate.getMonth()+1,2));
  sOut = sOut.replace(/Month/g, aMonth[oDate.getMonth()]);
  sOut = sOut.replace(/MONTH/g, aMonth[oDate.getMonth()].toUpperCase());
  sOut = sOut.replace(/Mon/g, aMonth[oDate.getMonth()].substr(0,3));
  sOut = sOut.replace(/MON/g, aMonth[oDate.getMonth()].substr(0,3).toUpperCase());
  sOut = sOut.replace(/DD/gi, digits(oDate.getDate(),2));
  var nHours = oDate.getHours();
  sOut = sOut.replace(/H24/gi, digits(nHours,2));
  var sAMPM = 'AM';
  if (nHours > 12) {sAMPM = 'PM'; nHours -= 12;};
  sOut = sOut.replace(/HH/gi, digits(nHours,2));
  sOut = sOut.replace(/MI/gi, digits(oDate.getMinutes(),2));
  sOut = sOut.replace(/SS/gi, digits(oDate.getSeconds(),2));
  sOut = sOut.replace(/AM/gi, sAMPM);
  var sYear = oDate.getYear();
  if (sYear < 1000) sYear += 1900;
  sYear = String(sYear);
  sOut = sOut.replace(/YYYY/gi, sYear);
  sOut = sOut.replace(/YY/gi, sYear.substr(2,2));
  return sOut;
}
function formatTime(sInput, sMask) {
  if (arguments.length < 2) sMask = 'HH:MI AM';
  var sOut = sMask;
  var nHours = getHours(sInput);
  var nMinutes = getMinutes(sInput);
  var nSeconds = getSeconds(sInput);
  sOut = sOut.replace(/H24/gi, digits(nHours,2));
  var sAMPM = 'AM';
  if (nHours > 12) {sAMPM = 'PM'; nHours -= 12;};
  sOut = sOut.replace(/HH/gi, digits(nHours,2));
  sOut = sOut.replace(/MI/gi, digits(nMinutes,2));
  sOut = sOut.replace(/SS/gi, digits(nSeconds,2));
  sOut = sOut.replace(/AM/gi, sAMPM);
  return sOut;
}
function isTime(sInput) {
  if (!isFull(sInput)) return false;
  if (getHours(sInput) < 0) return false;
  if (getMinutes(sInput) < 0) return false;
  if (getSeconds(sInput) < 0) return false;
  if (sInput.search(/[^: 0123456789apmAPM]/) >= 0) return false;
  return true;
}
function isValidTime(sInput) {
  return isTime(sInput);
}
function isEmail(sInput) {
  var bIPAddress;
  // There must be something there
  if (!isFull(sInput)) return false;
  // There must not be any whitespace
  if (sInput.search(/[\s]/) != -1) return false;
  // There must be an @ sign, it must be at least the second character
  if (sInput.search('@') < 1) return false;
  // Split the address at the @ sign
  var aAddress = sInput.split('@');
  // Only A-Z 0-9 .s and -s are allowed in the first half
  if (aAddress[0].search(/[^a-zA-Z0-9-\._]/) != -1) return false;
  // Look for at least one . in the second half of address
  if (aAddress[1].search('.') == -1) return false;
  // Check to see if the end half is a domain or ip address
  if (aAddress[1].match(/\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/))
    bIPAddress=true;
  else
    bIPAddress=false;
  // Split the domain at the .s
  var aDomain = aAddress[1].split('.');
  if (bIPAddress) {
    // Each section must contain a number between 0 and 255
    for (var x=0; x<aDomain.length; x++)
      if (Number(aDomain[x]) > 255) return false;
  }
  else {
    // There must be at least 2 sections to the domain
    if (aDomain.length < 2) return false;
    // Search each piece of the domain to make sure it has at least on char and contains only valid characters
    for (var x=0; x<aDomain.length; x++) {
      if (aDomain[x].length < 1) return false;
      if (aDomain[x].search(/[^a-zA-Z0-9-]/) != -1) return false;
      if (aDomain[x].substr(0,1) == '-') return false;
    }
    // The last part of the domain must have at least 2 alpha characters
    if (aDomain[aDomain.length-1].search(/[^A-Za-z]/) != -1) return false;
  }
  return true;
}
function isValidEmail(sInput) {
  return isEmail(sInput);
}
function isEmailList(sInput, sSeparator, aInvalidAddresses) {
  if (sSeparator == null) {
    sInput = sInput.replace(/;/g, ',');
    sInput = sInput.replace(/\n/g, ',');
    sInput = sInput.replace(/\f/g, ',');
    sInput = sInput.replace(/\r/g, ',');
    sInput = sInput.replace(/\s/g, ',');
    sInput = sInput.replace(/,{2,}/g, ',');
    sSeparator = ',';
  }
  if (sSeparator != ' ') sInput = sInput.replace(/\s/g, '');
  if (sSeparator != '\n') sInput = sInput.replace(/\n/g, '');
  if (sInput.substr(sInput.length-1) == sSeparator) sInput = sInput.substr(0, sInput.length-1);
  if (!isArray(aInvalidAddresses)) aInvalidAddresses = new Array();
  var aValues = sInput.split(sSeparator);
  for (var x=0; x<aValues.length; x++) {
    if (!isValidEmail(trim(aValues[x])))
      aInvalidAddresses.push(aValues[x]);
  }
  if (aInvalidAddresses.length > 0) return false;
  return true;
}
function isValidEmailList(sInput, sSeparator, aInvalidAddresses) {
  return isEmailList(sInput, sSeparator, aInvalidAddresses);
}
function isValidPhone(sInput, sCountryCode) {
  if (!isFull(sInput)) return false;
  if (arguments.length < 2) sCountryCode = 'US';
  if (sCountryCode == 'US' || sCountryCode == 'CA') {
    if (sInput.match(/[^\d\(\)-\.\s]/) != null) return false;  
    // ##########
    if (sInput.match(/^\d{10}$/) != null) return true;
    // ###-###-####
    if (sInput.match(/^\d{3}\-\d{3}\-\d{4}$/) != null) return true;
    // (###) ###-####
    if (sInput.match(/^\(\d{3}\) \d{3}\-\d{4}$/) != null) return true;
    // (###)###-####
    if (sInput.match(/^\((\d{3})\)(\d{3})\-(\d{4})$/) != null) return true;
    // ### ###-####
    if (sInput.match(/^(\d{3}) (\d{3})\-(\d{4})$/) != null) return true;
    // ### #######
    if (sInput.match(/^(\d{3}) (\d{3})(\d{4})$/) != null) return true;
    // ###.###.####
    if (sInput.match(/^(\d{3})\.(\d{3})\.(\d{4})$/) != null) return true;
    // ### ###.####
    if (sInput.match(/^(\d{3}) (\d{3})\.(\d{4})$/) != null) return true;
    // ### ### ####
    if (sInput.match(/^(\d{3}) (\d{3}) (\d{4})$/) != null) return true;
    return false;
  }
  else {
    if (sInput.search(/[^\d\(\)\s-]/) >= 0) return false;
    return true;
  }
}
function formatPhone(sInput, sMask) {
  if (arguments.length < 2) sMask = '(###) ###-####';
  sInput = sInput.replace(/[^\d]/gi, '');
  var nMaskDigits = sMask.replace(/[^#]/gi, '').length;
  if (sInput.length != nMaskDigits) return sInput;
  switch(sMask) {
    case '(###)###-####':
      return '('+sInput.substring(0, 3)+')'+sInput.substring(3, 6)+'-'+sInput.substring(6, 10);
    case '###-###-####':
      return sInput.substring(0, 3)+'-'+sInput.substring(3, 6)+'-'+sInput.substring(6, 10);
    case '(###) ###-####':
      return '('+sInput.substring(0, 3)+') '+sInput.substring(3, 6)+'-'+sInput.substring(6, 10);
    default:
      return sInput;
  }
}
function isValidURL(sInput) {
  if (sInput.match(/^(https?|mailto|ftp|mms):\/\/[\w-]+[\w-\.\/\(\)~\?=\-&%@\$#]+$/))
    return true;
  else
    return false;
}
function isValidCreditCard(sInput, sCCType) {
  if (sCCType == 'test') return true;
  if (!isNumeric(sInput)) return false;
  var nMulitplier = 0;
  var nMultiplied = 0;
  var nSum = 0;
  if (sInput.length%2 == 0) {
    for (var x=0; x<sInput.length; x++) {
      nMultiplier = 2 - x % 2;
      nMultiplied = Number(sInput.charAt(x)) * nMultiplier;
      if (nMultiplied > 9) nMultiplied -= 9;
      nSum += nMultiplied;
    }
  }
  else {
    for (var x=0; x<sInput.length; x++) {
      nMultiplier = x % 2 + 1;
      nMultiplied = Number(sInput.charAt(x)) * nMultiplier;
      if (nMultiplied > 9) nMultiplied -= 9;
      nSum += nMultiplied;
    }
  }
  if (nSum%10 == 0) {
    if (arguments.length == 1)
      return true;
    else {
      switch (sCCType) {
        case '001': // Visa
          if (sInput.substr(0,1) == '4' && (sInput.length == 16 || sInput.length == 13))
            return true;
          else
            return false;
          break;
        case '002': // Mastercard
          if (sInput.substr(0,1) == '5' && sInput.length == 16)
            return true;
          else
            return false;
          break;
        case '003': // American Express
          if (sInput.substr(0,1) == '3' && sInput.length == 15)
            return true;
          else
            return false;
          break;
        case '004': // Discover
          if (sInput.substr(0,1) == '6' && sInput.length == 16)
            return true;
          else
            return false;
          break;
        case '005': // Diners Club
          if (sInput.substr(0,1) == '3' && sInput.length == 14)
            return true;
          else
            return false;
          break;
        case '006': // Carte Blanche
          if (sInput.substr(0,1) == '6' && sInput.length == 16)
            return true;
          else
            return false;
          break;
        case '007': // Japanese Credit Bank
          if (sInput.substr(0,1) == '6' && (sInput.length == 16 || sInput.length == 15))
            return true;
          else
            return false;
          break;
        default:
          return true;
          break;
      }
    }
  }
  else
    return false;
}
function isArray(testObject) {   
    return testObject && !(testObject.propertyIsEnumerable('length')) && typeof testObject === 'object' && typeof testObject.length === 'number';
}
function getStates(sCountryCode) {
  if (arguments.length == 0) sCountryCode = 'US';
  var aStates;
  switch (sCountryCode) {
    case 'US':
      aStates = ['AL','AK','AS','AZ','AR','CA','CO','CT','DE','DC','FM','FL','GA','GU','HI','ID','IL','IN','IA','KS','KY','LA','ME','MH','MD','MA','MI','MN','MS','MO','MT','NE','NV','NH','NJ','NM','NY','NC','ND','MP','OH','OK','OR','PW','PA','PR','RI','SC','SD','TN','TX','UT','VT','VI','VA','WA','WV','WI','WY'];
      break;
    case 'CA':
      aStates = ['AB','BC','MB','NB','NL','NS','NT','NU','ON','PE','QC','SK','YT'];
      break;
  }
  return aStates;
}
function isValidState(sValue, sCountryCode) {
  if (arguments.length < 2) sCountryCode = 'US';
  if (sCountryCode != 'US' && sCountryCode != 'CA')
    return isValidLength(sValue, 0, 100);
  var aStates = getStates(sCountryCode);
  for (var x=0; x<aStates.length; x++) {
    if (aStates[x] == sValue.toUpperCase()) return true;
  }
  return false;
}
function isValidZip(sValue, sCountryCode) {
  if (arguments.length < 2) sCountryCode = 'US';
  if (sCountryCode != 'US' && sCountryCode != 'CA')
    return isValidLength(sValue, 1, 20);
  switch (sCountryCode) {
    case 'US':
      var aMatch = sValue.match(/\d{5}(-?\d{4})?/);
      if (aMatch == null) return false;
      return (aMatch[0] == sValue);
      break;
    case 'CA':
      var aMatch = sValue.match(/[A-Za-z]\d[A-Za-z]\s?\d[A-Za-z]\d/);
      if (aMatch == null) return false;
      return (aMatch[0] == sValue);
      break
  }
}
function getHours(sInput) {
  var isPm = false;
  var nHourEndPos = sInput.indexOf(':');
  var nAmPmPos = sInput.indexOf('A');
  if (nAmPmPos < 0) nAmPmPos = sInput.indexOf('a');
  if (nAmPmPos < 0) nAmPmPos = sInput.indexOf('P');
  if (nAmPmPos < 0) nAmPmPos = sInput.indexOf('p');
  if (nAmPmPos < 0) nAmPmPos = sInput.length;
  if (sInput.indexOf('p') >= 0 || sInput.indexOf('P') >= 0) isPm = true;
  if (nHourEndPos < 0) nHourEndPos = nAmPmPos;
  var nHour = Number(sInput.substring(0, nHourEndPos));
  if (isNaN(nHour)) return -1;
  if (nHour < 0 || nHour > 24) return -1;
  if (nHour > 12 && isPm) return -1;
  if (isPm) nHour += 12;
  return nHour;
}
function getMinutes(sInput) {
  var nColonPos = sInput.indexOf(':');
  if (nColonPos < 0) return 0;
  var nMinEndPos = sInput.indexOf(':', nColonPos+1)
  if (nMinEndPos < 0) nMinEndPos = sInput.indexOf('A');
  if (nMinEndPos < 0) nMinEndPos = sInput.indexOf('a');
  if (nMinEndPos < 0) nMinEndPos = sInput.indexOf('P');
  if (nMinEndPos < 0) nMinEndPos = sInput.indexOf('p');
  if (nMinEndPos < 0) nMinEndPos = sInput.length;
  var nMinutes = Number(sInput.substring(nColonPos+1, nMinEndPos));
  if (isNaN(nMinutes)) return -1;
  if (nMinutes < 0 || nMinutes >= 60) return -1;
  return nMinutes;
}
function getSeconds(sInput) {
  nColonPos = sInput.indexOf(':');
  if (nColonPos < 0) return 0;
  var nColon2Pos = sInput.indexOf(':', nColonPos+1);
  if (nColon2Pos < 0) return 0;
  var nAmPmPos = sInput.indexOf('A');
  if (nAmPmPos < 0) nAmPmPos = sInput.indexOf('a');
  if (nAmPmPos < 0) nAmPmPos = sInput.indexOf('P');
  if (nAmPmPos < 0) nAmPmPos = sInput.indexOf('p');
  if (nAmPmPos < 0) nAmPmPos = sInput.length;
  nSeconds = Number(sInput.substring(nColon2Pos+1, nAmPmPos));
  if (isNaN(nSeconds)) return -1;
  if (nSeconds < 0 || nSeconds >= 60) return -1;
  return nSeconds;
}
function validateLength(theField, minLength, maxLength, errMessage) {
  if (!isValidLength(theField.value, minLength, maxLength)) {
    alert(errMessage);
    theField.focus();
    return 0;
  }
  return 1;
}
function validateNumber(theField, minValue, maxValue, errMessage, bWholeNumber) {
  if (arguments.length < 5) bWholeNumber = false;
  if (!isNumeric(theField.value) || !isNumberInRange(theField.value, minValue, maxValue)) {
    alert(errMessage);
    theField.focus();
    return 0;
  }
  if (bWholeNumber && !isWholeNumber(theField.value)) {
    alert(errMessage);
    theField.focus();
    return 0;
  }
  return 1;
}
function validateDate(theField, errMessage) {
  if (!isDate(theField.value)) {
    alert(errMessage);
    theField.focus();
    return 0;
  }
  return 1;
}
function validateSelected(theListbox, errMessage) {
  if (theListbox.selectedIndex == 0) {
    alert(errMessage);
    theListbox.focus();
    return 0;
  }
  return 1;
}
function isChecked(theInput) {
  var nChecked = 0;
  if (theInput == null) return 0;
  if (theInput.length == null) {
    if (theInput.checked) nChecked++;
  }
  else {
    for (var x=0; x<theInput.length; x++)
      if (theInput[x].checked) nChecked++;
  }
  return nChecked;
}
function validateChecked(theInput, errMessage) {
  var nChecked = isChecked(theInput);
  if (!nChecked) {
      alert(errMessage);
      theInput.focus();
  }
  return nChecked;
}
function trim(sInput) {
  if (sInput == null) return null;
  var sOutput = sInput;
  sOutput = sOutput.replace(/^\s+/, '');
  sOutput = sOutput.replace(/\s+$/, '');
  return sOutput;
}