// rev. Apr-09-2002 - mc - added isAlphaNumeric

// rev. Apr-11-2002 - mc - added optional fcsName for pretty names

// rev. Apr-22-2002 - mc - added required for a select list box where a value of
//                         "0" indicates nothing selected. This means OPTION[0]
//                         must contain something like '---enter your choice --' 
//        
// rev Apr-24-2002 - mc -  added firstErrorElement to focus the first error element.
//
// rev Apr-28-2002 - mc -  removed redundant if statement after alert
//
//     Apr 28-2002 - st -  added areLegalCharacters()
//
// rev May-11-2002 - mc -  added fcsFirstDate and dateGreater()
//     May 21-2002 - st -  changed areLegalCharacters to quietly change quotes to `
//
// rev jun-13-2002 - mc -  added fcsUnCheckedRadio 

//   Dec 6 2005      - st - Dollars should accept negative.  Use min of 0 for postive only

//March 27th 2007	- BC - Added email verification (that I stole off the internet and modified)

//  08-10-2009  - Rad -  added a date check with a separator.  This is how you
//  use it        form.anInput.fcsDateWithSep = true;
//                form.anInput.fcsDateSeparator = "/";
//
//      Also added a match check to see if 2 fields are the same.  Yes you could
//do the check yourself but then you get 2 alerts.  This is how you use it
//            form.email.fcsName = 'E-mail Address';
//            form.email.fcsMatchName = 'Confirm E-mail';
//            form.email.fcsMatch = true;
//            form.email.fcsMatchMe = form.email_confirm.value;
//
//9-18-2009 JLB added prototype functionality.  
//          call verify(form, true or false, true) to use prototype.
//          Calling file must include prototype.js
//          All old forms and new ones can continue to work without prototype by 
//          continuing to call verifyForm(form)
//
//9-21-2009 JLB added suppressErrorMessage option to verify.
//          call verify(form, true) to suppress pop-up
//          This will suppress the pop-up message
//          new fcsDiv property allows you to define a div element.
//            - messages that used to be in pop up, will appear in the div
//
//          For an example on how to use these new features, see website/edit_account.jsp
//
//9-22-2009 JLB Moved "The field" out of div errors.  It should only be displayed on popup

//09/23/2009 Rad - Fixed global variables so they don't cause problems.
//  Added element.fcsVerifyMsg so you can use js to check what fields have
//  errors on your page.
//
//9/30/2009 JLB provided verifyElement function call.  
//          Added fcsNoNumbers to prevent numbers - works with this.allNumbers
//          Added fcsNoLetters to prevent letters - works with this.allLetters
//          Added fcsNoSpecialChars to prevent special characters - works with this.allSpecialChars
//          Added fcsSpecialCharExceptions to allow certain special characters
//
//          i.e. the only special characters that should be allowed are # and $
//          element.fcsNoSpecialChars = true;
//          element.fcsSpecialCharExceptions = "#$"
var fcsVerify = new function(){
  this.lastError = "";
  this.empty_fields = "";
  this.errors = "";
  this.firstErrorElement = -1;
  this.elementHasError = false;

  this.allNumbers = "1234567890";
  this.allLetters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  this.allSpecialChars = "!@#$%^&*()-_=+[]{};:'\",.<>/\\?|`~ ";
};

function hasNoNumbers(element) {
  return passesCharacterRestriction(element, fcsVerify.allNumbers);
}

function hasNoLetters(element) {
  return passesCharacterRestriction(element, fcsVerify.allLetters);
}

function hasNoSpecialChars(element) {
  return passesCharacterRestriction(element, fcsVerify.allSpecialChars, element.fcsSpecialCharExceptions);
}

function passesCharacterRestriction(element, badCharacters, exceptions) {
  var s = element.value;

  if(exceptions == null) {
      exceptions = "";
  }
  if(s == null || badCharacters == null || badCharacters == 0) {
    return true;
  }
  
  for(var i=0; i < s.length; i++) {
    if(badCharacters.indexOf(s.charAt(i)) >= 0 &&
       exceptions.indexOf(s.charAt(i)) == -1) {

      return false;
    }
  }

  return true;
}

function areLegalCharacters(element) {
 
  var s = element.value ;

  if ( s == null) 
    return true ;  // buttons, etc. not text

  //alert(e.type + " " + s) ;

  for ( var i=0 ; i < s.length ; i++ ) {
      
    if ( ( s.charAt(i) == '\n' ) ||
      ( s.charAt(i) == '\r' ) )
      continue ;

    if (
      ( s.charAt(i) == "'" ) ||
      ( s.charAt(i) == '"' )  ||
      ( s.charAt(i) < " " )  ||
      ( s.charAt(i) > "~" ) )
      //return false ;
      element.value = element.value.substring(0,i) + '`' + element.value.substring(i+1) ;
       
  }
    
  return true ;
}

// A utility function that returns true if a string contains only 
// whitespace characters.
function isblank(s) {
  for(var i = 0; i < s.length; i++) {
    var c = s.charAt(i);
    if ((c != ' ') && (c != '\n') && (c != '\t')) return false;
  }
  return true;
}

function isNumber(s) {
  for(var i = 0; i < s.length; i++) {
    var c = s.charAt(i);
    if ( (c < '0') || (c > '9')) return false;
  }
  return true;
}

function isAlphaNumeric(s) {
 
  for ( var i=0 ; i < s.length ; i++ ) {
      
    if (   (( s.charAt(i) > "9" ) || ( s.charAt(i) < "0" )) &&
      (( s.charAt(i) > "z" ) || ( s.charAt(i) < "a" )) &&
      (( s.charAt(i) > "Z" ) || ( s.charAt(i) < "A" ))  ) {
 
      return false ;
    }
  }
  return true ;
}

function dateGreater(s1,s2) {
  var ymd1 = s1.substring(4,8) + s1.substring(0,4) ;
  var ymd2 = s2.substring(4,8) + s2.substring(0,4) ;
  return ( ymd1 <= ymd2 )  ;

       
}


function isDollars(s) {
  var c=0 ;
  for ( var i=0 ; i < s.length ; i++ ) {

    // allow negative:
    if ( ( s.charAt(i) == "-" ) && ( i == 0 ) )
      continue ;

    if (s.charAt(i) == ".") {
      if ( c++ != 0 ) {
        return false ;
      }
                    
      // 01234.67 (len=8) 45.56 (length=5)
      if (( s.length - i ) != 3 ) {
        return false ;
      }
    }
    else
    if (( s.charAt(i) < "0" ) ||
      ( s.charAt(i) > "9" ) ) {
      return false ;
    }
  }
  return true ;
}

function BROKENisDollars(s) {
  var c=0 ;
  for ( var i=0 ; i < s.length ; i++ ) {

    // allow negative:
    if ( ( s.charAt(i) == "-" ) && ( i == 0 ) )
      continue ;

    // one decimal only:
    if (s.charAt(i) == ".")
      if ( c++ != 0 ) {
        return false ;
      }
      else
        continue ;
          
           
    // 01234.67 (len=8) 45.56 (length=5)
    // if (( s.length - i ) != 3 ) {
    // return false ;
    // }

    if (( s.charAt(i) < "0" ) ||
      ( s.charAt(i) > "9" ) ) {
      return false ;
    }
  }
  return true ;
}

// this stupid function is required because braindead Date.getYear returns 2 digit years in 20th century:
function y2k(number) { 
  return (number < 1000) ? number + 1900 : number;
}

function isValidDate (myDate) {

  // checks if date passed is in valid mmddyyyy format

  if ((myDate == null) || (myDate=='') )
    return '' ;
	   
  if (myDate.length == 8) {
       
    var idate  = myDate.substring(2,4)  ;
    var month = myDate.substring(0,2)  ;
    var year  = myDate.substring(4,8)  ;

    var test = new Date(year,month-1,idate);

    //alert( "entered year = " + year + " year = " + test.getYear()  ) ;

    if (year == y2k(test.getYear()) && (month-1 == test.getMonth()) && (idate == test.getDate()))
      return '' ;
    else
      return 'is an Invalid Date' ;
  }
  else
    return  'must be entered as mmddyyyy';
}

function isValidDateWithSep(myDate, separator){
  //checks if myDate is in mm/dd/yyy format

  if(!(myDate.substring(2,3) == separator && myDate.substring(5,6) == separator)){
    return 'must be entered as mm/dd/yyyy';
  }else{
    var split = myDate.split(separator);
    var theReturn = isValidDate(split[0] + split[1] + split[2]);
    if(theReturn=='must be entered as mmddyyyy'){
      return 'must be entered as mm/dd/yyyy';
    }else{
      return theReturn;
    }
  }
}

function isMatch(val1, val2){
  //I can has match plz
  if(val1==val2){
    return true;
  }
  return false;
}


function isEmail(s)
{
  <!-- This script and many more are available free online at -->
  <!-- The JavaScript Source!! http://javascript.internet.com -->
	
  <!-- V1.1.3: Sandeep V. Tamhankar (stamhankar@hotmail.com) -->
  <!-- Original:  Sandeep V. Tamhankar (stamhankar@hotmail.com) -->
  <!-- Changes:
  /* 1.1.4: Fixed a bug where upper ASCII characters (i.e. accented
	letters
	international characters) were allowed.
	
	1.1.3: Added the restriction to only accept addresses ending in two
	letters (interpreted to be a country code) or one of the known
	TLDs (com, net, org, edu, int, mil, gov, arpa), including the
	new ones (biz, aero, name, coop, info, pro, museum).  One can
	easily update the list (if ICANN adds even more TLDs in the
	future) by updating the knownDomsPat variable near the
	top of the function.  Also, I added a variable at the top
	of the function that determines whether or not TLDs should be
	checked at all.  This is good if you are using this function
	internally (i.e. intranet site) where hostnames don't have to 
	conform to W3C standards and thus internal organization e-mail
	addresses don't have to either.
	Changed some of the logic so that the function will work properly
	with Netscape 6.
	
	1.1.2: Fixed a bug where trailing . in e-mail address was passing
	(the bug is actually in the weak regexp engine of the browser; I
	simplified the regexps to make it work).
	
	1.1.1: Removed restriction that countries must be preceded by a domain,
	so abc@host.uk is now legal.  However, there's still the 
	restriction that an address must end in a two or three letter
	word.
	
	1.1: Rewrote most of the function to conform more closely to RFC 822.
	
	1.0: Original  */
  // -->
	
  <!-- Begin
  //function emailCheck (emailStr) {
	
  /* The following variable tells the rest of the function whether or not
	to verify that the address ends in a two-letter country or well-known
	TLD.  1 means check it, 0 means don't. */
	
  //Note by Brent: added fcsEmail in verifyFrom.
  //Commented alerts for this function to display a gerneric alert for the email.
  //changed the function name and included  the comments as part of the function.
  //Left comments in tact so that anyone reading this knows where I got this code.
	
  var checkTLD=1;
	
  /* The following is the list of known TLDs that an e-mail address must
	end with. */
	
  var
  knownDomsPat=/^(com|net|org|edu|int|mil|gov|arpa|biz|aero|name|coop|info|pro|museum)$/;
	
  /* The following pattern is used to check if the entered e-mail address
	fits the user@domain format.  It also is used to separate the username
	from the domain. */
	
  var emailPat=/^(.+)@(.+)$/;
	
  /* The following string represents the pattern for matching all special
	characters.  We don't want to allow special characters in the address. 
	These characters include ( ) < > @ , ; : \ " . [ ] */
	
  var specialChars="\\(\\)><@,;:\\\\\\\"\\.\\[\\]";
	
  /* The following string represents the range of characters allowed in a
	username or domainname.  It really states which chars aren't allowed.*/
	
  var validChars="\[^\\s" + specialChars + "\]";
	
  /* The following pattern applies if the "user" is a quoted string (in
	which case, there are no rules about which characters are allowed
	and which aren't; anything goes).  E.g. "jiminy cricket"@disney.com
	is a legal e-mail address. */
	
  var quotedUser="(\"[^\"]*\")";
	
  /* The following pattern applies for domains that are IP addresses,
	rather than symbolic names.  E.g. joe@[123.124.233.4] is a legal
	e-mail address. NOTE: The square brackets are required. */
	
  var ipDomainPat=/^\[(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})\]$/;
	
  /* The following string represents an atom (basically a series of
	non-special characters.) */
	
  var atom=validChars + '+';
	
  /* The following string represents one word in the typical username.
	For example, in john.doe@somewhere.com, john and doe are words.
	Basically, a word is either an atom or quoted string. */
	
  var word="(" + atom + "|" + quotedUser + ")";
	
  // The following pattern describes the structure of the user
	
  var userPat=new RegExp("^" + word + "(\\." + word + ")*$");
	
  /* The following pattern describes the structure of a normal symbolic
	domain, as opposed to ipDomainPat, shown above. */
	
  var domainPat=new RegExp("^" + atom + "(\\." + atom +")*$");
	
  /* Finally, let's start trying to figure out if the supplied address is
	valid. */
	
  /* Begin with the coarse pattern to simply break up user@domain into
	different pieces that are easy to analyze. */
	
  var matchArray=s.match(emailPat);
	
  if (matchArray==null) {
	
    /* Too many/few @'s or something; basically, this address doesn't
	even fit the general mould of a valid e-mail address. */
	
    //alert("Email address seems incorrect (check @ and .'s)");
    return false;
  }
  var user=matchArray[1];
  var domain=matchArray[2];
	
  // Start by checking that only basic ASCII characters are in the
  //strings (0-127).
	
  for (i=0; i<user.length; i++) {
    if (user.charCodeAt(i)>127) {
      //alert("Ths username contains invalid characters.");
      return false;
    }
  }
  for (i=0; i<domain.length; i++) {
    if (domain.charCodeAt(i)>127) {
      //alert("Ths domain name contains invalid characters.");
      return false;
    }
  }
	
  // See if "user" is valid
	
  if (user.match(userPat)==null) {
	
    // user is not valid
	
    //alert("The username doesn't seem to be valid.");
    return false;
  }
	
  /* if the e-mail address is at an IP address (as opposed to a symbolic
	host name) make sure the IP address is valid. */
	
  var IPArray=domain.match(ipDomainPat);
  if (IPArray!=null) {
	
    // this is an IP address
	
    for (var i=1;i<=4;i++) {
      if (IPArray[i]>255) {
        //alert("Destination IP address is invalid!");
        return false;
      }
    }
    return true;
  }
	
  // Domain is symbolic name.  Check if it's valid.
	 
  var atomPat=new RegExp("^" + atom + "$");
  var domArr=domain.split(".");
  var len=domArr.length;
  for (i=0;i<len;i++) {
    if (domArr[i].search(atomPat)==-1) {
      //alert("The domain name does not seem to be valid.");
      return false;
    }
  }
	
  /* domain name seems valid, but now make sure that it ends in a
	known top-level domain (like com, edu, gov) or a two-letter word,
	representing country (uk, nl), and that there's a hostname preceding 
	the domain or country. */
	
  if (checkTLD && domArr[domArr.length-1].length!=2 &&
    domArr[domArr.length-1].search(knownDomsPat)==-1) {
    //alert("The address must end in a well-known domain or two letter " +
    //"country.");
    return false;
  }
	
  // Make sure there's a host name preceding the domain.
	
  if (len<2) {
    //alert("This address is missing a hostname!");
    return false;
  }
	
  // If we've gotten this far, everything's valid!
  return true;
}
	
//  End -->

// This is the function that performs form verification. It is invoked
// from the onsubmit event handler. The handler should return whatever
// value this function returns.
// f is the form
// styleErrors = true or false.
//   if true, any element that errors gets class="form_validation_error"
//   use style sheets to style appropriately.
// useDivInsteadOfPopup = true or false
//   if true, popup is not displayed
//   set fcsDiv to a corresponding div element
//   error message that used to appear in pop up will now go here
function verifyForm(f, useDivInsteadOfPopup, styleErrors, forcePopup) {
  //alert( "verifying...") ;

  var styleErrors = styleErrors || false;
  var forcePopup = forcePopup || false;

  var msg;

  var displayName = "" ;
  var displayName1 = "" ;
  var displayName2 = "" ;

  fcsVerify.lastError = "";
  fcsVerify.empty_fields = "";
  fcsVerify.errors = "";
  fcsVerify.firstErrorElement = -1;
  fcsVerify.elementHasError = false;
  

  
  var e;

  for(var i = 0; i < f.length; i++) {
	e = f.elements[i];
	verifyElement(e, styleErrors, useDivInsteadOfPopup, i, f);
  }


  // Now, if there were any errors, display the messages, and
  // return false to prevent the form from being submitted.
  // Otherwise return true.
  if (!fcsVerify.empty_fields && !fcsVerify.errors) return true;

  msg  = "______________________________________________________\n\n"
  msg += "The form was not submitted because of the following error(s).\n";
  msg += "Please correct these error(s) and re-submit.\n";
  msg += "______________________________________________________\n\n"

  if (fcsVerify.empty_fields) {
    msg += "- The following required field(s) are empty:"
    + fcsVerify.empty_fields + "\n";
    if (fcsVerify.errors) msg += "\n";
  }
  msg += fcsVerify.errors;

  if(!useDivInsteadOfPopup || forcePopup) {
    alert(msg);
  }

  f.elements[fcsVerify.firstErrorElement].focus() ;
      

  return false;
}


//e = element
//useDiv = add error message to Div
//styleErrors = use only if calling page includes prototype.
//	adds class="form_validation_error" to element.
//	use style sheet to style appropriately
//i = optional index
//f = optional from (needed for multi-part phone numbers)
function verifyElement(e, useDiv, styleErrors, i, f) {
    fcsVerify.lastError = "";

    var styleErrors = styleErrors || false;
    var useDiv = useDiv || false;
    var requiredAndFilled = true;

    fcsVerify.elementHasError = false;

    //alert ("checking " + e.name ) ;
     
    if (e.fcsName)  displayName = e.fcsName ; else  displayName = e.name  ;

    if ( !areLegalCharacters(e)) {
      adderror(e, "- The field ", "'" + displayName + "' cannot contain control characters or quotes", "\n", false, "", i);
    }


    if (e.fcsAlphaNumeric) {
      if (!isAlphaNumeric(e.value)) {
        adderror(e, "- The field ", "'" + displayName + "' cannot contain special characters", "\n", false, "", i);
      }
    }
    if  (e.fcsRequired)  {
      // first check if the field is empty
      if ((e.value == null) || (e.value == "") ){
        requiredAndFilled = false;
        adderror(e, "\n          ", displayName + " required.", "", true, displayName, i);
      }
    }

    if(requiredAndFilled) {
        var passNumbers = true;
        var passLetters = true;
        var passSpecialChars = true;

        if(e.fcsNoNumbers) {
            passNumbers = hasNoNumbers(e);
        }
        if(e.fcsNoLetters) {
            passLetters = hasNoLetters(e);
        }
        if(e.fcsNoSpecialChars) {
            passSpecialChars = hasNoSpecialChars(e);
        }

        if(!(passNumbers && passLetters && passSpecialChars)) {
            adderror(e, "- The field ", "'" + displayName + "' can only contain " +
                buildCharacterRestrictionMessage(e), "\n", false, "", i);
        }

        if  (e.fcsUnCheckedRadio)  {
          // set by caller if no radio options are checked in a group
          adderror(e, "\n          ", displayName + " required.", "", true, displayName, i);

        }

        if  (e.fcsSelectRequired)  {
          // first element not allowed
          if (e.value == "0"){
            adderror(e, "\n          ", displayName + " required.", "", true, displayName, i);
          }
        }

        // multi part telephone horrors:

        if (e.fcsMultiPartTelephone) {
          e.fcsRequiredLength = 3 ;
          e.fcsNumeric = true ;

          var e1 = f.elements[i+1] ;

          e1.fcsRequiredLength = 3 ;
          e1.fcsNumeric = true ;
          if (e1.fcsName)  displayName1 = e1.fcsName ; else  displayName2 = e1.name  ;

          var e2 = f.elements[i+2] ;
          e2.fcsRequiredLength = 4 ;
          e2.fcsNumeric = true ;
          if (e2.fcsName)  displayName2 = e2.fcsName ; else  displayName2 = e2.name  ;

          var l = e.value.length + e1.value.length + e2.value.length ;
          if (( l > 0 ) && ( l < 10 ) ) {
            adderror(e, "- ", "The telephone number '" + displayName + "/" + displayName1 + "/" +
              displayName2 + "' must be filled in completely if entered", "\n", false, "", i);
          }
        }


        if ( (e.fcsTelephone) && (e.value.length >0) ){
          if ( (!isNumber(e.value)) || ( e.value.length != 10) ) {
            adderror(e, "- ", "The telephone number '" + displayName + "' must be 10 digits - NO PUNTUATION", "\n", false, "", i);
          }
        }

        if (e.value.length >0)
          if ((e.fcsRequiredLength != null) && (e.fcsRequiredLength != e.value.length)) {
            adderror(e, "- The field ", "'" + displayName + "' must be " + e.fcsRequiredLength + " characters", "\n", false, "", i);

          }


        var testDate = '' ;

        if (e.fcsDate) {
          testDate = isValidDate(e.value ) ;
          if (testDate != '') {
            adderror(e, " - The field ", "'" + displayName + "' " + testDate, "\n", false, "", i);

          } else {

            if (e.fcsFirstDate != null )  {
              if ((e.fcsFirstDate.value != "" ) &&
                  (e.value != "" )) {
                if (!dateGreater(e.fcsFirstDate.value, e.value) ) {
                  adderror(e, " - The field ", "'" + displayName + "' is before '" + e.fcsFirstDate.fcsName + "'", "\n", false, "", i);
                }
              }
            }
          }
        }

        if(e.fcsDateWithSep){
          testDate = isValidDateWithSep(e.value, e.fcsDateSeparator) ;
          if (testDate != '') {
            adderror(e, " - The field ", "'" + displayName + "' " + testDate, "\n", false, "", i);

          }
        }

        if(e.fcsMatch){
          if(e.value != null && e.value != "" && e.fcsMatchMe.value != null && e.fcsMatchMe.value != "") {
            if (!isMatch(e.value, e.fcsMatchMe.value)) {
              adderror(e, " - The field ", "'" + displayName + "' and '" + e.fcsMatchName + "' do not match", "\n", false, "", i);
            }
          }
        }

        // Now check for fields that are supposed to be numeric.
        if (e.fcsNumeric) {
          if (!isNumber(e.value))  {
            adderror(e, "- The field ", "'" + displayName + "' must be a number", "\n", false, "", i);

          }
        }

        if (e.fcsDollars) {
          if (!isDollars(e.value))  {
            adderror(e, "- The field ", "'" + displayName + "' must be dollars or dollars & cents ", "\n", false, "", i);

          }
        }

        if ((e.fcsMin != null) && (e.value < e.fcsMin)) {
          adderror(e, "- The field ", "'" + displayName + "' must not be less than " + e.fcsMin, "\n", false, "", i);
        }


        if ((e.fcsMax != null) && (e.value > e.fcsMax)) {
          adderror(e, "- The field ", "'" + displayName + "' must not be greater than " + e.fcsMax, "\n", false, "", i);
        }

        if (e.fcsMinLength != null && e.fcsMaxLength != null) {
          if ((e.value.length < e.fcsMinLength) || (e.value.length > e.fcsMaxLength)) {
            adderror(e, "- The field ", "'" + displayName + "' must be between " + e.fcsMinLength + " and " + e.fcsMaxLength + " characters.", "\n", false, "", i);
          }
        }
        else {
          if(e.fcsMinLength != null && e.value.length < e.fcsMinLength) {
            adderror(e, "- The field ", "'" + displayName + "' must be at least " + e.fcsMinLength + " characters.", "\n", false, "", i);
          }
          if(e.fcsMaxLength != null && e.value.length > e.fcsMaxLength) {
            adderror(e, "- The field ", "'" + displayName + "' must be no more than " + e.fcsMaxLength + " characters.", "\n", false, "", i);
          }
        }


        if(e.fcsEmail)
        {
          if((e.value != null) && (e.value != ''))
          {
            if(!isEmail(e.value))
            {
              adderror(e, "- The Field ", "'" + displayName + "' is not a valid Email address", "\n", false, "", i);
            }
          }
        }
    }

    if(fcsVerify.elementHasError) {
      if(styleErrors) {
        $(e).addClassName("form_validation_error");
      }
      if(useDiv && e.fcsDiv) {
        e.fcsDiv.innerHTML = fcsVerify.lastError;
      }
    }
    else {
      if(styleErrors) {
        $(e).removeClassName("form_validation_error");
      }
      if(useDiv && e.fcsDiv) {
        e.fcsDiv.innerHTML = "";
      }
    }
}

//Builds a comprehensible sentence depicting which characters are allowed
function buildCharacterRestrictionMessage(e) {
    var restrictionError = "";
    if(!e.fcsNoNumbers) {
        restrictionError += "numbers";
    }
    if(!e.fcsNoLetters) {
        if(restrictionError != "") {
            restrictionError += ", ";
        }
        restrictionError += "letters";
    }
    if(!e.fcsNoSpecialChars) {
        if(restrictionError != "") {
            restrictionError += ", ";
        }
        restrictionError += "special characters";
    }
    else {
        var exceptions = e.fcsSpecialCharExceptions;
        var spaces = false;
        if(e.fcsSpecialCharExceptions != null && e.fcsSpecialCharExceptions != "") {
            if(e.fcsSpecialCharExceptions.indexOf(" ") >= 0) {
                spaces = true;
                exceptions = exceptions.replace(" ", "");
            }
            restrictionError += ", " + exceptions;
            if(spaces) {
                restrictionError += ", spaces";
            }
        }
    }

    //replace last ', ' with 'and'
    if(restrictionError.split(",").length == 2) {
        restrictionError = restrictionError.replace(", ", " and ");
    }
    if(restrictionError.split(",").length > 2) {
        restrictionError = restrictionError.substring(0, restrictionError.lastIndexOf(", ", restrictionError.length)) +
            restrictionError.substring(restrictionError.lastIndexOf(", ", restrictionError.length), restrictionError.length).replace(", ", " and ");
    }    

    return restrictionError;
}


function adderror(e, prefix, errorMessage, postfix, isEmptyField, emptyFieldDisplayName, index) {

  //add space between additional error messages.
  var endsWithPeriod = fcsVerify.lastError.length > 0 && fcsVerify.lastError.substr(fcsVerify.lastError.length - 1) == ".";
  if(endsWithPeriod) {
    fcsVerify.lastError += " ";
  }

  fcsVerify.lastError += errorMessage;

  //add period if not provided.
  if(fcsVerify.lastError != null && fcsVerify.lastError != "" && endsWithPeriod == false) {
    fcsVerify.lastError += ".";
  }

  if(isEmptyField) {
    fcsVerify.empty_fields += prefix + emptyFieldDisplayName;
  }
  else {
    fcsVerify.errors += prefix + errorMessage + postfix;
  }

  fcsVerify.elementHasError = true;
  if ( fcsVerify.firstErrorElement == -1 ) fcsVerify.firstErrorElement = index ;

  e.fcsVerifyMsg = errorMessage;
}
