Log in email validation : Form Validation « Form Control « JavaScript DHTML






Log in email validation

  
 <!--
  VALIDATE_FORM.JS
  Comprehensive solution for validating HTML forms.
  Copyright (C) 2002, Jeff Epstein, jeff_epstein@yahoo.com, http://www.jeffyjeffy.com#download

  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

  You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 -->
<HTML>
<HEAD>
   <TITLE>validate_form.js  --  Realistic Example:  Email Login</TITLE>

<SCRIPT LANGUAGE="JavaScript" TYPE='text/javascript'>
/**
  VALIDATE_FORM.JS
  Comprehensive solution for validating HTML forms.
  Copyright (C) 2002, Jeff Epstein, jeff_epstein@yahoo.com, http://www.jeffyjeffy.com#download

  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

  You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 **/


/**
  See validate_form_documentation.html for information.

  NOTES TO SELF
    //alert("The CODE for getRCBSMTrackerArrIdx=" + getRCBSMTrackerArrIdx);

    I would like to add a function to get the number of elements that have a (any) value.
 **/



//GLOBAL VARIABLES...start  (do not alter this section)
  var sDBG_INDENT = "     ";
  var asRCBSM_TRACKER_NAME = '';
  var aiRCBSM_TRACKER_SEL_COUNT = '';
  var aiRCBSM_TRACKER_ARR_IDX = '';
  var iELEMENT_COUNT = -1;
  var bFIRST_DEBUG_SCREEN_SEEN = false;
  var sCURRENT_LENGTH_FOR_TA = '~CURRLEN~';
  var bPHONE_ZIP_FORMATS_VALIDATED = false;
//GLOBAL VARIABLES...end

/**
  All messages must be at least one character in length.  If they are empty string, its as if they do not exist.
 **/
function getFormErrorMsgs(f_orm, s_userErrorPrefix, i_debugPerScreen)  {
  //This initialization function must be the very first line.
  initializeLocalVars();

  if(!arePhoneZipFormatsValid())  {
    return;
  }

  crashIfBadConfiguration(f_orm);

  if(hasCrashed())  {
    //For whatever reason utility.crash() was called, indicating
    //an error has occured.  Get out.  Get out while you still
    //can.
    return;
  }

  outputDebugging(f_orm, i_debugPerScreen);

  return getUserErrors(f_orm, s_userErrorPrefix);
}

/**
  PRIVATE FUNCTIONS...start
 **/
  function arePhoneZipFormatsValid()  {

    if(bPHONE_ZIP_FORMATS_VALIDATED)  {
      //Phone and zip code formats are checked only once.
      //They've already been checked once and are all were
      //found to be valid.
      return true;
    }

    //The formats have not yet been checked, or they were, but
    //were found to be invalid.

    var i = -1;

    var siPMin = "";
    var siPMax = "";
    for(i = 1; i < 11; i++)  {
      siPMin = eval("siPHONE_" + i + "_MINIMUM");
      siPMax = eval("siPHONE_" + i + "_MAXIMUM");

      if(!isPhoneFormatValid('false', siPMin, siPMax))  {
        alert("---  validate_form.js ERROR  ---\n\nPhone number format invalid:\n\tsiPHONE_" + i + "_MINIMUM='" + eval("siPHONE_" + i + "_MINIMUM") + "'\n\tsiPHONE_" + i + "_MAXIMUM='" + eval("siPHONE_" + i + "_MAXIMUM") + "'\n\nThe specific error message follows...");
        isPhoneFormatValid('true', siPMin, siPMax);
        return false;
      }
    }

    var siZRMin = "";
    var siZRMax = "";
    var siZAMin = "";
    var siZAMax = "";
    for(i = 1; i < 11; i++)  {
      siZRMin = eval("siZIP_" + i + "_RQD_MINIMUM");
      siZRMax = eval("siZIP_" + i + "_RQD_MAXIMUM");
      siZAMin = eval("siZIP_" + i + "_ALT_MINIMUM");
      siZAMax = eval("siZIP_" + i + "_ALT_MAXIMUM");

      if(!isZipFormatValid('false', siZRMin, siZRMax, siZAMin, siZAMax))  {
        alert("---  validate_form.js ERROR  ---\n\nZip code format invalid:\n\tsiZIP_" + i + "_RQD_MINIMUM='" + eval("siZIP_" + i + "_RQD_MINIMUM") + "'\n\tsiZIP_" + i + "_RQD_MAXIMUM='" + eval("siZIP_" + i + "_RQD_MAXIMUM") + "'\n\tsiZIP_" + i + "_ALT_MINIMUM='" + eval("siZIP_" + i + "_ALT_MINIMUM") + "'\n\tsiZIP_" + i + "_ALT_MAXIMUM='" + eval("siZIP_" + i + "_ALT_MAXIMUM") + "'\n\nThe specific error message follows...");
        isZipFormatValid('true', siZRMin, siZRMax, siZAMin, siZAMax)
        return false;
      }
    }

    bPHONE_ZIP_FORMATS_VALIDATED = true;
    return true;
  }


   function crashIfBadConfiguration(f_orm)  {
    crashIfMissing(f_orm, 'f_orm', 'validate_form.getFormErrorMsgs');

    crashIfBadBSSA('f_orm.asGlobalBadSubStrs', f_orm.asGlobalBadSubStrs);
    f_orm.bsGlobalTrimSpaces = getOptBooleanStringVF(f_orm.bsGlobalTrimSpaces, "f_orm.bsGlobalTrimSpaces");

    if(hasCrashed())  {
      return;
    }

    for(var i = 0; i < f_orm.length; i++)  {

      if(f_orm[i].type == "text"  ||  f_orm[i].type == "password")  {
        crashIfBadCfg_text(f_orm, f_orm[i]);

      }  else if(f_orm[i].type == "textarea")  {
        crashIfBadCfg_textarea(f_orm, f_orm[i]);

      }  else if(f_orm[i].type == "checkbox"  ||  f_orm[i].type == "select-multiple")  {
        crashIfBadCfg_cbsm(f_orm, i);

      }  else if(f_orm[i].type == "radio"  ||  f_orm[i].type == "select-one")  {
        crashIfBadCfg_rso(f_orm, i);
      }
    }
  }


  function outputDebugging(f_orm, i_debugPerScreen)  {
    if(!i_debugPerScreen  ||  i_debugPerScreen == -1)  {
      //No debugging is requested
      return;
    }

    if(typeof(i_debugPerScreen) != "number"  ||  i_debugPerScreen < 1)  {
      return crashVF("i_debugPerScreen is not required (currently '" + i_debugPerScreen + "'), but when provided, it must be a number (currently '" + typeof(i_debugPerScreen) + "') either equal to -1, or greater than zero.");
    }

    var iDebugItemsTotal = 0;
    var iDebugItemsThisRound = 0;
    var sDebugBuffer = '';
    var sDebugThisItem = '';

    for(var i = 0; i < f_orm.length; i++)  {
      if(f_orm[i].type == "text"  ||  f_orm[i].type == "password")  {
        sDebugThisItem = getDebugging_text(f_orm, f_orm[i]);

      }  else if(f_orm[i].type == "textarea")  {
        sDebugThisItem = getDebugging_textarea(f_orm, f_orm[i]);

      }  else if(f_orm[i].type == "checkbox"  ||  f_orm[i].type == "select-multiple")  {
        sDebugThisItem = getDebugging_cbsm(f_orm, i);

      }  else if(f_orm[i].type == "radio"  ||  f_orm[i].type == "select-one")  {
        sDebugThisItem = getDebugging_rso(f_orm, i);
      }

      if(sDebugThisItem)  {
        iDebugItemsTotal++;
        iDebugItemsThisRound++;

        sDebugBuffer += sDebugThisItem + "\n";

        if(iDebugItemsThisRound >= i_debugPerScreen)  {
          sDebugBuffer = getGlobalDebugging(sDebugBuffer, f_orm);

          alert("---  validate_form.js  DEBUGGING  (" + (iDebugItemsTotal - iDebugItemsThisRound + 1) + " to " + iDebugItemsTotal + " of " + iELEMENT_COUNT + ")  ---\n\n" + sDebugBuffer);

          iDebugItemsThisRound = 0;
          sDebugBuffer = '';
        }

        sDebugThisItem = '';
      }
    }

    if(sDebugBuffer)  {
      sDebugBuffer = getGlobalDebugging(sDebugBuffer, f_orm);
      alert("---  validate_form.js  DEBUGGING  (" + (iDebugItemsTotal - iDebugItemsThisRound + 1) + " to " + iDebugItemsTotal + " of " + iELEMENT_COUNT + ")  ---\n\n" + sDebugBuffer);
    }
  }

  function getGlobalDebugging(s_debugBuffer, f_orm)  {
    if(!bFIRST_DEBUG_SCREEN_SEEN)  {
      bFIRST_DEBUG_SCREEN_SEEN = true;

      var sGlobalDebug = '';

      if(f_orm.asGlobalBadSubStrs)  {
        sGlobalDebug = sDBG_INDENT + "f_orm.asGlobalBadSubStrs=  [ " + f_orm.asGlobalBadSubStrs + " ]\n";
      }

      if(f_orm.bsGlobalTrimSpaces == 'true')  {
        sGlobalDebug += sDBG_INDENT + "f_orm.bsGlobalTrimSpaces=  'true'\n";
      }

      if(sGlobalDebug)  {
        return "---  GLOBAL SETTINGS  ---\n" + sGlobalDebug + "\n\n" + s_debugBuffer;
      }
    }

    //Either the first debugging screen has already been displayed, or
    //this is the first screen, but there is no global settings
    return s_debugBuffer;
  }

  function getUserErrors(f_orm, s_prefix)  {
    var sUserErrors = '';

    for(var i = 0; i < f_orm.length; i++)  {

      if(f_orm[i].type == "text"  ||  f_orm[i].type == "password")  {
        sUserErrors += getUserErrors_text(f_orm, i, s_prefix);

      }  else if(f_orm[i].type == "textarea")  {
        sUserErrors += getUserErrors_textarea(f_orm, i, s_prefix);

      }  else if(f_orm[i].type == "checkbox"  ||  f_orm[i].type == "select-multiple")  {
        sUserErrors += getUserErrors_cbsm(f_orm, i, s_prefix);

      }  else if(f_orm[i].type == "radio"  ||  f_orm[i].type == "select-one")  {
        sUserErrors += getUserErrors_rso(f_orm, i, s_prefix);
      }
    }

    return sUserErrors;
  }
  /**
    form_element must be provided, and a form element...START
   **/
    function getDebuggingNameType(form_element)  {
      return "---  " + form_element.name + "  ---          [" + form_element.type + "]\n";
    }
    function getDebuggingMsgRequired(s_msgRequired)  {
      if(s_msgRequired)  {
        return sDBG_INDENT + "sMsgRequired:  '" + s_msgRequired + "'\n";
      }
      return '';
    }
    function getDebuggingValue(s_value)  {
      if(s_value)  {
        return sDBG_INDENT + "VALUE:  '" + s_value + "'\n";
      }
      return '';
    }
  /**
    form_element must be provided, and a form element...END
   **/

  /**
    Do not call this function without first calling crashIfBadCfg_cbsm for the form-and-form-element.
   **/
  function getUserErrors_cbsm(f_orm, i_arrIdx, s_prefix)  {
    var feCbsm = f_orm[i_arrIdx];

    var sMsgRequired = '';
    var sMsgMCRange = '';
    var iMCMin = '';
    var iMCMax = '';

    if(feCbsm.type == "checkbox")  {
      if(getFirstArrIdx(feCbsm.name) != i_arrIdx)  {
        //This checkbox has already had its user errors retrieved.
        return '';
      }
      //This checkbox has not yet had its user errors retrieved.

      sMsgRequired = f_orm[feCbsm.name + ".sMsgRequired"];
      sMsgMCRange = f_orm[feCbsm.name + ".sMsgMCRange"];
      iMCMin = f_orm[feCbsm.name + ".iMCMin"];
      iMCMax = f_orm[feCbsm.name + ".iMCMax"];

    }  else  {
      //this is a select-multiple type...which has not yet had its
      //user errors retrieved.

      sMsgRequired = feCbsm.sMsgRequired
      sMsgMCRange = feCbsm.sMsgMCRange
      iMCMin = feCbsm.iMCMin
      iMCMax = feCbsm.iMCMax
    }

    var iMCSelCount = getMCSelectedCount(feCbsm.name);
    if(sMsgRequired  &&  iMCSelCount < 1)  {
      return s_prefix + sMsgRequired + "\n";
    }
    //If its required, a value has been selected.

    if(iMCSelCount < 1)  {
      //Its not required, and no value has been selected,
      //which is okay.
      return '';
    }

    if((iMCMin  &&  iMCMin > iMCSelCount)  ||
       (iMCMax  &&  iMCMax < iMCSelCount))  {
      return s_prefix + sMsgMCRange + "\n";
    }

    return '';
  }

  /**
    Do not call this function without first calling crashIfBadCfg_cbsm for the form-and-form-element.
   **/
  function getDebugging_cbsm(f_orm, i_arrIdx)  {
    var feCbsm = f_orm[i_arrIdx];

    var sMsgRequired = '';
    var sMsgMCRange = '';
    var iMCMin = '';
    var iMCMax = '';

    if(feCbsm.type == "checkbox")  {
      if(getFirstArrIdx(feCbsm.name) != i_arrIdx)  {
        //This checkbox has already been debugged.
        return '';
      }
      //This checkbox has not yet been debugged

      sMsgRequired = f_orm[feCbsm.name + ".sMsgRequired"];
      sMsgMCRange = f_orm[feCbsm.name + ".sMsgMCRange"];
      iMCMin = f_orm[feCbsm.name + ".iMCMin"];
      iMCMax = f_orm[feCbsm.name + ".iMCMax"];

    }  else  {
      //this is a select-multiple type...which has not yet been debugged.

      sMsgRequired = feCbsm.sMsgRequired
      sMsgMCRange = feCbsm.sMsgMCRange
      iMCMin = feCbsm.iMCMin
      iMCMax = feCbsm.iMCMax
    }

    var s = getDebuggingNameType(feCbsm) + getDebuggingMsgRequired(sMsgRequired);
    if(sMsgMCRange)  {
      s += sDBG_INDENT + "sMsgMCRange:  '" + sMsgMCRange + "'\n";

      if(iMCMin)  {
        s += sDBG_INDENT + sDBG_INDENT + "iMCMin:  " + iMCMin + "\n";
      }

      if(iMCMax)  {
        s += sDBG_INDENT + sDBG_INDENT + "iMCMax:  " + iMCMax + "\n";
      }
    }
    var iMCSelCount = getMCSelectedCount(feCbsm.name);
    if(iMCSelCount > 0)  {
      s += sDBG_INDENT + "NUMBER OF CHOICES SELECTED:  " + iMCSelCount + "\n";
    }
    return s;
  }

  function crashIfBadCfg_cbsm(f_orm, i_arrIdx)  {
    conditionallyAddRCBSM(f_orm, i_arrIdx);

    var feCbsm = f_orm[i_arrIdx];
    var sMsgMCRange = '';
    var iMCMin = '';
    var iMCMax = '';
    var iTotalOptions = -1;
    var sErrVarPre = '';
    var sErrVarPost = '';

    if(feCbsm.type == "checkbox")  {
      if(getFirstArrIdx(feCbsm.name) != i_arrIdx)  {
        //This checkbox has already been validated.
        return '';
      }
      //This checkbox has not yet been validated

      sMsgMCRange = f_orm[feCbsm.name + ".sMsgMCRange"];
      iMCMin = f_orm[feCbsm.name + ".iMCMin"];
      iMCMax = f_orm[feCbsm.name + ".iMCMax"];
      iTotalOptions = f_orm[feCbsm.name].length;
      sErrVarPre = "f_orm['" + feCbsm.name;
      sErrVarPost = "']";

    }  else  {
      //this is a select-multiple type...which has not yet been validated.
      sMsgMCRange = feCbsm.sMsgMCRange;
      iMCMin = feCbsm.iMCMin;
      iMCMax = feCbsm.iMCMax;
      iTotalOptions = feCbsm.length;
      sErrVarPre = feCbsm.name;
      sErrVarPost = "";

    }

    if(sMsgMCRange)  {
      if(!iMCMin  &&  !iMCMax)  {
        return crashVF(sErrVarPre + ".sMsgMCRange" + sErrVarPost + " has been provided (currently '" + sMsgMCRange + "'), but neither " + sErrVarPre + ".iMCMin" + sErrVarPost + " nor " + sErrVarPre + ".iMCMax" + sErrVarPost + " have been provided.  At least one of these bounds are required.");
      }

      if(iMCMin)  {
        if(!isInteger(iMCMin))  {
          return crashVF(sErrVarPre + ".iMCMin" + sErrVarPost + " has been provided, but is not of type number.  Currently of type '" + typeof(iMCMin) + "' and equal to '" + iMCMin + "'.");
        }

        if(iMCMin < 1  ||  iMCMin > iTotalOptions)  {
          return crashVF(sErrVarPre + ".iMCMin" + sErrVarPost + " has been provided (currently " + iMCMin + "), but is either less than one, or greater than the total number of options (" + iTotalOptions + ").");
        }
      }

      if(iMCMax)  {
        if(!isInteger(iMCMax))  {
          return crashVF(sErrVarPre + ".iMCMax" + sErrVarPost + " has been provided, but is not of type number.  Currently of type '" + typeof(iMCMax) + "' and equal to '" + iMCMax + "'.");
        }

        if(iMCMax < 1  ||  iMCMax > iTotalOptions)  {
          return crashVF(sErrVarPre + ".iMCMax" + sErrVarPost + " has been provided (currently " + iMCMax + "), but is either less than one, or greater than the total number of options (" + iTotalOptions + ").");
        }
      }

      if(iMCMin  &&  iMCMax  &&  iMCMin > iMCMax)  {
        return crashVF(sErrVarPre + ".sMsgMCRange" + sErrVarPost + " has been provided (currently '" + sMsgMCRange + "'), and both " + sErrVarPre + ".iMCMin" + sErrVarPost + " (currently " + iMCMin + ") and " + sErrVarPre + ".iMCMax" + sErrVarPost + " (currently " + iMCMax + ") have been provided.  However, iMCMin must be less than or equal to iMCMax, which it is not.");
      }

    }  else if(iMCMin  ||  iMCMax)  {
      return crashVF(sErrVarPre + ".sMsgMCRange" + sErrVarPost + " has *not* been provided, but at least one of " + sErrVarPre + ".iMCMin" + sErrVarPost + " (currently '" + iMCMin + "') or " + sErrVarPre + ".iMCMax" + sErrVarPost + " (currently '" + iMCMax + "') has been provided.");
    }
  }


  /**
    Do not call this function without first calling crashIfBadCfg_rso for the form-and-form-element.
   **/
  function getUserErrors_rso(f_orm, i_arrIdx, s_prefix)  {
    var feRso = f_orm[i_arrIdx];
    var sValue = '';
    var sMsgRequired = '';

    if(feRso.type == "radio")  {
      if(getFirstArrIdx(feRso.name) != i_arrIdx)  {
        //We already debugged this radio element.
        return '';
      }

      sMsgRequired = f_orm[feRso.name + ".sMsgRequired"];
      sValue = getRadioValue(f_orm, feRso.name);

    }  else if(feRso.selectedIndex > -1) {
      sMsgRequired = feRso.sMsgRequired;
      sValue = feRso[feRso.selectedIndex].value;
    }

    if(sMsgRequired  &&  !sValue)  {
      return s_prefix + sMsgRequired + "\n";
    }
    //If its required, a value has been provided.

    return '';
  }


  /**
    Do not call this function without first calling crashIfBadCfg_rso for the form-and-form-element.
   **/
  function getDebugging_rso(f_orm, i_arrIdx)  {
    var feRso = f_orm[i_arrIdx];
    var sValue = '';
    var sMsgRequired = '';

    if(feRso.type == "radio")  {
      if(getFirstArrIdx(feRso.name) != i_arrIdx)  {
        //We already debugged this radio element.
        return '';
      }

      sMsgRequired = f_orm[feRso.name + ".sMsgRequired"];
      sValue = getRadioValue(f_orm, feRso.name);

    }  else if(feRso.selectedIndex > -1) {
      sMsgRequired = feRso.sMsgRequired;
      sValue = feRso[feRso.selectedIndex].value;
    }

    return getDebuggingNameType(feRso) + getDebuggingMsgRequired(sMsgRequired) + getDebuggingValue(sValue);
  }

  function getRadioValue(f_orm, s_radioName)  {
    var feRadio = f_orm[s_radioName];
    for(var i = 0; i < feRadio.length; i++)  {
      if(feRadio[i].checked)  {
        return feRadio[i].value;
      }
    }

    return '';
  }

  function crashIfBadCfg_rso(f_orm, i_arrIdx)  {
    var feRso = f_orm[i_arrIdx];
    if(feRso.type == "radio")  {
      conditionallyAddRCBSM(f_orm, i_arrIdx);

    }  else  {
      iELEMENT_COUNT++;
    }

    //Nothing to validate.  The only attribute that
    //can be associated to a radio or select-one type
    //is sMsgRequired...  Which either is or isn't...
    //doesn't matter which.
  }

  function conditionallyAddRCBSM(f_orm, i_arrIdx)  {
    var feCbsm = f_orm[i_arrIdx];
    if(wasRCBSMalreadyFound(feCbsm.name))  {
      //We already analyzed this element.
      return;
    }

    iELEMENT_COUNT++;

    addRCBSMtoTracker(f_orm, feCbsm, i_arrIdx);
  }

  /**
    Do not call this function without first calling crashIfBadCfg_textarea for the form-and-form-element.
   **/
  function getUserErrors_textarea(f_orm, i_arrIdx, s_prefix)  {
    var feTA = f_orm[i_arrIdx];
    if(feTA.sMsgRequired  &&  !feTA.value)  {
      return s_prefix + feTA.sMsgRequired + "\n";
    }

    if(!feTA.value)  {
      return '';
    }

    if(needsToBeTrimmed(f_orm, feTA))  {
      feTA.value = trimSpaces(feTA.value);
    }

    if(feTA.sMsgBadLength  &&
       (feTA.value.length < feTA.iMinLength  ||
        feTA.value.length > feTA.iMaxLength))  {

      return s_prefix + getBadLengthMsg(feTA) + '\n';
    }

    return getBadSubStrMessage(feTA.value, f_orm, feTA.asBadSubStrs, feTA.bsNoBadSubStrings, s_prefix, feTA.sMsgBadSubStr);
  }

  function getBadLengthMsg(fe_tta)  {
    var sMsg = fe_tta.sMsgBadLength;

    var iCLArrIdx = sMsg.indexOf(sCURRENT_LENGTH_FOR_TA);
    if(iCLArrIdx != -1)  {
      sMsg = sMsg.substring(0, iCLArrIdx) + fe_tta.value.length + sMsg.substring((iCLArrIdx + sCURRENT_LENGTH_FOR_TA.length), (sMsg.length + 1));
    }

    return sMsg;
  }

  function getBadSubStrMessage(s_value, f_orm, as_badSubStrs, bs_noBadSubStrings, s_prefix, s_errorMessage)  {
    if(!s_value)  {
      //Theres no value, so it can't have any illegal sub-string.
      return '';
    }

    if(bs_noBadSubStrings == 'true')  {
      //This element is exempt.
      return '';
    }

    //"x" is important...1/2
    var asBadSubStrs = "x";

    if(f_orm.asGlobalBadSubStrs)  {
      asBadSubStrs = f_orm.asGlobalBadSubStrs;
    }

    if(as_badSubStrs)  {
      asBadSubStrs = as_badSubStrs;
    }

    //"x" is important...2/2
    if(asBadSubStrs == "x")  {
      //There are no sub-strings to consider illegal.
      return '';
    }
    //There *are* sub-strings to be considered illegal.

    for(var i = 0; i < asBadSubStrs.length; i++)  {
      if(s_value.indexOf(asBadSubStrs[i]) != -1)  {
        return s_prefix + s_errorMessage + "\n";
      }
    }

    return '';
  }


  /**
    Do not call this function without first calling crashIfBadCfg_textarea for the form-and-form-element.
   **/
  function getDebugging_textarea(f_orm, fe_textarea)  {
    var s = getDebuggingNameType(fe_textarea) + getDebuggingMsgRequired(fe_textarea.sMsgRequired);

    if(fe_textarea.bsNoBadSubStrings == 'true')  {
      s += sDBG_INDENT + "bsNoBadSubStrings:  '" + fe_textarea.bsNoBadSubStrings + "'\n";

    }  else if(f_orm.asGlobalBadSubStrs  ||  fe_textarea.asBadSubStrs)  {
      if(fe_textarea.asBadSubStrs)  {
        s += sDBG_INDENT + "asBadSubStrs:  [" + fe_textarea.asBadSubStrs + "]\n";
      }  else if(f_orm.asGlobalBadSubStrs)  {
        s += sDBG_INDENT + "f_orm.asGlobalBadSubStrs:  [" + f_orm.asGlobalBadSubStrs + "]\n";
      }

      s += sDBG_INDENT + sDBG_INDENT + "sMsgBadSubStr:  '" + fe_textarea.sMsgBadSubStr + "'\n";
    }

    if(fe_textarea.sMsgBadLength)  {
      s += sDBG_INDENT + "sMsgBadLength:  '" + fe_textarea.sMsgBadLength + "'\n";

      if(fe_textarea.iMinLength)  {
        s += sDBG_INDENT + sDBG_INDENT + "iMinLength:  " + fe_textarea.iMinLength + "\n";
      }

      if(fe_textarea.iMaxLength)  {
        s += sDBG_INDENT + sDBG_INDENT + "iMaxLength:  " + fe_textarea.iMaxLength + "\n";
      }
    }

    s += getDebuggingValue(fe_textarea.value);

    return s;
  }

  function crashIfBadCfg_textarea(f_orm, fe_textarea)  {
    crashIfMissing(fe_textarea, 'fe_textarea', 'validate_form.crashIfBadCfg_textarea');

    if(fe_textarea.type != 'textarea')  {
      return crashVF("fe_textarea must be of type 'text'.  Currently '" + fe_textarea.type + "'...SANITY CHECK.  SHOULD NEVER HAPPEN.");
    }

    iELEMENT_COUNT++;

    var sName = sName;

    fe_textarea.bsNoBadSubStrings = getOptBooleanStringVF(fe_textarea.bsNoBadSubStrings, "f_orm." + sName + ".bsNoBadSubStrings");
    crashIfNBSSError(sName, fe_textarea.bsNoBadSubStrings, f_orm.asGlobalBadSubStrs, fe_textarea.asBadSubStrs);

    if(fe_textarea.bsNoBadSubStrings == 'false'  &&
      (f_orm.asGlobalBadSubStrs  ||  fe_textarea.asBadSubStrs)  &&
      !fe_textarea.sMsgBadSubStr)  {
      return crashVF("Either f_orm.asGlobalBadSubStrs (currently [" + f_orm.asGlobalBadSubStrs + "]) or f_orm." + sName + ".asBadSubStrs (currently [" + fe_textarea.asBadSubStrs + "]) have  been provided, AND f_orm." + sName + ".bsNoBadSubStrings equals 'false' (meaning there are sub-strings that are illegal for this field).  This means that f_orm." + sName + ".sMsgBadSubStr is required.  However, f_orm." + sName + ".sMsgBadSubStr has not been provided.");
    }

    crashIfBadSpaceTrimConfig(f_orm, fe_textarea);

    var iMin = fe_textarea.iMinLength;
    var iMax = fe_textarea.iMaxLength;
    if(fe_textarea.sMsgBadLength)  {

      if(!iMin  &&  !iMax)  {
        return crashVF("f_orm." + sName + ".sMsgBadLength has been provided (currently '" + fe_textarea.sMsgBadLength + "'), but neither f_orm." + sName + ".iMinLength nor f_orm." + sName + ".iMaxLength have been provided.");
      }

      if(iMin  &&  (!isInteger(iMin)  ||  iMin < 1))  {
        return crashVF("Both f_orm." + sName + ".sMsgBadLength (currently '" + fe_textarea.sMsgBadLength + "') and f_orm." + sName + ".iMinLength (currently " + iMin + ") have been provided, but iMinLength must be an integer, and at least equal to one.  Additional information:  f_orm." + sName + ".iMaxLength currently equals " + iMax + ".");
      }

      if(iMax  &&  (!isInteger(iMax)  ||  iMax < 1))  {
        return crashVF("Both f_orm." + sName + ".sMsgBadLength (currently '" + fe_textarea.sMsgBadLength + "') and f_orm." + sName + ".iMaxLength (currently '" + iMax + "') have been provided, but iMaxLength must be an integer, and at least equal to one.  Additional information:  f_orm." + sName + ".iMinLength currently equals " + iMin + ".");
      }

      if(iMin  &&  iMax  &&  iMin > iMax)  {
        return crashVF("f_orm." + sName + ".sMsgBadLength (currently '" + fe_textarea.sMsgBadLength + "'), f_orm." + sName + ".iMinLength (currently " + iMin + ") and f_orm." + sName + ".iMaxLength (currently " + iMax + ") have all been provided, but iMinLength must be less than or equal to iMaxLength.");
      }

    }  else if(iMin  ||  iMax)  {
      return crashVF("f_orm." + sName + ".sMsgBadLength has *not* been provided, but at least one of f_orm." + sName + ".iMinLength (currently " + iMin + ") and f_orm." + sName + ".iMaxLength (currently " + iMax + ") have been provided.");
    }
  }


  /**
    Do not call this function without first calling crashIfBadCfg_textarea for the form-and-form-element.
   **/
  function getUserErrors_text(f_orm, i_arrIdx, s_prefix)  {
    var feText = f_orm[i_arrIdx];

    if(needsToBeTrimmed(f_orm, feText))  {
      feText.value = trimSpaces(feText.value);
    }

    if(feText.sMsgRequired  &&  !feText.value)  {
      return s_prefix + feText.sMsgRequired + "\n";
    }

    if(!feText.value)  {
      return '';
    }

    //It is assumed/expected that there is only one "sMsgTxt"
    //variables associated to feText.  The only reason that
    //the following ifs are not else-ifs, is because of the
    //for loop of eval statements.
    if(feText.sMsgTxtEmail)  {
      if(!isEmail(feText.value))  {
        return s_prefix + feText.sMsgTxtEmail + '\n';
      }

    }  else if(feText.sMsgTxtInt)  {
      if(!isInteger(feText.value)  ||
         (feText.iIntMin  &&  feText.iIntMin > feText.value)  ||
         (feText.iIntMax  &&  feText.iIntMax < feText.value))  {
        return s_prefix + feText.sMsgTxtInt + '\n';
      }

    }  else if(feText.sMsgTxtDec)  {
      if(!isDecimal(feText.value)  ||
         (feText.iDecMin  &&  feText.iDecMin > feText.value)  ||
         (feText.iDecMax  &&  feText.iDecMax < feText.value))  {
        return s_prefix + feText.sMsgTxtDec + '\n';
      }

    }  else if(feText.sMsgTxtPhone)  {
      var sPhoneStripped = getValidPhone1(feText.value);
      if(!sPhoneStripped)  {
        return s_prefix + feText.sMsgTxtPhone + '\n';
      }

      feText.value = sPhoneStripped;

    }  else if(feText.sMsgTxtZip)  {
      var sZipStripped = getValidZip1(feText.value);
      if(!sZipStripped)  {
        return s_prefix + feText.sMsgTxtZip + '\n';
      }

      feText.value = sZipStripped;

    }  else  {
      for(var i = 1; i < 11; i++)  {
        if(eval("feText.sMsgTxtPhone" + i))  {
          var sPhoneStripped = eval("getValidPhone" + i + "(feText.value)");
          if(!sPhoneStripped)  {
            return s_prefix + eval("feText.sMsgTxtPhone" + i) + '\n';
          }

          feText.value = sPhoneStripped;

          break;    //There is only one sMsgTxt* per element
        }

        if(eval("feText.sMsgTxtZip" + i))  {
          var sZipStripped = eval("getValidZip" + i + "(feText.value)");
          if(!sZipStripped)  {
            return s_prefix + eval("feText.sMsgTxtZip" + i) + '\n';
          }

          feText.value = sZipStripped;

          break;    //There is only one sMsgTxt* per element
        }
      }
    }



    if(feText.sMsgBadLength  &&  feText.value.length < feText.iMinLength)  {
      return s_prefix + getBadLengthMsg(feText) + '\n';
    }

    return getBadSubStrMessage(feText.value, f_orm, feText.asBadSubStrs, feText.bsNoBadSubStrings, s_prefix, feText.sMsgBadSubStr);
  }

  function needsToBeTrimmed(f_orm, fe_tta)  {
    if(!fe_tta.value)  {
      return false;
    }

    if(fe_tta.bsDontTrimSpaces == 'true')  {
      return false;
    }

    if(f_orm.bsGlobalTrimSpaces == 'true'  ||  fe_tta.bsTrimSpaces == 'true')  {
      return isSurroundedBySpace(fe_tta.value);
    }
  }


  /**
    Do not call this function without first calling crashIfBadCfg_text for the form-and-form-element.
   **/
  function getDebugging_text(f_orm, fe_text)  {
    var sDBG_INDENT = "     ";
    var s = getDebuggingNameType(fe_text) + getDebuggingMsgRequired(fe_text.sMsgRequired);

    var bEM = fe_text.sMsgTxtEmail;
    var bInt = fe_text.sMsgTxtInt;
    var bDec = fe_text.sMsgTxtDec;
    var bZC = fe_text.sMsgTxtZip;
    var bZC1 = fe_text.sMsgTxtZip1;
    var bZC2 = fe_text.sMsgTxtZip2;
    var bZC3 = fe_text.sMsgTxtZip3;
    var bZC4 = fe_text.sMsgTxtZip4;
    var bZC5 = fe_text.sMsgTxtZip5;
    var bZC6 = fe_text.sMsgTxtZip6;
    var bZC7 = fe_text.sMsgTxtZip7;
    var bZC8 = fe_text.sMsgTxtZip8;
    var bZC9 = fe_text.sMsgTxtZip9;
    var bZC10 = fe_text.sMsgTxtZip10;
    var bPN = fe_text.sMsgTxtPhone;
    var bPN1 = fe_text.sMsgTxtPhone1;
    var bPN2 = fe_text.sMsgTxtPhone2;
    var bPN3 = fe_text.sMsgTxtPhone3;
    var bPN4 = fe_text.sMsgTxtPhone4;
    var bPN5 = fe_text.sMsgTxtPhone5;
    var bPN6 = fe_text.sMsgTxtPhone6;
    var bPN7 = fe_text.sMsgTxtPhone7;
    var bPN8 = fe_text.sMsgTxtPhone8;
    var bPN9 = fe_text.sMsgTxtPhone9;
    var bPN10 = fe_text.sMsgTxtPhone10;

    if(bEM)  {
      s += sDBG_INDENT + "sMsgTxtEmail:  '" + fe_text.sMsgTxtEmail + "'\n";
    }

    if(bZC)  {
      s += sDBG_INDENT + "sMsgTxtZip:  '" + fe_text.sMsgTxtZip + "'\n";
    }

    if(bPN)  {
      s += sDBG_INDENT + "sMsgTxtPhone:  '" + fe_text.sMsgTxtPhone + "'\n";
    }

    for(var i = 1; i < 11; i++)  {
      if(eval("bPN" + i))  {
        s += sDBG_INDENT + "sMsgTxtPhone" + i + ":  '" + eval("fe_text.sMsgTxtPhone" + i) + "'\n";
      }

      if(eval("bZC" + i))  {
        s += sDBG_INDENT + "sMsgTxtZip" + i + ":  '" + eval("fe_text.sMsgTxtZip" + i) + "'\n";
      }
    }

    if(bInt)  {
      s += sDBG_INDENT + "sMsgTxtInt:  '" + fe_text.sMsgTxtInt + "'\n";

      if(fe_text.iIntMin)  {
        s += sDBG_INDENT + sDBG_INDENT + "iIntMin:  '" + fe_text.iIntMin + "'\n";
      }

      if(fe_text.iIntMax)  {
        s += sDBG_INDENT + sDBG_INDENT + "iIntMax:  '" + fe_text.iIntMax + "'\n";
      }
    }

    if(bDec)  {
      s += sDBG_INDENT + "sMsgTxtDec:  '" + fe_text.sMsgTxtDec + "'\n";

      if(fe_text.iDecMin)  {
        s += sDBG_INDENT + sDBG_INDENT + "iDecMin:  '" + fe_text.iDecMin + "'\n";
      }

      if(fe_text.iDecMax)  {
        s += sDBG_INDENT + sDBG_INDENT + "iDecMax:  '" + fe_text.iDecMax + "'\n";
      }
    }


    if(fe_text.bsNoBadSubStrings == 'true')  {
      s += sDBG_INDENT + "bsNoBadSubStrings:  '" + fe_text.bsNoBadSubStrings + "'\n";

    }  else if(!bInt  &&  !bDec  &&
                   !bZC   &&  !bZC1  &&  !bZC2  &&  !bZC3  &&  !bZC4  &&  !bZC5  &&
                   !bZC6  &&  !bZC7  &&  !bZC8  &&  !bZC9  &&  !bZC10  &&
                   !bPN   &&  !bPN1  &&  !bPN2  &&  !bPN3  &&  !bPN4  &&  !bPN5  &&
                   !bPN6  &&  !bPN7  &&  !bPN8  &&  !bPN9  &&  !bPN10  &&
               (f_orm.asGlobalBadSubStrs  ||  fe_text.asBadSubStrs))  {

      var sSecondIndent = '';
      if(fe_text.asBadSubStrs)  {
        s += sDBG_INDENT + "asBadSubStrs:  [" + fe_text.asBadSubStrs + "]\n";
        sSecondIndent = sDBG_INDENT;
      }
    }

    if(fe_text.sMsgBadLength)  {
      s += sDBG_INDENT + "sMsgBadLength:  '" + fe_text.sMsgBadLength + "'\n" + sDBG_INDENT + sDBG_INDENT + "iMinLength:  " + fe_text.iMinLength + "\n";

      if(fe_text.maxLength)  {
        s += sDBG_INDENT + sDBG_INDENT + "MAXLENGTH:  " + fe_text.MAXLENGTH + "\n";
      }

    }

    s += getDebuggingValue(fe_text.value);

    return s;
  }

  function crashIfBadCfg_text(f_orm, fe_text)  {
    crashIfMissing(fe_text, 'fe_text', 'validate_form.crashIfBadCfg_text');

    if(fe_text.type != 'text'  &&  fe_text.type != 'password')  {
      return crashVF("fe_text must be of type 'text' or 'password'.  Currently '" + fe_text.type + "'...SANITY CHECK.  SHOULD NEVER HAPPEN.");
    }

    var sName = fe_text.name;

    iELEMENT_COUNT++;

    var bEM = fe_text.sMsgTxtEmail;
    var bInt = fe_text.sMsgTxtInt;
    var bDec = fe_text.sMsgTxtDec;
    var bZC = fe_text.sMsgTxtZip;
    var bPN = fe_text.sMsgTxtPhone;

    var iSpecialTypes = 0;
    var sSpecialTypes = '';
    if(bEM)  {
      iSpecialTypes++;
      sSpecialTypes += 'sMsgTxtEmail...';
    }

    if(bInt)  {
      iSpecialTypes++;
      sSpecialTypes += 'sMsgTxtInt...';
      crashIfBadIntDecCfg(fe_text.iIntMin, fe_text.iIntMax, 'false', sName, 'iIntMin', 'iIntMax');

    }  else if(fe_text.iIntMin  ||  fe_text.iIntMax)  {
      return crashVF("f_orm." + sName + ".sMsgTxtInt has *not* been provided, but one or both of the sub-variables " + sName + ".iIntMin (currently '" + fe_text.iIntMin + "')/" + sName + ".iIntMax (currently '" + fe_text.iIntMax + "') have been provided.");
    }


    if(bDec)  {
      iSpecialTypes++;
      sSpecialTypes += 'sMsgTxtDec...';
      crashIfBadIntDecCfg(fe_text.iDecMin, fe_text.iDecMax, 'true', sName, 'iDecMin', 'iDecMax');

    }  else if(fe_text.iDecMin  ||  fe_text.iDecMax)  {
      return crashVF("f_orm." + sName + "." + sAnIntADec + " has *not* been provided, but one or both of the sub-variables " + sName + ".iDecMin (currently '" + fe_text.iDecMin + "')/" + sName + ".iDecMax (currently '" + fe_text.iDecMax + "') have been provided.");
    }

    if(bPN)  {
      iSpecialTypes++;
      sSpecialTypes += 'sMsgTxtPhone...';
    }

    for(var i = 1; i < 11; i++)  {
      eval("var bPN" + i + " = fe_text.sMsgTxtPhone" + i);

      if(eval("bPN" + i))  {
        iSpecialTypes++;
        sSpecialTypes += 'sMsgTxtPhone' + i + '...';
      }
    }

    if(bZC)  {
      iSpecialTypes++;
      sSpecialTypes += 'sMsgTxtZip...';
    }

    for(var i = 1; i < 11; i++)  {
      eval("var bZC" + i + " = fe_text.sMsgTxtZip" + i);

      if(eval("bZC" + i))  {
        iSpecialTypes++;
        sSpecialTypes += 'sMsgTxtZip' + i + '...';
      }
    }


    if(iSpecialTypes > 1)  {
      return crashVF("f_orm." + sName + " is of type 'text', but has " + iSpecialTypes + " special text types associated to it.  Zero or one of the following special types may be used for a text form element:  sMsgTxtEmail, sMsgTxtInt, sMsgTxtDec, sMsgTxtZip, sMsgTxtZip1, sMsgTxtZip2, sMsgTxtZip3, sMsgTxtZip4, sMsgTxtZip5, sMsgTxtZip6, sMsgTxtZip7, sMsgTxtZip8, sMsgTxtZip9, sMsgTxtZip10, sMsgTxtPhone, sMsgTxtPhone1, sMsgTxtPhone2, sMsgTxtPhone3, sMsgTxtPhone4, sMsgTxtPhone5, sMsgTxtPhone6, sMsgTxtPhone7, sMsgTxtPhone8, sMsgTxtPhone9, sMsgTxtPhone10.\n\nActually existing special types found:  " + sSpecialTypes);
    }

    crashIfBadBSSA('f_orm.' + sName + '.asBadSubStrs', fe_text.asBadSubStrs);

    fe_text.bsNoBadSubStrings = getOptBooleanStringVF(fe_text.bsNoBadSubStrings, "f_orm." + sName + ".bsNoBadSubStrings");

    crashIfNBSSError(sName, fe_text.bsNoBadSubStrings, f_orm.asGlobalBadSubStrs, fe_text.asBadSubStrs);

    if(fe_text.bsNoBadSubStrings == 'false'  &&  !bInt  &&  !bDec  &&
         !bZC   &&  !bZC1  &&  !bZC2  &&  !bZC3  &&  !bZC4  &&  !bZC5  &&
         !bZC6  &&  !bZC7  &&  !bZC8  &&  !bZC9  &&  !bZC10  &&
         !bPN   &&  !bPN1  &&  !bPN2  &&  !bPN3  &&  !bPN4  &&  !bPN5  &&
         !bPN6  &&  !bPN7  &&  !bPN8  &&  !bPN9  &&  !bPN10  &&
      (f_orm.asGlobalBadSubStrs  ||  fe_text.asBadSubStrs)  &&
      !fe_text.sMsgBadSubStr)  {
      return crashVF("Either f_orm.asGlobalBadSubStrs (currently [" + f_orm.asGlobalBadSubStrs + "]) or f_orm." + sName + ".asBadSubStrs (currently [" + fe_text.asBadSubStrs + "]) have  been provided, AND f_orm." + sName + ".bsNoBadSubStrings equals 'false' (meaning there are sub-strings that are illegal for this field) AND this text/password field does not have a 'number' special type (sMsgTxtInt, sMsgTxtDec, sMsgTxtZip, sMsgTxtZip1, sMsgTxtZip2, sMsgTxtZip3, sMsgTxtZip4, sMsgTxtZip5, sMsgTxtZip6, sMsgTxtZip7, sMsgTxtZip8, sMsgTxtZip9, sMsgTxtZip10, sMsgTxtPhone, sMsgTxtPhone1, sMsgTxtPhone2, sMsgTxtPhone3, sMsgTxtPhone4, sMsgTxtPhone5, sMsgTxtPhone6, sMsgTxtPhone7, sMsgTxtPhone8, sMsgTxtPhone9, sMsgTxtPhone10).  This means that f_orm." + sName + ".sMsgBadSubStr is required.  However, f_orm." + sName + ".sMsgBadSubStr has not been provided.");
    }

    crashIfBadSpaceTrimConfig(f_orm, fe_text);

    var bIsSpecial = (bEM  ||  bInt  || bDec  ||
      bZC   ||  bZC1  ||  bZC2  ||  bZC3  ||  bZC4  ||  bZC5  ||
       bZC6  ||  bZC7  ||  bZC8  ||  bZC9  ||  bZC10  ||
       bPN   ||  bPN1  ||  bPN2  ||  bPN3  ||  bPN4  ||  bPN5  ||
       bPN6  ||  bPN7  ||  bPN8  ||  bPN9  ||  bPN10);
    if(bIsSpecial  &&
      (fe_text.bsTrimSpaces == 'true'  ||  fe_text.bsDontTrimSpaces == 'true'))  {
      return crashVF("Either f_orm." + sName + ".bsTrimSpaces (currently '" + fe_text.bsTrimSpaces + "') or f_orm." + sName + ".bsDontTrimSpaces (currently '" + fe_text.bsTrimSpaces + "') equal 'true'.  But this is illegal, because the element has these special types associated to it:  " + sSpecialTypes);
    }

    var iMin = fe_text.iMinLength;
    if(fe_text.sMsgBadLength)  {
      if(!iMin)  {
        return crashVF("f_orm." + sName + ".sMsgBadLength has been provided (currently '" + fe_text.sMsgBadLength + "'), but f_orm." + sName + ".iMinLength has not been provided");
      }

      if(iMin  &&  (!isInteger(iMin)  ||  iMin < 1))  {
        return crashVF("Both f_orm." + sName + ".sMsgBadLength (currently '" + fe_text.sMsgBadLength + "') and f_orm." + sName + ".iMinLength (currently '" + iMin + "') have been provided, but iMinLength must be an integer, and at least equal to one.");
      }

      //NOTE:  When MAXLENGTH is an attribute of the element,
      //fe_text.MAXLENGTH is undefined, but fe_text.maxLength
      //is not.  Things that make you go hmm.
      if(fe_text.maxLength  &&  fe_text.maxLength != -1  &&
         isInteger(fe_text.maxLength)  &&  iMin > fe_text.maxLength)  {
        return crashVF("Both f_orm." + sName + ".sMsgBadLength (currently '" + fe_text.sMsgBadLength + "') and f_orm." + sName + ".iMinLength (currently " + iMin + ") have been provided, but iMinLength must be an integer between one and f_orm." + sName + ".MAXLENGTH (currently " + fe_text.maxLength + "), inclusive.");
      }

    }  else if(iMin)  {
      return crashVF("f_orm." + sName + ".sMsgBadLength has *not* been provided, but the sub-attribute f_orm." + sName + ".iMinLength (currently " + iMin + ") has been provided.");
    }

    if(fe_text.iMaxLength)  {
      return crashVF("f_orm." + sName + ".iMaxLength (currently " + fe_text.iMaxLength + ") is only a legal sub-attribute for text elements.  To enforce maximum length in a text or password element, use the standard MAXLENGTH attribute.");
    }
  }

  //"di_" prefix stands for decimal-or-integer
  function crashIfBadIntDecCfg(di_min, di_max, bs_decimalAllowed, s_formLmntName, s_nameMin, s_nameMax)  {
    var sIntDecPostfix = 'Int';
    var sAnIntADec = 'an integer';
    var sIntDec = 'integer';
    var sIsFuncName = 'isInteger';
    if(bs_decimalAllowed == 'true')  {
      sIntDecPostfix = 'Dec';
      sAnIntADec = 'a decimal';
      sIntDec = 'decimal';
      sIsFuncName = 'isDecimal';
    }

    if(di_min  &&  !isNumber(di_min, bs_decimalAllowed))  {
      return crashVF("f_orm." + s_formLmntName + ".sMsgTxt" + sIntDecPostfix + " has been provided, and the sub-variable " + s_formLmntName + "." + s_nameMin + " has also been provided.  However, " + s_nameMin + " must be " + sAnIntADec + ".  Currently '" + di_min + "'.");
    }

    if(di_max  &&  !isNumber(di_max, bs_decimalAllowed))  {
      return crashVF("f_orm." + s_formLmntName + ".sMsgTxt" + sIntDecPostfix + " has been provided, and the sub-variable " + s_formLmntName + "." + s_nameMax + " has also been provided.  However, " + s_nameMax + " must be " + sAnIntADec + ".  Currently '" + di_max + "'.");
    }

    if(di_min  &&  di_max  &&
      !isValidRange(di_min, di_max))  {
      return crashVF("f_orm." + s_formLmntName + ".sMsgTxt" + sIntDecPostfix + " has been provided, and both the sub-variables " + s_formLmntName + "." + s_nameMin + " and " + s_formLmntName + "." + s_nameMax + " have also been provided.  Both these variables are definitely legal " + sIntDec + "s (according to util_string." + sIsFuncName + "()), however, " + s_nameMin + " (currently '" + di_min + "') and " + s_nameMax + " (currently '" + di_max + "') are not a legal range according to util_number.isValidRange().");
    }
  }


  function crashIfBadSpaceTrimConfig(f_orm, fe_tta)  {
    fe_tta.bsTrimSpaces = getOptBooleanStringVF(fe_tta.bsTrimSpaces, "f_orm." + fe_tta.name + ".bsTrimSpaces");
    fe_tta.bsDontTrimSpaces = getOptBooleanStringVF(fe_tta.bsDontTrimSpaces, "f_orm." + fe_tta.name + ".bsDontTrimSpaces");

    if(f_orm.bsGlobalTrimSpaces == 'true')  {
      if(fe_tta.bsTrimSpaces == 'true')  {
        return crashVF("Both f_orm.bsGlobalTrimSpaces and f_orm." + fe_tta.name + ".bsTrimSpaces equal 'true'.  Only one of these variables may be 'true'.");
      }

    }  else  if(fe_tta.bsDontTrimSpaces == 'true')  {
      return crashVF("f_orm.bsGlobalTrimSpaces has *not* been provided (or is equal to 'false'), but f_orm." + fe_tta.name + ".bsDontTrimSpaces equals 'true'.  ");
    }
  }

  function crashIfNBSSError(s_textPwName, b_noBadSubStrings, as_globalBadSubStrs, as_badSubStrs)  {
    if(b_noBadSubStrings == 'true'  &&
       (as_badSubStrs  ||  !as_globalBadSubStrs))  {
      return crashVF("f_orm." + s_textPwName + ".bsNoBadSubStrings equals 'true', but either , f_orm.asGlobalBadSubStrs has *not* been provided (currently " + as_globalBadSubStrs + ") or f_orm." + s_textPwName + ".asBadSubStrs *has* been provided (currently " + as_badSubStrs + ").  When bsNoBadSubStrings equals 'true', it is required that or asBadSubStrs not be provided and f_orm.asGlobalBadSubStrs should be provided.");
    }
  }

  function getRqdMissingMsg(s_requiredMsg, s_value)  {
    crashIfMissing(s_value, 's_value ("missing" means empty string)', 'validate_form.getRqdMissingMsg');

    if(!s_requiredMsg)  {
      //This value is not required.
      return '';
    }
    //This value *is* required...

    if(s_value == '')  {
      //...but has not been provided.
      return s_requiredMsg;
    }

    //...and has been provided.
    return '';
  }

  /**
    Crash If the provided bad-sub-string-array is bad.
   **/
  function crashIfBadBSSA(s_variableName, as_badSubStrs)  {
    if(!as_badSubStrs)  {
      return;
    }

    var sRule = " is not required, but when it is provided, it must be of type array, at least one element in length, and each element must be of type string, at least one character in length, and all elements must be unique.  Currently, ";

    if(!isArray(as_badSubStrs))  {
      return crashVF("crashIfBadBSSA:  " + s_variableName + sRule + "it is of type '" + typeof(as_badSubStrs) + "'.");
    }

    if(as_badSubStrs.length < 1)  {
      return crashVF("crashIfBadBSSA:  " + s_variableName + sRule + "it is zero elements in length.");
    }

    for(var i = 0; i < as_badSubStrs.length; i++)  {
      if(typeof(as_badSubStrs[i]) != "string")  {
        return crashVF("crashIfBadBSSA:  " + s_variableName + sRule + " s_variableName[" + i + "] is of type '" + typeof(as_badSubStrs[i]) + "'.");
      }

      if(as_badSubStrs[i].length < 1)  {
        return crashVF("crashIfBadBSSA:  " + s_variableName + sRule + " s_variableName[" + i + "] is zero characters in length.");
      }

      for(var j = i + 1; j < as_badSubStrs.length; j++)  {
        if(as_badSubStrs[i] == as_badSubStrs[j])  {
          return crashVF("crashIfBadBSSA:  " + s_variableName + sRule + " Element " + i + " (currently '" + as_badSubStrs[i] + "') is equal to element " + j + ".");
        }
      }
    }
    //All elements are definitely of type string.

    for(var i = 0; i < as_badSubStrs.length; i++)  {
      for(var j = i + 1; j < as_badSubStrs.length; j++)  {
        if(as_badSubStrs[i] == as_badSubStrs[j])  {
          return crashVF("crashIfBadBSSA:  " + s_variableName + sRule + " Element " + i + " (currently '" + as_badSubStrs[i] + "') is equal to element " + j + ".");
        }
      }
    }
  }

  function  wasRCBSMalreadyFound(s_elementName)  {
    return (getRCBSMTrackerArrIdx(s_elementName) != -1);
  }

  function  getFirstArrIdx(s_elementName)  {
    var iArrIdx = getAndValidateRCBSMTArrIdx("getFirstArrIdx", s_elementName);
    var iFirstArrIdx = aiRCBSM_TRACKER_ARR_IDX[iArrIdx];

    if(iFirstArrIdx == -1)  {
      return crashVF("getFirstArrIdx:  Element named '" + s_elementName + "' *was* found in the tracker array objects, but it is of type select-multiple, which does not have multiple instances, and is therefore invalid for this function.  SANITY CHECK.  SHOULD NEVER HAPPEN.");
    }

    return iFirstArrIdx;
  }

  function  getMCSelectedCount(s_elementName)  {
    var iArrIdx = getAndValidateRCBSMTArrIdx("getMCSelectedCount", s_elementName);
    var iSelCt = aiRCBSM_TRACKER_SEL_COUNT[iArrIdx];

    if(iSelCt == -1)  {
      return crashVF("getMCSelectedCount:  Element named '" + s_elementName + "' *was* found in the tracker array objects, but it is of type radio, which is a single-choice element, and is therefore invalid for this function.  SANITY CHECK.  SHOULD NEVER HAPPEN.");
    }
    return iSelCt;
  }

  function getAndValidateRCBSMTArrIdx(s_callingFunction, s_elementName)  {
    var iArrIdx = getRCBSMTrackerArrIdx(s_elementName);

    if(iArrIdx == -1)  {
      return crashVF("getAndValidateRCBSMTArrIdx ('" + s_callingFunction + "'):  Element named '" + s_elementName + "' was not found in the tracker array objects.  SANITY CHECK.  SHOULD NEVER HAPPEN.");
    }

    return iArrIdx;
  }


  function  getRCBSMTrackerArrIdx(s_elementName)  {
    for(var i = 0; i < asRCBSM_TRACKER_NAME.length; i++)  {
      if(asRCBSM_TRACKER_NAME[i] == s_elementName)  {
        return i;
      }
    }

    return -1;
  }


  function addRCBSMtoTracker(f_orm, fe_rcbsm, i_formArrIdx)  {
    if(asRCBSM_TRACKER_NAME.length < 1)  {
      //This is the first to be tracked.  Just create a new
      //array containing this name as the only element.
      asRCBSM_TRACKER_NAME = [fe_rcbsm.name];
      aiRCBSM_TRACKER_SEL_COUNT = [getMCSelectedCountForTracker(f_orm, fe_rcbsm)];
      aiRCBSM_TRACKER_ARR_IDX = [getRCBSMFirstArrIdx(fe_rcbsm, i_formArrIdx)];

      return;
    }
    //At least one element is already being tracked.  Add this
    //element to the existing tracking arrays.

    if(wasRCBSMalreadyFound(fe_rcbsm.name))  {
      return crashVF("addRCBSMtoTracker:  Element named '" + fe_rcbsm.name + "' already exists in the TRACKER arrays.  SANITY CHECK.  SHOULD NEVER HAPPEN.");
    }

    var asTrackerNames = new Array(asRCBSM_TRACKER_NAME.length + 1);
    for(var i = 0; i < asTrackerNames.length; i++)  {
      if(i < (asTrackerNames.length - 1))  {
        asTrackerNames[i] = asRCBSM_TRACKER_NAME[i];
      }  else  {
        asTrackerNames[i] = fe_rcbsm.name;
      }
    }
    asRCBSM_TRACKER_NAME = asTrackerNames;

    var aiTrackerCounts = new Array(aiRCBSM_TRACKER_SEL_COUNT.length + 1);
    for(var i = 0; i < aiTrackerCounts.length; i++)  {
      if(i < (aiTrackerCounts.length - 1))  {
        aiTrackerCounts[i] = aiRCBSM_TRACKER_SEL_COUNT[i];
      }  else  {
        aiTrackerCounts[i] = getMCSelectedCountForTracker(f_orm, fe_rcbsm);
      }
    }
    aiRCBSM_TRACKER_SEL_COUNT = aiTrackerCounts;

    var aiTrackerArrIdx = new Array(aiRCBSM_TRACKER_ARR_IDX.length + 1);
    for(var i = 0; i < aiTrackerArrIdx.length; i++)  {
      if(i < (aiTrackerArrIdx.length - 1))  {
        aiTrackerArrIdx[i] = aiRCBSM_TRACKER_ARR_IDX[i];
      }  else  {
        aiTrackerArrIdx[i] = getRCBSMFirstArrIdx(fe_rcbsm, i_formArrIdx);
      }
    }
    aiRCBSM_TRACKER_ARR_IDX = aiTrackerArrIdx;
  }

  function getRCBSMFirstArrIdx(fe_rcbsm, i_formArrIdx)  {
    if(fe_rcbsm.type == "select-multiple")  {
      //select-multiple only has one instance in the form.  -1 indicates that.
      return -1;
    }

    return i_formArrIdx;
  }

  function getMCSelectedCountForTracker(f_orm, fe_rcbsm)  {
    if(fe_rcbsm.type != "radio"  &&
       fe_rcbsm.type != "checkbox"  &&
       fe_rcbsm.type != "select-multiple")  {
      return crashVF("getMCSelectedCount:  Element named '" + fe_rcbsm.name + "' is not of type radio, checkbox or select-multiple.  Type of this element is '" + fe_rcbsm.type + "'.  SANITY CHECK.  SHOULD NEVER HAPPEN.");
    }

    if(fe_rcbsm.type == "radio")  {
      //This is not a multiple choice type.  -1 indicates that.
      return -1;
    }

    var iMCSelectedCount = 0;

    if(fe_rcbsm.type == "checkbox")  {
      for(var i = 0; i < f_orm[fe_rcbsm.name].length; i++)  {
        if(f_orm[fe_rcbsm.name][i].checked)  {
          iMCSelectedCount++;
        }
      }
      return iMCSelectedCount;
    }
    //Type is definitely select-multiple.

    for(var i = 0; i < fe_rcbsm.length; i++)  {
      if(fe_rcbsm.options[i].selected)  {
        iMCSelectedCount++;
      }
    }
    return iMCSelectedCount;
  }

  function getOptBooleanStringVF(bs_potential, s_variableName)  {
    return getOptBooleanString(bs_potential, s_variableName, 'validate_form.getFormErrorMsgs');
  }


  function crashVF(s_message)  {
    return crash("validate_form.getFormErrorMsgs:  " + s_message);
  }

  function initializeLocalVars()  {
    resetCrashedFlag();
    asRCBSM_TRACKER_NAME = [];
    aiRCBSM_TRACKER_SEL_COUNT = [];
    aiRCBSM_TRACKER_ARR_IDX = [];
    iELEMENT_COUNT = 0;
    bFIRST_DEBUG_SCREEN_SEEN = false;
  }


  /**
    For backwards compatibility only.  Only use getFormErrorMsgs.  This function will eventually be eliminated.
   **/
  function validateForm(f_orm, s_userErrorPrefix, i_debugPerScreen)  {
    return getFormErrorMsgs(f_orm, s_userErrorPrefix, i_debugPerScreen);
  }


/**
  PRIVATE FUNCTIONS...end
 **/


/**************************************************************************************************
  util_string.js...START

  Do not edit this file.  This file is dynamically generated by the validate_form.js
  ant build process
 **************************************************************************************************/

/**
  VALIDATE_FORM.JS
  Comprehensive solution for validating HTML forms.
  Copyright (C) 2002, Jeff Epstein, jeff_epstein@yahoo.com, http://www.jeffyjeffy.com#download

  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

  You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 **/


  //PHONE NUMBER AND ZIP CODE FORMAT/RANGES
    //For documentation, see
    //    documentation/index.html#string_zip
    //
    //Demo/testing values exist at the bottom of
    //    documentation/vf_string_phone_zip.html
    //
    //To test these formats for validity, see
    //    documentation/unit_test.html#util_string_tests
  //PHONE NUMBER FORMATS/RANGES...start
    //US 3 then 7
      var siPHONE_1_MINIMUM = "1001001000";
      var siPHONE_1_MAXIMUM = "9999999999";

    //US 7 only
      var siPHONE_2_MINIMUM = "1001000";
      var siPHONE_2_MAXIMUM = "9999999";

    var siPHONE_3_MINIMUM = "1000";
    var siPHONE_3_MAXIMUM = "9999";

    var siPHONE_4_MINIMUM = "001000";
    var siPHONE_4_MAXIMUM = "999999";

    var siPHONE_5_MINIMUM = "00000000";
    var siPHONE_5_MAXIMUM = "99999999";

    var siPHONE_6_MINIMUM = "1000000000";
    var siPHONE_6_MAXIMUM = "5555555555";

    var siPHONE_7_MINIMUM = "0";
    var siPHONE_7_MAXIMUM = "1";

    var siPHONE_8_MINIMUM = "1";
    var siPHONE_8_MAXIMUM = "9";

    var siPHONE_9_MINIMUM = "000";
    var siPHONE_9_MAXIMUM = "000";

    var siPHONE_10_MINIMUM = "010101";
    var siPHONE_10_MAXIMUM = "787374";

  //PHONE NUMBER FORMATS/RANGES...end

  //ZIP CODE FORMATS/RANGES...start
    //US 5+4
      var siZIP_1_RQD_MINIMUM = "00000";
      var siZIP_1_RQD_MAXIMUM = "99999";
      var siZIP_1_ALT_MINIMUM = "0001";
      var siZIP_1_ALT_MAXIMUM = "9999";

    //US 5 only
      var siZIP_2_RQD_MINIMUM = "00001";
      var siZIP_2_RQD_MAXIMUM = "99999";
      var siZIP_2_ALT_MINIMUM = "";
      var siZIP_2_ALT_MAXIMUM = "";

    var siZIP_3_RQD_MINIMUM = "1";
    var siZIP_3_RQD_MAXIMUM = "1";
    var siZIP_3_ALT_MINIMUM = "2";
    var siZIP_3_ALT_MAXIMUM = "2";

    var siZIP_4_RQD_MINIMUM = "01";
    var siZIP_4_RQD_MAXIMUM = "99";
    var siZIP_4_ALT_MINIMUM = "0001";
    var siZIP_4_ALT_MAXIMUM = "9999";

    var siZIP_5_RQD_MINIMUM = "00";
    var siZIP_5_RQD_MAXIMUM = "55";
    var siZIP_5_ALT_MINIMUM = "0";
    var siZIP_5_ALT_MAXIMUM = "7";

    var siZIP_6_RQD_MINIMUM = "54321";
    var siZIP_6_RQD_MAXIMUM = "55555";
    var siZIP_6_ALT_MINIMUM = "";
    var siZIP_6_ALT_MAXIMUM = "";

    var siZIP_7_RQD_MINIMUM = "00001";
    var siZIP_7_RQD_MAXIMUM = "00001";
    var siZIP_7_ALT_MINIMUM = "0001";
    var siZIP_7_ALT_MAXIMUM = "0001";

    var siZIP_8_RQD_MINIMUM = "09000";
    var siZIP_8_RQD_MAXIMUM = "91111";
    var siZIP_8_ALT_MINIMUM = "0003873874038834";
    var siZIP_8_ALT_MAXIMUM = "0020837401092837";

    var siZIP_9_RQD_MINIMUM = "0003873874038834";
    var siZIP_9_RQD_MAXIMUM = "0020837401092837";
    var siZIP_9_ALT_MINIMUM = "09000";
    var siZIP_9_ALT_MAXIMUM = "91111";

    var siZIP_10_RQD_MINIMUM = "0";
    var siZIP_10_RQD_MAXIMUM = "7";
    var siZIP_10_ALT_MINIMUM = "00";
    var siZIP_10_ALT_MAXIMUM = "55";

  //ZIP CODE FORMATS/RANGES...end





/**
  Does the provided string start or end with a space?

  EQUAL TO
    isSurroundedByChar(s_tring, ' ');
 **/
function isSurroundedBySpace(s_tring)  {
  return isSurroundedByChar(s_tring, ' ');
}

/**
  Does the provided string start or end with the provided character?

  PARAMETERS
    s_tring  The string to analyze.
    c_har    The character that is determined to exist at the start or end of s_tring.

  RETURNS
    true   If the first or last character in s_tring is c_har.
    false  If s_tring is null or zero characters in length.
         If both the first and last characters in s_tring are *not* c_har.
 **/
function isSurroundedByChar(s_tring, char_toTrim)  {
  if(!s_tring)  {
    return false;
  }

  if(!char_toTrim  ||  char_toTrim.length != 1)  {
    return crash('isSurroundedByChar:  char_toTrim parameter must be provided, and be exactly one character in length.');
  }

  if(s_tring.length < 1)  {
    return false;
  }

  if(s_tring.substring(0, 1) == char_toTrim)  {
    return true;
  }

  return (s_tring.substring(s_tring.length - 1, s_tring.length) == char_toTrim);
}



/**
  Is the provided string a legal integer?

  RETURNS
    isNumber(s_potentialInteger, 'false')
 **/
function isInteger(s_potentialInteger)  {
  return isNumber(s_potentialInteger, 'false');
}


/**
  Is the provided string a legal decimal?

  RETURNS
    isNumber(s_potenitalDecimal, 'true')
 **/
function isDecimal(s_potentialDecimal)  {
  return isNumber(s_potentialDecimal, 'true');
}

/**
  Is the provided string a legal number?

  PARAMETERS
    s_potentialNumber
      The string to analyze.  Required.
    bs_decimalAllowed
      Is the potential number allowed to be a decimal?  If 'true', then yes.  If 'false', no.

  RETURNS
    true
      If s_potentialNumber is a legal integer (regardless the value of bs_decimalAllowed).  A legal integer is a string that...
        ...contains one or more zeros.  Note that 0 equals 0000 equals 0000000000 equals ...
        ...starts with zero or one dashes (indicating negative), followed by one or more digits (0-9), where at least one is greater than zero.
      If bs_decimalAllowed is 'true' and s_potentialNumber is a legal decimal.  A legal decimal is a string that...
        ...is an integer.
        ...starts with zero or one dashes (indicating negative) followed by zero or more digits, followed by a decimal point ('.'), followed by *one* or more digits.

      (Note that s_potentialNumber is checked to be an integer first.  If it is, then true is returned, regardless the value of bs_decimalAllowed.  If the string is an integer, it is not checked, specifically, to see if it's a decimal.  Hence, the description of a legal decimal number says "a decimal point" instead of "zero or one decimal points".)

    false
      If otherwise.

  LEGAL EXAMPLES (both integers and decimals)
      -1
      0
      1
      -50
      8750328754
      00008750328754
      08750328754
      -487584758475235
      -0000000487584758475235
      -0487584758475235

  ILLEGAL EXAMPLES (both integers and decimals)
      4875847-58475235
      487584758475235-
      [EMPTY_STRING]
      a
      0-
      -0
      Not a number!!!
      Some 123 numbers 456
      123 456
      -0.0
      -.0
      -0.000000
      -.000000
      1.
      .

  LEGAL EXAMPLES (decimals, but only after it is determined that the value is *not* an integer)
      1.1
      1.000830847018374
      058763408562473.01837486564417308746
      .1
      .0
      .01
      -1.0
 **/
function isNumber(s_potentialNumber, bs_decimalAllowed)  {
  crashIfMissing('util_string.jsNumber', s_potentialNumber, 's_potentialNumber');
  crashIfBadBooleanString(bs_decimalAllowed, 'bs_decimalAllowed', 'util_string.jsNumber');

  if(s_potentialNumber.length < 1)  {
    return false;
  }

  if(s_potentialNumber == '-')  {
    //A negative sign only makes no sense.
    return false;
  }

  if(/^-[0]+$/.test(s_potentialNumber))  {
    //Negative zero makes no sense.
    return false;
  }

  if(/^[0]+$/.test(s_potentialNumber))  {
    //Zero is a legal number:
    //0  ==  0000000000000  ==  000
    return true;
  }
  //It is definitely not zero.

  //^         The start of the line.
  //[-]{0,1}  Zero or one dashes.
  //[0-9]+    One or more of any digit.
  //$         The end of the line.
  if(/^[-]{0,1}[0-9]+$/.test(s_potentialNumber))  {
    //No matter what, this is valid.  This is a leagal integer
    //and decimal.
    return true;
  }
  //It's not an integer...

  if(bs_decimalAllowed == 'false')  {
    //...but it must be.
    return false;
  }
  //...and that's okay.  It might be a decimal

  //Due to precision:
  //10.0000000000001 is legal (12 zeros)
  //10.00000000000001 is not  (13 zeros)

  //^         The start of the line.
  //[-]{0,1}  Zero or one dashes.
  //[0-9]*    Zero or more digits.
  //[.]      A decimal point.
  //[0-9]+    One or more digits.
  //$         The end of the line.
  if(/^[-]{0,1}[0-9]*[.][0-9]+$/.test(s_potentialNumber))  {
    //It is a "raw" decimal.  The only thing that would make
    //this illegal is if it were -0.0 or -.0, or -0.0000 or
    //-.0000 or ...

    return !(/^-0*[.]0+$/.test(s_potentialNumber));
  }

  //It is not a legal decimal number.
  return false;
}



function isEmail(s_potentialEmail)  {
  if(!s_potentialEmail  ||  s_potentialEmail.length < 1)  {
    return crash("isValidNumber:  s_potentialEmail must be defined, and at least one character in length.");
  }

  if(s_potentialEmail.indexOf(" ") != -1  ||
     s_potentialEmail.indexOf("/") != -1  ||
     s_potentialEmail.indexOf("\\") != -1  ||
     s_potentialEmail.indexOf(",") != -1)  {
    //A space, slash or comma was found.
    return false;
  }

  if(/[@.][@.]/.test(s_potentialEmail))  {
    //An @ or dot is followed by an @ or dot.
    return false;
  }

  if(/^[@.]/.test(s_potentialEmail))  {
    //The first character is an @ or dot.
    return false;
  }

  if(/[@.]$/.test(s_potentialEmail))  {
    //The last character may not be an @ or dot.
    return false;
  }

  if(!/^[^@]+@[^@]+$/.test(s_potentialEmail))  {
    //Only one @ allowed
    //    (Negative of:
    //     Must have one or more non-@ starting the line,
    //     exactly one @, and then
    //     one or more non-@ ending the line.)
    return false;
  }
  //There is exactly one @.

  if(!/@.*[.]/.test(s_potentialEmail))  {
    //At least one dot must follow the (single) @.
    return false;
  }
  //At least one dot follows the @.  We already determined
  //above that it does not immediately follow it,


  //No negative conditions were met.  This is a legal email address.
  //Cool, eh?  : )
  return true;
}


function removeNonNumbers(s_tring)  {
  if(!s_tring  ||  s_tring.length < 1)  {
    return crash("removeNonNumbers:  s_tring must be defined, and at least one character in length.");
  }

  var reNonNumbers = /^\D$/;
  if(/^\D$/.test(s_tring))  {
    //There are no numbers at all.
    return "";
  }
  //There is at least one number.

  var asNumberParts = s_tring.split(/\D/);

  var sNumber = asNumberParts[0];
  for(var i = 1; i < asNumberParts.length; i++)  {
    sNumber += asNumberParts[i];
  }

  return sNumber;
}

/**
  Are the provided phone format strings valid?

  See the documentation above, regarding PHONE NUMBER FORMATS/RANGES.  Specifically, under the "phone" section, under "--- RULES ---".

  Call this function manually, if you wish.  It is not called by any other function in this js file...except crashIfBadPhoneFormat.

  PARAMETER
    bs_crashIfBad
      Must equal either "true" or "false".  If "true", then if the formats are invalid, this function crashes with a descriptive message.  See utility.crash().
 **/
function isPhoneFormatValid(bs_crashIfBad, si_minFormat, si_maxFormat)  {
  return isFormatValid("Phone", bs_crashIfBad, "si_minFormat", "si_maxFormat", si_minFormat, si_maxFormat);
}


function getValidPhone(s_potentialPhone)  {
  return getValidPhone1(s_potentialPhone);
}

function getValidPhone1(s_potentialPhone)  {
  return getValidPhoneFromFormat(siPHONE_1_MINIMUM, siPHONE_1_MAXIMUM, s_potentialPhone);
}

function getValidPhone2(s_potentialPhone)  {
  return getValidPhoneFromFormat(siPHONE_2_MINIMUM, siPHONE_2_MAXIMUM, s_potentialPhone);
}

function getValidPhone3(s_potentialPhone)  {
  return getValidPhoneFromFormat(siPHONE_3_MINIMUM, siPHONE_3_MAXIMUM, s_potentialPhone);
}

function getValidPhone4(s_potentialPhone)  {
  return getValidPhoneFromFormat(siPHONE_4_MINIMUM, siPHONE_4_MAXIMUM, s_potentialPhone);
}

function getValidPhone5(s_potentialPhone)  {
  return getValidPhoneFromFormat(siPHONE_5_MINIMUM, siPHONE_5_MAXIMUM, s_potentialPhone);
}

function getValidPhone6(s_potentialPhone)  {
  return getValidPhoneFromFormat(siPHONE_6_MINIMUM, siPHONE_6_MAXIMUM, s_potentialPhone);
}

function getValidPhone7(s_potentialPhone)  {
  return getValidPhoneFromFormat(siPHONE_7_MINIMUM, siPHONE_7_MAXIMUM, s_potentialPhone);
}

function getValidPhone8(s_potentialPhone)  {
  return getValidPhoneFromFormat(siPHONE_8_MINIMUM, siPHONE_8_MAXIMUM, s_potentialPhone);
}

function getValidPhone9(s_potentialPhone)  {
  return getValidPhoneFromFormat(siPHONE_9_MINIMUM, siPHONE_9_MAXIMUM, s_potentialPhone);
}

function getValidPhone10(s_potentialPhone)  {
  return getValidPhoneFromFormat(siPHONE_10_MINIMUM, siPHONE_10_MAXIMUM, s_potentialPhone);
}

/**
  Get the phone number out of the provided string.

  PARAMETERS
    si_minFormat
      The format string representing the minimum allowable bound for a legal phone number.  It is *assumed* that this string is provided and valid.  Use isPhoneFormatValid() to validate this, along with si_maxFormat.  For specific information on this variable, see the documentation above, regarding PHONE NUMBER FORMATS/RANGES, under the "phone" section.
    si_maxFormat
      The format string representing the maximum allowable bound for a legal phone number.  It is *assumed* that this string is provided and valid.  Use isPhoneFormatValid() to validate this, along with si_maxFormat.  For specific information on this variable, see the documentation above, regarding PHONE NUMBER FORMATS/RANGES, under the "phone" section.
    s_potentialPhone
      The string containing the (potentially legal) phone number, including any surrounding text.  For example:
        (215) 555-1212
        215 555 1212
        2155551212

  RETURNS
    If the phone number is invalid, according to the format, empty string ("") is returned.  Otherwise, the non-digits are stripped from s_potentialPhone, and the digits alone are returned (but as a string, preserving leading zeros).  For example, all of the above examples (under s_potentialPhone) return "2155551212".
 **/
function getValidPhoneFromFormat(si_minFormat, si_maxFormat, s_potentialPhone)  {
  if(!s_potentialPhone  ||  s_potentialPhone.length < 1)  {
    return crash("isValidNumber:  s_potentialPhone must be defined, and at least one character in length.");
  }

  //This also removes dashes (negative symbols) and decimal points.
  var siPhoneNumber = removeNonNumbers(s_potentialPhone);

  if(!siPhoneNumber  ||  siPhoneNumber.length < 1  ||
       siPhoneNumber.length != si_minFormat.length)  {
    //The length is illegal.
    return "";
  }

  //Must supply radix=10
  var iMin = parseInt(si_minFormat, 10);
  var iMax = parseInt(si_maxFormat, 10);

  if(isValidNumber(siPhoneNumber, iMin, iMax))  {
    //The phone number is in bounds.
    return siPhoneNumber;
  }
  //It is not a valid phone number.

  return "";
}



/**
  Are the provided zip format strings valid?

  See the documentation above, regarding PHONE NUMBER FORMATS/RANGES.  Specifically, under the "zip code" section, under "--- RULES ---".

  Call this function manually, if you wish.  It is not called by any other function in this js file.

  PARAMETER
    bs_crashIfBad
      Must equal either "true" or "false".  If "true", then if the formats are invalid, this function crashes with a descriptive message.  See utility.crash().
 **/
function isZipFormatValid(bs_crashIfBad, si_rqdMinFormat, si_rqdMaxFormat, si_altMinFormat, si_altMaxFormat)  {

  if(!isFormatValid("Zip", bs_crashIfBad, "si_rqdMinFormat", "si_rqdMaxFormat", si_rqdMinFormat, si_rqdMaxFormat))  {
    return false;
  }
  //The required format is valid.


  if(!si_altMinFormat ^ !si_altMaxFormat)  {
    if(bs_crashIfBad == "true")  {
      return crash("util_string.jsZipFormatValid:  si_altMinFormat ('" + si_altMinFormat + "') and si_altMaxFormat ('" + si_altMaxFormat + "') must both be either undefined or defined.");
    }

    return false;
  }
  //Both are either undefined, or defined.

  if(!si_altMinFormat)  {
    //One is undefined, therefore both are undefined.
    return true;
  }
  //Both are defined.

  return isFormatValid("Zip", bs_crashIfBad, "si_altMinFormat", "si_altMaxFormat", si_altMinFormat, si_altMaxFormat)
}


function getValidZip(s_potentialZip)  {
  return getValidZip1(s_potentialZip);
}
function getValidZip1(s_potentialZip)  {
  return getValidZipFromFormat(siZIP_1_RQD_MINIMUM, siZIP_1_RQD_MAXIMUM, siZIP_1_ALT_MINIMUM, siZIP_1_ALT_MAXIMUM, s_potentialZip);
}
function getValidZip2(s_potentialZip)  {
  return getValidZipFromFormat(siZIP_2_RQD_MINIMUM, siZIP_2_RQD_MAXIMUM, siZIP_2_ALT_MINIMUM, siZIP_2_ALT_MAXIMUM, s_potentialZip);
}
function getValidZip3(s_potentialZip)  {
  return getValidZipFromFormat(siZIP_3_RQD_MINIMUM, siZIP_3_RQD_MAXIMUM, siZIP_3_ALT_MINIMUM, siZIP_3_ALT_MAXIMUM, s_potentialZip);
}
function getValidZip4(s_potentialZip)  {
  return getValidZipFromFormat(siZIP_4_RQD_MINIMUM, siZIP_4_RQD_MAXIMUM, siZIP_4_ALT_MINIMUM, siZIP_4_ALT_MAXIMUM, s_potentialZip);
}
function getValidZip5(s_potentialZip)  {
  return getValidZipFromFormat(siZIP_5_RQD_MINIMUM, siZIP_5_RQD_MAXIMUM, siZIP_5_ALT_MINIMUM, siZIP_5_ALT_MAXIMUM, s_potentialZip);
}
function getValidZip6(s_potentialZip)  {
  return getValidZipFromFormat(siZIP_6_RQD_MINIMUM, siZIP_6_RQD_MAXIMUM, siZIP_6_ALT_MINIMUM, siZIP_6_ALT_MAXIMUM, s_potentialZip);
}
function getValidZip7(s_potentialZip)  {
  return getValidZipFromFormat(siZIP_7_RQD_MINIMUM, siZIP_7_RQD_MAXIMUM, siZIP_7_ALT_MINIMUM, siZIP_7_ALT_MAXIMUM, s_potentialZip);
}
function getValidZip8(s_potentialZip)  {
  return getValidZipFromFormat(siZIP_8_RQD_MINIMUM, siZIP_8_RQD_MAXIMUM, siZIP_8_ALT_MINIMUM, siZIP_8_ALT_MAXIMUM, s_potentialZip);
}
function getValidZip9(s_potentialZip)  {
  return getValidZipFromFormat(siZIP_9_RQD_MINIMUM, siZIP_9_RQD_MAXIMUM, siZIP_9_ALT_MINIMUM, siZIP_9_ALT_MAXIMUM, s_potentialZip);
}
function getValidZip10(s_potentialZip)  {
  return getValidZipFromFormat(siZIP_10_RQD_MINIMUM, siZIP_10_RQD_MAXIMUM, siZIP_10_ALT_MINIMUM, siZIP_10_ALT_MAXIMUM, s_potentialZip);
}

/**
  Get the zip code out of the provided string.

  PARAMETERS
    si_rqdMinFormat
      The format string representing the minimum allowable bound for the required portion of a legal zip code.  It is *assumed* that this string is provided and valid.  Use isZipFormatValid() to validate this, along with si_maxFormat.  For specific information on this variable, see the documentation above, regarding PHONE NUMBER FORMATS/RANGES, under the "zip code" section.
    si_rqdMaxFormat
      The format string representing the maximum allowable bound for the required portion of a legal zip code.  It is *assumed* that this string is provided and valid.  Use isZipFormatValid() to validate this, along with si_maxFormat.  For specific information on this variable, see the documentation above, regarding PHONE NUMBER FORMATS/RANGES, under the "zip code" section.
    si_altMinFormat
      The format string representing the minimum allowable bound for the alternate portion of a legal zip code.  It is *assumed* that this string is provided and valid.  Use isZipFormatValid() to validate this, along with si_maxFormat.  For specific information on this variable, see the documentation above, regarding PHONE NUMBER FORMATS/RANGES, under the "zip code" section.
    si_altMaxFormat
      The format string representing the maximum allowable bound for the alternate portion of a legal zip code.  It is *assumed* that this string is provided and valid.  Use isZipFormatValid() to validate this, along with si_maxFormat.  For specific information on this variable, see the documentation above, regarding PHONE NUMBER FORMATS/RANGES, under the "zip code" section.
    s_potentialZip
      The string containing the (potentially legal) zip code, including any surrounding text.  For example:
        08052-3848
        19130 (0408)
        00483

  RETURNS
    If the zip code is invalid, according to the format, empty string ("") is returned.  Otherwise, the non-digits are stripped from s_potentialZip, and the digits alone are returned (but as a string, preserving leading zeros).  For example, the second example above (under s_potentialZip) returns "191300408".
 **/
function getValidZipFromFormat(si_rqdMinFormat, si_rqdMaxFormat, si_altMinFormat, si_altMaxFormat, s_potentialZip)  {
  if(!s_potentialZip  ||  s_potentialZip.length < 1)  {
    return crash("isValidNumber:  s_potentialZip must be defined, and at least one character in length.");
  }

  var siZip = removeNonNumbers(s_potentialZip);

  var bLegalLength = false;
  if(siZip)  {
    //There is at least one digit in the zip code...it does
    //exist and...

    if(siZip.length == si_rqdMinFormat.length)  {
      //...it is the required length.
      bLegalLength = true;

    }  else if(si_altMinFormat  &&  si_altMinFormat.length > 0  &&
                   siZip.length == (si_rqdMinFormat.length + si_altMinFormat.length))  {
      //...although it is not the required length, there is
      //an alternate length format, and the zip code has
      //the same length as it PLUS the required part.
      bLegalLength = true;

    }  //ELSE:  There is no alternate format.
  }

  if(!bLegalLength)  {
    return "";
  }
  //The length is legal, according to the format.

  var sRqdPart = siZip.substring(0, si_rqdMinFormat.length);

  //Must specify 10 as the radix (base).  If you don't, and the
  //format has leading zeros, it may get confused and assume
  //that it has a different radix.
  var iMin = parseInt(si_rqdMinFormat, 10);
  var iMax = parseInt(si_rqdMaxFormat, 10);

  if(!isValidNumber(sRqdPart, iMin, iMax))  {
    //The zip is out of bounds.
    return "";
  }
  //The required part is legal.

  if(siZip.length > sRqdPart.length)  {
    //The length of the overall zip (siZip) is longer than the
    //length of the required part.  In other words, the
    //potential zip definitely has an alternate part.

    var sAltPart = siZip.substring(si_rqdMinFormat.length, siZip.length);

    //Must specify 10 as the radix (base).
    iMin = parseInt(si_altMinFormat, 10);
    iMax = parseInt(si_altMaxFormat, 10);

    if(!isValidNumber(sAltPart, iMin, iMax))  {
      //The zip is out of bounds.
      return "";
    }
  }

  //Every part is in range.
  return siZip;
}



/**
  Is the provided string (who's value is a non-negative integer) legal?

  PARAMETERS
    s_potentialInt
      The string to analyze.  Required, and it is *assumed* that this only contains digits (0-9.  Decimal points ['.'] and negative symbols ['-'] are not legal).  If it contains anything else, this function will behave unpredictably.
    bs_trailingZeroOk
      Required.  Must equal "true" or "false".  If "true", then s_potentialInt is considered legal if it starts with one or more zeros (regardless if it actually equals zero).  If "false", then when s_potentialInt starts with a zero, this function returns false.  This parameter is primary, over bs_zeroOk (see "NOTE").
    bs_zeroOk
      Required.  Must equal "true" or "false".  If "true", then s_potentialInt is considered legal if it is equal to zero ("0", "00", "00000", "0000000000", ...).  If "false", then when s_potentialInt equals zero, this function returns false.  No matter what, a non-zero value is okay, even if there are trailing zeros (however, this does not override bs_trailingZeroOk).  This parameter is secondary to bs_trailingZerosOk (see "NOTE").

    NOTE.
      Note which combinations of bs_trailingZeroOk and bs_zeroOk are legal:

      bs_trailingZeroOk     bs_zeroOk       LEGAL?
        true                 true            yes
        true                 false           yes
        false                true            NO
        false                false           yes


  RETURNS
    true
      If s_potentialInt conforms to the rules defined by bs_zeroOk and bs_trailingZeroOk parameters.
    false
      If otherwise.
 **/
function isValidPosIntStr(s_potentialInt, bs_trailingZeroOk, bs_zeroOk)  {
  crashIfMissing('util_string.jsValidPosIntStr', s_potentialInt, 's_potentialInt');
  crashIfBadBooleanString(bs_trailingZeroOk, 'bs_trailingZeroOk', 'util_string.jsValidPosIntStr');
  crashIfBadBooleanString(bs_zeroOk, 'bs_zeroOk', 'util_string.jsValidPosIntStr');

  if(bs_zeroOk == "true"  &&  bs_trailingZeroOk == "false")  {
    return crash("util_string.jsValidPosIntStr:  bs_trailingZero equals 'false', but bs_zeroOk equals 'true'.");
  }

  if(bs_zeroOk == "true")  {
    //No matter what, s_potentialInt is valid.
    return true;
  }
  //Zero, as a whole, is not okay, however, trailing zeros may
  //be okay.

  var iTrailingZeros = 0;
  for(var i = 0; i < s_potentialInt.length; i++)  {
    var cDigit = s_potentialInt.substring(i, i + 1);
    if(cDigit == "0")  {
      iTrailingZeros++;
    }  else  {
      //We've reached the first non-zero.
      break;
    }
  }

  if(iTrailingZeros == 0)  {
    //There are no trailing zeros.  No further analysis
    //needed.
    return true;
  }
  //There is at least one trailing zero.

  if(iTrailingZeros == s_potentialInt.length)  {
    //EVERY digit is equal to zero.
    //s_potentialInt equals zero.
    //s_potentialInt contains only zeros.

    //If bs_zeroOk equals "true":  return true.
    //If bs_zeroOk equals "false":  return false.
    return (bs_zeroOk == "true");
  }
  //There is at least one non-zero digit, following the
  //initial trailing zero(s).

  //If bs_trailingZeroOk equals "true":  return true.
  //If bs_trailingZeroOk equals "false":  return false.
  return (bs_trailingZeroOk == "true");
}


function trimSpaces(s_tring)  {
  return trimChar(' ', s_tring);
}


function trimChar(c_harToTrim, s_tring)  {
  if(!c_harToTrim  ||  c_harToTrim.length != 1)  {
    return crash("util_sting.trimChar:  c_harToTrim must be provided, and must be exactly one character in length.  Currently '" + c_harToTrim + "'.");
  }

  crashIfMissing('util_string.trimSpaces', s_tring, 's_tring');

  var i = 0;
  var iStartingSpaces = 0;
  while(s_tring.substring(i, (i + 1)) == c_harToTrim)  {
    iStartingSpaces++
    i++;
  }

  if(iStartingSpaces == s_tring.length)  {
    return '';
  }

  i = 0;
  var iEndingSpaces = 0;
  while(s_tring.substring((s_tring.length - i), (s_tring.length - (i + 1))) == c_harToTrim)  {
    iEndingSpaces++
    i++;
  }

  if(iStartingSpaces == 0  &&  iEndingSpaces == 0)  {
    return s_tring;
  }

  return s_tring.substring(iStartingSpaces, (s_tring.length - iEndingSpaces));
}


function isFormatValid(s_type, bs_crashIfBad, s_minDesc, s_maxDesc, si_minimum, si_maximum)  {
  crashIfBadBooleanString(bs_crashIfBad, 'bs_crashIfBad', 'util_string.js' + s_type + 'FormatValid');
  crashIfMissing('util_string.js' + s_type + 'FormatValid', si_minimum, s_minDesc);
  crashIfMissing('util_string.js' + s_type + 'FormatValid', si_maximum, s_maxDesc);

  if(si_minimum.length != si_maximum.length)  {
    if(bs_crashIfBad == "true")  {
      return crash("util_string.js." + s_type + "FormatValid:  " + s_minDesc + " ('" + si_minimum + "') must be the same length as " + s_maxDesc + " ('" + si_maximum + "').");
    }

    return false;
  }

  if(!isInteger(si_minimum)  ||  si_minimum < 0)  {
    if(bs_crashIfBad == "true")  {
      return crash("util_string.js." + s_type + "FormatValid:  " + s_minDesc + " (currently '" + si_minimum + "') must be an integer greater than or equal to zero.");
    }

    return false;
  }
  if(!isInteger(si_maximum)  ||  si_maximum < 0)  {
    if(bs_crashIfBad == "true")  {
      return crash("util_string.js." + s_type + "FormatValid:  " + s_maxDesc + " (currently '" + si_maximum + "') must be an integer greater than or equal to zero.");
    }

    return false;
  }

  //Must supply radix=10
  var iMin = parseInt(si_minimum, 10);
  var iMax = parseInt(si_maximum, 10);

  if(iMin > iMax)  {
    if(bs_crashIfBad == "true")  {
      return crash("util_string.js." + s_type + "FormatValid:  " + s_minDesc + " (" + si_minimum + ") is numerically greater than " + s_maxDesc + " (" + si_maximum + ").");
    }

    return false;
  }

  return true;
}


function getPadded(s_tring, i_padLength)  {
  crashIfMissing("util_string.js.getPadded", s_tring, "s_tring");
  crashIfMissing("util_string.js.getPadded", i_padLength, "i_padLength");

  if(!isInteger(i_padLength))  {
    return crash("util_string.js.getPadded:  i_padLength ('" + i_padLength + "') must be an *integer* greater than or equal to zero.");

  }  else if(!isValidNumberOpt(i_padLength, 0, "true", -1, "false"))  {
    return crash("util_string.js.getPadded:  i_padLength ('" + i_padLength + "') must be an *integer* greater than or equal to zero.");
  }

  if(s_tring.length >= i_padLength)  {
    return s_tring;
  }

  for(var i = s_tring.length; i < (i_padLength + 1); i++)  {
    s_tring = s_tring + " ";
  }

  return s_tring;
}

/**************************************************************************************************
  util_number.js...START

  Do not edit this file.  This file is dynamically generated by the validate_form.js
  ant build process
 **************************************************************************************************/

/**
  VALIDATE_FORM.JS
  Comprehensive solution for validating HTML forms.
  Copyright (C) 2002, Jeff Epstein, jeff_epstein@yahoo.com, http://www.jeffyjeffy.com#download

  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

  You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 **/


function isValidRangeOpt(i_min, bs_enforceMin, i_max, bs_enforceMax)  {
  crashIfBadBooleanString(bs_enforceMin, 'bs_enforceMin', 'util_number.isValidRangeOpt');
  crashIfBadBooleanString(bs_enforceMax, 'bs_enforceMax', 'util_number.isValidRangeOpt');

  if(bs_enforceMin == 'false'  ||  bs_enforceMax == 'false')  {
    //At least one of the bounds are not being enforced.
    return true;
  }

  return !(i_min > i_max);
}

function isValidRange(i_min, i_max)  {
  return isValidRangeOpt(i_min, 'true', i_max, 'true');
}

function isValidNumber(i_number, i_min, i_max)  {
  return isValidNumberOpt(i_number, i_min, 'true', i_max, 'true');
}

/**
  It is assumed that the range is valid.  You will get unpredictable results if it is not.
 **/
function isValidNumberOpt(i_number, i_min, bs_enforceMin, i_max, bs_enforceMax)  {
  crashIfMissing("util_number.isValidNumber", i_number, "i_number");

        //alert("isValidRangeOpt(" + i_number + ", " + i_min + ", " + bs_enforceMin + ", " + i_max + ", " + bs_enforceMax + ")...\n...isValidRangeOpt(" + i_min + ", " + bs_enforceMin + ", " + i_number + ", 'true')=" + isValidRangeOpt(i_min, bs_enforceMin, i_number, 'true') + "\n...isValidRangeOpt(" + i_number + ", 'true', " + i_max + ", " + bs_enforceMax + ")=" + isValidRangeOpt(i_number, 'true', i_max, bs_enforceMax));

  return (isValidRangeOpt(i_min, bs_enforceMin, i_number, 'true')  &&
          isValidRangeOpt(i_number, 'true', i_max, bs_enforceMax));
}



/**************************************************************************************************
  utility.js...START

  Do not edit this file.  This file is dynamically generated by the validate_form.js
  ant build process
 **************************************************************************************************/

/**
  VALIDATE_FORM.JS
  Comprehensive solution for validating HTML forms.
  Copyright (C) 2002, Jeff Epstein, jeff_epstein@yahoo.com, http://www.jeffyjeffy.com#download

  This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.

  You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 **/


//GLOBAL VARIABLES...start

  //A secret public global variable.  For testing purposes, you may want to
  //avoid re-displaying the error after the alert box (within H1 tags).
  //
  //This prevents the crash function from re-presenting the
  //error, after the alert box, within H1 tags.  It makes it so you
  //don't have to press the back button between each error, in order
  //to get back to this page.
  var bCRASH_ONLY_ALERT_BOX = false;

  //This is automatically manipulated by this js file.  It is private
  //and should never be altered.
  var bCrashed = false;
//GLOBAL VARIABLES...end

/**
  Present an error message in an alert box, and also print the provided error message to screen, surrounded by H1 tags.  This function is intended for programming errors, not user errors.

  Although execution is not truly interrupted, this should be significant enough to alert the programmer to an error.

  PARAMETERS
    s_callingFuncAndError
      The function name, followed by the error message.

  RETURNS
    false
      Always.
 **/
function crash(s_callingFuncAndError)  {
  alert("-------ERROR-------\n\nERROR in " + s_callingFuncAndError);

  if(!bCRASH_ONLY_ALERT_BOX)  {
    document.writeln("<h1>ERROR in " + s_callingFuncAndError + "</h1>");
  }

  bCrashed = true;

  return false;
}

/**
  Was crash() called?

  RETURNS
    true
      If crash() was called.
    false
      If crash() was never called...or when it was, but you since called resetCrashedFlag().
 **/
function hasCrashed()  {
  return bCrashed;
}

/**
  Make it appear as if crash() was never called, regardless of whether or not it actually was.  This is probably only useful for testing purposes.
 **/
function resetCrashedFlag()  {
  bCrashed = false;
}

/**
  Conditionally print the provided message in an alert box.

  PARAMETERS
    b_condition
      If true, present s_message in an alert box.  If false, do nothing.
    s_message
      The message to present in an alert box, should b_condition be true.  If b_condition is false, this parameter is ignored.

  RETURNS
    true
      If b_condition is true.
    false
      If b_condition is false.
 **/
function calert(b_condition, s_message)  {
  if(b_condition)  {
    alert(s_message);
    return false;
  }

  return true;
}


/**
  Convenience function to print an error message, should a required parameter not be provided.

  PARAMETERS
    s_callingFileFunc
      Passed directly to crash, if !o_param.  If o_param is true, this parameter is ignored.
    s_paramName
      The name of o_param, only for the potential error message.  If o_param is true, this parameter is ignored.
    o_param
      The required parameter.  If "false" (!o_param) the an error message is printed.

  RETURNS
    true
      If o_param is true.
    false
      If o_param is false.
 **/
function crashIfMissing(s_callingFileFunc, s_paramName, o_param)  {
  if(!o_param)  {
    return crash(s_callingFileFunc + ':  Required parameter ' + s_paramName + ' not provided.');
  }

  return true;
}

/**
  A single unit test.  If the actual result differs from the actual, an error alert box is presented.

  PARAMETERS
    s_nameOfTest
      The name of the calling JavaScript file and function name, currently being tested.  Required.
    i_testNumber
      The number of the test, for potential error messages only.  Required.
    s_expected
      The expected response from this test.
    s_actual
      The actual response from this test.

  RETURNS
    true
      If s_expected equals s_actual.
    false
      If s_expected does not equal s_actual.
 **/
function test(s_nameOfTest, i_testNumber, s_expected, s_actual)  {
  crashIfMissing(s_nameOfTest, 's_nameOfTest', 'utility.test');
  crashIfMissing(i_testNumber, 'i_testNumber', 'utility.test');

  if(s_expected != s_actual)  {
    alert("---ERROR---\n\n\tTest name:\t" + s_nameOfTest + '\n\tTest number:\t' + i_testNumber + '\n\tExpected:\t"' + s_expected + '"\n\tActual:\t\t"' + s_actual + '"');
    return false;
  }

  return true;
}

function crashIfBadBooleanString(bs_potential, s_variableName, s_callingFunc)  {
  if(!bs_potential)  {
    return crash(s_callingFunc + ":  " + s_variableName + " must be a *string*, provided, and equal to either 'true' or 'false'.  It is currently a *boolean* equal to 'false'.");
  }

  if(bs_potential != 'true'  &&  bs_potential != 'false')  {
    var sValue = "string equal to '" + bs_potential;
    if(typeof(bs_potential) == 'boolean')  {
      //It is equal to *boolean* true.  It's not a string.
      //Note that it's NOT false, because the first line of this
      //function eliminated this possibility.
      sValue = "*boolean* equal to '" + bs_potential;
    }
    return crash(s_callingFunc + ":  " + s_variableName + " must be a string, provided, and equal to either 'true' or 'false'.  It is currently a " + sValue + "'.");
  }
}

function crashIfBadBooleanStringOpt(bs_potential, s_variableName, s_callingFunc)  {
  if(!bs_potential)  {
    return;
  }
  //bs_potential has been provided.

  if(bs_potential != 'true'  &&  bs_potential != 'false')  {
    var sValue = "string equal to '" + bs_potential + "";
    if(typeof(bs_potential) == 'boolean')  {
      //It is equal to *boolean* true.  It's not a string.
      //Note that it's NOT false, because the first line of this
      //function eliminated this possibility.
      sValue = "*boolean* equal to '" + bs_potential + "";
    }
    return crash(s_callingFunc + ":  " + s_variableName + " is not required, but when provided it must be a string, and equal to either 'true' or 'false'.  It is currently a " + sValue + "'.");
  }
}


function getOptBooleanString(bs_potential, s_variableName, s_callingFunc)  {
  if(bs_potential)  {
    crashIfBadBooleanStringOpt(bs_potential, s_variableName, s_callingFunc);
    return bs_potential;
  }  else  {
    return 'false';
  }
}




/**
  Is the provided object an array?

  This concept comes from Kas Thomas, at
  http://www.planetpdf.com/mainpage.asp?webpageid=1144

  PARAMETERS
    o_potentialArray
      The object that is analyzed to see if it is an array.  Required.

  RETURNS
    true
      If o_potentialArray is an array.
    false
      If o_potentialArray is anything but an array.

 **/
function isArray(o_potentialArray)  {
  crashIfMissing(o_potentialArray, 'o_potentialArray', 'utility.isArray');

  if(typeof o_potentialArray != 'object')  {
    return false;
  }
  //It is definitely an object.

  return (o_potentialArray.constructor.toString().match(/array/i) != null);
}

</SCRIPT>
<SCRIPT LANGUAGE="JavaScript">
<!--
  function isFormValid(f_orm)  {
    var sPrefix = '       --';

    f_orm.email_address.sMsgRequired = 'What is your email address?';
    f_orm.email_address.sMsgTxtEmail = 'Your email address is invalid.';

    f_orm.password.sMsgRequired = 'What is your password?';

    var sErrors = getFormErrorMsgs(f_orm, sPrefix, -1);

    if(sErrors != '')  {
      alert("ERROR!\n\n" + sErrors);
      return false;
    }

    alert("HOORAY!!!  You have successfully logged in.\n\n(Normally, this would just return true, which would cause the form to submit...)");
    return false;
  }
//-->
</SCRIPT>
</HEAD>

<BODY><a name="top"></a>

<H3>Realistic Example:  Email Login</H3>

<P>To login, provide your email address (which is your username) and password.</P>

<FORM onSubmit="return isFormValid(this);">
  <BR>Email address:  <INPUT TYPE="text" NAME="email_address">
  <BR>Password:  <INPUT TYPE="password" NAME="password">
  <P><INPUT TYPE="submit"></P>
  <P><INPUT TYPE="reset"></P>
</FORM>

</BODY>
</HTML>





           
         
    
  








Related examples in the same category

1.Form Validator: time, date email, phone number, age etc
2.Form Validate: is blank, is digit and is integer
3.Log in form validation
4.Comprehensive form validation
5.Illegal sub string validation
6.Email form validation
7.Form Validator
8.Form valiation for empty data, file name
9.Email Address Validate
10.Time Validate
11.URL Validate
12.Use JavaScript to check the password input
13.Form value validation and onsubmit action
14.Check form input value and alert user by change the control background