/*
  Get the value of a form field in the current window or a given
  window. The field can be text, textarea, hidden or combobox.

  Parameters:
  	sName			The name of the field. 
  	sFormName	The name of the form containing the field.
 
  Returns:
  	The field value as a string. 
*/
function StdGetFieldValue(sName, sFormName)
{

	//Name is not valid for XHTML
	var f= null;
	f = window.document.getElementById(sFormName);
	if (f==null) f = window.document.forms[sFormName];	
	if (f==null) return null;

	var fld = f[sName];	
	if (fld==null) return null;

	var sType = fld.type ? fld.type : fld[0].type ;

	if (sType=="text"||sType=="textarea"||sType=="hidden"||sType=="password") {
        if (fld.length) {
			alert("Duplicate fields for name "+sName);
           return null;
		}
		return fld.value;
	}

	if (sType=="select-one" ) {
		var opt = fld.options[fld.selectedIndex]
		return (opt.value.length) ? opt.value : opt.text 
	}

	if (!fld.length) fld = new Array(fld);

    if (sType=="radio" || sType=="checkbox") {

		var s = "";
	    for (var n=0; n<fld.length; n++)  
			if (fld[n].checked=="1") s += fld[n].value;
        return s;   

	}

	return null;
}

var defaultEmptyOK = true;
/*
  Characters considered to be white space.
*/
var Whitespace = " \t\n\r";

/*
  Determine whether a string is effectively blank.
  
  Parameters:
    s - the string to examine
    
  Returns:
    true if the string is blank, false otherwise
*/

function ValIsWhitespace (s)
{   
    /*
	 Check for an empty string.
    */
    if (s==null||s.length==0) return true;

    /*
	Check for combobox noise string.
    */
    var regexp = /[- ]*select from list[- ]*/i ;
    if (regexp.test(s)) return true ;

    /*
    	 Loop through the string looking for a non-whitespace character.
    */
    for (var i=0; i<s.length; i++) 
      if (Whitespace.indexOf(s.charAt(i))<0) return false;

    /* 
	 All characters are whitespace.
    */
    return true;
}

function ValCheckMandatoryFields(asFields, sFormName)
{
  var sErr = "";

  for (var n=0; n<asFields.length; n+=2) {
 	var sName = asFields[n];
	if (ValIsWhitespace(StdGetFieldValue(sName, sFormName))) {
	  if (sErr!="") sErr += "\n";
	  sErr += asFields[n+1];	
	}
  }
  
  return sErr;
}


/*
  Determine whether a given year is a leap year.
  
  Parameters:
    nYear - the year as an integer
    
  Returns:
    true if the year is a leap year, false otherwise
*/
function ValIsLeapYear(nYear)
{
  if (nYear%400==0) return true;
  if (nYear%100==0) return false;
  return (nYear%4==0);
}


/*
  This table defines the valid month naming strings and supplies
  data for the ValDaysInMonth function.
*/
var ValMonthData = new Object;
ValMonthData.jan = 31;
ValMonthData.january = 31;
ValMonthData.feb = 28;
ValMonthData.february = 28;
ValMonthData.mar = 31;
ValMonthData.march = 31;
ValMonthData.apr = 30;
ValMonthData.april = 30;
ValMonthData.may = 31;
ValMonthData.jun = 30;
ValMonthData.june = 30;
ValMonthData.jul = 31;
ValMonthData.july = 31;
ValMonthData.aug = 31;
ValMonthData.august = 31;
ValMonthData.sep = 30;
ValMonthData.sept = 30;
ValMonthData.september = 30;
ValMonthData.oct = 31;
ValMonthData.october = 31;
ValMonthData.nov = 30;
ValMonthData.november = 30;
ValMonthData.dec = 31;
ValMonthData.december = 31;

/*
  Determine the number of days in a given month in a given year.
  
  Parameters:
    sMonth - the month as a name string
    nYear - the year as an integer
    
  Returns:
    the number of days in the given month
*/
function ValDaysInMonth(sMonth, nYear)
{
/*
  This table defines the valid month naming strings and supplies
  data for the ValDaysInMonth function.
*/
var ValMonthData = new Object;
ValMonthData.jan = 31;
ValMonthData.january = 31;
ValMonthData.feb = 28;
ValMonthData.february = 28;
ValMonthData.mar = 31;
ValMonthData.march = 31;
ValMonthData.apr = 30;
ValMonthData.april = 30;
ValMonthData.may = 31;
ValMonthData.jun = 30;
ValMonthData.june = 30;
ValMonthData.jul = 31;
ValMonthData.july = 31;
ValMonthData.aug = 31;
ValMonthData.august = 31;
ValMonthData.sep = 30;
ValMonthData.sept = 30;
ValMonthData.september = 30;
ValMonthData.oct = 31;
ValMonthData.october = 31;
ValMonthData.nov = 30;
ValMonthData.november = 30;
ValMonthData.dec = 31;
ValMonthData.december = 31;

  var d = ValMonthData.sMonth.toLowerCase();
  if (d==null) return 0;
  
  if (d==28&&ValIsLeapYear(nYear)) d++;
  return d;
}


/*
  Determine whether a given string is a date in 
  the format DD MMM YYYY such as 11 Nov 2002.
  (This is the most appropriate format to use in a
  global system due to its lack of unambiguity.)
  
  Parameters:
    sDate - the string to test
    
  Returns:
    true if the string is a valid date, false otherwise
*/
function ValIsD2M3Y4Date(sDate)
{
  
/*
    Use a regular expression to both check the syntax and extract the 
    component parts of the date.
  */
  var a = sDate.match(/^[ ]*(\d{1,2})[ ]+([A-Za-z]+)[ ]+(\d{2}|\d{4})[ ]*$/i);
  if (a==null) return false;
  
  /*
    Recover the date components.
  */
  var nDay = parseInt(a[1],10); 
  var sMonth = a[2]; 
  var nYear = parseInt(a[3],10);

   
  /*
    Validate the month name and the day number.
  */
 // if (nDay<1||nDay>ValDaysInMonth(sMonth, nYear))  return false;
  
  return true
}

// Check whether string s is empty.

function isEmpty(s)
{   return ((s == null) || (s.length == 0))
}

// isInteger (STRING s [, BOOLEAN emptyOK])
// 
// Returns true if all characters in string s are numbers.
//
// Accepts non-signed integers only. Does not accept floating 
// point, exponential notation, etc.
//
// We don't use parseInt because that would accept a string
// with trailing non-numeric characters.
//
// By default, returns defaultEmptyOK if s is empty.
// There is an optional second argument called emptyOK.
// emptyOK is used to override for a single function call
//      the default behavior which is specified globally by
//      defaultEmptyOK.
// If emptyOK is false (or any value other than true), 
//      the function will return false if s is empty.
// If emptyOK is true, the function will return true if s is empty.
//
// EXAMPLE FUNCTION CALL:     RESULT:
// isInteger ("5")            true 
// isInteger ("")             defaultEmptyOK
// isInteger ("-5")           false
// isInteger ("", true)       true
// isInteger ("", false)      false
// isInteger ("5", false)     true


function isInteger (s)

{   var i;

    if (isEmpty(s)) 
       if (isInteger.arguments.length == 1) return defaultEmptyOK;
       else return (isInteger.arguments[1] == true);
// BOI, followed by one or more digits, followed by EOI.

var reInteger = /^[-]?\d+$/
    return reInteger.test(s)
}



// Added 2nd parameter to isFloat call so that empty values are ok
function ValCheckFloatFields(asFields, sFormName)
{
  var sErr = "";
  for (var n=0; n<asFields.length; n+=2) {
 	var sName = asFields[n];
	if (isFloat(StdGetFieldValue(sName, sFormName), true) == false ) {
	  if (sErr!="") sErr += "\n";
	  sErr += asFields[n+1];	
	}
  }
  
  return sErr;
}




function ValCheckDateFields(asFields, sFormName)
{
 
  var sErr = "";

  for (var n=0; n<asFields.length; n+=2) {
 	var sName = asFields[n];

 	if (isEmpty(StdGetFieldValue(sName, sFormName))) continue;
 	
	if (ValIsD2M3Y4Date(StdGetFieldValue(sName, sFormName)) == false ) {
	  if (sErr!="") sErr += "\n";
	  sErr += asFields[n+1];	
	}
  }
  
  return sErr;
}


function ValCheckIntegerFields(asFields, sFormName)
{
  var sErr = "";

  for (var n=0; n<asFields.length; n+=2) {
 	var sName = asFields[n];
	if (isInteger(StdGetFieldValue(sName, sFormName)) == false ) {
	  if (sErr!="") sErr += "\n";
	  sErr += asFields[n+1];	
	}
  }
  
  return sErr;
}



function ValCheckPercentageFields(asFields, sFormName)
{
  var sErr = "";

  for (var n=0; n<asFields.length; n+=2) {
 	var sName = asFields[n];
	
	if (isFloatInRange(StdGetFieldValue(sName, sFormName), 0, 100, true) == false ) {
	  if (sErr!="") sErr += "\n";
	  sErr += asFields[n+1];	
	}
  }
  
  return sErr;
}

// isIntegerInRange (STRING s, INTEGER a, INTEGER b [, BOOLEAN emptyOK])
// 
// isIntegerInRange returns true if string s is an integer 
// within the range of integer arguments a and b, inclusive.
// 
// For explanation of optional argument emptyOK,
// see comments of function isInteger.


function isIntegerInRange (s, a, b)
{    
if (isEmpty(s)) 
       if (isIntegerInRange.arguments.length == 3) return defaultEmptyOK;
       else return (isIntegerInRange.arguments[3] == true);


    // Catch non-integer strings to avoid creating a NaN below,
    // which isn't available on JavaScript 1.0 for Windows.

  if (!isInteger(s, false)) return false;


    // Now, explicitly change the type to integer via parseInt
    // so that the comparison code below will work both on 
    // JavaScript 1.2 (which typechecks in equality comparisons)
    // and JavaScript 1.1 and before (which doesn't).
    var num = parseInt (s);
 
    return ((num >= a) && (num <= b));
}


// isFloat (STRING s [, BOOLEAN emptyOK])
// 
// True if string s is a signed floating point (real) number. 
//
// Does not accept exponential notation.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.

function isFloat (s)
{	
    if (isEmpty(s)) 
       if (isFloat.arguments.length == 1) return defaultEmptyOK;
       else return (isFloat.arguments[1] == true);
    
    var reFloat = /^(\+|-)?((\d+(\.\d*)?)|((\d*\.)?\d+))$/
    return reFloat.test(s) ;
}



function isFloatInRange (s, a, b)
{       

if (isEmpty(s)) 
       if (isFloatInRange.arguments.length == 3) return defaultEmptyOK;
       else return (isFloatInRange.arguments[3] == true);

    // Catch non-integer strings to avoid creating a NaN below,
    // which isn't available on JavaScript 1.0 for Windows.

  if (!isFloat(s, false)) return false;

   return ((s>= a) && (s <= b));
}



// BOI, followed by one or more lower or uppercase English letters
// or digits, followed by EOI.
var reAlphanumeric = /^[a-zA-Z0-9]+$/

// isAlphanumeric (STRING s [, BOOLEAN emptyOK])
// 
// Returns true if string s is English letters 
// (A .. Z, a..z) and numbers only.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.
//
// NOTE: Need i18n version to support European characters.
// This could be tricky due to different character
// sets and orderings for various languages and platforms.

function isAlphanumeric (s)

{   var i;

    if (isEmpty(s)) 
       if (isAlphanumeric.arguments.length == 1) return defaultEmptyOK;
       else return (isAlphanumeric.arguments[1] == true);

    else {
       return reAlphanumeric.test(s)
    }
}

// BOI, followed by one or more lower or uppercase HEX letters
// or digits, followed by EOI.
var reHex = /^[a-fA-F0-9]+$/

// isHex (STRING s [, BOOLEAN emptyOK])
// 
// Returns true if string s is Hex letters (A .. F, a..f) and numbers only.
//
// For explanation of optional argument emptyOK, see comments of function isInteger.
//
// NOTE: Need i18n version to support European characters.
// This could be tricky due to different character sets and orderings for various languages and platforms.

function isHex (s)

{   var i;

    if (isEmpty(s)) 
       if (isHex.arguments.length == 1) return defaultEmptyOK;
       else return (isHex.arguments[1] == true);

    else {
       return reHex.test(s)
    }
}



// isDate (STRING year, STRING month, STRING day)
//
// isDate returns true if string arguments year, month, and day 
// form a valid date.
// 

function isDate (year, month, day)
{   // catch invalid years (not 2- or 4-digit) and invalid months and days.
    if (! (isYear(year, false) && isMonth(month, false) && isDay(day, false))) return false;

    // Explicitly change type to integer to make code work in both
    // JavaScript 1.1 and JavaScript 1.2.
    var intYear = parseInt(year);
    var intMonth = parseInt(month);
    var intDay = parseInt(day);

    // catch invalid days, except for February
    if (intDay > daysInMonth[intMonth]) return false; 

    if ((intMonth == 2) && (intDay > daysInFebruary(intYear))) return false;

    return true;
}