//<------------------------------------------------------------------------------------------------------
// @General [-!Overview-] Public Validation code. This functionality is also contained
// in the 'Validators' module and is part of the namespace there.
// @module valid.js
// Public Validators are designed to be called from a Javascript module.
//   They are as follows:
//     *Data Expected *Optional - validate if data is found
//      IsDate         DateOrNone
//      IsDecimal      DecimalsOrNone
//      IsPhone        PhoneOrNone
//      IsTime         TimeOrNone
//      IsUInt         UIntOrNone
//      IsInt          IntOrNone
//      IsZipCode      ZipCodeOrNone
//      IsYear         YearOrNone
//      IsMoney        MoneyOrNone
//      IsEmail         EmailOrNone
//     *Data or action expected 
//      ButtonClicked
//      BoxesChecked
//      ExBoxesChecked
//      IsPassword
//      RadioChecked
//      Selected
//      TextEntered
//      TextAreaEntered
//      TextIsEqual,
// @Note With one exception, all validators are passed two required arguments.
//   1)Widget object 
//   2)Label used to inform user of invalid input.
//     All Validators provide an alert box informing the user, and
//     put focus on the widget (where possible) - if the input is invalid.
//     The exception is TextIsEqual, which takes two widgets and two lables.
//   3)Optional extra text.
//>-----------------------------------------------------------------------------------------------------
var valid_js = 1; // "register" this file with calling code
//<------------------------------------------------------------------------------------------------------
// @syntax [-IsUndefined(<obj>)-] Is object not defined?
//>-----------------------------------------------------------------------------------------------------
function IsUndefined(obj){
  if(!obj) return true;
  var type = typeof(obj);
  if(type.toUpperCase() == 'UNDEFINED')
		return true;
  else return false;
	}
//<------------------------------------------------------------------------------------------------------
// @syntax [-TryAgain(<obj-widget>,<str-message>)-]
// @description Display an error message and put focus on the widget of interest
//>-----------------------------------------------------------------------------------------------------
function TryAgain(widget,message,extra){
  // note: to get focus on a widget that is out of view, 
  // for text, press right or left arrow, 
  // for radio buttons, press TAB
	if(extra){
		alert(message + "\nNOTE:\n" + extra);
		} 
	else alert(message);
	widget.focus();
	widget.select();
	return false;
}
//<------------------------------------------------------------------------------------------------------
// @syntax [-GetIntsOnly(<element-ID>)-]
// @description Remove non-integers from the value of a widget identified by 'ID'
// @example GetIntsOnly('MyTextField') [holds "1 more time 2 go"] => "12"
//>-----------------------------------------------------------------------------------------------------
function GetIntsOnly(ID){
  var widget = document.getElementById(ID);
  var str = widget.value;
  var acceptables = '0123456789';
  var filtered = "";
  var ch;
  for (var i = 0; i < str.length; i++) {
	ch = str.substr(i,1);
	if(acceptables.indexOf(ch) >= 0){
	   filtered = filtered + ch;
	 }
	if(strFind('oO',ch)) filtered = filtered + '0';
  }
  widget.value = filtered;
  return filtered;
}
//<------------------------------------------------------------------------------------------------------
// @syntax [-GetValue(<elemen-ID>)-]
// @description Gets the value attribute from widget identified by ID
//>-----------------------------------------------------------------------------------------------------
function GetValue(ID){
  var widget = document.getElementById(ID);
  return widget.value;
}
//<------------------------------------------------------------------------------------------------------
// @description Same as GetIntsOnly - deprecated
//>-----------------------------------------------------------------------------------------------------
function DigitsOnly(ID){
  var widget = document.getElementById(ID)
  var original = widget.value;
  var filtered = Filter(original,'0123456789');
  widget.value = filtered;
}
//<------------------------------------------------------------------------------------------------------
// @syntax [-File(<str-str>,<str-acceptables>)-]
// @description returns first agument with only chars found in second
//>-----------------------------------------------------------------------------------------------------
function Filter(str,acceptables){
   var filtered = "";
   for (var i = 0; i < str.length; i++) {
		 if(acceptables.indexOf(str.substr(i,1)) >= 0){
			 filtered = filtered + str.substr(i,1);
			 }
		 }
   return filtered;
	}
// =================================================================================
function HelpPhone(){
    alert("Please Include Area Code and hyphens:\n\nEXAMPLE: \"123-456-7890\".\n")
    }
// =================================================================================
function HelpUInt(){
    alert("Integer whole number expected:\n\nPlease use only numbers.\n")
    }
// =================================================================================
function HelpZipCode(){
    alert("First Five Digits of US Zip Code:\n\nPlease use only numbers.\n")
    }
// =================================================================================
function HelpMoney(){
    alert("Currency (money) value expected:\n\nPlease use only numbers and a decimal point.\nTwo (2) digits " + 
          " must be placed to the right of the decimal point.\nDollar signs and minuses are ignored.")
    }
//<------------------------------------------------------------------------------------------------------
// @syntax [-NoCommas(<str-with-some-commas>)-]
// @description Returns argument with commas removed
//>-----------------------------------------------------------------------------------------------------
function NoCommas(str){
  var tmp = str.split(",");
  return tmp.join("");
} 
// @description Reverse a string
function reverse(str) {
	var text = "", i;
	for (var i = 0; i <= str.length; i = i + 1) {
		text = str.substring(i, i + 1) + text;
		}
	return text;
	}
// @description Formats string representation of a decimal with commas
function NewCommas(str){
  var tary = str.split(".");
  var tmp = reverse(tary[0]);
  var done = 0;
  var text = "";
  var len = tary[0].length;
  if(str.charAt(0) == '-') len = len -1;
  if (len < 4){
		return str;	
		}
  for(var i = 0; i < tmp.length; i++){
		text = text + tmp.substr(i,1);
		done++;
		if(done == 3){
			done = 0;
			if (i != tmp.length - 1)
				text = text + ",";
			}
		}
  text = reverse(text);
  if(tary.length > 1){
		text = text + "." + tary[1];
		}
  return text;
	}
// @description Inform user the widget is not an integer and put focus on it.
function NotanInt(ID,value){
  widget = document.getElementById(ID);
  alert('The following value:\n' + value + '\nis not a valid whole number.\n' +
		'Please correct before proceeding.'
		)
  widget.focus();
  widget.select();
  return false;
}
// @description Validates a decimal value in a field. Public Validator
function IsDecimal(field,fieldLabel){
	if(IsUndefined(field)) return true;
  var fieldValue;
  var tmpA;
  var lDigits;   // right of decimal place
	var rDigits;   // left of decimal place
	var minus = '';
	fieldValue = trim(NoCommas(field.value));
    if (StrEmpty(field.value)) 
         return TryAgain(field,"An input field near the following text:\n\"" +  
		    fieldLabel +  "\"\nIs empty, requires a valid number with 1 or more decimal places.")
    if (isNaN(fieldValue)) 
         return TryAgain(field,"An input field near the following text:\n\"" + fieldLabel + 
                               "\"\nContains an incorrect value: " + fieldValue +
                               "\nA valid number with 1 or more decimal places is required.\nNO DOLLAR SIGNS, PLEASE!")
	if(First(fieldValue) == '-'){
	  fieldValue = Rest(fieldValue);
	  minus = '-';
	}
	tmpA = fieldValue.split(".")
    lDigits = tmpA[0];
    if (tmpA.length == 1)
	  rDigits = '00';
	else rDigits = RoundDecimal(tmpA[1]);
	lDigits = NewCommas(lDigits);
	field.value = minus + lDigits + "." + rDigits;
	//	alert("'" + fieldLabel + "'\n" + 'value: ' + field.value + '\nrDigits: ' + rDigits);
	return true;
}
//<------------------------------------------------------------------------------------------------------
// @syntax [-IsEmail(<obj-field>,<str-label>)-]
// @description Validates that a field has a legitimate email value. Public Validator
//>-----------------------------------------------------------------------------------------------------
function IsEmail(field,fieldLabel){
  if(IsUndefined(field)) return true;
  var str = field.value;
  var msg = "An input field near the following text:\n\"" +
	fieldLabel +  "\"\nrequires a valid email address.";
  if (StrEmpty(str))
	return TryAgain(field,"An input field near the following text:\n\"" +
					fieldLabel +  "\"\nIs empty, requires a valid email address.");
  var at="@";
  var dot=".";
  var lat=str.indexOf(at);
  var lstr=str.length;
  var ldot=str.indexOf(dot);
  if (str.indexOf(at)==-1) return TryAgain(field,msg);
  if (str.indexOf(at)==-1 || str.indexOf(at)==0 || str.indexOf(at)==lstr)
	return TryAgain(field,msg);
  if (str.indexOf(dot)==-1 || str.indexOf(dot)==0 || str.indexOf(dot)==lstr)
	return TryAgain(field,msg);
  if (str.indexOf(at,(lat+1))!=-1) return TryAgain(field,msg);
  if (str.substring(lat-1,lat)==dot || str.substring(lat+1,lat+2)==dot)
	return TryAgain(field,msg);
  if (str.indexOf(dot,(lat+2))==-1) return TryAgain(field,msg);
  if (str.indexOf(" ")!=-1) return TryAgain(field,msg);
  return true;
}
// @description Confirms that a field has a valid email address or nothing
function EmailOrNone(S,L){
	if(IsUndefined(S)) return true;
    if (StrEmpty(S.value)) return true; // if empty validate (field not required)
    return IsEmail(S,L);
    }
//<------------------------------------------------------------------------------------------------------
// @syntax [-IsMoney(<obj-field>,<str-label>)-]
// @description Confirms that a field has a valid monetary value or nothing.
//>-----------------------------------------------------------------------------------------------------
function IsMoney(field,fieldLabel){
  //	alert('fieldLabel: ' + fieldLabel); //debug
	if(IsUndefined(field)) return true;
    var fieldValue;
    var tmpA;
    var lDigits;   // right of decimal place
	var rDigits;   // left of decimal place
	fieldValue = field.value;
	if (First(fieldValue) == '-' || First(fieldValue) == '$') // repeat to remove possibilty
	  fieldValue = Rest(fieldValue);                          // of two unneeded characters
	if (First(fieldValue) == '-' || First(fieldValue) == '$')
	  fieldValue = Rest(fieldValue);
	fieldValue = trim(NoCommas(fieldValue));
    if (StrEmpty(field.value)) 
         return TryAgain(field,"An input field near the following text:\n\"" +  
		    fieldLabel +  "\"\nIs empty, requires a valid monetary number with two decimal places.")
    if (isNaN(fieldValue)) 
         return TryAgain(field,"An input field near the following text:\n\"" + fieldLabel + 
                               "\"\nContains an incorrect value: " + fieldValue +
                               "\nA valid number with 2 decimal places is required.\nNO DOLLAR SIGNS, PLEASE!")
	tmpA = fieldValue.split(".")
    lDigits = tmpA[0];
    if (tmpA.length == 1)
	  rDigits = '00';
	else rDigits = RoundDecimal(tmpA[1],2);
	lDigits = NewCommas(lDigits);
	field.value = lDigits + "." + rDigits;
	//	alert("'" + fieldLabel + "'\n" + 'value: ' + field.value + '\nrDigits: ' + rDigits);
	return true;
}
// @description round a decimal to two decimal places
function RoundDecimal(str,len){
	var tmp = str.split('.');
  //  alert('tmp: ' + tmp); //debug
  //  if(tmp.length == 1){ // no decimal point
  //	return str + '.00'
  //  }
	if(len){
		var maxlen = len;
		} else{
				var maxlen = 6;
			}
  var num;   // numeric representation of first two digits
  var third; // numeric representation of third digits
  if (str.length == 1) return str + "0"; // pad with a zero
  if (str.length <= maxlen) return str;       // do nothing
  // parseInt
  num = parseInt(str.substring(0,maxlen),10);
  var lastD = parseInt(str[maxlen],10);
  if(lastD > 4){ // round up
	num = num + 1;
  }
  return "" + num;
}
// @description Rounds a string without a decimal point to two digits
function RoundCents(str){
  var num;   // numeric representation of first two digits
  var third; // numeric representation of third digits
  if (str.length == 1) return str + "0"; // pad with a zero
  if (str.length == 2) return str;       // do nothing
  // parseInt
  num = parseInt(str.substring(0,2),10);
  third = parseInt(str[2],10);
  if(third > 4){ // round up
	num = num + 1;
  }
  return "" + num;
}
//<------------------------------------------------------------------------------------------------------
// @syntax [-IsPhone(<obj-field>,<str-label>)-]
// @description Validates that a field holds a string with a phone format
//>-----------------------------------------------------------------------------------------------------
function IsPhone(field,fieldLabel){
	if(IsUndefined(field)) return true;
	var strString = field.value;
    if (StrEmpty(strString))
            return TryAgain(field,"An input field near the following text:\n\"" +  
			   fieldLabel + "\"\nrequires a phone number.")
    if (strString.search(/^[0-9][0-9][0-9]\-[0-9][0-9][0-9]\-[0-9][0-9][0-9][0-9]$/) == -1)
        return TryAgain(field,"An input field near the following text:\n\"" +  
		   fieldLabel + "\"\nrequires a valid phone number.\nNOTE: Use the following format: \"123-456-7890\"")
    return true;
    }
// =================================================================================
// Original JavaScript code by Chirp Internet: www.chirp.com.au 
// Please acknowledge use of this code by including this header.
// =================================================================================
//<------------------------------------------------------------------------------------------------------
// @syntax [-IsTime(<obj-field>,<str-label>)-]
// @description Validates a field with a time format
//>-----------------------------------------------------------------------------------------------------
function IsTime(field,label){
   if(IsUndefined(field)) return true;
   var FieldValue = field.value;
   //   var tmp = "";
   var acceptables = "0123456789apm:";
   var mlabel = "An input field near the following text:\n\"" + label + "\"\nhas been incorrectly entered.\n" +
               "Problem is below:\n";
   var errorMsg = "";
   var instructions = "\n\nEXAMPLE CORRECT TIME - 12:30am\nHour is 1 or 2 digits, minute is 2 digits, seperated by ':'" +
                      "\n followed by 'am' or 'pm' (NO SPACE)"
   // regular expression to match required time format
   re = /^(\d{1,2}):(\d{2})([ap]m)?$/;
     if (StrEmpty(FieldValue)){
            alert("An input field near the following text:\n\"" +  fieldLabel + "\"\nrequires a valid TIME.")
            return false;
            }
   FieldValue = field.value = Filter(field.value,acceptables);
   if(FieldValue != '') {
      if(regs = FieldValue.match(re)) {
	     if(regs[3]) {
		    // 12-hour time format with am/pm
			if(regs[1] < 1 || regs[1] > 12) {
			   errorMsg = "Invalid value for hours: " + FieldValue;
			}
         } else {
		    // 24-hour time format
			if(regs[1] > 23) {
			   errorMsg = "Invalid value for hours: " + FieldValue;
			}
         }
         if(!errorMsg && regs[2] > 59) {
		    errorMsg = "Invalid value for minutes: " + FieldValue;
            }
         } else {
		    errorMsg = "Invalid time format: " + FieldValue + instructions;
         }
      }   
   if(errorMsg != "") return TryAgain(field,mlabel + errorMsg);
   else return true;
}
//<------------------------------------------------------------------------------------------------------
// @syntax [-IsZipCode(<obj-field>,<str-label>)-]
// @description Validates a zipcode format. Public Validator
//>-----------------------------------------------------------------------------------------------------
function IsZipCode(field,fieldLabel){
	if(IsUndefined(field)) return true;
    if (StrEmpty(field.value))
            return TryAgain(field,"An input field near the following text:\n" + "\"" +  
			   fieldLabel + "\""  +  "\nrequires a valid 5-digit Zip Code.")
    if (field.value.search(/^[0-9][0-9][0-9][0-9][0-9]$/) == -1)
        return TryAgain(field,"An input field near the following text:\n" + "\"" +  
		   fieldLabel + "\""  +  "\nrequires a valid 5-digit Zip Code.\nNOTE: Use the following format: \"12345\"")
    return true;
    }
//<------------------------------------------------------------------------------------------------------
// @syntax  [-IsColorCode(<obj-field>,<str-label>)-]
// @description Validates a colorcode format.
//>-----------------------------------------------------------------------------------------------------
function IsColorCode(field,fieldLabel){
	if(IsUndefined(field)) return true;
    if (StrEmpty(field.value))
            return TryAgain(field,"An input field near the following text:\n" + "\"" +  
			   fieldLabel + "\""  +  "\nrequires a valid ColorCode.")
    if (field.value.search(/^#[0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef][0-9ABCDEFabcdef]$/) == -1)
        return TryAgain(field,"An input field near the following text:\n" + "\"" +  
		   fieldLabel + "\""  +  "\nrequires a valid 7-byte Color Code.\nNOTE: Use the 'Pick' link.")
    return true;
    }
//<------------------------------------------------------------------------------------------------------
// @syntax [-IsYear(<obj-field>,<str-label>)-]
// @description Validates a year format.
//>-----------------------------------------------------------------------------------------------------
function IsYear(field,fieldLabel){
	if(IsUndefined(field)) return true;
    if (StrEmpty(field.value))
            return TryAgain(field,"An input field near the following text:\n" + "\"" +  
			   fieldLabel + "\""  +  "\nrequires a valid 4-digit Year.")
    if (field.value.search(/^[0-9][0-9][0-9][0-9]$/) == -1)
        return TryAgain(field,"An input field near the following text:\n" + "\"" +  
		   fieldLabel + "\""  +  "\nrequires a valid 4-digit Year.\nNOTE: Use the following format: \"1999\"")
    return true;
    }
// @description Validates a whole number format. Probably deprecated.
function NotNumber(val){
    var strValidChars = "0123456789,";
    for (var i = 0; i < val.length; i++){
	  strChar = val.charAt(i);
	  if (strValidChars.indexOf(strChar) == -1){
		alert('found invalid');
		return true;
		}
	}
	alert('OK');
    return false;
}
//<------------------------------------------------------------------------------------------------------
// @syntax [-IsUInt(<obj-field>,<str-label>)-]
// @description Validates a unsigned integer format. May have commas.
//>-----------------------------------------------------------------------------------------------------
function IsUInt(field,fieldLabel,def){
	if(IsUndefined(field)) return true;
	var strValidChars = "0123456789,";
	var strChar;
	var blnResult = true;
	var strString = field.value;
	var tmpAry = strString.split("."); 
	strString = tmpAry[0];   // get rid of any decimal points
  //if(isNaN(month))
	if(StrEmpty(strString)){
		if(def){
			if(isNaN(def)){
				def = 1;
				}
			strString = "" + def;
			field.value = strString;
			}	
		}
	if (StrEmpty(strString))
		return TryAgain(field,"An input field near the following text:\n" + "\"" +  fieldLabel+ "\""  +  
			"\nrequires an unsigned whole number (no decimals please!).");
	for (var i = 0; i < strString.length && blnResult == true; i++){
		strChar = strString.charAt(i);
		if (strValidChars.indexOf(strChar) == -1){
			return TryAgain(field,"An input field near the following text:\n" + "\"" +  
				fieldLabel+ "\""  +  "\nrequires a unsigned WHOLE NUMBER (no decimals please!).");
			}
		}
	//strString = NewCommas(NoCommas(strString));
	field.value = strString;
	return strString;
	}
//<------------------------------------------------------------------------------------------------------
// @syntax [-IsInt(<obj-field>,<str-label>)-]
// @description Validates a signed integer value. May have a minus.
//>-----------------------------------------------------------------------------------------------------
function IsInt(field,fieldLabel){
	if(IsUndefined(field)) return true;
	var strValidChars = "-0123456789,";
	var strChar;
	var blnResult = true;
	var strString = field.value;
	var tmpAry = strString.split(".");
	strString = tmpAry[0];   // get rid of any decimal points
	if (StrEmpty(strString))
		return TryAgain(field,"An input field near the following text:\n" + "\"" +  fieldLabel+ "\""  
			+  "\nrequires an whole number (no decimals please!).");
	for (var i = 0; i < strString.length && blnResult == true; i++){
		strChar = strString.charAt(i);
		if (strValidChars.indexOf(strChar) == -1)
			return TryAgain(field,"An input field near the following text:\n" + "\"" +  
				fieldLabel+ "\""  +  "\nrequires a WHOLE NUMBER (no decimals please!).");
		}
	var minus = "";
	var newString = strString;
	if(newString[0] == "-"){
	  newString = Rest(newString);
	  minus = "-";
		}
	newString = NewCommas(NoCommas(newString));
	field.value = minus + newString;
	return true;
	}
// @description Validates a date. Or an empty field. Public Validator
function DateOrNone(S,L){
	if(IsUndefined(S)) return true;
    if (StrEmpty(S.value)) return true; // if empty validate (field not required)
    return IsDate(S,L);
    }
// @description Validates a time. Or an empty field. Public Validator
function TimeOrNone(S,L){
	if(IsUndefined(S)) return true;
    if (StrEmpty(S.value)) return true; // if empty validat (field not required)
    return IsTime(S,L);
    }
// @description Validates an unsigned integer. Or an empty field. Public Validator
function UIntOrNone(S,L){
  //alert('L: ' + L); //debug
	if(IsUndefined(S)) return true;
    if (StrEmpty(S.value)) return true; // if empty validate (field not required)
    return IsInt(S,L);
    }
// @description Validates a signed integer. Or an empty field. Public Validator
function IntOrNone(S,L){
  //alert('L: ' + L); //debug
	if(IsUndefined(S)) return true;
    if (StrEmpty(S.value)) return true; // if empty validate (field not required)
    return IsInt(S,L);
    }
// @description Validates a year. Or an empty field. Public Validator
function YearOrNone(S,L){
	if(IsUndefined(S)) return true;
    if (StrEmpty(S.value)) return true; // if empty validate (field not required)
    return IsYear(S,L);
    }
// @description Validates a phone number. Or an empty field. Public Validator
function PhoneOrNone(S,L){
	if(IsUndefined(S)) return true;
    if (StrEmpty(S.value)) return true; // if empty validate (field not required)
    return IsPhone(S,L);
    }
// @description Validates a Zip code. Or an empty field. Public Validator
function ZipCodeOrNone(S,L){
	if(IsUndefined(S)) return true;
    if (StrEmpty(S.value)) return true; // if empty validate (field not required)
    return IsZipCode(S,L);
    }
// @description Validates a Color code. Or an empty field. Public Validator
function ColorCodeOrNone(S,L){
	if(IsUndefined(S)) return true;
    if (StrEmpty(S.value)) return true; // if empty validate (field not required)
    return IsColorCode(S,L);
    }
// @description Validates a decimal amount. Or an empty field. Public Validator
function DecimalsOrNone(S,L){
	if(IsUndefined(S)) return true;
    if (StrEmpty(S.value)) return true; // if empty validate (field not required)
    return IsDecimal(S,L);
    }
// @description Validates a monetary amount. Or an empty field. Public Validator
function MoneyOrNone (S,L){
	if(IsUndefined(S)) return true;
    if (StrEmpty(S.value)) return true; // if empty validate (field not required)
    return IsMoney(S,L);
    }
//<------------------------------------------------------------------------------------------------------
// @syntax [-RadioChecked(<obj-field>,<str-label>)-]
// @description Returns true if a member of a radio button group has been checked.
//>-----------------------------------------------------------------------------------------------------
function RadioChecked(r,label){
	if(IsUndefined(r)) return true;
    for (var n = 0; n < r.length; n++ )
        if(r[n].checked){
			return true;
			}
    return TryAgain(r[0],"A group of buttons near the following text:\n\"" +  
	   label + "\"\nrequires a selection.");
    }
//<------------------------------------------------------------------------------------------------------
// @syntax [-ExBoxesChecked(<obj-field>,<str-label>)-]
// @description Returns true if one member of an exclusive checkbox group has been checked.
//>-----------------------------------------------------------------------------------------------------
function ExBoxesChecked(r,label){
	if(IsUndefined(r)) return true;
    for (var  n = 0; n < r.length; n++ )
        if(r[n].checked) return true;
    return TryAgain(r[0],"A group of checkboxes near the following text:\n\"" +  
	   label + "\"\nrequires a selection.");
    }
// @description Returns true if password field is empty. Probably deprecated.
function PwdEmpty(str){return StrEmpty(str);}
// @description Returns true if a string value is empty.
function StrEmpty(str){
    for (var  n = 0; n < str.length; n++ )
        if(str.charAt(n) != " ") return false;
    return true;
    }
//<------------------------------------------------------------------------------------------------------
// @syntax [-ButtonClicked(<obj-field>,<str-label>)-]
// @description Returns true if a button has been clicked. Public Validator
//>-----------------------------------------------------------------------------------------------------
function ButtonClicked(B,label){
   if(IsUndefined(B)) return true;
   var val = B.value;
   if (StrEmpty(val))
      return TryAgain(B,"A button near the following text:\n" + "\""
					  +  label + "\""  +  "\nrequires a selection.");
   return true;
}
//<------------------------------------------------------------------------------------------------------
// @syntax [-TextEntered(<obj-field>,<str-label>)-]
// @description Returns true if a fields holds some text. Public Validator
//>-----------------------------------------------------------------------------------------------------
function TextEntered(B,label){
	 //alert("Label: " + label +" B: " + B);  // DEBUG GLOBAL
   if(IsUndefined(B)) return true;
   if (StrEmpty(B.value))
      return TryAgain(B,"An input field near the following text:\n\""
					  +  label +  "\"\nmust be filled in.");
   return true;
}
//<------------------------------------------------------------------------------------------------------
// @syntax [-IsPassword(<obj>,<label>,<int-maxlen>,<int-minlen>)-]
// @description Return true if the value for a password field has at least minlen
// characters and no more than maxlen characters. Public Validator
//>-----------------------------------------------------------------------------------------------------
function IsPassword(B,label,maxlen,minlen){
  if(IsUndefined(B)) return true;
  var val = trim(B.value);
  var msg = "A password field with the following label:\n" + "\"" +  label + "\"";
  if (StrEmpty(val))
     return TryAgain(B,msg + "\nmust be filled in.");
  if(val.length < minlen){
	return TryAgain(B,msg + "\nmust have at least " + minlen + " characters")
  }
  if(val.length > maxlen){
	return TryAgain(B, msg + "\nmust have no more than " + maxlen + " characters")
  }
  if(strFind(val,' ')){
	return TryAgain(B, msg + "\nmust not have any embedded spaces.")
  }
  return true;
}
// @description Probably deprecated.
function PasswordOrNone(S,L){
	if(IsUndefined(S)) return true;
    if (StrEmpty(S.value)) return true; // if empty, confirm (field not required)
    return IsPassword(S,L);
    }
//<------------------------------------------------------------------------------------------------------
// @syntax [-Password(<obj-field>,<str-label>)-]
// @description Test a password field for data. 
//>-----------------------------------------------------------------------------------------------------
function PasswordEntered(B,label){
   if(IsUndefined(S)) return true;
   if (StrEmpty(B.value))
      return TryAgain(B,"A password field with the following label:\n" +
					  "\"" +  label + "\""  +  "\nmust be filled in.");
   return true;
}
//<------------------------------------------------------------------------------------------------------
// @syntax [-TextAreaEntered(<obj-field>,<str-label>)-]
// @description Validates text in a textarea field.
//>-----------------------------------------------------------------------------------------------------
function TextAreaEntered(B,label){
   if(IsUndefined(B)) return true;
   if (StrEmpty(B.value))
      return TryAgain(B,"A multiple line field near the following text:\n"
					  + "\"" +  label + "\""  +  "\nmust be filled in.");
   return true;
} // test
//<------------------------------------------------------------------------------------------------------
// @syntax [-LimitCheckBoxes(<obj-chk>,<obj-form>,<int-ncheck>,<str-label>)-]
// @description Returns true if no more than 'ncheck' items are checked.
// @Returns false and alerts user is too many are checked.
//>-----------------------------------------------------------------------------------------------------
function LimitCheckBoxes(chk,form,ncheck,label){
	var b = document[form][chk];
	if(IsUndefined(b)) return true;
	var num = 0;
	for (var n = 0; n < b.length; n++){
	  if(b[n].checked) num++;
	  if(num > ncheck){
		b[n].checked = false;
		alert('No more than ' + ncheck + " checkboxes can be checked for\n" +
			  label + "\nYou may need to uncheck one or more boxes.")
	    break;
	  }
	}
}
//<------------------------------------------------------------------------------------------------------
// @syntax [-BoxesChecked(<str-obj>,<int-ncheck>,<str-label>)-]
// @description Returns true if 'ncheck' items of a group of checkboxes are checked.
//>-----------------------------------------------------------------------------------------------------
function BoxesChecked(b,ncheck,label){
	if(IsUndefined(b)) return true;
    var num = 0;
	var message;
    if(IsDefined(b.length)){  // multiple boxes
		for (var n = 0; n < b.length; n++ ){
			if(b[n].checked) num++;
			}
		if(num < ncheck){ 
		   if(ncheck == 1)
			  message = "A group of checkboxes with the following label:\n\"" +  label 
				 + "\"\nrequires at least 1 selection."
		   else
			  message = "A group of checkboxes with the following label:\n\"" +  label 
				 + "\"\nrequires at least " + ncheck + " selections."
		   return TryAgain(b[0],message);
			}
		else return true;
		} // end multiple checkboxes
	else{
		if(!b.checked){
		   return TryAgain(b,"A checkbox with the following label:\n\"" +  label + "\nmust be checked.")
			}
		else return true
		}
	}
// @description Informs of a missing value.
function MissingValue(str){
    alert("A field named:\n" + "\"" +  str + "\""  +  "\nis required.")
    return false;
    }
// @description Informs of a missing password.
function MissingPwd(str){
    alert("A password field named:\n" + "\"" +  str + "\""  +  "\nis required.")
    return false;
    }
// @description Informs of a unchecked box
function MissingCheckBox(str,num){
    alert("A group of checkboxes with the following label:\n" + "\"" +  str + "\""
		  +  "\nrequires at least " + num + " selection(s).");
    return false;
	}
// @description Informs of a button not checked.
function MissingButton(str){
    alert("A button with the following label:\n" + "\"" +  str + "\""  +
		  "\nneeds to be clicked.");
	return false;
	}
// =================================================================================
function NonUIntData(str){
    alert("A field with the following label:\n" + "\"" +  str + "\""  +
		  "\nmust have numbers and commas only.");
    return false;
    }
// @description Returns true if a valid item in a drop-down list is checked.
// L is the lower limit of indexes to be selected. Probably deprecated.
function SelectChecked(s,L){
	if(IsUndefined(s)) return true;
    if (s.selectedIndex < L){return false;}
    return true;
    }
//<------------------------------------------------------------------------------------------------------
// @syntax [-Selected(<obj>,<int-min-index>,<str-label>)-]
// @description Returns true if a valid item in a drop-down list is checked.
// min-index is the lower limit of indexes to be selected. Public Validator
//>-----------------------------------------------------------------------------------------------------
function Selected(s,ndx,L){
	if(IsUndefined(s)) return true;
    if (s.selectedIndex < ndx)
	  return MissingListSelection(L);
    return true;
    }
//<------------------------------------------------------------------------------------------------------
// @syntax [-IsDate(<obj-field>,<str-label>,<str-extra>)-]
// @description Validates a date field. Public Validator
//>-----------------------------------------------------------------------------------------------------
function IsDate(field,label,extra){
   if(IsUndefined(field)) return true;
   var LeapYear = 0;
   var month;  // string
   var day;    // string
   var year;   // string
   var iMonth; // integer
   var iDay;   // integer
   var iYear;  // integer
   var PartsMessage = "A date must have a month, day, and year. All must be a number\n" +
	                  "and must be seperated by a forward slash.\n";
   var Examples = "EXAMPLE: January 12, 2003 => 1/12/2003\n" + "EXAMPLE: December 2, 2003 => 12/2/2003\n";
   var tary;
   var errmsg;
   var parts = 1; // must be three
   var DateTemp = "";
   var checkstr = "0123456789";
   var mlabel = "An input field near the following text:\n\"" + label +
	            "\"\nrequires a valid date.\nThe problem is:\n";
   var DateValue = field.value;
   if (StrEmpty(DateValue))
      return TryAgain("An input field near the following text:\n" + "\"" +  
	     label + "\""  +  "\nrequires a valid date.",extra)
		// correct for delimiters, changing any non-numeric character to a "/"
   for (var i = 0; i < DateValue.length; i++) {
	  if (checkstr.indexOf(DateValue.substr(i,1)) >= 0) {
	     DateTemp = DateTemp + DateValue.substr(i,1);
	  }else{ // replace with forward slash
		DateTemp = DateTemp + "/";
		parts++;
	  }
   }
   if (parts != 3)
	 return TryAgain(field,mlabel + PartsMessage + Examples,extra);
   // now split into month, day, and year
   tary = DateTemp.split("/");
   month = tary[0];
   if(isNaN(month))
	 return TryAgain(field,mlabel + "Month (first part) must be a number.",extra);
   day = tary[1];
   if(isNaN(day))
	 return TryAgain(field,mlabel + "Day (second part) must be a number.",extra);
   year = tary[2];
   if(isNaN(year))
	 return TryAgain(field,mlabel + "Year (third part) must be a number.",extra);
   if(year.length != 4)
	 return TryAgain(field,mlabel + "Year (third part) must have exactly FOUR (4) digits.",extra)
   iMonth = ParseIntZeroes(tary[0]);
   iDay = ParseIntZeroes(tary[1]);
   iYear = ParseIntZeroes(tary[2]);
   if ((iMonth < 1) || (iMonth > 12))
	 return TryAgain(field,mlabel + "Month (first part) must be between 1 and 12",extra);
   // handle for leapyear and february => adjust day to legal
   if ((iYear % 4 == 0) || (iYear % 100 == 0) || (iYear % 400 == 0) ) LeapYear = 1;
   if ((iMonth == 2) && (LeapYear == 1) && (iDay > 29))
	 iDay = 29;
   if ((iMonth == 2) && (LeapYear != 1) && (iDay > 28))
	 iDay = 28;
   // Validation of other months => adjust day to legal
   if ((iDay > 31) && ((iMonth == 1) || (iMonth == 3) || (iMonth == 5) || (iMonth == 7) 
	  || (iMonth == 8) || (iMonth == 10) || (iMonth == 12)))
	 iDay = 31;
   if ((iDay > 30) && ((iMonth == 4) || (iMonth == 6) || (iMonth == 9) || (iMonth == 11)))
	   iDay = 30;
   if (iMonth < 10)
	 month = "0" + iMonth;
   else month = "" + iMonth;
   if (iDay < 10)
	 day = "0" + iDay;
   else day = "" + iDay;
   field.value = month + "/" + day + "/" + year;
   return true;
}
// @description Informs of a missing select list option checked.
function MissingListSelection(label){
  alert('A selection from a list with the following label:\n'
        + '\"' + label + '\"' + '\nis required.')
  return false;
  }
// @description Compares two text fields for equality. Public Validator
function TextIsEqual(B1,label1,B2,label2){
  if(trim(B1.value) == trim(B2.value)) return true;
  else {
  	alert("Two fields with the following labels:\n" + "\""
          + label1 + "\" AND \"" + label2 + "\"\n" + "MUST be equal." )
	  return false;
    }
  }
// =================================================================================
function trim(str) { 
  return str.replace(/^\s+/g, '').replace(/\s+$/g, '');
  } 
