///////////////////////////////////////////////////////
// JavaScript form validation functions script.  
///////////////////////////////////////////////////////
function isBlank(Ctrl) {  // returns true if blank   
   if (Ctrl.value.length < 1) return true;
   else if (isEmpty(Ctrl.value)) return true;
   else return false; }
function isEmpty(s) { // prevents entering empty strings
   for (var i = 0; i < s.length; i++) {
      var c = s.charAt(i);
      if ((c != ' ') && (c != '\n') && (c != '\t')) return false; 
   }
   return true; }
function isSpacey(Ctrl) { // true if string has spaces, return, or tab
    var s = Ctrl.value;
   for (var i = 0; i < s.length; i++) { var c = s.charAt(i);
      if ((c == ' ') || (c == '\n') || (c == '\t')) return true; }
   return false; }
function isTooShort(Ctrl,num) {
   if (Ctrl.value.length < num) return true;
   else return false; }
function isTooLong(Ctrl,num) {
   if (Ctrl.value.length > num) return true;
   else return false; }
function isIndexOf(Ctrl,str) { // returns true if substring found in string
   if (Ctrl.value.indexOf(str) > -1) return true;
   else return false; }
function isNotANumber(Ctrl) {  // returns true if not a number
   if (isNaN(Ctrl.value)) return true;
   else return false; }
function isChecked(Ctrl) {
   if (Ctrl.checked) return true;
   else return false; }
function isCheckedByLength(Ctrl) {   // for one or more checkboxes with same name
   var boxIsChecked = false;
   if (typeof(Ctrl.length) == "undefined") {    // only one checkbox
      return (!Ctrl.checked);
   } 
   for (i=0; i < Ctrl.length; i++) { if (Ctrl[i].checked) { boxIsChecked = true; break; }}
   return (!boxIsChecked);
}
function isSelected(Ctrl, index){  // returns true if the index indicated is selected
   if (Ctrl.options[index].selected) return true;
   else return false; }
function isSelectedOrHigher(Ctrl, upLimit){ // works with numerically-valued select options only!
   var ctrlValue = Ctrl.options[Ctrl.selectedIndex].value;
   if (ctrlValue == 0) return true;
   else if (ctrlValue > upLimit) return true;
   else return false; }
function isSelectedRange(Ctrl, loLimit, upLimit){ // works with numerically-valued select options
   var ctrlRangeValue = Ctrl.options[Ctrl.selectedIndex].value;
   if (!(ctrlRangeValue > loLimit && Ctrl.value < upLimit)) return true;
   else return false; }
function trim(s) {
  if (window.RegExp) {
     var r1 = /^[ ]*/;    var r2 = /[ ]*$/;
     return s.replace(r1,'').replace(r2,'');
  } else if (s.length > 0) {
      var a = ''; 
      var b = '';
      // remove initial spaces
      for (var i = 0; i < s.length; i++) {
         c = s.charAt(i);
         if (c != ' ') { a = s.substring(i,s.length); break; }
     }
     // remove trailing spaces
     for (var j = a.length-1; j > 0; j--) {
        c = a.charAt(j);
        if (c != ' ') { b = a.substring(0,j+1);  break; }
     }
     return b;
  } 
  else return '';
}
function checkZip(Ctrl) {  // returns true if not properly formatted zip code
   zipString = Ctrl.value;
   if (zipString.length == 5) {
      if (isNaN(zipString)) return true;
   } else if (zipString.length < 5) {
      return true;
   } else if ( 
      zipString.length < 10 ||
      isNaN( zipString.substring(0,5) ) || 
      isNaN( zipString.substring(6,10) ) ||
      (zipString.substring(5,6) != '-') ) {
         return true;
   } 
   else return false;
}   // end checkZip()
function testSimpleEmail(Ctrl){  // returns true if invalid email

      var material = Ctrl.value
      var separator = ",";
      var tokenizer = new StringTokenizer (material, separator);
      var email;
      var err=0;
      while (tokenizer.hasMoreTokens()) {
         email = tokenizer.nextToken();
   emailString = email;
   if (window.RegExp) {
      var regexEmail = /^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.(([a-zA-Z]{2,3})|(aero|coop|info|museum|name|biz))$/;
      if(!regexEmail.test(emailString)) {
        err=1;
      }
   } else {
      if (emailString.indexOf("@",1) == -1) err=1;  // need @ symbol
      if (emailString.indexOf("@",1) != emailString.lastIndexOf("@")) err=1;  // only one @ symbol
      if (emailString.indexOf(".",3) == -1) err=1;  // need at least one "."
      if (emailString.lastIndexOf(".") == (emailString.length-1)) err=1;  // can't end with a "."
      // check length
      if (err==0) {
         var at = (emailString.indexOf("@"))+1;
         var lastDot = (emailString.lastIndexOf("."))+1;
         // test to make sure there's at least one character between "at" and "lastDot"
         if (lastDot - at == 1) err=1;
      }
   }
      }  // end while

   if (err==1) return true;
   else return false;
}   // end testSimpleEmail()
function checkDateWSlash(Ctrl) {
   var yearFrom = 1800;
   var yearTo   = 2100;
   if (checkDateWSlash.arguments.length == 3) {
      yearFrom = parseInt(checkDateWSlash.arguments[1]);
      yearTo   = parseInt(checkDateWSlash.arguments[2]);
   } 
   var err=0;
   a = Ctrl.value;
   var firstSlash=(a.indexOf("/")) + 1;
   var secondSlash=(a.lastIndexOf("/")) + 1;   
   if (a.length != secondSlash+4) err=1;         // four-digit year
   if (err == 0) {
      // set date variables for testing
      b = a.substring(0, firstSlash-1);             // month
      c = a.substring(firstSlash-1, firstSlash);    
      d = a.substring(firstSlash, secondSlash-1);    // day      
      e = a.substring(secondSlash-1, secondSlash); 
      f = a.substring(secondSlash, secondSlash+4); // year      
      if (isNaN(b)) err=1;
      if (isNaN(d)) err=1;
      if (isNaN(f)) err=1;      
      if (d.indexOf("/") != -1) err=1;
      if (b<1 || b>12) err=1;
      if (c != '/') err=1;
      if (d<1 || d>31) err=1;
      if (e != '/') err=1;
      if (f<yearFrom || f>yearTo) err=1;  // valid year range
      if ((b==4 || b==6 || b==9 || b==11) && d==31)  err=1;
      if (b==2) {                     // February
          var g=parseInt(f/4);
          if (isNaN(g)) err=1;
          else if (d>29) err=1;
          else if (d==29) {
            /* Leap year rules: the year is a leap year if it is divisible by 4, e.g. 1960 
               UNLESS divisible by 100 - it is not a leap year, e.g. 1900
               UNLESS divisible by 400 - it is a leap year, e.g. 2000 */
            var isDivBy4   = (f %   4 == 0) ? true : false;
            var isDivBy100 = (f % 100 == 0) ? true : false;
            var isDivBy400 = (f % 400 == 0) ? true : false;
            if (!isDivBy4) err = 1;
            if (isDivBy100 && !isDivBy400) err = 1;
          } 
      }
   }
   if (err==1) return true;
   else return false; 
} // end checkDateWSlash()

function isCCNumber(Ctrl) {
   var cnum = Ctrl.value;
   // clean number
   if (window.RegExp) cnum = cnum.replace(/[^0-9]*/g,"");
   else {
      var a = '';  var allnum =  '1234567890';
      for (var i = 0; i < cnum.length; i++) {
         var c = s.charAt(i);
         if (allnum.indexOf(c) > -1) a += c;
      }
      cnum = a;
   }
   var lgth = cnum.length;

   if (lgth > 19) return false;
   else if (lgth < 15) return false;
   else {
      // validate number
      tally = 0; multTemp = 0; 
      lengthCheck = lgth % 2;
      if (lengthCheck == 0) { counter = 2; } else { counter = 1; }
      
      for (i = 0; i < lgth; i++) {
         tempNumb = parseInt(cnum.charAt(i));
         multTemp = tempNumb * counter;
         if (multTemp >= 10) {
            multTemp2 = parseInt(multTemp.charAt(0)) + parseInt(multTemp.charAt(multTemp.length));
            multTemp = multTemp2;
         }
         tally += multTemp; multTemp = 0;
         if (counter == 1) counter = 2; else counter = 1;
      }
      if (tally % 10 != 0) return false;
   } 
   return true;
}      
function isSSN(Ctrl) {
   var s = Ctrl.value;
   if (window.RegExp) {
      // only numbers or hypens
      if ( s.search(/[^-0-9]/) > -1 ) return false;
      // clean up number
      s = s.replace(/[^0-9]*/g,"");
   } else {
      var myA = '';  var myAllnum =  '1234567890';
      for (var i = 0; i < cnum.length; i++) {
         var c = s.charAt(i);
         if (myAllnum.indexOf(c) > -1) myA += c;
      }
      s = myA;   
   } 
   if (s.length == 9) return true;
   else return false;
}
function errorAlert(e) {
    // If ErrorString "e" has content, there was at least one error; let them know.
   if (e.length > 0) {
      msg  = "____________________________________________________\n\n";
      msg += "  The form was not submitted for the following reason(s): \n";
      msg += "____________________________________________________\n";
      alert(msg + e);
      return false;
   } else {
        return true;
    }
} // end errorAlert()


/*
   Client side JavaScript object for tokenization of a string.
   Best used for something as simple as a comma separated record of values.

   Sample usage:

   <script type="text/javascript" language="javascript" src="../lib/stringTokenizer.js"></script>
   <script type="text/javascript" language="javascript">

   	var separator = ",";
   	var names = "one,two,three";

   	var tokenizer = new StringTokenizer (names, separator);

   	while (tokenizer.hasMoreTokens())
   	{
   		document.write("<p>Name " + tokenizer.nextToken() + "</p>");
   	}  // end while

   </script>

Edited 27/09/2004 11:26AM
   Added a trim function and fixed a few "this"
   references that were not there and should have
   been.
Edited 14/02/2005 9:33PM
   Thanks to Cliff Hale for this!
   getTokens() is dropping the last token in the string if the
   last token is only 1 char in length (e.g.,  "1,2,3" would result
   in it returning "1,2")  To remedy this, I made the following change:   ....
   // Go through material, token at a time.
    while (this.material.length - start >= 1)

   Also changed the while in getTokens to skip over repeating instances
   of the separator.

*/



/*
   Constructor.
   Split up a material string based upong the separator.

   Param    -  material, the String to be split up.
   Param    -  separator, the String to look for within material. Should be
               something like "," or ".", not a regular expression.

*/
function StringTokenizer (material, separator)
{
   // Attributes.
   this.material = material;
   this.separator = separator;

   // Operations.
   this.getTokens = getTokens;
   this.nextToken = nextToken;
   this.countTokens = countTokens;
   this.hasMoreTokens = hasMoreTokens;
   this.tokensReturned = tokensReturned;

   // Initialisation code.
   this.tokens = this.getTokens();
   this.tokensReturned = 0;

}  // end constructor




/*
   Go through material, putting each token into a new array.

   Return      - the array with all the tokens in it.
*/
function getTokens()
{
   // Create array of tokens.
   var tokens = new Array();
   var nextToken;

   // If no separators found, single token is the material string itself.
	if (this.material.indexOf (this.separator) < 0)
	{
		tokens [0] = this.material;
		return tokens;
	}  // end if

   // Establish initial start and end positions of the first token.
   start = 0;
   end = this.material.indexOf (this.separator, start);

   // Counter for how many tokens were found.
   var counter = 0;

   // Go through material, token at a time.
   var trimmed;
 	while (this.material.length - start >= 1)
	{
		nextToken = this.material.substring (start, end);
		start = end + 1;
		if (this.material.indexOf (this.separator, start + 1) < 0)
		{
			end = this.material.length;
		}  // end if
		else
		{
			end = this.material.indexOf (this.separator, start + 1);
		}  // end else

      trimmed = trim (nextToken);

      // Remove any extra separators at start.
      while (trimmed.substring(0, this.separator.length) == this.separator) {
         trimmed = trimmed.substring (this.separator.length);
      }
      trimmed = trim(trimmed);
      if (trimmed == "") {
         continue;
      }
      tokens [counter] = trimmed;
		counter ++;
	}   // end if

   // Return the initialised array.
   return tokens;


}  // end getTokens function


/*
   Return a count of the number of tokens in the material.

   Return      - int number of tokens in material.
*/
function countTokens()
{
  return this.tokens.length;
}  // end countTokens function



/*
   Get next token in material.

   Return      - next token in material.
*/
function nextToken()
{

   if (this.tokensReturned >= this.tokens.length)
   {
      return null;
   }  // end if
   else
   {
      var returnToken = this.tokens [this.tokensReturned];
      this.tokensReturned ++;
      return returnToken;
   }  // end else

}  // end nextToken function



/*
   Tests if there are more tokens available from this tokenizer's string. If
   this method returns true, then a subsequent call to nextToken
   will successfully return a token.

   Return      true if more tokens, false otherwise.
*/
function hasMoreTokens()
{
   if (this.tokensReturned < this.tokens.length)
   {
      return true;
   }  // end if
   else
   {
      return false;
   }  // end else
}  // end hasMoreTokens function

function tokensReturned()
{
   return this.tokensReturned;
}  // end tokensReturned function


function trim (strToTrim) {
   return(strToTrim.replace(/^\s+|\s+$/g, ''));
}  // end trim function





