function VerifyForm() {

  this.msgSeparator = '\n';
  this.blankValue   = '';
  this._gripes      = new Array();

  this._StateUSA = /^(A[AEKLPRSZ]|C[AOT]|DC|DE|FL|FM|GA|GU|HI|I[ADLN]|KS|KY|LA|M[ADEHINOPST]|N[CDEHJMVY]|O[HKR]|P[ARW]|RI|SC|SD|T[NTX]|UT|V[AIT]|W[AIVY])$/i;
  this._StateCan = /^(AB|BC|MB|N[BFST]|ON|PE|PQ|QC|SK|YT)$/i;
  this._ZipUSA   = /^\d{5}([- ]?\d{4})?$/;
  this._ZipCan   = /^[A-Z]\d[A-Z] ?\d[A-Z]\d$/i;
  this._PhoneNA  = /^\(?\d{3}\)?\D?\d{3}\D?\d{4}$/;
  this._Email    = /^([0-9a-z_&.+-]+!)*[0-9a-z_&.+-]+@(([0-9a-z]([0-9a-z-]*[0-9a-z])?\.)+[a-z]{2,3}|([0-9]{1,3}\.){3}[0-9]{1,3})$/i;
  this._EmailBad = /^(((postmaster|root|hostmaster|mailer-daemon|webmaster)@(adobe|frame)\.com)|.*@(.*\.(adobe|frame)\.com|localhost\.com|127\.0\.0\.1))$/i;
  this._Country = {
    us: /^(u\.?s\.?(a\.?)?|united states)$/i,
    ca: /^(ca\.?|can\.?|canada)$/i,
    jp: /^(jp\.?|japan|nippon)$/i,
    at: /^(at\.?|austria|osterreich)$/i,
    be: /^(be\.?|belgium|belgie)$/i,
    dk: /^(dk\.?|denmark|danmark)$/i,
    fi: /^(fi\.?|finland|suomi)$/i,
    fr: /^(fr\.?|france)$/i,
    de: /^(de\.?|germany|deutschland)$/i,
    gr: /^(gr\.?|greece|hellas)$/i,
    ie: /^(ie\.?|(republic of )?ireland|eire)$/i,
    it: /^(it\.?|italy|italia)$/i,
    lu: /^(lu\.?|luxembourg)$/i,
    nl: /^(nl\.?|(the )?netherlands|holland)$/i,
    pt: /^(pt\.?|portugal)$/i,
    es: /^(es\.?|spain|espana)$/i,
    se: /^(se\.?|sweden|sverige)$/i,
    uk: /^(u\.?k\.?|united kingdom|(great )?britain|england)$/i,
    no: /^(no\.?|norway|norge)$/i,
    ch: /^(ch\.?|switzerland.*)$/i
  };
  this._CC = {
    Visa: /^4\d{12}(\d{3})?$/,
    MasterCard: /^5[1-5]\d{14}$/,
    'American Express': /^3[47]\d{13}$/,
    Discover: /^6011\d{12}$/
  };

  this.addError      = _VerifyForm_addError;
  this.showErrors    = _VerifyForm_showErrors;
  this.hasValue      = _VerifyForm_hasValue;
  this.getValue      = _VerifyForm_getValue;
  this.getAllValues  = _VerifyForm_getAllValues;
  this.clearFirst    = _VerifyForm_clearFirst;
  this.clearLast     = _VerifyForm_clearLast;
  this.clearAll      = _VerifyForm_clearAll;
  this.setFirst      = _VerifyForm_setFirst;
  this.setLast       = _VerifyForm_setLast;
  this.setAll        = _VerifyForm_setAll;
  this.checkFirst    = _VerifyForm_checkFirst;
  this.checkLast     = _VerifyForm_checkLast;
  this.checkAll      = _VerifyForm_checkAll;
  this.uncheckFirst  = _VerifyForm_uncheckFirst;
  this.uncheckLast   = _VerifyForm_uncheckLast;
  this.uncheckAll    = _VerifyForm_uncheckAll;
  this._setField     = _VerifyForm__setField;
  this.validState    = _VerifyForm_validState;
  this.validZip      = _VerifyForm_validZip;
  this.validPhone    = _VerifyForm_validPhone;
  this.validEmail    = _VerifyForm_validEmail;
  this.getCountry    = _VerifyForm_getCountry;
  this.isNA          = _VerifyForm_isNA;
  this.isEU          = _VerifyForm_isEU;
  this.isEuData      = _VerifyForm_isEuData;
  this.isUSA         = _VerifyForm_isUSA; // deprecated
  this.isCanada      = _VerifyForm_isCanada; // deprecated
  this.validCardType = _VerifyForm_validCardType;
  this.validCard     = _VerifyForm_validCard;
  this.getCardType   = _VerifyForm_getCardType;
  this._mod10        = _VerifyForm__mod10;

  return this;
}

function _VerifyForm_addError (field, msg) {
  if ( ! this._gripes.length) {
    if (field.all || field.focus)  field.focus();
    //if (field.value && (field.all || field.select)) field.select();
  }
  this._gripes[this._gripes.length] = msg;
}
function _VerifyForm_showErrors (head, foot) {
  if (this._gripes.length) {
    alert((head ? head + this.msgSeparator : '') + this._gripes.join(this.msgSeparator) + (foot ? this.msgSeparator + foot : ''));
    return false;
  }
  return true;
}

function _VerifyForm_hasValue (field) {
  if ( ! field.type && field.length ) {
    for (var i = 0; i < field.length; i++)
      if (field[i].type && this.hasValue(field[i]))
        return true;
    return false;
  }
  if (/select/.test(field.type))
    return (field.selectedIndex != -1 && (field.options[field.selectedIndex].value != this.blankValue));
  if (/(checkbox|radio)/.test(field.type))
    return ( field.checked && (field.value != this.blankValue) );
  if (/(button|reset|submit)/.test(field.type))
    return false;
  return (field.value != this.blankValue)
}
function _VerifyForm_getValue (field) {
  if ( ! field.type && field.length ) {
    for (var i = 0; i < field.length; i++) {
      if (field[i].type) {
        var value = this.getValue(field[i]);
        if (value) return value;
      }
    }
    return null;
  }
  if (/select/.test(field.type))
    return ( (field.selectedIndex != -1 && (field.options[field.selectedIndex].value != this.blankValue))
      ? field.options[field.selectedIndex].value : null );
  if (/(checkbox|radio)/.test(field.type))
    return ( (field.checked && (field.value != this.blankValue)) ? field.value : null );
  return ( ( ! /(button|reset|submit)/.test(field.type) && (field.value != this.blankValue)) ? field.value : null )
}
function _VerifyForm_getAllValues (field) {
  var arr = new Array();
  if ( ! field.type && field.length ) {
    var temparr;
    for (var i = 0; i < field.length; i++) {
      if (field[i].type) {
        temparr = this.getAllValues(field[i]);
        for (var j = 0; j < temparr.length; j++)
          arr[arr.length] = temparr[j];
      }
    }
  }
  else if (/select/.test(field.type)) {
    for (var i = 0; i < field.length; i++)
      if (field.options[i].selected && (field.options[i].value != this.blankValue))
        arr[arr.length] = field.options[i].value;
  }
  else if (/(checkbox|radio)/.test(field.type) && field.checked && (field.value != this.blankValue))
    arr[arr.length] = field.value;
  else if ( ! /(button|reset|submit)/.test(field.type) && (field.value != this.blankValue))
    arr[arr.length] = field.value;
  return arr;
}

function _VerifyForm_clearFirst (field, val) { return this._setField(field,  1, val, this.blankValue, true) }
function _VerifyForm_clearLast  (field, val) { return this._setField(field, -1, val, this.blankValue, true) }
function _VerifyForm_clearAll   (field, val) { return this._setField(field,  0, val, this.blankValue, true) }
function _VerifyForm_setFirst     (field, toval, val) { return this._setField(field,  1, val, toval,  true) }
function _VerifyForm_setLast      (field, toval, val) { return this._setField(field, -1, val, toval,  true) }
function _VerifyForm_setAll       (field, toval, val) { return this._setField(field,  0, val, toval,  true) }
function _VerifyForm_checkFirst   (field, val)        { return this._setField(field,  1, val,  true, false) }
function _VerifyForm_checkLast    (field, val)        { return this._setField(field, -1, val,  true, false) }
function _VerifyForm_checkAll     (field, val)        { return this._setField(field,  0, val,  true, false) }
function _VerifyForm_uncheckFirst (field, val)        { return this._setField(field,  1, val, false, false) }
function _VerifyForm_uncheckLast  (field, val)        { return this._setField(field, -1, val, false, false) }
function _VerifyForm_uncheckAll   (field, val)        { return this._setField(field,  0, val, false, false) }
function _VerifyForm__setField    (field, whichway, val, toval, valueorcheck) {
  var retval = false;
  if ( ! field.type && field.length ) {
    for (var i = (whichway == 1 ? 0 : field.length - 1); i < field.length && i >= 0; i += (whichway || -1))
      if (field[i].type && this._setField(field[i], whichway, val, toval, valueorcheck))
        if (whichway) return true;
        else retval = true;
    return retval;
  }
  if (valueorcheck) {
    if (/(file|password|text)/.test(field.type) && (typeof val != 'string' || field.value == val)) {
      field.value = toval;
      return true;
    }
  }
  else if (/select/.test(field.type)) {
    for (var i = (whichway == 1 ? 0 : field.length - 1); i < field.length && i >= 0; i += (whichway || -1)) {
      if ( typeof val != 'string' || field.options[i].value == val) {
        field.options[i].selected = toval;
        if (whichway) return true;
        else retval = true;
      }
    }
    return retval;
  }
  else if (/(checkbox|radio)/.test(field.type) && (typeof val != 'string' || field.value == val)) {
    field.checked = toval;
    return true;
  }
  return false
}


function _VerifyForm_validState (s, c) { return ( this.isUSA(c) ? this._StateUSA.test(s) : (this.isCanada(c) ? this._StateCan.test(s) : true) ) }
function _VerifyForm_validZip (z, c) { return ( this.isUSA(c) ? this._ZipUSA.test(z)   : (this.isCanada(c) ? this._ZipCan.test(z)   : true) ) }
function _VerifyForm_validPhone (p, c) { return ( this.isNA(c)  ? this._PhoneNA.test(p)  : true ) }
function _VerifyForm_validEmail (e) { return ( this._Email.test(e) && ! this._EmailBad.test(e) ) }
function _VerifyForm_getCountry (c) {
  for (var i = 1; i < arguments.length; i++)
    if (this._Country[arguments[i]] && this._Country[arguments[i]].test(c))
      return arguments[i];
  return null;
}
function _VerifyForm_isNA (c) { return ( this.getCountry(c, 'us', 'ca') ) }
function _VerifyForm_isEU (c) { return ( this.getCountry(c, 'at', 'be', 'de', 'dk', 'es', 'fi', 'fr', 'gr', 'ie', 'it', 'lu', 'nl', 'pt', 'se', 'uk') ) }
function _VerifyForm_isEuData (c) { return ( this.getCountry(c, 'at', 'be', 'ch', 'de', 'dk', 'es', 'fi', 'fr', 'ie', 'it', 'nl', 'no', 'pt', 'se', 'uk') ) }
function _VerifyForm_isUSA (c) { return ( this._Country.us.test(c) ) } // deprecated
function _VerifyForm_isCanada (c) { return ( this._Country.ca.test(c) ) } // deprecated

function _VerifyForm_validCardType (n, t) {
  return ( this._CC[t] && this._CC[t].test(n) && this._mod10(n) )
}
function _VerifyForm_validCard (n) {
  for (var t in this._CC) if (this._CC[t].test(n))
    return (this._mod10(n) ? t : null); return null
}
function _VerifyForm_getCardType (n) {
  for (var t in this._CC) if (this._CC[t].test(n)) return t; return null
}
function _VerifyForm__mod10 (num) {
  var sum = 0;
  for (var i = num.length - 1; i >= 0; i -= 2)
    sum += num.charAt(i) * 1 + num.charAt(i - 1) * 2 - (num.charAt(i - 1) >= 5 ? 9 : 0);
  return ( sum % 10 == 0 );
}

