/* -----------------------------------------------------------------
  Filename:             Common.js
  Purpose:              Common functions
  Dependencies:         none
----------------------------------------------------------------- */

/* ----------------------------------------------------------------------------
  GLOBAL variable declarations required for all browsers
---------------------------------------------------------------------------- */
var g_oTimeout;  /* Timeout object for both Netscape 4.x and W3 browsers */
var g_sValidationAlert = ""; /* string to contain validation alerts, global var
                                accomodates concatentation of default validation
                                with special case validation */
var g_oFocusElement = null; /* Object reference for validation routines, global var
                               accomodates setting focus element in either standard
                               validation function or in special case function */
var g_sCurrentElement = ""; /* String reference for form element currently
                                 being validated; allows checking element name
                                 prefix to determine the input type for unspecified
                                 datatypes */
var g_bFormSubmit = false;  /* Global variable for supporting submitting a form once */
/* ----------------------------------------------------------------------------
  CONSTANTS - this term, of course, used loosely in .js
---------------------------------------------------------------------------- */
var S_MSG_VALIDATION_ELEMENT = "";
var S_MSG_VALIDATION_CONTACT =  "Please enter a valid address, phone number or email address so that we may contact you"
var S_MSG_VALIDATION_REF =      "Please enter a reference with a valid address, phone number, or email address"
var S_MSG_VALIDATION_EMERGENCY = "Please enter a valid phone number for an emergency contact"
var S_MSG_VALIDATION_ELEMENT_ALPHA        = "Please enter letters";
var S_MSG_VALIDATION_ELEMENT_ALPHANUM     = "Please enter letters and numbers only (no special characters)";
var S_MSG_VALIDATION_ELEMENT_ALPHANUMTEXT1    = "Please enter letters and numbers";
var S_MSG_VALIDATION_ELEMENT_ALPHANUMTEXT2    = "\n    The following special characters are not allowed: < > [ ] ^ ` { | }\n";
var S_MSG_VALIDATION_ELEMENT_ALPHANUMSPECIAL1 = "Please enter letters and numbers";
var S_MSG_VALIDATION_ELEMENT_ALPHANUMSPECIAL2 = "\n    The following special characters are not allowed: @ < > ; : \' \\ \" & ? *\n";
var S_MSG_VALIDATION_ELEMENT_ALPHANUMSPECIALEX = "\n    The following special characters are not allowed: < > ; \\ \" *\n";
var S_MSG_VALIDATION_ELEMENT_ALPHASPECIAL1 = "Please enter letters";
var S_MSG_VALIDATION_ELEMENT_ALPHASPECIAL2 = "\n    The following special characters are not allowed: @ < > ; : \' \\ \" & ? *\n";
var S_MSG_VALIDATION_ELEMENT_ALPHASPECIALEX = "\n    The following special characters are not allowed: < > ; \\ \" *\n";
var S_MSG_VALIDATION_ELEMENT_EML          = "Please enter a valid email";
var S_MSG_VALIDATION_ELEMENT_PHN          = "Please enter a valid phone number in the format ###-###-####";
var S_MSG_VALIDATION_ELEMENT_ZIP		  = "Please enter a valid postal code";
var S_MSG_VALIDATION_ELEMENT_NAME         = "Please enter letters and numbers";
var S_MSG_VALIDATION_ELEMENT_NAME2				= "  \n    The following are some of the special characters that are not allowed: < >  | } { [ ]\n";       

/* ----------------------------------------------------------------------------
  FORM VALIDATION FUNCTIONS
---------------------------------------------------------------------------- */

/* ----------------------------------------------------------------------------
  Function:       validateForm
  Purpose:        performs standard validation routines and throws alert
                  specifying all invalid fields on failure
  Affects:        DHTML DOM
  Arguments In:   sFormName   = name of form to validate
                  saElements  = array of elements specifying
                                element name^required bit^datatype
                  sLyr        = name of layer if the form is on a DIV, this is
                                used by NN4.x to resolve the form object ref
                                since layers have their own document objects
                  bSpecialCase = true:  do not throw alert, this will be done
                                        by page-level validation functions that
                                        wrap this function
                                 false: throw alert, this function is in the
                                        form's onsubmit event handler
  Arguments Out:  true        = all form elements successfully validated
                  false       = at least one form element failed validation
---------------------------------------------------------------------------- */
function validateForm(sFormName, saElements, sLyr, bSpecialCase)
{
  var oForm = getFormObject(sFormName, sLyr);
  var iLen = saElements.length;
  var iCnt;
  var saElement;
  var sElement;
  var sLabel;
  var bReq;
  var sDT;
  var oElement;
  g_oFocusElement = null;
  g_sCurrentElement = "";
  g_sValidationAlert = "";

  /* Iterate the form elements validation array */
  for (iCnt = 0; iCnt < iLen; iCnt++)
  {
    /* Split the elements array member */
    saElement = saElements[iCnt].split("^");
    sElement  = saElement[0];
    sLabel    = saElement[1];
    bReq      = parseInt(saElement[2]);
    sDT       = saElement[3];

    /* Get object ref to the element and call validate */
    oElement = getElementObject(oForm, sElement);
    if (!(validateElement(oElement, bReq, sDT)))
    {
      if (null == g_oFocusElement)
      {
        g_oFocusElement = oElement;
      }
      g_sValidationAlert += makeValidationAlert(sLabel, sDT);
    }
  }

  /* Test for invalid elements:
     if necessary, generate an alert and return false */
  if ("" != g_sValidationAlert)
  {

    /* If this is the only validation being performed, throw the alert and
       focus here, else do not throw alert as further validation could
       concatenate more on g_sValidationAlert */
    if (!(bSpecialCase))
    {
      handleInvalidForm();
    }
    return false;
  }
  else
  {
    return true;
  }
}

/* ----------------------------------------------------------------------------
  Function:       handleInvalidForm
  Purpose:        focuses first invalid form element and throws alert
  Affects:        FORM Object
  Arguments In:   none
  Arguments Out:  none
---------------------------------------------------------------------------- */
function handleInvalidForm()
{
  g_oFocusElement.focus();
  g_oFocusElement = null;
  alert(g_sValidationAlert);
  g_sValidationAlert = "";
}

/* ----------------------------------------------------------------------------
  Function:       clearForm
  Purpose:        Clears all form fields
  Affects:        FORM Object
  Arguments In:   form object
  Arguments Out:  none
---------------------------------------------------------------------------- */
function clearForm(oForm)
{
  var iCnt = 0;
  var iLen = oForm.elements.length;
  var sType = "";

  for (iCnt = 0; iCnt < iLen; iCnt++)
  {
    sType = oForm.elements[iCnt].type;
    switch (sType)
    {
      case "text":
        oForm.elements[iCnt].value = "";
        break;
      case "textarea":
        oForm.elements[iCnt].value = "";
        break;
      case "select":
        oForm.elements[iCnt].options[0].selected = "true";
        break;
      case "select-one":
        oForm.elements[iCnt].options[0].selected = "true";
        break;
      case "password":
        oForm.elements[iCnt].value = "";
        break;
      case "checkbox":
        oForm.elements[iCnt].checked = oForm.elements[iCnt].defaultChecked;
        break;
      case "radio":
        oForm.elements[iCnt].checked = oForm.elements[iCnt].defaultChecked;
        break;
      //default is to not do anything with the element, certain element types should not be modified
    }
  }
}

/* ----------------------------------------------------------------------------
  Function:       validateElement
  Purpose:        perform validation on the form element
  Affects:        nothing
  Arguments In:   oElement  = reference to the form element
                  bReq      = bit, required?
                  sDT       = datatype
  Arguments Out:  true =  valid
                  false = invalid
---------------------------------------------------------------------------- */
function validateElement(oElement, bReq, sDT)
{
  var bRetVal = true; /* Assume validity */
  var sVal = getElementValue(oElement);
  var sElementType = oElement.type;

  g_sCurrentElement = oElement.name;

  /* If the element is required, ensure that a value exists */
  if (bReq && sVal.replace(/\s*/,'').length == 0)
  {
    return false;
  }
  /* Test radio button to ensure it is checked if required */
  else if (bReq && "radio" == oElement.type)
  {
    bRetVal = oElement.checked;
  }

  /* Only call datatype validation if the element is populated
     (and selected in case of radio button)  */
  if (("" != sVal && "radio" != sElementType) ||
      (bRetVal && "radio" == sElementType))
  {
    /* Always disallow special characters */
    /* Call the datatype-specific validation routine */
    switch (sDT)
    {
      case "alpha":
        bRetVal = isValidAlpha(sVal);
        break;
      case "alphanum":
        bRetVal = isValidAlphaNum(sVal);
        break;
      case "alphanumtext":
        bRetVal = isValidText(sVal);
        break;
      case "alphanumspecial":
        bRetVal = isValidAlphaNumSpecial(sVal);
        break;
      case "alphanumspecialex":
        bRetVal = isValidAlphaNumSpecialEx(sVal);
        break;
      case "alphaspecial":
        bRetVal = isValidAlphaSpecial(sVal);
        break;
      case "alphaspecialex":
        bRetVal = isValidAlphaSpecialEx(sVal);
        break;
      case "int":
        bRetVal = isValidInt(sVal);
        break;
      case "date":
        bRetVal = isDate(sVal, true, ""); /* validates for SBOB-format date */
        break;
      case "dategtetoday":
        bRetVal = isDate(sVal, true, "gte"); /* validates for SBOB-format
                                                date >= today */
        break;
      case "datelttoday":
        bRetVal = isDate(sVal, true, "lt"); /* validates for SBOB-format
                                                      date < today */
        break;
      case "dateltetoday":
        bRetVal = isDate(sVal, true, "lte"); /* validates for SBOB-format
                                                      date <= today */
        break;
      case "datebp":
        bRetVal = isDate(sVal, true, "bp"); /* validates for SBOB-format
                                                      date >= today and < today + 1 year */
        break;
      case "phone":
        bRetVal = isValidPhone(sVal, true);
        break;
      case "email":
        bRetVal = isValidEmail(sVal);
       break;
      case "zip":
        bRetVal = isValidZip(sVal);
        break;
      case "name":
        bRetVal = isValidName(sVal);
        break;
      default:
        /* sDT (datatype) is an optional arg, if no valid arg passed then do not
           validate for datatype */
        break;
    }
  }

  return bRetVal;
}

/* ----------------------------------------------------------------------------
  Function:       makeValidationAlert
  Purpose:        creates a line of a validation alert
  Affects:        nothing
  Arguments In:   sLabel    = label of the form element
                  sDT       = datatype of the form element, if not cased then
                              failure to validate is due to requirement rather
                              than datatype
  Arguments Out:  sRetVal   = message string
---------------------------------------------------------------------------- */
function makeValidationAlert(sLabel, sDT)
{
  var sRetVal = "";
  var sPrefix = "";

  switch (sDT)
  {
    case "alpha":
      sRetVal = S_MSG_VALIDATION_ELEMENT_ALPHA + " in " + sLabel + ".\n";
      break;
    case "alphanum":
      sRetVal = S_MSG_VALIDATION_ELEMENT_ALPHANUM + " in " + sLabel + ".\n";
      break;
    case "alphanumtext":
      sRetVal = S_MSG_VALIDATION_ELEMENT_ALPHANUMTEXT1 + " in " + sLabel + "." + S_MSG_VALIDATION_ELEMENT_ALPHANUMTEXT2;
      break;
    case "alphaspecial":
      sRetVal = S_MSG_VALIDATION_ELEMENT_ALPHASPECIAL1 + " in " + sLabel + "." + S_MSG_VALIDATION_ELEMENT_ALPHASPECIAL2;
      break;
    case "alphaspecialex":
      sRetVal = S_MSG_VALIDATION_ELEMENT_ALPHASPECIAL1 + " in " + sLabel + "." + S_MSG_VALIDATION_ELEMENT_ALPHASPECIALEX;
      break;
    case "alphanumspecial":
      sRetVal = S_MSG_VALIDATION_ELEMENT_ALPHANUMSPECIAL1 + " in " + sLabel + "." + S_MSG_VALIDATION_ELEMENT_ALPHANUMSPECIAL2;
      break;
    case "alphanumspecialex":
      sRetVal = S_MSG_VALIDATION_ELEMENT_ALPHANUMSPECIAL1 + " in " + sLabel + "." + S_MSG_VALIDATION_ELEMENT_ALPHANUMSPECIALEX;
      break;
    case "int":
      sRetVal = S_MSG_VALIDATION_ELEMENT_INT + " in " + sLabel + ".\n";
      break;
    case "date":
      sRetVal = S_MSG_VALIDATION_ELEMENT_DTE + " in " + sLabel + ".\n";
      break;
    case "phone":
      sRetVal = S_MSG_VALIDATION_ELEMENT_PHN + " in " + sLabel + ".\n";
      break;
    case "phonenoext":
      sRetVal = S_MSG_VALIDATION_ELEMENT_PHN + " in " + sLabel + ".\n";
      break;
    case "email":
      sRetVal = S_MSG_VALIDATION_ELEMENT_EML + " in " + sLabel + ".\n";
      break;
    case "zip":
      sRetVal = S_MSG_VALIDATION_ELEMENT_ZIP + " in " + sLabel + ".\n";
      break;
    case "name":
      sRetVal = S_MSG_VALIDATION_ELEMENT_NAME + " in " + sLabel + ".\n";
      break;

    default:
      // GSC: Check for SEL prefix in element name; if present, change wording
      g_sCurrentElement != "" ?
        sPrefix = g_sCurrentElement.substring(0,3).toLowerCase() :
        sPrefix = "";
      if (sPrefix == "sel") {
        sRetVal = "Please select " + sLabel + ".\n";
      } else {
        sRetVal = "Please enter " + sLabel + ".\n";
      }
      break;

  }

  return sRetVal;
}

/* ----------------------------------------------------------------------------
  Function:       getFormObject
  Purpose:        gets a reference to a form object by eval
                    * special case NN4.x form on layer
  Affects:        DHTML DOM
  Arguments In:   sFormName   = name of form
                  sLyr        = name of layer if the form is on a DIV, this is
                                used by NN4.x to resolve the form object ref
                                since layers have their own document objects
  Arguments Out: oForm       = reference to the form object
---------------------------------------------------------------------------- */
function getFormObject(sFormName, sLyr)
{
  var oForm;
  if (g_bIsNN4 && "" != sLyr)
  {
    var oForm = document.layers[sLyr].document.forms[sFormName];
  }
  else
  {
    var oForm = document[sFormName];
  }

  return oForm;
}

/* ----------------------------------------------------------------------------
  Function:       getElementObject
  Purpose:        get a reference to a form element
  Affects:        nothing
  Arguments In:   oForm = reference to the form object containing the element
                  sElement = name of the element to get a reference to
  Arguments Out:  oElement = reference to the form element
---------------------------------------------------------------------------- */
function getElementObject(oForm, sElement)
{
  var sPrefix = getElementPrefix(sElement);
  var oElement;

  /* Get reference to element */
  //oElement = eval("oForm." + sElement);
  oElement = oForm[sElement];

  /* If a radio button, drill down and get ref to selected */
  if ("rdo" == sPrefix || "rad" == sPrefix)
  {
    oElement = getRadioObject(oElement);
  }

  return oElement;
}

/* ----------------------------------------------------------------------------
  Function:       getRadioObject
  Purpose:        get a reference to a radio object
  Affects:        nothing
  Arguments In:   sElement = name of the element to get prefix of
  Arguments Out:  sRetVal = prefix of element name
  Notes:          This function will return a reference to the checked radio
                  button if one exists, or to the single radio button - this
                  function is not responsible for validating, only ref'ing the
                  object
---------------------------------------------------------------------------- */
function getRadioObject(oElement)
{
  var oElement;

  if ("undefined" != typeof oElement.length) /* Radio button group */
  {
    /* iterate and get value of checked radio button */
    iLen = oElement.length;
    for (iCnt = 0; iCnt < iLen; iCnt++)
    {
      if (oElement[iCnt].checked)
      {
        oElement = oElement[iCnt];
        return oElement;
      }
    }
    /* If a checked radio button was not found return a ref to the first
       button */
    oElement = oElement[0];
  }

  /* Return a ref to the element, this handles groups with nothing checked or
     a single radio button */
  return oElement;
}

/* ----------------------------------------------------------------------------
  Function:       getElementPrefix
  Purpose:        get a form element name's prefix
  Affects:        nothing
  Arguments In:   sElement = name of the element to get prefix of
  Arguments Out:  sRetVal = prefix of element name
---------------------------------------------------------------------------- */
function getElementPrefix(sElement)
{
  /* parse the first three characters from the element name */
  var sRetVal = sElement.substr(0,3);
  return sRetVal;
}

/* ----------------------------------------------------------------------------
  Function:       getElementValue
  Purpose:        gets the value of a form element
  Affects:        nothing
  Arguments In:   oElement = reference to the form element
  Arguments Out:  sRetVal =  value of the form element
  Notes:          for purposes of granularity, handles various element types
---------------------------------------------------------------------------- */
function getElementValue(oElement)
{
  var sPrefix = getElementPrefix(oElement.name);
  var sRetVal = "";
  var iCnt;
  var iLen;

  /* get the value of the element based on the type of element */
  switch (sPrefix)
  {
    /* Select lists selected item value from array */
    case "sel":
      sRetVal = oElement.options[oElement.selectedIndex].value;
      break;
    /* All other inputs have simple .value property access */
    default:
      sRetVal = trim(oElement.value);
      break;
  }

  return sRetVal;
}

/* ----------------------------------------------------------------------------
  Function:       setInputValue
  Purpose:        sets the value of an input
  Affects:        FORM object
  Arguments In:   oForm = reference to the FORM
                  sInput = the name of the input
                  sValue = the value to set it to
  Arguments Out:  nothing
---------------------------------------------------------------------------- */
function setInputValue(oForm, sInput, sValue)
{
  var oInput    = getElementObject(oForm, sInput);
  oInput.value  = sValue;
}

/* ----------------------------------------------------------------------------
  Function:       selectOption
  Purpose:        selects the option in the referenced SELECT that has
                  value equal to the value arg passed
  Affects:        FORM object
  Arguments In:   oSelect = reference to the SELECT
                  sValue = the value property to search for
  Arguments Out:  nothing
---------------------------------------------------------------------------- */
function selectOption(oSelect, sValue)
{
  var colOptions = oSelect.options;
  var iLen = colOptions.length;
  var iCnt;

  for (iCnt = 0; iCnt < iLen; iCnt++)
  {
    if (colOptions[iCnt].value == sValue)
    {
      colOptions[iCnt].selected = true;
      break;
    }
  }
}

/* ----------------------------------------------------------------------------
  Function:       selectRadio
  Purpose:        selects the radio button with the passed value
  Affects:        nothing
  Arguments In:   oForm  = reference to the containing FORM object
                  sRadio = name of the RADIO object
                  sValue = the value property to search for
  Arguments Out:  none
---------------------------------------------------------------------------- */
function selectRadio(oForm, sRadio, sValue)
{
  var oRadio = eval("oForm." + sRadio);
  var iLen;
  var iCnt;
  if ("undefined" != typeof oRadio.length)
  {
    iLen = oRadio.length;
    for (iCnt = 0; iCnt < iLen; iCnt++)
    {
      if (sValue == oRadio[iCnt].value)
      {
        oRadio[iCnt].checked = true;
      }
    }
  }
  else
  {
    if (sValue == oRadio.value)
    {
      oRadio.checked = true;
    }
  }
}

/* ----------------------------------------------------------------------------
  Function:       setHiddenFormValues
  Purpose:        wrapper function : calls validateForm on one or both forms
                  and transfers values to the hidden form
  Affects:        DHTML DOM / FORM Object(s)
  Arguments In:   sFormSrc
                  sLyrSrc
                  sFormDest
                  sLyrDest
  Arguments Out:  none
  Notes:          Used only by Transfer Add and Transfer Modify
---------------------------------------------------------------------------- */
function setHiddenFormValues(sFormSrc, sLyrSrc, sFormDest, sLyrDest)
{
  var oFormSrc = getFormObject(sFormSrc, sLyrSrc);
  var oFormDest = getFormObject(sFormDest, sLyrDest);
  var oaElementsSrc = oFormSrc.elements;
  var oElementSrc;
  var oElementDest;
  var iCnt;
  var iLen = oaElementsSrc.length;

  for (iCnt = 0; iCnt < iLen; iCnt++)
  {
    /* Get and validate a reference to the matching element in the destination
       form */
    oElementSrc  = oaElementsSrc[iCnt];
    if ("radio" == oElementSrc.type && true != oElementSrc.checked)
    {
      oElementSrc = null;
    }

    if ("undefined" != typeof oElementSrc)
    {
      if (oElementSrc != null)
      {
        oElementDest = getElementObject(oFormDest, oElementSrc.name);
        if ("undefined" != typeof oElementDest)
        {
          /* Copy the value from source to destination element */
          oElementDest.value = getElementValue(oElementSrc);
        }
      }
    }
  }
}

/* ----------------------------------------------------------------------------
  Function:       isValidAlpha
  Purpose:        tests a string for validity as an alpha (including space)
  Affects:        nothing
  Arguments In:   sVal  = string to test for validity as an alpha
  Arguments Out:  true = is an alpha; false = not an alpha
---------------------------------------------------------------------------- */
function isValidAlpha(sVal)
{
  return (-1 == sVal.search(/[^ a-zA-Z]/));
}

/* ----------------------------------------------------------------------------
  Function:       isValidAlphaNum
  Purpose:        tests a string for validity as an alphanumeric
                  (including space)
  Affects:        nothing
  Arguments In:   sVal  = string to test for validity as an alphanumeric
  Arguments Out:  true = is an alphanumeric; false = not an alphanumeric
---------------------------------------------------------------------------- */
function isValidAlphaNum(sVal)
{
  return (-1 == sVal.search(/[^ a-zA-Z0-9]/));
}


/* ----------------------------------------------------------------------------
  Function:       isValidText
  Purpose:        tests a string for validity as an basic text datatype
                  (including [space] ! " # $ % & ' ( ) * + , - . / : ; = ? @ \ _ ~)
  Affects:        nothing
  Arguments In:   sVal  = string to test for validity as basic text
  Arguments Out:  true = is basic text; false = not basic text
---------------------------------------------------------------------------- */
function isValidText(sVal)
{
  return (-1 == sVal.search(/[^a-zA-Z0-9\ \!\"\#\$\%\&\'\(\)\*\+\,\-\.\/\:\;\=\?\@\\\_\~]/));
}


/* ----------------------------------------------------------------------------
  Function:       isValidAlphaNumSpecial
  Purpose:        tests a string for validity as an alphanumeric including a
                  limited set of special characters
  Affects:        nothing
  Arguments In:   sVal  = string to test for validity
  Arguments Out:  true = is valid; false = not valid
---------------------------------------------------------------------------- */
function isValidAlphaNumSpecial(sVal)
{
  if (isValidText(sVal) && !(hasSpecialChar(sVal)))
  {
    return true;
  }
  else
  {
    return false;
  }
}

/* ----------------------------------------------------------------------------
  Function:       isValidAlphaNumSpecialEx
  Purpose:        tests a string for validity as an alphanumeric including an
                  extended set of special characters
  Affects:        nothing
  Arguments In:   sVal  = string to test for validity
  Arguments Out:  true = is valid; false = not valid
---------------------------------------------------------------------------- */
function isValidAlphaNumSpecialEx(sVal)
{
  if (isValidText(sVal) && !(hasSpecialCharEx(sVal)))
  {
    return true;
  }
  else
  {
    return false;
  }
}

/* ----------------------------------------------------------------------------
  Function:       isValidAlphaSpecial
  Purpose:        tests a string for validity as an alpha including a
                  limited set of special characters
  Affects:        nothing
  Arguments In:   sVal  = string to test for validity
  Arguments Out:  true = is valid; false = not valid
---------------------------------------------------------------------------- */
function isValidAlphaSpecial(sVal)
{
  if (hasSpecialChar(sVal))
  {
    return false;
  }
  else
  {
    return (-1 == sVal.search(/[\d]/));
  }
}

/* ----------------------------------------------------------------------------
  Function:       isValidAlphaSpecialEx
  Purpose:        tests a string for validity as an alpha including an
                  extended set of special characters
  Affects:        nothing
  Arguments In:   sVal  = string to test for validity
  Arguments Out:  true = is valid; false = not valid
---------------------------------------------------------------------------- */
function isValidAlphaSpecialEx(sVal)
{
  if (hasSpecialCharEx(sVal))
  {
    return false;
  }
  else
  {
    return (-1 == sVal.search(/[\d]/));
  }
}

/* ----------------------------------------------------------------------------
  Function:       isValidInt
  Purpose:        tests a string for validity as an integer
  Affects:        nothing
  Arguments In:   sVal  = string to test for validity as an integer
  Arguments Out:  true = is a numeric; false = not an integer
---------------------------------------------------------------------------- */
function isValidInt(sVal)
{
  return (-1 == trim(sVal).search(/[^0-9]/));
}

/* ----------------------------------------------------------------------------
  Function:       isDate
  Purpose:        tests a string for validity as a date
  Affects:        nothing
  Arguments In:   sVal        = string to test for validity as a date
                  bSBOB       = boolean specifies whether to check date format to
                                SBOB specifications
                  sTimeframe  = string specifying timeframe
                                lt  = less than today
                                gte = greater than or equal to today
  Arguments Out:  true = is a valid date; false = not a valid date
---------------------------------------------------------------------------- */
function isDate(sVal, bSBOB, sTimeframe)
{
  /* Convert the string to date to ensure it is a valid date */
  var dtDate = new Date(sVal);
  var dtBPDate = new Date(g_dtToday);
  var iYear   = -1;
  var iMonth  = -1;
  var iDay    = -1;

  var saValidDays = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

  if ("NaN" != dtDate)
  {
    /* if timeframe specified, perform initial timeframe test */
    /* Changed the getYear()[obsolete funciton] to getFullYear() */
  	dtBPDate = new Date(dtBPDate.setFullYear(g_dtToday.getFullYear() + 1));

    if (("gte" == sTimeframe && dtDate < g_dtToday) ||
        ("lt" == sTimeframe && dtDate >= g_dtToday) ||
        ("lte" == sTimeframe && dtDate > g_dtToday) ||
        ("bp" == sTimeframe && ((dtDate < g_dtToday) || (dtDate > dtBPDate))))
    {
      return false;
    }
    else
    {
      /* if SBOB-specific date format required then validate the format as well */
      if (bSBOB)
      {
        if (isValidSBOBDate(sVal))
        {
          /* test for invalid dates, e.g., 02/31/2003 */
          iYear   = parseInt(sVal.substr(6, 4));

          iMonth  = sVal.substr(0, 2);
          if (0 == iMonth.indexOf("0")) { iMonth = iMonth.substr(1, 1); }
          iMonth = parseInt(iMonth) - 1;
                  /* 0-based for use as array index */

          iDay    = sVal.substr(3, 2);
          if (0 == iDay.indexOf("0")) { iDay = iDay.substr(1, 1); }
          iDay    = parseInt(iDay);

          /* modify days for leap years */
          if (isCenturyLeapYear(iYear) || isNonCenturyLeapYear(iYear))
          {
            saValidDays[1] = 29;
          }
          /* make sure the day is not greater than the month supports */
          return (iDay <= saValidDays[iMonth]);
        }
      }
      else
      {
        return true;
      }
    }
  }
  else
  {
    /* did not convert to a date, invalid */
    return false;
  }
}

/* ----------------------------------------------------------------------------
  Function:       isValidPhone
  Purpose:        tests a string for validity as a properly formatted phone
  Affects:        nothing
  Arguments In:   sVal = string to test for validity as a phone number
                  bAllowExt = boolean, allow trailing digits for extension?
  Arguments Out:  true = is a valid phone format per SBOB specifications
                  false = not a valid phone format per SBOB specifications
  Notes:          xxx-xxx-xxxx OR (xxx)xxx-xxxx OR xxx.xxx.xxxx OR xxxxxxxxxx
                    ** allows trailing characters to support extensions **
---------------------------------------------------------------------------- */
function isValidPhone(sVal, bAllowExt)
{
	var xPhone
		if (bAllowExt)
		{
			xPhone = /^(\([a-zA-Z2-9]{1}[a-zA-Z0-9]{2}\)\ *[a-zA-Z0-9]{3}(\-|\ |\.)?[a-zA-Z0-9]{4}|[a-zA-Z2-9]{1}[a-zA-Z0-9]{2}[a-zA-Z0-9]{3}[a-zA-Z0-9]{4}|[a-zA-Z2-9]{1}[a-zA-Z0-9]{2}\.[a-zA-Z0-9]{3}\.[a-zA-Z0-9]{4}|[a-zA-Z2-9]{1}[a-zA-Z0-9]{2}\ [a-zA-Z0-9]{3}\ [a-zA-Z0-9]{4}|[a-zA-Z2-9]{1}[a-zA-Z0-9]{2}\-[a-zA-Z0-9]{3}\-[a-zA-Z0-9]{4})([a-zA-Z0-9\#?\+\.\,\ ]*)?$/gi;
		}
		else
		{
			xPhone = /^(\([a-zA-Z2-9]{1}[a-zA-Z0-9]{2}\)\ *[a-zA-Z0-9]{3}(\-|\ |\.)?[a-zA-Z0-9]{4}|[a-zA-Z2-9]{1}[a-zA-Z0-9]{2}[a-zA-Z0-9]{3}[a-zA-Z0-9]{4}|[a-zA-Z2-9]{1}[a-zA-Z0-9]{2}\.[a-zA-Z0-9]{3}\.[a-zA-Z0-9]{4}|[a-zA-Z2-9]{1}[a-zA-Z0-9]{2}\ [a-zA-Z0-9]{3}\ [a-zA-Z0-9]{4}|[a-zA-Z2-9]{1}[a-zA-Z0-9]{2}\-[a-zA-Z0-9]{3}\-[a-zA-Z0-9]{4})$/gi;
		}
		return (0 == sVal.search(xPhone));
}

/* ----------------------------------------------------------------------------
  Function:       isValidTenDigitPhone
  Purpose:        tests a string for properly formatted ten digit phone
  Affects:        nothing
  Arguments In:   sVal = string to test for validity as a phone number
  Arguments Out:  true = is a valid phone format per SBOB specifications
                  false = not a valid phone format per SBOB specifications
  Notes:          xxx-xxx-xxxx OR (xxx)xxx-xxxx OR xxx.xxx.xxxx OR xxxxxxxxxx
				  strict version of isValidPhone for host application compliance
---------------------------------------------------------------------------- */
function isValidTenDigitPhone(sVal)
{
	var xPhone
	xPhone = /^(\([2-9]{1}[0-9]{2}\)\ *[0-9]{3}(\-|\ |\.)?[0-9]{4}|[2-9]{1}[0-9]{2}[0-9]{3}[0-9]{4}|[2-9]{1}[0-9]{2}\.[0-9]{3}\.[0-9]{4}|[2-9]{1}[0-9]{2}\ [0-9]{3}\ [0-9]{4}|[2-9]{1}[0-9]{2}\-[0-9]{3}\-[0-9]{4})$/gi;
	//return (xPhone.test(sVal));
    return (0 == sVal.search(xPhone));	
}

/* ----------------------------------------------------------------------------
  Function:       isValidEmail
  Purpose:        tests a string for validity as properly formatted Email
  Affects:        nothing
  Arguments In:   sVal = string to test for validity as Email
  Arguments Out:  true = is valid Email
                  false = not valid Email
  Notes:          <= 64 characters long
                  Matches 99.99% of e-mail addresses (excludes IP e-mails, which
				  are rarely used). The {2,7} at the end leaves space for top level
				  domains as short as .ca but leaves room for new ones like .museum, etc.

---------------------------------------------------------------------------- */
function isValidEmail(sVal)
{
  /* test length */
  if (-1 == trim(sVal).search(/^[\ -\~]{1,64}\@[\ -\~]{4,255}$/)) 
  {
    return false;
  }
  else
  /* test format */
  {
    //return (0 == trim(sVal).search(/^[\w-]+(\.[\w-]+)*@([\w-]+\.)+[a-zA-Z]{2,7}$/));
    return (0 == trim(sVal).search(/^([a-zA-Z0-9_\-\"\'\/\(\)\;\~\,\.\&\ ]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/));
  }
}

/* ----------------------------------------------------------------------------
  Function:       isValidZip
  Purpose:        tests a string for validity as properly formatted ZipCode
  Affects:        nothing
  Arguments In:   sVal = string to test for validity as ZipCode
  Arguments Out:  true = is valid ZipCode
                  false = not valid ZipCode
  Notes:          ##### OR #####-#### OR #########
---------------------------------------------------------------------------- */
function isValidZip(sVal)
{
  return (0 == trim(sVal).search(/^(\d{4}[1-9]{1})((\+|\ |\-)?(\d{4}))?$/));
}

/* ----------------------------------------------------------------------------
  Function:       hasSpecialChar
  Purpose:        tests a string for special characters not allowed in SBOB
  Affects:        nothing
  Arguments In:   sVal = string to test for special characters
  Arguments Out:  true = contains special characters
                  false = does not contain special characters
  Notes:          special characters are: @ < > ; : ' " \ & ? *
---------------------------------------------------------------------------- */
function hasSpecialChar(sVal)
{
  return (0 == sVal.search(/[\@\<\>\;\:\'\"\\\&\?\*]/));
}


/* ----------------------------------------------------------------------------
  Function:       hasSpecialCharEx
  Purpose:        tests a string for a smaller subset of special characters
                  not allowed in SBOB - Ex since it's the EXTENDED set of
                  allowed characters
  Affects:        nothing
  Arguments In:   sVal = string to test for special characters
  Arguments Out:  true = contains special characters
                  false = does not contain special characters
  Notes:          special characters are: < > ; " \ *
---------------------------------------------------------------------------- */
function hasSpecialCharEx(sVal)
{
  return (0 == sVal.search(/[\<\>\;\"\\\*]/));
}


/* ----------------------------------------------------------------------------
  Function:       isValidName
  Purpose:        tests a string to ensure it appears to be a name, will not allow
                    numbers or spaces.
  Affects:        nothing
  Arguments In:   sVal = string to test for name characters
  Arguments Out:  true = appears to be valid name, allows some special characters
                  false = contains numbers, spaces or "special characters"
---------------------------------------------------------------------------- */
function isValidName(sVal)
{
  return (0 == (trim(sVal).search(/^([a-zA-Z0-9!#%@_\"\$\&\'\(\)\*\+\,\-\.\/\:\;\=\?\\\~\ ]+)$/)));
  /*if (!(hasSpecialChar(sVal)))
  {
    return (-1 == sVal.search(/[ \d]/));
  }
  else
  {
    return false;
  }*/
}

/* ----------------------------------------------------------------------------
  Function:       trim
  Purpose:        removes leading and trailing spaces
  Affects:        nothing
  Arguments In:   value = string to trim
  Arguments Out:  none
  Notes:
---------------------------------------------------------------------------- */
function trim(value) {
   var temp = value;
   var obj = /^(\s*)([\W\w]*)(\b\s*$)/;
   if (obj.test(temp)) {
   	temp = temp.replace(obj, '$2');
	}
   return temp;
}

/* ----------------------------------------------------------------------------
  Function:       isCenturyLeapYear
  Purpose:        Tests the year to see if it is a leap year - this fn
                  is used when the current year is the end of a century
  Affects:        nothing
  Arguments In:   iYear = the current year - used for leap year calc
  Arguements Out: true = is a leap year
                  false = is not a leap year
--------------------------------------------------------------------------- */
function isCenturyLeapYear(iYear)
{
  return (parseInt(iYear/400) == iYear/400);
}

/* ----------------------------------------------------------------------------
  Function:       isNonCenturyLeapYear
  Purpose:        Tests the year to see if it is a leap year - this fn
                  is used when the current year is not the end of a
                  century
  Affects:        nothing
  Arguments In:   iYear = the current year - used for leap year calc
  Arguements Out: true = is a leap year
                  false = is not a leap year
---------------------------------------------------------------------------- */
function isNonCenturyLeapYear(iYear)
{
  return (parseInt(iYear/4) == iYear/4);
}

/* ----------------------------------------------------------------------------
  Function:       replaceEx
  Purpose:        string replace function
  Affects:        nothing
  Arguments In:   sExpression   = string to search
                  sFind         = string to search for
                  sReplacement  = string to replace instances of sFind with
  Arguements Out: sExpression   = modified string
---------------------------------------------------------------------------- */
function replaceEx(sExpression, sFind, sReplacement)
{
  var iMatchPos       = -1;
  var iMatchRightPos  = -1;
  var iMatchLen       = sFind.length;
  var iExpLen         = sExpression.length;

  /* find the text in the expression and set left and right positions */
  iMatchPos = sExpression.indexOf(sFind);
  iMatchRightPos = iMatchPos + iMatchLen;

  /* replace the string  - iterate until the string is no longer found */
  while (iMatchPos > -1)
  {
    sExpression = sExpression.substr(0, iMatchPos) + sReplacement +
                  sExpression.substr(iMatchRightPos, iExpLen - iMatchRightPos);

    iExpLen         = sExpression.length;
    iMatchPos       = sExpression.indexOf(sFind);
    iMatchRightPos  = iMatchPos + iMatchLen;
  }

  return sExpression;

}

/* ----------------------------------------------------------------------------
  Function:       navigateTo
  Purpose:        navigates to the referenced URL
  Affects:        location object of the top level window
  Arguments In:   sURL = the URL to navigate to - pass in a virtual path
  Arguments Out:  nothing
---------------------------------------------------------------------------- */
function navigateTo(sURL)
{
  if ("" != sURL)
  {
    window.top.document.location.href = sURL;
  }
}

/* ----------------------------------------------------------------------------
  Function:      checkRadio
  Purpose:       checks a radio or checkbox control
  Arguments:     sValue - Value to test, usually the value entered in the field.
                          If not empty-string, the radio or checkbox will be
                          selected or checked.
                 sFormName - Name of form being manipulated.
                 sRadioName - Name of radio or checkbox control to auto-check.
                 iRadioIdx - Index number of control to check, used when multiple
                             controls have the same name.
                 sLyr - If form is contained in a DIV in NN 4.x specify
                        the DIV name to allow drill-down in the NN 4.x Layers.
  Dependencies:  getFormObject function
  Arguments In:  none
  Arguments Out: nothing
  Notes:         Call this function in the onChange evt handler of a form field.
---------------------------------------------------------------------------- */
function checkRadio(sValue, sFormName, sRadioName, iRadioIdx, sLyr)
{
  /* get element objects */
  var oForm = getFormObject(sFormName, sLyr);
  var oField = eval("oForm.elements['" + sRadioName + "']");
  var iLen = oField.length;
  var iCnt = -1;

  /* handle possible point of failure on length property */
  if ("undefined" == typeof iLen)
  {
    iLen = 0;
  }

  /* if a value was entered in the calling input then set radio button to checked
     unless the radio index passed in was -1, which is an explicit UnCheck operation */
  if (sValue != "")
  {
    /* if there's more than one control with this name - access via index */
    if (iLen > 1)
    {
      if (iRadioIdx == -1)
      {
        /* iterate the collection of radio buttons and uncheck them all */
        for (iCnt = 0; iCnt < iLen; iCnt++)
        {
          oField[iCnt].checked = false;
        }
      }
      else
      {
        oField[iRadioIdx].checked = true;
      }
    }
    else /* there's just one control with this name - index not required */
    {
      iRadioIdx == -1 ? oField.checked = false : oField.checked = true;
    }
  }
  else /* a value was not entered in the calling input -
          uncheck the corresponding radio button */
  {
    /* if there's more than one control with this name - access via index */
    if (iLen > 1)
    {
      oField[iRadioIdx].checked = false;
    }
    else
    {
      oField.checked = false;
    }
  }
}

/* ----------------------------------------------------------------------------
  CLIENT SNIFFING
  Purpose:  Inline code determines browser/version/platform and sets global
            varibables for use by other clientside functions
---------------------------------------------------------------------------- */

/* ----------------------------------------------------------------------------
  Global variable declarations
---------------------------------------------------------------------------- */
var g_bIsMSIE;          // true = Internet Explorer browser
var g_bIsWin;           // true = Windows operating system
var g_nBrowserVersion;  // browser version (integer)

var g_bIsNN4 = false;   // true = Netscape 4.x -- since there are so
                        //   many special cases that apply only to
                        //   NN4, this is an especially handy var.

var g_bIsIE4 = false;   // true = IE 4.x -- does not support document.getElementById
                        //   nor document.getElementsByTagName

var g_bIsW3 = false;    // true = NN 6+ or MSIE 4+

/* ----------------------------------------------------------------------------
  Perform client sniffing
---------------------------------------------------------------------------- */
// Test for Netscape browser - if not Netscape the browser is most
// likely MSIE-compatible.
g_bIsMSIE = (-1 == navigator.appName.indexOf("Netscape"));

// Get browser version
if (g_bIsMSIE)
{
  if (navigator.appVersion.indexOf("MSIE 5.") > -1)
  {
    // special case MSIE 5 since it lists 4.0 as the appversion
    g_nBrowserVersion = 5;
  }
  else
  {
    // Set the current browser version
    g_nBrowserVersion = parseInt(navigator.appVersion);
  }

  if (navigator.appVersion.indexOf("MSIE 4") > -1)
  {
    g_bIsIE4 = true;
  }
  else if (g_nBrowserVersion >= 4)
  {
    g_bIsW3 = true;
  }
}
else
{
  // Set the current browser version
  g_nBrowserVersion = parseInt(navigator.appVersion);

  if (g_nBrowserVersion < 5) // NN4
  {
    g_bIsNN4 = true;
  }
  else  // NN6
  {
    g_bIsW3 = true;
  }
}

// If browser is 4.0+ test for Windows Operating Systems
if (g_nBrowserVersion >= 4)
{
  g_bIsWin = (navigator.platform.indexOf("Win") > -1);
}

/* -------------------------------------------------------------------------
Function:      singleFormSubmit
Purpose:       To prevent multiple submit of the same form
Arguments:     none
Dependencies:  global variable g_bFormSubmit
Returns:       true for 1st call, false for all other call to this function on the page
---------------------------------------------------------------------------- */
function singleFormSubmit() {
  if (!g_bFormSubmit) {
    g_bFormSubmit = true;
    return true;
  } 
  else {
    return false;
  }
}
