var fm_valid_js = 1; // "register" this file with calling code
// =================================================================================
//   Use for the rebol fmflds.r module
// =================================================================================
function TryAgain(widget,message){
  // note: to get focus on a widget that is out of view, 
  // for text, press right or left arrow, 
  // for radio buttons, press TAB
   alert(message);
   widget.focus();
   widget.select();
   return false;
}
// remove any chars not found in acceptables
// "tainted" characters.
// =================================================================================
function GetIntsOnly(ID){
  var widget = document.getElementById(ID);
  var str = widget.value;
  var acceptables = '0123456789';
  var filtered = "";
  var ch;
  for (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;
}
// =================================================================================
function GetValue(ID){
  var widget = document.getElementById(ID);
  return widget.value;
}
// =================================================================================
function DigitsOnly(ID){
  var widget = document.getElementById(ID)
  var original = widget.value;
  var filtered = Filter(original,'0123456789');
  widget.value = filtered;
}
// =================================================================================
// Return only acceptables in str
// =================================================================================
function Filter(str,acceptables){
   var filtered = "";
   for (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.")
    }
// =================================================================================
function NoCommas(str){
  var tmp = str.split(",");
  return tmp.join("");
} 
// =================================================================================
function reverse(str) {
  var text = "";
  for (i = 0; i <= str.length; i++)
     text = str.substring(i, i+1) + text;
  return text;
}
// =================================================================================
function NewCommas(str){
  var tary = str.split(".");
  var tmp = reverse(tary[0]);
  var done = 0;
  var text = "";
  if (tary[0].length < 4) return str;
  for(i = 0; i < tmp.length; i++){
	text = text + tmp.substr(i,1);
	//alert('text: ' + text);
	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;
}
// =================================================================================
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;
}
// =================================================================================
function IsDecimal(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
	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 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!")
	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;
}
// =================================================================================
//  Round a decimal value to a monetary-suitable value with 2 degrees of precision
// =================================================================================
function MoneyRound(v){
  if(isNaN(v)){
	alert('Value is not a number: [' + val + ']');
	return false
  }
  var val = '' + v;  // make sure we have a string
  if(val[0] == '.')
	val = '0' + val;
  var tmp = val.split('.')
  if (tmp.length == 1)   // no decimal
    return val + '.00'   // just append two zeroes
  if(tmp[1].length == 1) // one degree of precision, append 1 zero
	 return val + '0';   
  if(tmp[1].length == 2) return val; // no operation needed
  // presume that we now have a precision of 3 or more
  var leftn = parseInt(tmp[0],10);
  var rightn = parseInt(tmp[1].slice(0,2),10);
  var rightmost = parseInt(tmp[1].slice(2,3),10);
  if(rightmost > 4){ // need to round up
	if(rightn == 99){ // must round up left
	  leftn = leftn + 1;
	  return '' + leftn + '.00';
	}else{
	  rightn = rightn + 1;
	  return '' + leftn + '.' + rightn;
	}
  }else{ 
	return '' + leftn + '.' + rightn;
  }
  return val;
}
// =================================================================================
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]);
	lDigits = NewCommas(lDigits);
	field.value = lDigits + "." + rDigits;
	//	alert("'" + fieldLabel + "'\n" + 'value: ' + field.value + '\nrDigits: ' + rDigits);
	return true;
}
// Round a decimal to two places
// =================================================================================
function RoundDecimal(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;
}
// =================================================================================
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.
// =================================================================================
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;
            }
//    for (i = 0; i < FieldValue.length; i++) {
// 	 if(acceptables.indexOf(FieldValue.substr(i,1)) >= 0){
// 	   tmp = tmp + FieldValue.substr(i,1);
// 	 }
//    }
   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;
}
// =================================================================================
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;
    }
// =================================================================================
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;
    }
// =================================================================================
function NotNumber(val){
    var strValidChars = "0123456789,";
    for (i = 0; i < val.length; i++){
	  strChar = val.charAt(i);
	  if (strValidChars.indexOf(strChar) == -1){
		alert('found invalid');
		return true;
		}
	}
	alert('OK');
    return false;
}
// =================================================================================
function IsUInt(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 a number (no decimals please!).");
	for(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!).");
		}
	field.value =  NewCommas(NoCommas(strString));
	return true;
	}
// =================================================================================
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);
    }
// =================================================================================
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);
    }
// =================================================================================
function UIntOrNone(S,L){
  if(IsUndefined(S)){
	return true;
  }
    if (StrEmpty(S.value)) return true; // if empty validate (field not required)
    return IsUInt(S,L);
    }
// =================================================================================
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);
    }
// =================================================================================
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);
    }
// =================================================================================
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);
    }
// =================================================================================
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);
    }
// =================================================================================
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);
    }
// =================================================================================
function RadioChecked(r,label){
	if(IsUndefined(r)) return true;
    for ( 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.");
    }
// =================================================================================
function ExBoxesChecked(r,label){
	if(IsUndefined(r)) return true;
    for ( 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.");
    }
// ================================================================================= for MU
function PwdEmpty(str){return StrEmpty(str);}
// =================================================================================
function StrEmpty(str){
    for ( n = 0; n < str.length; n++ )
        if(str.charAt(n) != " ") return false;
    return true;
    }
// =================================================================================
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;
}
// =================================================================================
function TextEntered(B,label){
  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;
}
// =================================================================================
function PwdEntered(B,label){
   if(IsUndefined(B)) return true;
   if (StrEmpty(B.value))
      return TryAgain(B,"An password field near the following text:\n\""
					  +  label +  "\"\nmust be filled in.");
   return true;
}
// =================================================================================
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;
}
// =================================================================================
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);
    }
// =================================================================================
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;
}
// =================================================================================
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;
}
// =================================================================================
function BoxesChecked(b,ncheck,label){
	if(IsUndefined(b)) return true;
    var num = 0;
	var message;
    if(IsDefined(b.length)){  // multiple boxes
		for ( 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
		}
	}
// =================================================================================
function MissingValue(str){
    alert("A field named:\n" + "\"" +  str + "\""  +  "\nis required.")
    return false;
    }
// =================================================================================
function MissingPwd(str){
    alert("A password field named:\n" + "\"" +  str + "\""  +  "\nis required.")
    return false;
    }
// =================================================================================
function MissingCheckBox(str,num){
    alert("A group of checkboxes with the following label:\n" + "\"" +  str + "\""  +
		  "\nrequires at least " + num + " selection(s).");
    return false;
	}
// =================================================================================
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;
    }
// =================================================================================
function SelectChecked(s,L){
	if(IsUndefined(L)) return true;
    if (s.selectedIndex < L){return false;}
    return true;
    }
// =================================================================================
function Selected(s,ndx,L){
    if(IsUndefined(s)) return true;
    if(s.length == 1) return true;
    if (s.selectedIndex < ndx)
	  return MissingListSelection(L);
    return true;
    }
// =================================================================================
function IsDate(field,label){
   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(field,"An input field near the following text:\n" + "\"" +  
	     label + "\""  +  "\nrequires a valid date.")
		// correct for delimiters, changing any non-numeric character to a "/"
   for (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);
   // 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.");
   day = tary[1];
   if(isNaN(day))
	 return TryAgain(field,mlabel + "Day (second part) must be a number.");
   year = tary[2];
   if(isNaN(year))
	 return TryAgain(field,mlabel + "Year (third part) must be a number.");
   if(year.length != 4)
	 return TryAgain(field,mlabel + "Year (third part) must have exactly FOUR (4) digits.")
   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");
   // 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;
}
// =================================================================================
function MissingListSelection(label){
  alert('A selection from a list with the following label:\n'
        + '\"' + label + '\"' + '\nis required.')
  return false;
  }
// =================================================================================
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, '');
} 
