// ---------------------------------------------------------------------------
//  Filename: validate.js
//   Version: 3.0
//      Date: 12/3/2007
//    Author: B. Zink
//   Purpose: Miscellaneous utility javascript functions
// ---------------------------------------------------------------------------
// Copyright© 2004-2010 Brz, Inc. All Rights Reserved
// ---------------------------------------------------------------------------
// Note: NO portion of this code may be copied, manipulated, viewed, or used
//       in ANY way without express written permission of the author and
//       BRZ, Inc.
// ---------------------------------------------------------------------------
// Revisions:
//
// 1. 12/3/2007 - bz
//    3.0.0 - Initial creation
// ---------------------------------------------------------------------------

// ---------------------------------------------------------------------------
// These names MUST match the same names in defines.inc.php (a php file) to insure
// that javascript validation is properly performed/created by php output.
//
// Validation occurs automatically based on the HTML name that is created by
// PHP and output to the HTML field name in the form. A typical name:
//
//    checkeeId___nu___rq___Pilot_Needing_Checkride
//
// This long name is split into four(4) parts:
//
//    checkeeId         - typically a short name from a datatable column
//    nu                - this is a numeric field entry
//    rq                - this is a required field
//    Pilot_Needing_C.. - 'Friendly' name for displaying error information
// ---------------------------------------------------------------------------
var VALID_SEPARATOR        = "___";
var VALID_RANGE_SEPARATOR  = "_";
var VALID_DATE             = "dt";  
var VALID_TIME             = "tm";  
var VALID_NUMBER           = "nu";  
var VALID_FLOAT            = "fl";  
var VALID_LETTER           = "lt";  
var VALID_ALPHA            = "al";  
var VALID_PHONE            = "ph";  
var VALID_TEXTAREA         = "ta";  
var VALID_CHECKBOX         = "cb";  
var VALID_RADIO            = "ra";  
var VALID_NA               = "na";  
var VALID_REQUIRED         = "rq";  
var VALID_NOTREQUIRED      = "nr";  
var VALID_REVIEW           = "rv";
var DATA_SEPARATOR         = "__";


var SPECIAL_COMMA          = "x";
var SPECIAL_PERIOD         = "y";
var SPECIAL_SLASH          = "z";

var CATEGORY_TITLE         = "category";
var SUBJECT_TITLE          = "subject";
var ALLOWPASTDATES         = 12500;


// ---------------------------------------------------------------------------
// IsBlank 
//
//      Purpose: Determine if a string is blank - replaces all spaces with null
// ---------------------------------------------------------------------------
function IsBlank ( string )
{
   // ------------------------------------------------------------------------
   // if there is a string length, replace all spaces with nulls
   // ------------------------------------------------------------------------
   if (string.length > 0) {
      var str = Replace(string, ' ', '');              
      // ---------------------------------------------------------------------
      // no nulls, if string still has length, must not be blank
      // ---------------------------------------------------------------------
      if (str.length > 0) 
         return false;    
   }    
   
   // ------------------------------------------------------------------------
   // string is blank
   // ------------------------------------------------------------------------
   return true;
}

// ---------------------------------------------------------------------------
// CheckValid 
//
//      Purpose: Determine if a string has valid characters
// ---------------------------------------------------------------------------
function CheckValid ( string, validString )
{
   // ------------------------------------------------------------------------
   // look at each character to see if it is in valid string
   // ------------------------------------------------------------------------
   for ( var i=0; i<string.length; i++ ) {
      if (validString.indexOf(string.charAt(i)) < 0) {
         return false;        
      }
   }  
   
   // ------------------------------------------------------------------------
   // must be valid
   // ------------------------------------------------------------------------
   return true;
}

// ---------------------------------------------------------------------------
// CheckValidRange
//
//      Purpose: Determine if value is in proper range
// ---------------------------------------------------------------------------
function CheckValidRange ( number, start, stop )
{
   // ------------------------------------------------------------------------
   // force all parameters to be numeric
   // ------------------------------------------------------------------------
   var value   = parseInt(number,10);
   var range1  = parseInt(start,10);
   var range2  = parseInt(stop,10);
   
   // ------------------------------------------------------------------------
   // check for valid range
   // ------------------------------------------------------------------------
   return ( value >= range1 && value <= range2 );
}

// ---------------------------------------------------------------------------
// IsNumeric
//
//      Purpose: Determine if a string has only numeric characters
// ---------------------------------------------------------------------------
function IsNumeric ( string, decimal, sign )
{
   // ------------------------------------------------------------------------
   // allow/disallow decimal,sign
   // ------------------------------------------------------------------------
   switch (arguments.length ) {
      case 1: decimal = 1;
      case 2: sign    = 0;
         break;
   }
   
   // ------------------------------------------------------------------------
   // setup valid numbers and get the length of the string
   // ------------------------------------------------------------------------
   var validString   =  "0123456789";
   
   // ------------------------------------------------------------------------
   // if decimal desired, then allow it ( off by default )
   // ------------------------------------------------------------------------
   if ( decimal ) {
      validString = validString + '.';
   }
   
   // ------------------------------------------------------------------------
   // if sign desired, then allow it ( off by default )
   // ------------------------------------------------------------------------
   if ( sign ) {
      validString = validString + '-';
   }
   
   // ------------------------------------------------------------------------
   // look at each number determine if it is a "valid" number
   // ------------------------------------------------------------------------
   return CheckValid( string, validString);
}

// ---------------------------------------------------------------------------
// IsPhone
//
//      Purpose: Determine if a string has phone number chars
// ---------------------------------------------------------------------------
function IsPhone (string)
{
   // ------------------------------------------------------------------------
   // allow decimal or dash as separator
   // ------------------------------------------------------------------------
   var decimal = 1;
   var sign    = 1;
   
   // ------------------------------------------------------------------------
   // do numeric validation with decimal allowed
   // ------------------------------------------------------------------------
   return IsNumeric ( string, decimal, sign );
}

// ---------------------------------------------------------------------------
// IsPhone
//
//      Purpose: Determine if a string has phone number chars
// ---------------------------------------------------------------------------
function IsPhone2 (string)
{
   // ------------------------------------------------------------------------
   // allow decimal or dash as separator
   // ------------------------------------------------------------------------
   var decimal = 1;
   var sign    = 1;
   
   // ------------------------------------------------------------------------
   // NO quotes around the expression
   // ------------------------------------------------------------------------
   var regex = /[0-9]{3}\.[0-9]{3}\.[0-9]{4}/;
   
   // ------------------------------------------------------------------------
   // do regular expression match
   // ------------------------------------------------------------------------
   return string.match(regex);
   
   // ------------------------------------------------------------------------
   // do numeric validation with decimal allowed
   // ------------------------------------------------------------------------
   return IsNumeric ( string, decimal, sign );
}

// ---------------------------------------------------------------------------
// IsAlpha
//
//      Purpose: Determine if a string has letters, number, comma, period, space
// ---------------------------------------------------------------------------
function IsAlpha ( string, spaces, punctuation, quotes )
{
   // ------------------------------------------------------------------------
   // allow default parameter
   // ------------------------------------------------------------------------
   switch ( arguments.length ) {
      case 1: spaces       = 1;
      case 2: punctuation  = 1;
      case 3: quotes       = 1;
   }
   
   // ------------------------------------------------------------------------
   // setup valid characters
   // ------------------------------------------------------------------------
   var validString   =  "0123456789ABCDEFGHIJKLMNOPQRSTUVWXZY";
   
   // ------------------------------------------------------------------------
   // allow spaces if desired
   // ------------------------------------------------------------------------
   if (spaces) {
      validString    = validString + " ";    
   }
   
   // ------------------------------------------------------------------------
   // allow single/double quotes if desired
   // ------------------------------------------------------------------------
   if (quotes) {
      validString    = validString + "\'\"";    
   }
   
   // ------------------------------------------------------------------------
   // allow punctuation if desired
   // ------------------------------------------------------------------------
   if (punctuation) {
      validString    = validString + "!@#$%^&*()-_=+{}[]<>/?;:";    
   }
   
   // ------------------------------------------------------------------------
   // convert to uppercase for comparison
   // ------------------------------------------------------------------------
   string = string.toUpperCase();
   
   // ------------------------------------------------------------------------
   // look at each number determine if it is a "valid" number
   // ------------------------------------------------------------------------
   return CheckValid( string, validString);
}

// ---------------------------------------------------------------------------
// IsLetter
//
//      Purpose: Determine if a string has only letters
// ---------------------------------------------------------------------------
function IsLetter ( string )
{
   var validString = "ABCDEFGHIJKLMNOPQRSTUVWXZY";

   // ------------------------------------------------------------------------
   // force string to upper case for comparison
   // ------------------------------------------------------------------------
   string = string.toUpperCase();
   
   // ------------------------------------------------------------------------
   // look at each character and determine if it is a "valid" letter
   // ------------------------------------------------------------------------
   return CheckValid(string, validString);   
}   

// ---------------------------------------------------------------------------
// IsSlashDate
//
//      Purpose: Determine if a string is a valid date
// ---------------------------------------------------------------------------
function IsSlashDate ( string, rangeString, noFutureDates, pastDaysAllowed )
{
   // ------------------------------------------------------------------------
   // get today
   // ------------------------------------------------------------------------
   var today      = new Date();
   var thisYear   = today.getFullYear();
   
   // ------------------------------------------------------------------------
   // allow default parameter for quotes
   // ------------------------------------------------------------------------
   switch (arguments.length ) {
      case 1:  rangeString       = "";
      case 2:  noFutureDates     = false;
      case 3:  pastDaysAllowed   = ALLOWPASTDATES;
   }
   
   // ------------------------------------------------------------------------
   // 'standard' date format error message
   // ------------------------------------------------------------------------
   var improper   = "Improper Date Format (mm/dd/yyyy) e.g. 11/25/2002\n\n";
   var futureErr  = "Cant enter dates in the future\n\n";

   // ------------------------------------------------------------------------
   // must have at at least 8 characters, or cant be a valid date
   // ------------------------------------------------------------------------
   if ( string.length < 8 ) {
      return new Array(false, improper + "Length not correct - four digit year ?");
   }
      
   // ------------------------------------------------------------------------
   // break the date into the individual parts - must have three parts
   // ------------------------------------------------------------------------
   var parts = string.split("/");
   
   if ( parts.length != 3 ) {
      return new Array(false, improper + "Not separated correctly - check slashes(/)");
   }
   
   // ------------------------------------------------------------------------
   // assign each part to appropriate value
   // ------------------------------------------------------------------------
   var month = parts[0];
   var day   = parts[1];
   var year  = parts[2];

   // ------------------------------------------------------------------------
   // make sure day is numeric and in proper range
   // ------------------------------------------------------------------------
   if (!IsNumeric(day) || parseInt(day,10) > 31 || parseInt(day,10) < 1 ) {
      return new Array(false, improper + "Check \'day\' for improper value\n" +
                "Check range (1-31) or check for letters");
   }
      
   // ------------------------------------------------------------------------
   // make sure month is in correct range
   // ------------------------------------------------------------------------
   if (!IsNumeric(month) || parseInt(month,10) > 12 || parseInt(month,10) < 1 ) {
      return new Array(false, improper + "Check \'month\' for improper value\n" +
                "Check range (1-12) or check for letters");
   }
   
   // ------------------------------------------------------------------------
   // create default start and stop dates for date range
   // ------------------------------------------------------------------------
   var stopDate   = 2021;
   var startDate  = 1971;
      
   var rangeParts = rangeString.split(VALID_RANGE_SEPARATOR);

   // ------------------------------------------------------------------------
   // if range was passed, then parse it to get start/stop dates
   // ------------------------------------------------------------------------
   switch (rangeParts.length) {
      case 1:
         break;
      case 2:
         startDate = parseInt(rangeParts[1],10);
         pastDaysAllowed = ( thisYear - startDate + 1) * 366;
         break;
      case 3:
         startDate = parseInt(rangeParts[1],10);
         stopDate  = parseInt(rangeParts[2],10);
         pastDaysAllowed = ( thisYear - startDate + 1) * 366;
         break;
   }

   // ------------------------------------------------------------------------
   // setup error for past days
   // ------------------------------------------------------------------------
   var pastMsg;
   
   if ( pastDaysAllowed < 90 ) {
      pastMsg = pastDaysAllowed + ' days Maximum';
   }
   else if (pastDaysAllowed < 366 ) {
      var months = parseInt(pastDaysAllowed / 30,10);
      pastMsg = months + ' months Maximum';
   }
   else {
      var years = parseInt(pastDaysAllowed / 365,10);
      pastMsg = years + ' years Maximum';
   }
   
   var pastErr    = 'Date Is Too Far In The Past (' + pastMsg + ')\n\n';
   
   // ------------------------------------------------------------------------
   // insure year is numeric (should be, since it is in a dropdown) and that
   // it is in proper range - defaults to (2000-2021)
   // ------------------------------------------------------------------------
   if ( !IsNumeric(year) || 
      parseInt(year,10) > stopDate || 
      parseInt(year,10) < startDate ) {
      return new Array(false, improper + "Check \'year\' for improper value\n" +
                "Check range (" + startDate + " - " + stopDate +
                ") or check for letters");
   }

   // ------------------------------------------------------------------------
   // build array for days and months - use 13 to start data at one (1)
   // ------------------------------------------------------------------------
   var daysInMonth = new Array(13);
   
   // ------------------------------------------------------------------------
   // hard code number of days in month
   // ------------------------------------------------------------------------
   daysInMonth[1]  = 31; daysInMonth[2]  = 28; daysInMonth[3]  = 31;
   daysInMonth[4]  = 30; daysInMonth[5]  = 31; daysInMonth[6]  = 30;
   daysInMonth[7]  = 31; daysInMonth[8]  = 31; daysInMonth[9]  = 30;
   daysInMonth[10] = 31; daysInMonth[11] = 30; daysInMonth[12] = 31;
   
   // ------------------------------------------------------------------------
   // cheapo calculation for leap year
   // ------------------------------------------------------------------------
   if ( year % 4 == 0 )
      daysInMonth[2] = 29;

   // ------------------------------------------------------------------------
   // build array for month names
   // ------------------------------------------------------------------------
   var months = new Array(13);         

   // ------------------------------------------------------------------------
   // hard code month names
   // ------------------------------------------------------------------------
   months[1]  = "JAN";    months[2]  = "FEB";    months[3]  = "MAR";
   months[4]  = "APR";    months[5]  = "MAY";    months[6]  = "JUN";
   months[7]  = "JUL";    months[8]  = "AUG";    months[9]  = "SEP";
   months[10] = "OCT";    months[11] = "NOV";    months[12] = "DEC";
   
   // ------------------------------------------------------------------------
   // months/ max days in month do not match
   // ------------------------------------------------------------------------
   if ( day > daysInMonth[month] ) {
      return new Array(false, improper + "Check \'day\' for improper range\n" +
               "e.g. There are only " + daysInMonth[month] + 
               " days in " + months[month]);
   }
      
      
   // ------------------------------------------------------------------------
   // get today's date and convert value to date object
   // ------------------------------------------------------------------------
   var date       = new Date(year, month-1, day );          // date entered
   var monthDiff  = 1000 * 60 * 60 * 24 * pastDaysAllowed;  // 30 days default
      
   // ------------------------------------------------------------------------
   // if date is in the future, then notify user and return
   // ------------------------------------------------------------------------
   if ( noFutureDates && (today.getTime() < date.getTime()) ) {
      return new Array(false, futureErr + 
               "Check \'year\' and/or \'month\' for improper value\n" );
   }
   
   // ------------------------------------------------------------------------
   // if more than 30 days in the past, notify user
   // ------------------------------------------------------------------------
  
   if ( date.getTime() < (today.getTime() - monthDiff) ) {
      return new Array(false, pastErr + 
               "Check \'year\' and/or \'month\' for improper value\n" );
   }
   
   // ------------------------------------------------------------------------
   // good date
   // ------------------------------------------------------------------------
   return new Array(true,'');
}

// ---------------------------------------------------------------------------
// IsTime
//
//      Purpose: Determine if a string is a valid time
// ---------------------------------------------------------------------------
function IsTime ( string, delimiter )
{
   // ------------------------------------------------------------------------
   // allow default parameter for delimiter
   // ------------------------------------------------------------------------
   if ( arguments.length != 2 ) {
      delimiter = ":";
   }
   
   // ------------------------------------------------------------------------
   // 'standard' date format error message
   // ------------------------------------------------------------------------
   var improper   = "Improper Time Format (HH:MM - 24 hour) e.g. 22:10\n\n";

   // ------------------------------------------------------------------------
   // setup valid numbers and get the length of the string
   // ------------------------------------------------------------------------
   var validString   =  "0123456789:";
   
   // ------------------------------------------------------------------------
   // look at each number determine if it is a "valid" number
   // ------------------------------------------------------------------------
   if ( !CheckValid( string, validString) ) {
      return new Array(false, improper + "Check for invalid characters in time.");
   }

   // ------------------------------------------------------------------------
   // split string (10:12) into two parts
   // ------------------------------------------------------------------------
   var parts = string.split(delimiter);
   
   // ------------------------------------------------------------------------
   // make sure there are two parts
   // ------------------------------------------------------------------------
   if (parts.length != 2) {
      return new Array(false, improper + "Check Proper Format (e.g. 14:15)");    
   }
      
   var hour    = parseInt(parts[0],10);
   var minute  = parseInt(parts[1],10);   
   
   // ------------------------------------------------------------------------
   // make sure hours/minutes are appropriate
   // ------------------------------------------------------------------------
   if ( (hour > 23) || (minute > 59)) {
      return new Array(false, improper + "Check for bad hour/minute in time.");
   }
   
   // ------------------------------------------------------------------------
   // must be ok if it got here
   // ------------------------------------------------------------------------
   return new Array(true,'');
}

// ---------------------------------------------------------------------------
// IsValidName
//
//      Purpose: Checks to see if the name passed can be broken down into 
//               exactly four(4) elements
// ---------------------------------------------------------------------------
function IsValidName ( name )
{
   // ------------------------------------------------------------------------
   // split the array into pieces based on separator defined at top
   // ------------------------------------------------------------------------
   var nameArray = name.split(VALID_SEPARATOR);
   
   // ------------------------------------------------------------------------
   // array must contain exactly four(4) elements separated by the separator
   // string defined at the top of this file - currently tilde (~). This
   // character must also be defined in the "defines.inc" file for PHP
   // fieldInfo[0] = field name;
   // fieldInfo[1] = field type validation ( date, number, etc )
   // fieldInfo[2] = required/not required indicator
   // fieldInfo[3] = user friendly display name of field
   // NOTE: MUST take into account hidden field names
   // ------------------------------------------------------------------------
   if ( nameArray.length > 1 && nameArray.length < 4) {
      ErrorMsg("Invalid Form Element Name\n\n" + 
               "API Error: Please Contact BRZ, Inc. Immediately\n\n" +
               "Field: " + name );
      return false;
   }
   
   // ------------------------------------------------------------------------
   // good form field name (name___lt___rq___First_Name)
   // ------------------------------------------------------------------------
   return true;
}
   
function HandleBadElement( theElement, errorMsg )
{
   // ------------------------------------------------------------------------
   // display the appropriate error message
   // ------------------------------------------------------------------------
   ErrorMsg( errorMsg );
   
   // ------------------------------------------------------------------------
   // get the name of the element
   // ------------------------------------------------------------------------
   var theName = theElement.name;
   
   // ------------------------------------------------------------------------
   // look for double tilde
   // ------------------------------------------------------------------------
   var parts = theName.split('~~');
   
   // ------------------------------------------------------------------------
   // decide what to do ...
   // ------------------------------------------------------------------------
   switch(parts.length) {
      case 1:  // no tab information
      case 2:
         break;      
      case 3:
         var chkbox =  GetObjectFromName(parts[2]);
         chkbox.click();
         break;
   }
   
   // ------------------------------------------------------------------------
   // set focus to the element, and select if text or password
   // ------------------------------------------------------------------------
   theElement.focus();
   if ( theElement.type == 'text' || theElement.type == 'password') {
      theElement.select();
   }
}

// ---------------------------------------------------------------------------
// ValidateForm
//
//      Purpose: Check all form elements based on their type (in field name)
// ---------------------------------------------------------------------------
function ValidateForm ( form, useConfirm ) 
{
   var daysPastAllowed = ALLOWPASTDATES;

   // ------------------------------------------------------------------------
   // allow default parameter for delimiter
   // ------------------------------------------------------------------------
   switch ( arguments.length ) {
      case 0:  
         form = document.forms[0];
      case 1:
         useConfirm = 1;
   }
      
   // ------------------------------------------------------------------------
   // go through each element in the form and validate as appropriate
   // ------------------------------------------------------------------------
   for ( var i=0; i < form.elements.length; i++ ) {
      // ---------------------------------------------------------------------
      // build shortcuts to the element, name, and value
      // ---------------------------------------------------------------------
      var theElement = form.elements[i];
      var name       = theElement.name;
      
      // ---------------------------------------------------------------------
      // elements like fieldset and legend dont have names, so ignore them
      // ---------------------------------------------------------------------      
      if ( name == undefined || name == 'undefined' ) {
         continue;
      }
      
      var fieldInfo  = theElement.name.split(VALID_SEPARATOR);
      var value      = theElement.value;

      // ---------------------------------------------------------------------
      // dont validate 'short' named, e.g. hidden fields
      // ---------------------------------------------------------------------
      if ( fieldInfo.length != 4 ) {
         if (theElement.name == 'recordId' && parseInt(value,10) > 0)
             daysPastAllowed = 9999;
         continue;
      }
      
      // ---------------------------------------------------------------------
      // check name for valid name for BRZ, Inc. - fieldInfo should contain 4
      // array elements:
      // fieldInfo[0] = field name;
      // fieldInfo[1] = field type validation ( date, number, etc )
      // fieldInfo[2] = required/not required indicator
      // fieldInfo[3] = user friendly display name of field
      // ---------------------------------------------------------------------
      if ( !IsValidName( theElement.name ) ) {
         return false;
      }
      
      // ---------------------------------------------------------------------
      // replace underlines with space for more 'friendly' name
      // ---------------------------------------------------------------------
      var friendly = BuildFriendlyName( fieldInfo[3], VALID_RANGE_SEPARATOR );
      
      // ---------------------------------------------------------------------
      // if this field is required, then make sure it is not blank
      // ---------------------------------------------------------------------
      if ( fieldInfo[2] == VALID_REQUIRED && IsBlank(value) ) {
         var errorMsg = 'The following field:' +
                        '\n\n\t' + 
                        friendly + 
                        '\n\nMust NOT Be Empty!';
         HandleBadElement(theElement, errorMsg);                        
         return false;
      }
      
      // ---------------------------------------------------------------------
      // dont check blanks and look for 'time' in the element name
      // ---------------------------------------------------------------------
      if ( !IsBlank(value) && FirstString(fieldInfo[1], VALID_TIME) ) {
         // ------------------------------------------------------------------
         // determine if this is a time
         // ------------------------------------------------------------------
         var timeValid = IsTime(value);
         
         // ------------------------------------------------------------------
         // not good, so set the focus to it and select it, return false
         // ------------------------------------------------------------------
         if ( !timeValid[0] ) {
            HandleBadElement(theElement, timeValid[1]);                        
            return false;
         }
         // ------------------------------------------------------------------
         // element was a date and all was well, so go to next element
         // ------------------------------------------------------------------
         continue;
      }
      
      // ---------------------------------------------------------------------
      // dont check blanks and look for 'date' in the element name
      // ---------------------------------------------------------------------
      if ( !IsBlank(value) && FirstString(fieldInfo[1], VALID_DATE) ) {
         // ------------------------------------------------------------------
         // determine if this is a date with slashes, e.g. 1/31/2000
         // ------------------------------------------------------------------
         var dateValid = IsSlashDate(value,fieldInfo[1],false,daysPastAllowed);
         
         // ------------------------------------------------------------------
         // not good, so set the focus to it and select it, return false
         // ------------------------------------------------------------------
         if ( !dateValid[0]) {
            HandleBadElement(theElement, dateValid[1]);                        
            return false;
         }
         // ------------------------------------------------------------------
         // element was a date and all was well, so go to next element
         // ------------------------------------------------------------------
         continue;
      }
      
      // ---------------------------------------------------------------------
      // dont check blanks and look for numeric in the element name
      // ---------------------------------------------------------------------
      if ( !IsBlank(value) && FirstString(fieldInfo[1],VALID_NUMBER) ) {
         // ------------------------------------------------------------------
         // determine if this is a numeric only field
         // ------------------------------------------------------------------
         var ok = IsNumeric(value);
         
         // ------------------------------------------------------------------
         // not good, so set the focus to it and select it, return false
         // ------------------------------------------------------------------
         if ( !ok ) {
            var errorMsg = 'The following field:' +
                           '\n\n\t' + 
                           friendly + 
                           '\n\nContains Non-Numeric Characters, e.g.' + 
                           '\n\n\t' + value;
            HandleBadElement(theElement, errorMsg);                        
            return false;
         }
         
         // ------------------------------------------------------------------
         // it is a number, now check if there is an associated range
         // ------------------------------------------------------------------
         var rangeString = fieldInfo[1];
         var rangeParts = rangeString.split(VALID_RANGE_SEPARATOR);
         
         switch(rangeParts.length) {
            case 1:  // no range associated
               break;
            case 2:  // problem, must have starting and ending range
               alert('Programming Validation Error!');
               return false;
            case 3:  // check value against the range
               if ( value < rangeParts[1] ||
                    value > rangeParts[2] ) {
                  // ---------------------------------------------------------
                  // not good, build the error message
                  // ---------------------------------------------------------
                  var errorMsg = 'The following field:' +
                                 '\n\n\t' + 
                                 friendly + 
                                 '\n\nIs not in proper range (' + 
                                 rangeParts[1] +
                                 ' - ' + 
                                 rangeParts[2] +
                                 ') e.g. You entered:' +
                                 '\n\n\t' + value;
                  // ---------------------------------------------------------
                  // notify user of range error
                  // ---------------------------------------------------------
                  HandleBadElement(theElement, errorMsg);                                          
                  return false;
               }
               break;
         }
         
         
         // ------------------------------------------------------------------
         // element was a date and all was well, so go to next element
         // ------------------------------------------------------------------
         continue;
      }
 
      // ---------------------------------------------------------------------
      // dont check blanks and look for numeric in the element name
      // ---------------------------------------------------------------------
      if ( !IsBlank(value) && FirstString(fieldInfo[1],VALID_LETTER) ) {
         // ------------------------------------------------------------------
         // determine if this is a "letter only" field
         // ------------------------------------------------------------------
         var ok = IsLetter(value);
         
         // ------------------------------------------------------------------
         // not good, so set the focus to it and select it, return false
         // ------------------------------------------------------------------
         if ( !ok ) {
            var errorMsg = 'The following field:' +
                           '\n\n\t' + 
                           friendly + 
                           '\n\nContains Numeric Characters, e.g.' +
                           '\n\n\t' + value;
            HandleBadElement(theElement, errorMsg);                                          
            return false;
         }
         // ------------------------------------------------------------------
         // element was a date and all was well, so go to next element
         // ------------------------------------------------------------------
         continue;
      }
      
      // ---------------------------------------------------------------------
      // dont check blanks and look for numeric in the element name
      // ---------------------------------------------------------------------
      if ( !IsBlank(value) && FirstString(fieldInfo[1],VALID_FLOAT) ) {
         // ------------------------------------------------------------------
         // determine if this is a "letter only" field
         // ------------------------------------------------------------------
         var useDecimal = 1;
         var useSign    = 1;
         var ok = IsNumeric(value, useDecimal, useSign);
         
         // ------------------------------------------------------------------
         // not good, so set the focus to it and select it, return false
         // ------------------------------------------------------------------
         if ( !ok ) {
            var errorMsg = 'The following field:' +
                           '\n\n\t' + 
                           friendly + 
                           '\n\nContains Non-Numeric Characters, e.g.' +
                           '\n\n\t' + value;
            HandleBadElement(theElement, errorMsg);                                          
            return false;
         }
         // ------------------------------------------------------------------
         // element was a date and all was well, so go to next element
         // ------------------------------------------------------------------
         continue;
      }
      
      // ---------------------------------------------------------------------
      // dont check blanks and look for phone in the element name
      // ---------------------------------------------------------------------
      if ( !IsBlank(value) && FirstString(fieldInfo[1],VALID_PHONE) ) {
         // ------------------------------------------------------------------
         // determine if this is a "letter only" field
         // ------------------------------------------------------------------
         var ok = IsPhone(value);
         
         // ------------------------------------------------------------------
         // not good, so set the focus to it and select it, return false
         // ------------------------------------------------------------------
         if ( !ok ) {
            var errorMsg = 'The following field:' +
                           '\n\n\t' + 
                           friendly + 
                           '\n\nContains Letters or other characters not allowed' +
                           '\nin phone numbers. Only numbers, periods(.), or' +
                           '\ndashes(-) are valid.' +
                           '\n\nFor US Phone Numbers, the preferred format is' +
                           '\nusing a period(.) as the separator, e.g.' + 
                           '\n\n\t888.555.1212';

            HandleBadElement(theElement, errorMsg);                                          
            return false;
         }
         // ------------------------------------------------------------------
         // element was a date and all was well, so go to next element
         // ------------------------------------------------------------------
         continue;
      }
   }

   // ------------------------------------------------------------------------
   // Build confirmation message
   // ------------------------------------------------------------------------
   var confirmMsg = "Are You Sure All Information Is Exactly As You Want It ?";
   
   // ------------------------------------------------------------------------
   // Display confirm message to user - asking to continue
   // ------------------------------------------------------------------------
   if ( useConfirm ) {
      if ( confirm(confirmMsg) == false )
         return false;
   }   
      
   // ------------------------------------------------------------------------
   // each element has been validated at this point
   // ------------------------------------------------------------------------
   return true;
}


// ---------------------------------------------------------------------------
// ValidatePasswords
//
//      Purpose: insure password and verification passwords match
// ---------------------------------------------------------------------------
function ValidatePasswords ( form )
{
   // ------------------------------------------------------------------------
   // initialize variables
   // ------------------------------------------------------------------------
   var passwordElement  = '';
   var password         = '';
   var verifyPassword   = '';
   
   // ------------------------------------------------------------------------
   // go through each element in the form and validate as appropriate
   // ------------------------------------------------------------------------
   for ( var i=0; i < form.elements.length; i++ ) {
      // ---------------------------------------------------------------------
      // build shortcuts to the element, name, and value
      // ---------------------------------------------------------------------
      var theElement = form.elements[i];
      var fieldInfo  = theElement.name.split(VALID_SEPARATOR);
      var value      = theElement.value;
      var name       = fieldInfo[0].toLowerCase();
      
      // ---------------------------------------------------------------------
      // fieldsets and legends don't have name properties
      // ---------------------------------------------------------------------
      if ( theElement.name == undefined || theElement.name == 'undefined' ) {
         continue;
      }
      
      // ---------------------------------------------------------------------
      // look for password in name of field (password - verifypassword)
      // ---------------------------------------------------------------------
      var index = name.indexOf('PASSWORD');
      
      // ---------------------------------------------------------------------
      // based on where it is, do something
      // ---------------------------------------------------------------------
      switch ( index ) {
         // ------------------------------------------------------------------
         // not found, so nothing to do
         // ------------------------------------------------------------------
         case -1:
            break;
         // ------------------------------------------------------------------
         // found the initial password e.g. name = password
         // ------------------------------------------------------------------
         case 0:
            password = value;
            passwordElement = theElement;
            break;
         // ------------------------------------------------------------------
         // found another password e.g. name = verifypassword
         // ------------------------------------------------------------------
         default:
            verifyPassword = value;
      }
   }
   
   // ------------------------------------------------------------------------
   // passwords must match if either one is entered
   // ------------------------------------------------------------------------
   if ( password != verifyPassword ) {
      var errorMsg = 'Password and Verify Password Do Not Match!\n\n' +
                     'Passwords are case sensitive and must match exactly';
      ErrorMsg ( errorMsg );
      passwordElement.focus();
      passwordElement.select();
      return false;
   }
   
   // ------------------------------------------------------------------------
   // all is well, so ok to proceed
   // ------------------------------------------------------------------------
   return true;
}

// ---------------------------------------------------------------------------
// ValidatePasswordChange
//
//      Purpose: insure password and verification passwords match
// ---------------------------------------------------------------------------
function ValidatePasswordChange ( form )
{
   // ------------------------------------------------------------------------
   // initialize variables
   // ------------------------------------------------------------------------
   var newPassword;
   var confirmPassword;
   var passwordElement;
   
   // ------------------------------------------------------------------------
   // make sure passwords match
   // ------------------------------------------------------------------------
   for ( var i=0; i < form.elements.length; i++ ) {
      // ---------------------------------------------------------------------
      // build shortcuts to the element, name, and value
      // ---------------------------------------------------------------------
      var theElement = form.elements[i];
      
      // ---------------------------------------------------------------------
      // fieldsets and legends don't have name properties
      // ---------------------------------------------------------------------
      if ( theElement.name == undefined || theElement.name == 'undefined' ) {
         continue;
      }
      
      var fieldInfo  = theElement.name.split(VALID_SEPARATOR);
      var value      = theElement.value;
      var name       = fieldInfo[0].toLowerCase();
      
      // ---------------------------------------------------------------------
      // look for password in name of field (password - verifypassword)
      // ---------------------------------------------------------------------
      if ( name == 'NEWPASSWORD' ) {
         newPassword = value;
         passwordElement = theElement;
         continue;
      }
      
      if ( name == 'CONFIRMPASSWORD' ) {
         confirmPassword = value;
         continue;
      }      
   }
   
   // ------------------------------------------------------------------------
   // passwords must match if either one is entered
   // ------------------------------------------------------------------------
   if ( newPassword != confirmPassword ) {
      var errorMsg = 'Password and Confirm Password Do Not Match!\n\n' +
                     'Passwords are case sensitive and must match exactly';
      ErrorMsg ( errorMsg );
      passwordElement.focus();
      passwordElement.select();
      return false;
   }
   
   // ------------------------------------------------------------------------
   // all is well, so ok to proceed
   // ------------------------------------------------------------------------
   return ValidateForm( form, 0 );
}

// ---------------------------------------------------------------------------
// SetValidateElement
//
//      Purpose: Setup element used for conditional validation
// ---------------------------------------------------------------------------
function SetValidateElement ( name, value )
{
   // ------------------------------------------------------------------------
   // validate element name is ALWAYS validateElement
   // ------------------------------------------------------------------------
   var validateElement = "validateElement";
   
   // ------------------------------------------------------------------------
   // get access to the element
   // ------------------------------------------------------------------------
   var theElement = eval ( BuildElementCode(validateElement) );
   
   // ------------------------------------------------------------------------
   // set name of element to check for validation
   // ------------------------------------------------------------------------
   theElement.value = name;

   // ------------------------------------------------------------------------
   // validate element name is ALWAYS validateElement
   // ------------------------------------------------------------------------
   var validateValue = "validateValue";
   
   // ------------------------------------------------------------------------
   // get access to the element
   // ------------------------------------------------------------------------
   theElement = eval ( BuildElementCode(validateValue) );
   
   // ------------------------------------------------------------------------
   // set name of element to check for validation
   // ------------------------------------------------------------------------
   theElement.value = value;
}

function GetCharacterCount( theString, theToken, min )
{
   // ------------------------------------------------------------------------
   // initialize variables outside case statement
   // ------------------------------------------------------------------------
   var thePattern;
   var exp;
   
   // ------------------------------------------------------------------------
   // build character class based on token passed
   // ------------------------------------------------------------------------
   switch (theToken) {
      case 'lower':
         exp = "[a-z]";      
         break;
      case 'upper':
         exp = "[A-Z]";      
         break;
      case 'number':
         exp = "[0-9]";
         break;
      case 'special':
         exp = "[-|\\\\`~!{}@#$%^&-*()_+=<>,./?'\":;\\]\\[]";
         break;
   }
   
   // ------------------------------------------------------------------------
   // setup appropriate pattern
   // ------------------------------------------------------------------------
   thePattern = new RegExp(exp, "g");
   
   // ------------------------------------------------------------------------
   // get array of matches
   // ------------------------------------------------------------------------
   var found = theString.match(thePattern);
   
   // ------------------------------------------------------------------------
   // if match not found, return false
   // ------------------------------------------------------------------------
   if ( found == null ) {
      return false;
   }
   
   // ------------------------------------------------------------------------
   // if the number found (not necessarily in a row) less than required ...
   // ------------------------------------------------------------------------
   if ( found.length < min) {
      return false;
   }
   
   // ------------------------------------------------------------------------
   // match found
   // ------------------------------------------------------------------------
   return true;   
}

function BadWordsFound ( password )
{
	var result	=	false;

	if (password.search(/suck/i) != -1) {
		result = true;
	}

	if (password.search(/suk/i) != -1) {
		result = true;
	}

	if (password.search(/fuck/i) != -1) {
		result = true;
	}
		
	if (password.search(/phuck/i) != -1) {
		result = true;
	}
	
	if (password.search(/fuk/i) != -1) {
		result = true;
	}
	
	if (password.search(/phuk/i) != -1) {
		result = true;
	}
	
	return result;
}

// ---------------------------------------------------------------------------
// ValidatePassword
//
//      Purpose: Validate password to have appropriate number of characters
// ---------------------------------------------------------------------------
function ValidatePassword ( theElement, min, max, upper, lower, number, special )
{
   // ------------------------------------------------------------------------
   // use default arguments if not passed
   // ------------------------------------------------------------------------
   switch (arguments.length) {
      case 1:
         min = 6;
      case 2:
         max = 15;
      case 3:
         upper = 1;
      case 4:
         lower = 1;
      case 5:
         number = 1;
      case 6:
         special = 1;
         break;
   }
   
   // ------------------------------------------------------------------------
   // initialze variables
   // ------------------------------------------------------------------------
   var errorTitle = 'Invalid Password';
   var errorMsg   =  '';
   var theMin;

   // ------------------------------------------------------------------------
   // get string in password field and its length
   // ------------------------------------------------------------------------
   var theValue   =  theElement.value;
   var length  =  theElement.value.length;
   
   // ------------------------------------------------------------------------
   // if not proper length, no more testing required .. 
   // ------------------------------------------------------------------------
   if ( length < min || length > max ) {
      errorMsg += "Password Is Not Correct Length**Passwords Must Be " +
                  min + ' to ' + max + ' Characters In Length.';
      ErrorMsg(errorMsg, errorTitle);
      theElement.focus();
      theElement.select();
      return false;
   }
   
   // ------------------------------------------------------------------------
   // look for the word 'password' - if there, reject it
   // ------------------------------------------------------------------------
   if (theValue.search(/password/i) != -1) {
         errorMsg = '**Password Must NOT Have The Word "Password" In It.';
         ErrorMsg(errorMsg, errorTitle);
         theElement.focus();
         theElement.select();
         return false;
   }
   
   if (BadWordsFound(theValue)) {
       errorMsg = '**Password Not In Compliance With Professional Standards';
       ErrorMsg(errorMsg, errorTitle);
       theElement.focus();
       theElement.select();
       return false;
   }
   
   // ------------------------------------------------------------------------
   // if minimum number of lower characters is > 0, then handle it ...
   // ------------------------------------------------------------------------
   if ( lower > 0 ) {
      theMin = lower;
      if (!GetCharacterCount(theValue, 'lower', theMin) ) {
         errorMsg = '**Password Must Have At Least (' +lower+') Lower Case Character(s).';
         ErrorMsg(errorMsg, errorTitle);
         theElement.focus();
         theElement.select();
         return false;         
      }      
   }
   
   // ------------------------------------------------------------------------
   // if minimum number of upper characters is > 0, then handle it ...
   // ------------------------------------------------------------------------
   if ( upper > 0 ) {
      theMin = upper;
      if (!GetCharacterCount( theValue, 'upper', theMin ) ) {
         errorMsg = '**Password Must Have At Least (' +upper+') Upper Case Character(s).';
         ErrorMsg(errorMsg, errorTitle);
         theElement.focus();
         theElement.select();
         return false;         
      }      
   }
   
   // ------------------------------------------------------------------------
   // if minimum number of numeric characters is > 0, then handle it ...
   // ------------------------------------------------------------------------
   if ( number > 0 ) {
      theMin = number;
      if (!GetCharacterCount( theValue, 'number', theMin ) ) {
         errorMsg = '**Password Must Have At Least (' +number+') Numeric Character(s).';
         ErrorMsg(errorMsg, errorTitle);
         theElement.focus();
         theElement.select();
         return false;         
      }      
   }
   
   // ------------------------------------------------------------------------
   // if minimum number of special characters is > 0, then handle it ...
   // ------------------------------------------------------------------------
   if ( special > 0 ) {
      theMin = 1;
      theMax = special;
      if (!GetCharacterCount( theValue, 'special', theMin, theMax ))  {
         errorMsg = '**Password Must Have At Least (' +special+') Special Character(s).';
         ErrorMsg(errorMsg, errorTitle);
         theElement.focus();
         theElement.select();
         return false;         
      }      
   }
}

// ---------------------------------------------------------------------------
// ValidateThisElement
//
//      Purpose: determine conditional validation
// ---------------------------------------------------------------------------
function ValidateThisElement ( )
{
   // ------------------------------------------------------------------------
   // validate element name is ALWAYS validateElement
   // ------------------------------------------------------------------------
   var validateElement = "validateElement";
   
   // ------------------------------------------------------------------------
   // get access to the element
   // ------------------------------------------------------------------------
   var theElement = eval ( BuildElementCode(validateElement) );
   
   // ------------------------------------------------------------------------
   // get the name of the element to check
   // ------------------------------------------------------------------------
   var elementName = theElement.value;

   // ------------------------------------------------------------------------
   // if no conditional validation, then ALWAYS validate
   // ------------------------------------------------------------------------
   if ( elementName == 'none' ) {
      return true;
   }
   
   // ------------------------------------------------------------------------
   // get access to the element
   // ------------------------------------------------------------------------
   var elementToCheck = eval ( BuildElementCode(elementName) );

   // ------------------------------------------------------------------------
   // get the value of the element to check
   // ------------------------------------------------------------------------
   elementToCheckValue = elementToCheck.value;

   // ------------------------------------------------------------------------
   // validate element name is ALWAYS validateElement
   // ------------------------------------------------------------------------
   var validateValueName = "validateValue";
   
   // ------------------------------------------------------------------------
   // get access to the element
   // ------------------------------------------------------------------------
   var validateValueElement = eval ( BuildElementCode(validateValueName) );
   
   // ------------------------------------------------------------------------
   // set name of element to check for validation
   // ------------------------------------------------------------------------
   var validateValue = validateValueElement.value;
   
   // ------------------------------------------------------------------------
   // if the element to check has the appropriate value, then 
   // ------------------------------------------------------------------------
   return ( elementToCheckValue == validateValue );
}

//---------------------------------------------------------------------------
//ValidateSquadron
//
//   Purpose: Keeps user from selecting a fleet or wing in squadron selection
//Parameters: squadron select element
//   Returns: nothing
//---------------------------------------------------------------------------
function ValidateSquadron ( squadronSelect )
{
   // ------------------------------------------------------------------------
   // get current value of select
   // ------------------------------------------------------------------------
   var value = squadronSelect.value;
   
   // ------------------------------------------------------------------------
   // if less than 999 (allows for 999 squadrons), nothing to do
   // ------------------------------------------------------------------------
   if ( value < 999 ) {
      return;
   }
   
   // ------------------------------------------------------------------------
   // error must have occurred - remove current selection
   // ------------------------------------------------------------------------
   squadronSelect.selectedIndex = 0;
   
   // ------------------------------------------------------------------------
   // build error message
   // ------------------------------------------------------------------------
   var error = "Please Select a Single Unit - Not A Grouping\n\n" + 
               "Groupings Are For Organizational Display Only";
   
   // ------------------------------------------------------------------------
   // display the error message
   // ------------------------------------------------------------------------
   ErrorMsg(error, "Invalid Selection");
}