// lib_formval.js - validate that certain fields in a form match a given format

// Requires: lib_core.js, lib_clickgrab.js, lib_keygrab.js
if (!LIB_CORE_LOADED || !LIB_CLICKGRAB_LOADED || !LIB_KEYGRAB_LOADED) {
  // Here is where you _could_ do something to alert the user to a problem, but we don't want to do that.
}

/*** Basic RegEx Definitions (primarily used by ValidateForm function) ***/
  var MultiLine = /.+/;				    	        // matches pretty much everything
  var FreeForm = /^.+$/;				    	      // matches everything on one line
  var Alpha = /^[a-zA-Z\s]+$/;					    // matches character strings ONLY
  var Numeric = /^-?(\d{1,3}(,?\d{3})*|\.\d+)(\.\d+)?$/; // matches positive/negative, integer/decimal values
  var PosInt = /^\d+$/;					            // matches positive integers only
  var Alphanumeric = /^[\w\d\s\'\"\:\;\!\?\@\#\$\%\&\(\)\.\,\[\]\\\|\{\}\_\-\+\/\=]+$/;
  							                            // matches alphanumeric strings, pluse some special characters
  var ZipCode = /^\d{5}(-?\d{4})?$/;	      // matches full zip codes 12345-1234
  var Currency = /^\$?\-?(\d{1,3}(,?\d{3})*)(\.\d{2})?$/;	// matches $17.23 or $14,281,545.45 or ...
  var Time12 = /^(0?[0-9]|1[0-2]):[0-5][0-9]$/;        // matches 05:04 or 12:34 but not 75:83
  var Time24 = /^(0?[0-9]|1[0-9]|2[0-3]):[0-5][0-9]$/; // matches 05:04 or 23:11 but not 75:83
  var EmailAddress = /^.+\@(\[?)[a-zA-Z0-9\+\_\-\.\']+\.\w{2,4}(\]?)$/;
  							                            //matches email a.b@c.o.m or any variation (see RFC822)
  var PhoneNumber = /^\d{10}$/;			        // matches a plain 10 digit phone number
  var PhoneNumberExt = /^\(?\d{3}\)?\s*\-?\.?\d{3}\-?\s*\.?\d{4}(\s\d+)?$/;
  							                            // matches a phone number, any delimiter, with extention
  var PhoneNumberFmt = /^\(?\d{3}\)?\s*|-?\.?\d{3}\-?\s*\.?\d{4}$/;
                                            // matches a standard phone/fax number, w/ or w/o parens for zip
  var PhoneNumberInt = /^\d(\d|-){7,20}$/;  // International Phone Number
  var Year = /^(17|18|19|20)[\d]{2,2}$/;    // 4 digit year from 1700 - 2099
  var DateFull = /^(\?|(0?[1-9]|1[0-2])(\-|\/|\.)(0?[1-9]|[1-2][0-9]|3[0-1])((\-|\/|\.)([0-9]{2}|[1-2][0-9]{3}))?)$/;
  							                            // Full Date MM/DD/YYYY or MM/DD/YY, or Short Date MM/DD
  var Date4dYr = /^(0?[1-9]|1[0-2])(\-|\/|\.)(0?[1-9]|[1-2][0-9]|3[0-1])(\-|\/|\.)([1-2][0-9]{3})$/;
  							                            // Full Date MM/DD/YYYY with enforced 4-digit year
  var Months = /^(\?|(0?[0-9]|1[0-1])?)$/;  // matches number of months; 0-11 (note the offset); not the month in MM/DD/YY
  var SSN = /^\d{3}(\-?\s?\.?)\d{2}(\-?\s?\.?)\d{4}$/;	// Social Security Number, any delimiter, or none
  var ProperName = /^[\w\s\'\.\,]+$/;       // matches a first or last name, including some special characters
  var Username = /^[\w\d]+$/;               // matches on alphanumeric character set for username
  var Password = /^[\w\W\d]{4,20}$/;	      // Password validation, min 4, can contain digits, lower, upper, and special chars
                                            // \!\@\#\$\%\^\&\,\(\)\:\;\~\"\'\?\/\\\[\]\_\-\+\=\|\.\,
  var Branch = /^\d{3,8}$/;                 // matches branch ID (min 3, max 8 digits)
  var Product = /^\d{1,5}$/;                // matches product code (min 1, max 5 digits)
  var Time = /^\d{2}\:\d{2}\:\d{2}$/;       // matches standard HH:MM:SS time format
  var CreditScore = /^\d{3}$/;			        // 3 digit credit score
  var DebtToInc = /^\d{1,2}(\.\d{1,3})?$/;  // DTI format: 99.999 max.
/*** End RegEx Definitions ***/

// doLeave(thisElement) : Performs a trim and quick (silent) validation on the form.
function doLeave(thisElement,thisForm) {
  doTrim(thisElement);
  thisValidation = thisElement.getAttribute('valtype');
  if (submitAttempted) {
    ValidateForm(thisForm,1);
  }
}

// disables a set of checkboxes
function disableChecks(myForm,myField,isDisabled) {
  var thisName;
  var thisType;
  for (var i=1; i<myForm.length; i++) {
    with (myForm.elements[i]) {
      thisName = getAttribute('name');
      thisType = getAttribute('type');
	    if (thisType == "checkbox" && thisName == myField) {
	    	if (isDisabled == "false") {
	    	  myForm.elements[i].checked = checked;
	    	} else {
	    	  myForm.elements[i].checked = false;
	    	}
	    }
    }
  }
}

// disables all form fields
// Opt. Param 2: req/unreq - Affect only required or unrequired fields.
function disableForm(myForm) {
  var thisRequired;
  var optArg = "";
  for (var i=1; i<myForm.length; i++) {
    with (myForm.elements[i]) {
      thisRequired = getAttribute('req') || "false";
	    if (myForm.elements[i].type != "button" && myForm.elements[i].type != "reset" && myForm.elements[i].type != "hidden") {
	    	if (arguments.length >= 2) { optArg=arguments[1]; }
	    	if (optArg == "" ||
	    	    (thisRequired == "true" && optArg == "req") ||
	    	    (thisRequired != "true" && optArg == "unreq")) {
	    	  myForm.elements[i].disabled = true;
	    	}
	    }
    }
  }
}

// enables all form fields
// Opt. Param 2: req/unreq - Affect only required or unrequired fields.
function enableForm(myForm) {
  var thisRequired;
  var optArg = "";
  for (var i=1; i<myForm.length; i++) {
    with (myForm.elements[i]) {
      thisRequired = getAttribute('req') || "false";
	    if (myForm.elements[i].type != "button" && myForm.elements[i].type != "reset") {
	      if (arguments.length >= 2) { optArg=arguments[1]; }
	    	if (optArg == "" ||
	    	    (thisRequired == "true" && optArg == "req") ||
	    	    (thisRequired != "true" && optArg == "unreq")) {
	    	  myForm.elements[i].disabled = false;
	    	}
	    }
    }
  }
}

// toggleRequired(isReq,myField[,myField2,myField3,...,myFieldN])
// Sets the required state of a given field (or fields).
function toggleRequired(isReq,myField) {
  var thisField;
  var myReturn = true;
  if (!(isReq == "true" || isReq == "false")) { return false; }
  for (var i=1; i<arguments.length; i++) {
    thisField = document.getElementById(arguments[i]);
    if (thisField) {
      thisField.setAttribute("req",isReq);
    } else {
      myReturn = false;
    }
  }
  return myReturn;
}

// toggleRequiredForm(isReq,myForm)
// Sets the required state of a given form's elements.
function toggleRequiredForm(isReq,myForm) {
  var myReturn = true;
  var thisType;
  var thisID;
  var thisField;
  if (myForm) {
    for (var i=0; i<myForm.length; i++) {
    	with (myForm.elements[i]) {
    	  thisID = getAttribute('id');
    	  thisType = getAttribute('type');
 	      if (!regexCheck(thisType,/^(hidden|button)$/)) {
          setAttribute("req",isReq);
 	      }
    	}
    }
  } else {
    myReturn = false;
  }
  return myReturn;
}

// highlightFields(myFields)
// Highlights a given list of comma-delimited fields.
function highlightFields(myFields) {
  var thisField;
  var arrayFields = myFields.split(",");
  var myReturn = true;
  for (var i=0; i<arrayFields.length; i++) {
    thisField = document.getElementById(arrayFields[i]);
    if (thisField && thisField.style.visibility != "hidden" && thisField.disabled != true) {
      if ((regexCheck(thisField.type,/^select/) || regexCheck(thisField.type,/radio/))  &&
          thisField.parentNode.nodeName == "SPAN") {
        thisField.parentNode.style.backgroundColor = "yellow";
      } else {
        thisField.style.borderColor = "yellow";
      }
    } else if (thisField && thisField.style.visibility == "hidden") {
      thisField.parentNode.style.backgroundColor = "";
    }
  }
  return myReturn;
}

// markRequired(myForm) : Marks all elements of a form with the proper tag if required
// Opt. Param 2: 0/1 - Determines if first item check should be skipped (0=check,1=skip).
// Opt. Param 3: 0/1 - Determines if error/info messages should be (re-)displayed (0=no,1=yes).
function markRequired(myForm) {
  var thisRequired;
  var thisLabel;
  var thisType;
  var thisID;
  var thisAstName;
  var foundFirst = false;
  var dispMsg = true;
  if (arguments.length >= 2) { foundFirst=arguments[1]; }
  if (arguments.length == 3) { dispMsg=arguments[2]; }
  if (myForm) {
    for (var i=0; i<myForm.length; i++) {
    	with (myForm.elements[i]) {
    	  thisID = getAttribute('id');
    	  thisType = getAttribute('type');
    	  thisRequired = getAttribute('req') || "false";
    	  // Remove any previous asterisks, if previously marked as required
    	  // This allows for a fresh start if the field is not actually going to be marked again
    	  thisAstName = "ast_" + thisID;
    	  if (document.getElementById(thisAstName)) {
    	    thisAsterisk = document.getElementById(thisAstName);
    	    thisAsterisk.innerHTML = "";
    	  }
        if (!regexCheck(thisType,/^(hidden|button|checkbox|radio)$/) && !foundFirst) {
          if (document.getElementById(thisID) != null) {
        	  if (document.getElementById(thisID).disabled == false) {
        		  document.getElementById(thisID).focus = true;
        		  foundFirst=true;
        		}
          }
        }
        if (thisRequired == "true") {
          // If any standard field type.
    	    if (regexCheck(thisType,/^(textarea|text|file|password|checkbox)$/) || regexCheck(thisType,/^select(-one)?(-multiple)?$/)) {
        		if (document.getElementById(thisID) != null) {
          		thisLabel = "lbl_" + thisID;
            	if (document.getElementById(thisLabel) != null) {
            	  if (document.getElementById(thisAstName)) {
            	    // If the span exists, just put back the *
            	    thisAsterisk.innerHTML = "*";
            	  } else {
            	    // Otherwise put in a * within the proper span tags
            	    thisReplace = document.getElementById(thisLabel);
            	    thisReplace.innerHTML = thisReplace.innerHTML + '<span class="redAsterisk" id="' + thisAstName + '">*</span>';
                }
            	}
        		}
        	} else {
            // If radio or checkbox fields.
            if (document.getElementById(thisID) != null) {
          		thisLabel = "lbl_" + thisID;
            	if (document.getElementById(thisLabel) != null) {
            	  if (document.getElementById(thisAstName)) {
            	    // If the span exists, just put back the *
            	    thisAsterisk.innerHTML = "*";
            	  } else {
            	    // Otherwise put in a * within the proper span tags
            	    thisReplace = document.getElementById(thisLabel);
            	    thisReplace.innerHTML = thisReplace.innerHTML + '<span class="redAsterisk" id="' + thisAstName + '">*</span>';
                }
            	}
            }
        	}
        }
    	} /* This form element - with */
    } /* Done looping through form elements */
  }
  /* Show any "pending" error/info messages. */
  var thisAlertBox = document.getElementById("alertBox");
  if (thisAlertBox) {
    if (dispMsg && thisAlertBox.style.display == "none") {
      showPendingErrors();
      showPendingInfo();
    }
  } // thisAlertBox exists

}

function showPendingErrors() {
  var pendErrors = document.getElementById("pendingErrors");
  if (!pendingErrorsShown && pendErrors) {
    if (document.getElementById("alertBox")) {
      showErrMsg(pendErrors.innerHTML);
    } else {
      pendErrors.style.display = "block";
    }
    pendingErrorsShown = true;
  }
}

// Override this var to force an alert box instead of inline messages
// Only applies to messages shown within the standard form pane
var forceErrorAlert = false;

function showErrMsg(myMessage) {
  var thisAlertBox = document.getElementById("alertBox");
  if (myMessage != "") {
    if (thisAlertBox && !forceErrorAlert) {
   	  thisAlertBox.innerHTML = "<span class='error'>" + myMessage + "</span><br/>" + thisAlertBox.innerHTML;
   	  thisAlertBox.style.display = "block";
   	  thisAlertBox.scrollIntoView();
    } else {
      showMsgBox(myMessage);
    }
  } else {
    if (thisAlertBox) {
      thisAlertBox.style.display = "none";
   	  thisAlertBox.innerHTML = "";
    }
  }
}

function showPendingInfo() {
  var pendInfo = document.getElementById("pendingInfo");
  if (!pendingInfoShown && pendInfo) {
    if (document.getElementById("alertBox")) {
      showInfoMsg(pendInfo.innerHTML);
    } else {
      pendInfo.style.display = "block";
    }
    pendingInfoShown = true;
  }
}

// Override this var to force an alert box instead of inline messages
// Only applies to messages shown within the standard form pane
var forceInfoAlert = false;

function showInfoMsg(myMessage) {
  var thisAlertBox = document.getElementById("alertBox");
  if (myMessage != "") {
    if (thisAlertBox && !forceInfoAlert) {
   	  thisAlertBox.innerHTML = "<span class='alert'>" + myMessage + "</span><br/>" + thisAlertBox.innerHTML;
   	  thisAlertBox.style.display = "block";
    } else {
      showMsgBox(myMessage);
    }
  } else {
    if (thisAlertBox) {
      thisAlertBox.style.display = "none";
   	  thisAlertBox.innerHTML = "";
    }
  }
}

function showPendingAlerts() {
  var pendAlert = document.getElementById("pendingAlert");
  if (!pendingAlertsShown && pendAlert) {
    showMsgBox(pendAlert.innerHTML);
    pendingAlertshown = true;
  }
}

// Override this var to show the fancier alert box
var showFancyAlert = false;
function showMsgBox(myText) {
  if (showFancyAlert) {
    createCustomAlert(myText);
  } else {
    alert(myText);
  }
}

// disableFields("fld1[,fld2,fld3,fldN]") : Disable specific form fields
function disableFields(flds) {
  var fld_array = flds.split(",");
  for (ix=0; ix<fld_array.length; ix++) {
    if (fld_array[ix] != "") {
      var fld = document.getElementsByName(fld_array[ix]);
      if (fld && fld != null) {
        for (iy=0; iy<fld.length; iy++) {
          if (fld[iy] != null)
            fld[iy].disabled=true;
        }
      }
    }
  }
}

// enableFields("fld1[,fld2,fld3,fldN]") : Enable specific form fields
function enableFields(flds) {
  var fld_array = flds.split(",");
  for (ix=0; ix<fld_array.length; ix++) {
    if (fld_array[ix] != "") {
      var fld = document.getElementsByName(fld_array[ix]);
      if (fld && fld != null) {
        for (iy=0; iy<fld.length; iy++) {
          if (fld[iy] != null)
            fld[iy].disabled=false;
        }
      }
    }
  }
}

// disableButton(btn1,[btn2,btn3,btnN]) : Disable specific form buttons
function disableButton(btns) {
  btn_array = btns.split(",");
  for (ix=0; ix<btn_array.length; ix++) {
    btn = document.getElementsByName(btn_array[ix]);
    if (btn != null) {
      for (iy=0; iy<btn.length; iy++) {
        if (btn[iy] != null)
          btn[iy].disabled=true;
      }
    }
  }
}

// resizeFields(maxWidth,fld0,"[fld1,fld2,fldN]") : Resize the listed fields, using the max width or the start field
function resizeFields(maxWidth,startField,fieldList) {
  var newWidth = 0;
  var initObj = document.getElementById(startField);
  if (!initObj) { return false; } // Exit if field is unavailable.

  // Find the width of the initial field, and ensure it doesn't surpass the maximum width.
  if (initObj.clientWidth > 0) { newWidth = initObj.clientWidth + 3; }
  if (newWidth == 0 && initObj.width > 0) { newWidth = initObj.width + 3; }
  if (newWidth == 0 && initObj.style.pixelWidth > 0) { newWidth = initObj.style.pixelWidth + 3; }
  if (newWidth == 0 || newWidth > maxWidth) { newWidth = maxWidth; }

  // Assign the new width to all of the selected fields.
  var fieldArray = fieldList.split(",");
  for (ix=0; ix<fieldArray.length; ix++) {
    if (fieldArray[ix] != "") {
      var thisField = document.getElementById(fieldArray[ix]);
      if (thisField && thisField != null) {
        thisField.style.pixelWidth = newWidth;
      }
    }
  }
}

// checkFieldChange(myForm) : Checks if fields have been modified, returns list of changed fields.
function checkFieldChange(myForm) {
  var i, temp;
  var changedFields = new Array();
  for (i=0; i<myForm.length; i++) {
    temp = myForm.elements[i];
    if (temp.type == "radio") {
      if (temp.defaultChecked) {
      	if (!temp.checked) {
          changedFields.push(temp.id);
        }
      } else {
      	if (temp.checked) {
          changedFields.push(temp.id);
        }
      }
    } else if (temp.type == "checkbox") {
      if (temp.defaultChecked) {
        if (!temp.checked) {
          changedFields.push(temp.id);
        }
      } else {
      	if (temp.checked) {
          changedFields.push(temp.id);
      	}
      }
    } else if(temp.type == "select-one" || temp.type == "select-multiple") {
      var m;
      for (m = 0; m < temp.length; m++) {
        if (temp.options[m].defaultSelected) {
          if (!temp.options[m].selected) {
            changedFields.push(temp.id);
          }
        }
      }
    } else if (temp.type == "text" || temp.type == "textarea") {
      if (temp.value != temp.defaultValue) {
        changedFields.push(temp.id);
      }
    }
  } // end looping
  if (changedFields.length == 0) {
    return false;
  } else {
    return changedFields;
  }
}

/* this portion by S.E. Southwell - BravePoint, Inc. Use as desired, but retain this notice */
function ValidateForm(myForm,silent) {
    var messages = new Array();
    var thisValidation;
    var thisFailMessage;
    var failedValidation;
    var thisRequired;
    var thisTitle;
    var thisType;
    var thisName;
    var thisID;
    var radioSets = new Array();
    var numRadioSets = 0;
    var msgcount = 0;
    var badcount = 0;
    var myReturn = true;
    for (var i=0; i<myForm.length; i++) {
      with (myForm.elements[i]) {
    	  thisID = getAttribute('id');
    	  thisValidation = getAttribute('valtype');
    	  thisFailMessage = getAttribute('failmsg');
    	  thisRequired = getAttribute('req') || "false";
    	  thisType = getAttribute('type');
    	  thisTitle = getAttribute('title');
    	  if (thisTitle == null || thisTitle == "") { thisTitle = myForm.elements[i].name; }
    	  if (!regexCheck(thisType,/^(hidden|button|reset|submit)$/)) {
           /* If text or unknown, but requires validation... */
           if (thisValidation != null && (regexCheck(thisType,/^(.*area|text|file|password)$/) || thisType == "")) {
              /* Let's make sure HTML is escaped properly. */
              if (regexCheck(thisValidation,/^(Alpha|Alphanumeric|FreeForm)$/) && thisType != "file") {
                value = value.replace(/\</g,"&lt;");
                value = value.replace(/\>/g,"&gt;");
              }
              /* If the field is required, or they've typed something,
                 then we need to run the validation checks on the field. */
              if (value != "" || thisRequired == "true") {
                /* If field fails RegEx check, or is a date and fails the date check... */
                if (!regexCheck(value,eval(thisValidation)) ||
                   (thisValidation == "DateFull" && !isValidDate(value))) {
                  failedValidation = true;
                } else {
                  failedValidation = false;
                }
              } else {
                failedValidation = false;
              }
              /* If it doesn't match our pattern checks, then throw an error. */
              if (failedValidation) {
                  if (thisFailMessage != null && thisFailMessage != "") {
                  	messages[msgcount] = thisTitle + ": " + thisFailMessage;
                  } else {
                  	messages[msgcount] = thisTitle + ": Please enter a correct value into this field";
                  }
                  msgcount++;
                  badcount++;
                  myReturn = false;
                  if (!silent) {
                    if (badcount == 1 && myForm.elements[i].disabled == false) {
                      myForm.elements[i].focus = true;
                    }
                    myForm.elements[i].style.borderColor = "#DD3333";
                  }
              } else {
                  myForm.elements[i].style.borderColor = "#CCCCCC";
              }
           } else {
          	/* There was no validation type on this field;
          	   This is mainly for selections/radios/checkboxes */
              if (thisRequired == "true" && (value == "" ||
                 (regexCheck(thisType,/^select/) && options[selectedIndex].value == ""))) {
                  /* Field is required but does not have any value present */
                  if (thisFailMessage != null && thisFailMessage != "") {
                  	messages[msgcount] = thisTitle + ": " + thisFailMessage;
                  } else {
                  	messages[msgcount] = thisTitle + ": Please enter/select a correct value for this field";
                  }
                  msgcount++;
                  badcount++;
                  myReturn = false;
                  if (!silent) {
                  	if (badcount == 1 && myForm.elements[i].disabled == false) {
                  	  myForm.elements[i].focus = true;
                  	}
                    if (regexCheck(thisType,/^select/) && myForm.elements[i].parentNode.nodeName == "SPAN") {
                      myForm.elements[i].parentNode.style.backgroundColor = "#DD3333";
                    } else {
                      myForm.elements[i].style.borderColor = "#DD3333";
                    }
                  }
              } else {
                  if (regexCheck(thisType,/^select/) && myForm.elements[i].parentNode.nodeName == "SPAN") {
                    myForm.elements[i].parentNode.style.backgroundColor = "#E0E0E0";
                  } else {
                    myForm.elements[i].style.borderColor = "#CCCCCC";
                  }
              }
              /* Just grab the names of the required radiosets, parse later */
              if (thisRequired == "true" && thisType == "radio") {
          		    radioSets[numRadioSets] = eval(myForm.elements[i]);
          		    numRadioSets++;
              }
              /* Make sure any required checkboxes are checked */
              if (thisRequired == "true" && thisType == "checkbox" && !myForm.elements[i].checked) {
                 if (thisFailMessage != null && thisFailMessage != "") {
                   messages[msgcount] = thisTitle + ": " + thisFailMessage;
                 } else {
                   messages[msgcount] = thisTitle + ": This checkbox should be selected";
                 }
                 msgcount++;
                 badcount++;
                 if (badcount == 1 && myForm.elements[i].disabled == false) {
                   myForm.elements[i].focus = true;
                 }
                 myReturn = false;
              }
           }
        } /* If Not a Button */
      } /* End With - this form element */
    } /* Done looping through form elements */

    /* We have to parse the radio sets last, now that we know which are required */
    if (numRadioSets > 0) {
        var lastRadio;
        var nextRadio;
        var selectedYet = false;

      	for (var i=0; i<radioSets.length; i++) {
  	    /* Update the "last" radioset name,
  	       then check for the next set name */
    	    lastRadio = radioSets[i].name;
    	    if (i+1 < radioSets.length) { nextRadio = radioSets[i+1].name; } else { nextRadio = "null"; }

    	    /* Do we have a selected value yet? */
    	    if (radioSets[i].checked) {
    		      selectedYet = true;
    	    }

    	    /* If the next radio set is different, make sure we get the name of our current set */
    	    if (radioSets[i].name != nextRadio) {
        		thisFailMessage = radioSets[i].getAttribute('failmsg');
        		thisTitle = radioSets[i].getAttribute('title');
        		if (thisTitle == null || thisTitle == "") { thisTitle = radioSets[i].name; }
           		/* If we still don't have anything selected,
          		   and we're on the last item of this radioset,
          		   then nothing was selected; set the error msg */
         		if (!selectedYet) {
         		    if (thisFailMessage != null && thisFailMessage != "") {
         			    messages[msgcount] = thisTitle + ": " + thisFailMessage;
         		    } else {
         			    messages[msgcount] = thisTitle + ": Please select one of the available values.";
         		    }
         		    msgcount++;
         		    badcount++;
         		    if (badcount == 1) radioSets[i].focus = true;
         		    myReturn = false;
         		    selectedYet = false;
         		} else {
         		    /* We're moving to the next radioset, set the default */
         		    selectedYet = false;
         		}
    	    } /* If not part of the next radio set */
    	  } /* Done cycling radio sets */
    } /* If number of radio sets > 0 */

    /* Display any error messages, if not silent */
    if (myReturn == false) {
      var myMessage = "There was a problem submitting this page. \nPlease correct the errors below and try again: \n\n";
      if (document.getElementById("alertBox")) {
        thisErrorBox = document.getElementById("alertBox");
        thisErrorBox.innerHTML = "";
        showPendingErrors();
        if (!silent) {
          thisErrorBox.style.display = "block";
        }
        if (FormErrorMsg && FormErrorMsg != "") {
          myMessage = "<span class='error'>" + FormErrorMsg + "</span><br/>";
        } else {
          myMessage = "<span class='error'>Please correct the errors below and try again.</span><br/>";
        }
        var split_array;
        for (i=0;i<messages.length;i++) {
            if (messages.length == 1) {
              myMessage = myMessage.replace(/fields are/g,"field is");
              myMessage = myMessage.replace(/fields/g,"field");
              myMessage = myMessage.replace(/errors/g,"error");
            }
            // Get just the field portion (field:message), since we know the message already
            split_array = messages[i].split(":");
            if (messages.length > 3) {
              if (messages[i] != null) myMessage = myMessage + "<span style='width:33%;'>&nbsp;-" + split_array[0] + "&nbsp;&nbsp;</span>";
              if (((i + 1) % 3) == 0) { myMessage = myMessage + "<br/>"; }
            } else {
              if (messages[i] != null) myMessage = myMessage + "<span style='width:99%;'>&nbsp;-" + split_array[0] + "&nbsp;&nbsp;</span><br/>";
            }
        }
     	  thisErrorBox.innerHTML = thisErrorBox.innerHTML + myMessage;
     	  if (!silent) {
     	    thisErrorBox.scrollIntoView();
     	  }
      } else {
        for (i=0;i<messages.length;i++) {
            if (messages[i] != null) myMessage = myMessage + messages[i] + "\n";
        }
        if (!silent) {
          alert(myMessage,1000);
        }
      }
      // If the validation failed, we must stop any other events from firing on the page.
      var evt = window.event;
      stopProcessing(evt);
      stopWait();
    } else {
      showErrMsg("");
      showPendingErrors();
    }
    return myReturn;
}
/* end of ValidateForm */

 // Validation for a particular field using a given list of values.
  function ValidateField(myField,myList) {  
    var arrayFields = myList.split(",");
    var thisField = getHdl(myField);   
    var thisString = thisField.value.toUpperCase();
    thisString = stripCharsInBag(thisString,' ');
    var myMessage;   
    if (thisField && thisField.style.visibility != "hidden" && thisField.disabled != true) {
      for (var i=0; i<arrayFields.length; i++) {
        if (thisString == arrayFields[i]) {
          thisField.style.borderColor = "#DD3333";     
          if (document.getElementById("alertBox")) {
            thisErrorBox = document.getElementById("alertBox");
            showPendingErrors();
            thisErrorBox.style.display = "block";
          }                   
          myMessage = "<span style='width:33%;'>&nbsp;-" + thisField.title + "&nbsp;&nbsp;</span>";  
          if ((FormErrorMsg && ( FormErrorMsg == '' || FormErrorMsg == null)) || (thisErrorBox.innerHTML == '')) {
            if (FieldErrorMsg && FieldErrorMsg != '') {
              myMessage = "<span class='error'>" + FieldErrorMsg + "</span><br/>" + myMessage;
            } 
          }        
         	thisErrorBox.innerHTML = thisErrorBox.innerHTML + myMessage;
          return false;      
        }
      } // for
    }  
    return true;
  } // function Validatefield
  
function clearRequiredHighlighting(myForm,silent) {
  var thisValidation;
  var thisRequired;
  var thisType;
  var thisID;
  for (var i=1; i<myForm.length; i++) {
    with (myForm.elements[i]) {
  	  thisID = getAttribute('id');
  	  thisValidation = getAttribute('valtype');
  	  thisRequired = getAttribute('req') || "false";
  	  thisType = getAttribute('type');
  	  if (!regexCheck(thisType,/^(hidden|button|reset|submit)$/)) {
         /* If text or unknown, but requires validation... */
         if (thisValidation != null && (regexCheck(thisType,/^(textarea|text|file|password)$/) || thisType == "")) {
            myForm.elements[i].style.borderColor = "#CCCCCC";
         } else {
        	/* There was no validation type on this field;
        	   This is mainly for selections/radios/checkboxes */
            if (thisRequired == "true" ) {
                /* Field is required but does not have any value present */
                if (regexCheck(thisType,/^select/) && myForm.elements[i].parentNode.nodeName == "SPAN") {
                  myForm.elements[i].parentNode.style.backgroundColor = "#E0E0E0";
                } else {
                  myForm.elements[i].style.borderColor = "#CCCCCC";
                }
            } // was required
         } //not text/textarea/password
      } /* If Not a Button */
    } /* End With - this form element */
  } /* Done looping through form elements */
  return true;
}
/* end of ClearRequiredHighlighting */

/* Date-checking functions */
function isValidDate(dateVal) {
  var dateArray = dateVal.split('\/');
  var month = parseInt(dateArray[0]);
  var day = parseInt(dateArray[1]);
  var year = parseInt(dateArray[2]);
  var validDays;
  // 30 days has Sep., Apr., Jun., and Nov.; all the rest have 31, except for Feb. with 28 (or 29 every 4 years).
  if (year > 1582 && isLeapYear(year)) {
    validDays = new Array(31,29,31,30,31,30,31,31,30,31,30,31);
  } else {
    validDays = new Array(31,28,31,30,31,30,31,31,30,31,30,31);
  }
  if (day > validDays[month-1]) {
    // If the given day of the month exceeds the standard max, return false.
    return false;
  }
  return true;
}

function isLeapYear(numYear) {
  // (a) If the number of the year is divisible by 4 then the year is a Leap Year, except
  // (b) If the number of the year ends in 00 then the year is not a leap year; however
  // (c) If the number of the year ends in 00 and the year is divisible by 400 the year is a Leap Year.
  return ( (numYear % 4) == 0 && ((numYear % 100) != 0 || (numYear % 400) == 0) );
}

function isFirstDateLater(firstDate,secondDate) {
  // First Date
  var dateArray1 = firstDate.split('\/');
  var month1 = parseFloat(dateArray1[0]);
  var day1 = parseFloat(dateArray1[1]);
  var year1 = parseFloat(dateArray1[2]);
  // Second Date
  var dateArray2 = secondDate.split('\/');
  var month2 = parseFloat(dateArray2[0]);
  var day2 = parseFloat(dateArray2[1]);
  var year2 = parseFloat(dateArray2[2]);
  // Create date objects
  var date1_obj = new Date(year1, month1, day1);
  var date2_obj = new Date(year2, month2, day2);
  // Compare the dates

  if (date1_obj > date2_obj) {
    return true;
  } else {
    return false;
  }
}
/* end date-checking functions */

/* Apply 999-99-9999 mask to SSN as it's typed in. */
function handleSSNMask(myField) {
  var myWait = predictKeypress();
  window.clearTimeout(hTimeOut);
  hTimeOut = setTimeout("hdlSSNMask(document.getElementById('" + myField.id + "'));",myWait);
}
function hdlSSNMask(myField) {
  for (i=0; i<myField.value.length; i++) {
    if (isNaN(parseInt(myField.value.substr(i,1))) || myField.value.substr(i,1) == "-") {
      myField.value = myField.value.substr(0,i) + myField.value.substr((i + 1));
      i = i - 1;
    }
  }
  if (myField.value.length > 3) {
    myField.value = myField.value.substr(0,3) + "-" + myField.value.substr(3);
  }
  if (myField.value.length > 6) {
    myField.value = myField.value.substr(0,6) + "-" + myField.value.substr(6);
  }
  resetKeypress();
}
/* End SSN Mask */

/* Apply number-only mask to any numeric field as it's typed in. */
function handleDigitMask(myField) {
  var myWait = predictKeypress();
  window.clearTimeout(hTimeOut);
  hTimeOut = setTimeout("hdlDigitMask(document.getElementById('" + myField.id + "'));",myWait);
}
function hdlDigitMask(myField) {
  var exp;
  for (i=0; i<myField.value.length; i++) {
    if (isNaN(parseInt(myField.value.substr(i,1))) && myField.value.substr(i,1) != ".") {
      expand = ""
      if (myField.value.substr(i,1) == "k" || myField.value.substr(i,1) == "K") { expand = "000"; }
      if (myField.value.substr(i,1) == "m" || myField.value.substr(i,1) == "M") { expand = "000000"; }
      myField.value = myField.value.substr(0,i) + expand + myField.value.substr((i + 1));
      i = i - 1;
    }
  }
  resetKeypress();
}
/* End Number Mask */

/* Apply strict alpha-numeric mask for usernames. */
function handleUNameMask(myField) {
  var myWait = predictKeypress();
  window.clearTimeout(hTimeOut);
  hTimeOut = setTimeout("hdlUNameMask(document.getElementById('" + myField.id + "'));",myWait);
}
function hdlUNameMask(myField) {
  for (i=0; i<myField.value.length; i++) {
    if (!regexCheck(myField.value.substr(i,1),Alpha) && !regexCheck(myField.value.substr(i,1),Numeric)) {
      myField.value = myField.value.substr(0,i) + myField.value.substr((i + 1));
      i = i - 1;
    }
  }
  resetKeypress();
}
/* End UName Mask */

/* Apply 999,999,...[.99] mask to Number as it's typed in. */
function handleGroupedDigitMask(myField) {
  var maxDecimals = 99; // By default we allow unlimited decimal places.
  if (arguments.length >= 2) { maxDecimals = arguments[1]; }
  var myWait = predictKeypress();
  window.clearTimeout(hTimeOut);
  if (maxDecimals != 99) {
    hTimeOut = setTimeout("hdlGroupedDigitMask(document.getElementById('" + myField.id + "')," + maxDecimals +");",myWait);
  } else {
    hTimeOut = setTimeout("hdlGroupedDigitMask(document.getElementById('" + myField.id + "'));",myWait);
  }
}
function hdlGroupedDigitMask(myField) {
  var maxDecimals = 99; // By default we allow unlimited decimal places.
  var thisValidation = myField.getAttribute('valtype');
  var isNegative = false;
  if (arguments.length >= 2) { maxDecimals = arguments[1]; }
  // This should just strip out the invalid characters, leaving us with only digits 0-9 and "," and a single "."
  myField.value = myField.value.replace(/\.+/g,".");
  if (myField.value < 0) { isNegative = true; } // Check this before stripping out non-digit characters.
  for (i=0; i<myField.value.length; i++) {
    if (myField.value.substr(i,1) != "." && (isNaN(parseInt(myField.value.substr(i,1))) || myField.value.substr(i,1) == ",")) {
      expand = ""
      if (myField.value.substr(i,1) == "k" || myField.value.substr(i,1) == "K") { expand = "000"; }
      if (myField.value.substr(i,1) == "m" || myField.value.substr(i,1) == "M") { expand = "000000"; }
      myField.value = myField.value.substr(0,i) + expand + myField.value.substr((i + 1));
      i = i - 1;
    }
  }
  // We HAVE to go backwards (right-to-left) in order to group the digits properly.
  var rawString = myField.value;
  var finalGrouping = "";
  var tmpCount = 0;
  var decPoint = rawString.indexOf(".");
  for (i=myField.value.length; i>0; i--) {
    if (decPoint == -1 || (decPoint >= 0 && i <= decPoint)) {
      // Everything from the decimal point, left.
      if (tmpCount == 3) {
        finalGrouping = myField.value.substr(i-1, 1) + "," + finalGrouping;
        tmpCount = 0;
      } else {
        finalGrouping = myField.value.substr(i-1, 1) + finalGrouping;
      }
      tmpCount++;
    } else {
      // Everything including the decimal point, right.
      if (i > decPoint && i <= (decPoint + 1 + maxDecimals)) {
        finalGrouping = myField.value.substr(i-1, 1) + finalGrouping;
      }
    }
  }
  if (thisValidation == "Currency") { finalGrouping = padZeroes(finalGrouping); }
  if (isNegative) { finalGrouping = "-" + finalGrouping; }
  myField.value = finalGrouping;
  resetKeypress();
}
function padZeroes(myValue) {
  // This will pad a value with a maximum of 2 zeroes, as needed by valtypes such as Currency.
  decPoint = myValue.indexOf(".");
  var newValue = myValue;
  if (decPoint > 0) {
    var startPoint = decPoint + 1;
    var lastDigits = myValue.substr(startPoint);
    if (lastDigits.length < 2) {
      // The currency type requires 2 decimal places, so we should pad with zero's as needed.
      if (lastDigits.length == 1) { newValue = newValue + "0"; }
      if (lastDigits.length == 0) { newValue = newValue + "00"; }
    }
  }
  return newValue;
}
/* End Grouped Digits Mask */

/* Apply 99999-9999 mask to Zip Code as it's typed in. */
function handleZipMask(myField) {
  var myWait = predictKeypress();
  window.clearTimeout(hTimeOut);
  hTimeOut = setTimeout("hdlZipMask(document.getElementById('" + myField.id + "'));",myWait);
}
function hdlZipMask(myField) {
  for (i=0; i<myField.value.length; i++) {
    if (isNaN(parseInt(myField.value.substr(i,1))) || myField.value.substr(i,1) == "-") {
      myField.value = myField.value.substr(0,i) + myField.value.substr((i + 1));
      i = i - 1;
    }
  }
  if (myField.value.length > 5) {
    myField.value = myField.value.substr(0,5) + "-" + myField.value.substr(5);
  }
  resetKeypress();
}
/* End Zip Mask */

/* Apply 99/99/9999 mask to Date as it's typed in. */
function handleDateMask(myField) {
  var myWait = predictKeypress();
  window.clearTimeout(hTimeOut);
  hTimeOut = setTimeout("hdlDateMask(document.getElementById('" + myField.id + "'));",myWait);
}
function hdlDateMask(myField) {
  for (i=0; i<myField.value.length; i++) {
    if (isNaN(parseInt(myField.value.substr(i,1))) || myField.value.substr(i,1) == "/") {
      myField.value = myField.value.substr(0,i) + myField.value.substr((i + 1));
      i = i - 1;
    }
  }
  if (myField.value.length > 2) {
    myField.value = myField.value.substr(0,2) + "/" + myField.value.substr(2);
  }
  if (myField.value.length > 5) {
    myField.value = myField.value.substr(0,5) + "/" + myField.value.substr(5);
  }
  resetKeypress();
}
/* End Date Mask */

/* Apply (999) 999-9999 mask to Phone/Fax as it's typed in. */
function handlePhoneMask(myField) {
  var myWait = predictKeypress();
  window.clearTimeout(hTimeOut);
  hTimeOut = setTimeout("hdlPhoneMask(document.getElementById('" + myField.id + "'));",myWait);
}
function hdlPhoneMask(myField) {
  for (i=0; i<myField.value.length; i++) {
    if (isNaN(parseInt(myField.value.substr(i,1))) || myField.value.substr(i,1) == "-" ||
        myField.value.substr(i,1) == "(" || myField.value.substr(i,1) == ")" ||
        myField.value.substr(i,1) == " ") {
      myField.value = myField.value.substr(0,i) + myField.value.substr((i + 1));
      i = i - 1;
    }
  }
  if (myField.value.length > 1) {
    myField.value = "(" + myField.value;
  }
  if (myField.value.length > 4) {
    myField.value = myField.value.substr(0,4) + ") " + myField.value.substr(4);
  }
  if (myField.value.length > 9) {
    myField.value = myField.value.substr(0,9) + "-" + myField.value.substr(9);
  }
  if (myField.value.length > 14) {
    myField.value = myField.value.substr(0,14) + " " + myField.value.substr(14);
  }
  resetKeypress();
}
/* End Phone/Fax Mask */

/* Apply 99:99:99 mask to Time as it's typed in. */
function handleTimeMask(myField) {
  var myWait = predictKeypress();
  window.clearTimeout(hTimeOut);
  hTimeOut = setTimeout("hdlTimeMask(document.getElementById('" + myField.id + "'));",myWait);
}
function hdlTimeMask(myField) {
  with (myField) {
    for (i=0; i<value.length; i++) {
      if (isNaN(parseInt(value.substr(i,1))) || value.substr(i,1) == ":") {
        value = value.substr(0,i) + value.substr((i + 1));
        i = i - 1;
      }
    }
    if (value.length == 3) value = value.substr(0,1) + ":" + value.substr(1);
    else if (value.length > 3) value = value.substr(0,2) + ":" + value.substr(2);
    if (value.length > 5) value = value.substr(0,5) + ":" + value.substr(5);
  } // myField
  resetKeypress();
}
/* End Time Mask */

// Set a global flag that indicates this library has been loaded by the browser.
var LIB_FORMVAL_LOADED = true;

// End library
