// Message prefixes and suffixes
var mPrefix = "Please enter a value for "
var mSuffix = ". This is a required field."
var msRequired = " is a required field."
var sPrefix = "Please make a selection for "
var mpSelection = "A selection must be made in order to "
var msSelection = ". Please make a selection from the " 

// Invalid Strings
var iNonNegIntOrZeroValue = " must be a whole number between 0 and "
var iNonNegIntOrZero = " must be a non negative whole number "
var iAmount = " must be in the format 999999999 or 9999999.99"
var iAmountValue = " must fall between " 
var iDate = " is not a valid date.\nPlease enter a valid date in the format mm/dd/yyyy"
var iRange = " must be greater than "
var iUnitType = "Please select the type of unit being measured"
var iEmail = " must be a valid email address in the format XXXXXXXX@XXXXXXXX.XXX"
var iDatePrefix = "The Day, Month, and Year for "
var iDateSuffix = " do not form a valid date."
var iZIPCode = " must be a 5 or 9 digit U.S. ZIP Code (e.g. 94043)."
var iUSPhone = " must be a 10 digit U.S. phone number (e.g. 415 555 1212)."
var iWorldPhone = " must be a valid international phone number."
var iYear = "Year is invalid"
var iMonth = "Month is invalid"
var iDay = "Day is invalid"
var iCarrierRefNbrType = "Please select the type of carrier reference number"
var iConsolidationRefNbrType = "Please select the type of consolidation reference number"
var iActualWeightType = "Please select the type of weight being measured"
var iActualCubeType = "Please select the type of cube being measured"
var iMoveRefNbrType = "Please select the type of move reference number"
var iTime = " is not a valid time.\nPlease enter a valid time in the format hh:mm"

// Strings
var sUSLastName = "Last Name"
var sUSFirstName = "First Name"
var sTitle = "Title"
var sCompanyName = "Company Name"
var sPhone = "Phone Number"
var sFax = "Fax Number"
var sEmail = "Email"

// Hints (used to fill controls with hints as to how to format but meant to be overridden)
var hDate = "mm/dd/yyyy"

// Prompts
var pEntryPrompt = "Please enter a "
var pZIPCode = "5 or 9 digit U.S. ZIP Code (like 94043)."
var pUSPhone = "10 digit U.S. phone number (like 415 555 1212)."
var pWorldPhone = "international phone number."
var pEmail = "valid email address (like jdoe@company.com)."
var pDate = "date in the format mm/dd/yyyy"
var pAmount = "valid amount (like -110.40, 50, +10.20)"

// Calendar Variables
var today = new Date();
var day   = today.getDate();
var month = today.getMonth();
var year  = y2k(today.getYear());
var dateField;

// regular expressions
var reWhitespace = /^\s+$/
var reLetter = /^[a-zA-Z]$/
var reAlphabetic = /^[a-zA-Z]+$/
var reAlphanumeric = /^[a-zA-Z0-9]+$/
var reDigit = /^\d/
var reLetterOrDigit = /^([a-zA-Z]|\d)$/
var reInteger = /^\d+$/
var reFloat = /^((\d+(\.\d*)?)|((\d*\.)?\d+))$/
var reAmount = /^((\d+(\.\d)?)|((\d*\.)?\d)|(\d+(\.\d\d)?)|((\d*\.)?\d\d))$/
var reEmail = /^.+\@.+\..+$/

// other variables
var digits = "0123456789";
var lowercaseLetters = "abcdefghijklmnopqrstuvwxyz"
var uppercaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
var whitespace = " \t\n\r";
var phoneNumberDelimiters = "()- ";
var validUSPhoneChars = digits + phoneNumberDelimiters;
var validWorldPhoneChars = digits + phoneNumberDelimiters + "+";
var digitsInUSPhoneNumber = 10;
var ZIPCodeDelimiters = "-";
var ZIPCodeDelimeter = "-"
var validZIPCodeChars = digits + ZIPCodeDelimiters
var digitsInZIPCode1 = 5
var digitsInZIPCode2 = 9
var defaultEmptyOK = false

function makeDayArray(n) {
   for (var i = 1; i <= n; i++) {
      this[i] = 0
   } 
   return this
}

var daysInMonth = makeDayArray(12);
daysInMonth[1] = 31;
daysInMonth[2] = 29;   // must programmatically check this
daysInMonth[3] = 31;
daysInMonth[4] = 30;
daysInMonth[5] = 31;
daysInMonth[6] = 30;
daysInMonth[7] = 31;
daysInMonth[8] = 31;
daysInMonth[9] = 30;
daysInMonth[10] = 31;
daysInMonth[11] = 30;
daysInMonth[12] = 31;

// Valid U.S. Postal Codes for states, territories, armed forces, etc.
// See http://www.usps.gov/ncsc/lookups/abbr_state.txt.

// Call the following check methods from your program and they will handle throwing alerts 

function checkForValue(fieldname, field) {
	if (checkForValue.arguments.length == 3)
		return hasValue(fieldname,field,checkForValue.arguments[2])
	else
		return hasValue(fieldname,field)

}

// hasValue( fieldName, field, [defaultValue] )
// desc: determines whether there is a value in the incoming field. 
// out: If there is then return true else false 
// If a third parameter is sent in (this is optional) and if the value of the field is 
// equal to that, then return false. 
// This method will go ahead and throw an alert popup if field has no value 
function hasValue(fieldname, field) {
	if (hasValue.arguments.length == 3) {
		if (field.value == hasValue.arguments[2])
			return warnEmpty(field,fieldname)
	}
	if (isWhitespace(field.value)) 
		return warnEmpty(field,fieldname)
	return true;
}

// hasSelection( fieldName, field )
// desc: determines whether the field has a selection (valid for select fields only) 
// out: If there is then return true else false 
// This method will go ahead and throw an alert popup if field has no value 
function hasSelection(fieldname, field) {
	if (field.selectedIndex == -1)
		return warnNotSelected(field,fieldname)
	return true;
}

function checkDate(fieldname,field)
{ return isValidDate(fieldname,field) 
}

// checkAmount( fieldName, field, [allowBlank] )
// desc: determines whether the incoming field is a valid amount. 
// Examples of valid amounts: -1.0 104.98 +480 
// out: If it is valid then return true else false 
// If a third parameter is sent in (this is optional) then check if the field is 
// empty, and return the third parameter. 
// This method will go ahead and throw an alert popup if field is invalid
function checkAmount(fieldname, field) {
   if (isEmpty(field.value)) { 
       if ((checkAmount.arguments.length == 2 && defaultEmptyOK == false) || 
	   (checkAmount.arguments.length > 2 && checkAmount.arguments[2] == false)) 
		return warnInvalid(field, fieldname + iAmount);
       else 
		return true;
   }
   else {
	if (isSignedAmount(field.value) || isSignedInteger(field.value))
		return true;
	else
		return warnInvalid(field, fieldname + iAmount);
   }
}

function checkAmountAndValue(fieldname, field,length,decimal) {
   if (isEmpty(field.value)) { 
       if ((checkAmountAndValue.arguments.length == 4 && defaultEmptyOK == false) || 
	   (checkAmountAndValue.arguments.length > 4 && checkAmountAndValue.arguments[4] == false)) 
		return warnInvalid(field, fieldname + iAmount);
       else 
		return true;
   }
   else {
	if (isSignedAmount(field.value) || isSignedInteger(field.value)) {
		return checkAmountValue(fieldname,field,length,decimal)
	}
	else
		return warnInvalid(field, fieldname + iAmount);
   }
}



// isValidDate( fieldName, field )
// desc: determines whether the incoming field is a valid date. 
// Examples of valid dates: 9/9/99, 09/09/99, 9/9/1999, 09/09/1999, 9-9-99 
// out: If it is valid then return true else false 
// This method will go ahead and throw an alert popup if field is invalid
// this method also goes ahead and reformats the value in the field to
// the format mm/dd/yyyy
function isValidDate(fieldname, field){
	var indate=field.value;
	var ret = true;

	if (indate.indexOf("-")!=-1){
		var sdate = indate.split("-")
	}
	else {
		var sdate = indate.split("/")
	}
	var chkDate=new Date(Date.parse(indate))
	var cmpDate=(chkDate.getMonth()+1)+"/"+(chkDate.getDate())+"/"+ y2k(chkDate.getYear())
	var indate2=(Math.abs(sdate[0]))+"/"+(Math.abs(sdate[1]))+"/"+ y2k((Math.abs(sdate[2])))
	if (indate2!=cmpDate) {
		warnInvalid(field, fieldname + " value: " + field.value + iDate);
		ret = false;
	}	
	else if (cmpDate=="NaN/NaN/NaN") {
		warnInvalid(field, fieldname + " value: " + field.value + iDate);
		ret = false;	
	}
	else {
		field.value = reformatDate(sdate);
	}
	return ret;
}


// checkZIPCode (NAME theFieldName, TEXTFIELD theField [, BOOLEAN emptyOK==false])
//
// Check that string theField.value is a valid ZIP code.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.

function checkZIPCode (theFieldName, theField, emptyOK)
{   if (checkZIPCode.arguments.length == 2) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    else
    { var normalizedZIP = stripCharsInBag(theField.value, ZIPCodeDelimiters)
      if (!isZIPCode(normalizedZIP, false)) 
         return warnInvalid (theField, theFieldName + iZIPCode);
      else 
      {  // if you don't want to insert a hyphen, comment next line out
         theField.value = reformatZIPCode(normalizedZIP)
         return true;
      }
    }
}

// checkUSPhone (NAME theFieldName, TEXTFIELD theField [, BOOLEAN emptyOK==false])
//
// Check that string theField.value is a valid US Phone.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.

function checkUSPhone (theFieldName, theField, emptyOK)
{   if (checkUSPhone.arguments.length == 2) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    else
    {  var normalizedPhone = stripCharsInBag(theField.value, phoneNumberDelimiters)
       if (!isUSPhoneNumber(normalizedPhone, false)) 
          return warnInvalid (theField, theFieldName + iUSPhone);
       else 
       {  // if you don't want to reformat as (123) 456-789, comment next line out
          theField.value = reformatUSPhone(normalizedPhone)
          return true;
       }
    }
}
			

//function checkUSPhone (fieldname, field) {
//   if (isEmpty(field.value)) {
//       if ((checkUSPhone.arguments.length == 2 && defaultEmptyOK == false) || 
//	   (checkUSPhone.arguments.length > 2 && checkUSPhone.arguments[2] == false)) 
//		return warnInvalid(field, fieldname + iUSPhone);
//       else 
//		return true;
// 
//   }
//   else {
//	var normalizedPhone = stripCharsInBag(field.value, phoneNumberDelimiters)
//        if (!isUSPhoneNumber(normalizedPhone, false)) 
//           return warnInvalid (field, fieldname + iUSPhone);
//        else 
//        {  // if you don't want to reformat as (123) 456-789, comment next line out
//           field.value = reformatUSPhone(normalizedPhone)
//           return true;
//        }
//   }
//}

//function checkZIPCode (fieldname, field){
//   if (isEmpty(field.value)) { 
//       if ((checkZIPCode.arguments.length == 2 && defaultEmptyOK == false) || 
//	   (checkZIPCode.arguments.length > 2 && checkZIPCode.arguments[2] == false)) 
//		return warnInvalid(field, fieldname + iZIPCode);
//       else 
//		return true;
//   }
//   else {
//	var normalizedZIP = stripCharsInBag(field.value, ZIPCodeDelimiters)
//        if (!isZIPCode(normalizedZIP, false)) 
//         	return warnInvalid (field, fieldname + iZIPCode);
//      	else 
//      	{  // if you don't want to insert a hyphen, comment next line out
//         	field.value = reformatZIPCode(normalizedZIP)
//         	return true;
//      	}
//   }
//}

function checkInternationalPhone (fieldname, field) {
   if (isEmpty(field.value)) { 
       if ((checkInternationalPhone.arguments.length == 2 && defaultEmptyOK == false) || 
	   (checkInternationalPhone.arguments.length > 2 && checkInternationalPhone.arguments[2] == false)) 
		return warnInvalid(field, fieldname + iWorldPhone);
       else 
		return true;
   }
   else
   {  if (!isInternationalPhoneNumber(field.value, false)) 
          return warnInvalid (field, fieldname + iWorldPhone);
       else return true;
   }
}

function checkEmail (fieldname, field)  {
   if (isEmpty(field.value)) { 
       if ((checkEmail.arguments.length == 2 && defaultEmptyOK == false) || 
	   (checkEmail.arguments.length > 2 && Email.arguments[2] == false)) 
		return warnInvalid(field, fieldname + iEmail);
       else 
		return true;
   }
    else if (!isEmail(field.value, false)) 
       return warnInvalid (field, fieldname + iEmail);
    else return true;
}


// some calendar functions

function y2k(year)
{		
	var fix;
	if (year > 1000)
		return year;
	else {
		fix = (year % 100) + 1900
		if ((year % 100 ) < 90)
			fix += 100
		return fix;
	}
}

function padout(number) { return (number < 10) ? '0' + number : number; }

//Calendar popup functions

// restart()
// desc: called by the calendar to refresh the calling window
function restart() {
//alert(dateField.name)
    dateField.value = '' + padout(month - 0 + 1) + '/' + padout(day) + '/' + year;
    calendar.close();
}
// openCalendar(field)
// desc: opens the calendar popup and sets the calling dateField to field
// When restart is called, the incoming field will be refreshed.
function openCalendar(field) {
	//(field.name)
    dateField = field;
//alert(dateField.name)
//alert (field.value)
    calendar=window.open('/calendar.htm','cal','width=350,height=280');
    calendar.location.href = '/calendar.htm';
//alert("before opener")
//alert("opener =" + calendar.opener.value)
    if (calendar.opener == null) {
	//	alert("opener == null");
		calendar.opener = self;
	}
//alert("after if")
}

// Alert popup functions

function warnEmpty (theField, s)
{   theField.focus()
    alert(s + msRequired)
    return false
}
function warnInvalid (theField, s)
{   theField.focus()
    alert(s)
    return false
}
function warnNotSelected (theField, s)
{   theField.focus()
    alert(sPrefix + s)
    return false
}

// Status bar message functions

function prompt (s)
{   window.status = s
}
function promptEntry (s)
{   window.status = pEntryPrompt + s
}

// String functions

function ltrim (s)
{   var i = 0;
    while ((i < s.length) && s.charAt(i) == " ")
       i++;
    return s.substring (i, s.length);
}

// Control functions

function getSelectedButtonValue(button) {
var buttonValue = -1;
 if (button.length > 0) {
	for (x = 0; x < button.length; x++) {
		if (button[x].checked == true) {
			buttonValue = button[x].value;
			break;
		}
	}
 }
 else {
	if (button.checked == true)
 		buttonValue = button.value; 
 }
 return buttonValue;
}

// is functions

// Returns true if character c is an English letter 
// (A .. Z, a..z).
//
// 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 isLetter (c)
{   return reLetter.test(c)
}

// Returns true if character c is a digit 
// (0 .. 9).
function isDigit (c)
{   return reDigit.test(c)
}

// Returns true if character c is a letter or digit.
function isLetterOrDigit (c)
{   return reLetterOrDigit.test(c)
}

// 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.
function isInteger (s)
{   var i;

    if (isEmpty(s)) 
       if (isInteger.arguments.length == 1) return defaultEmptyOK;
       else return (isInteger.arguments[1] == true);

    return reInteger.test(s)
}

// isSignedInteger (STRING s [, BOOLEAN emptyOK])
// 
// Returns true if all characters are numbers; 
// first character is allowed to be + or - as well.
//
// Does not accept floating point, exponential notation, etc.
function isSignedInteger (s)
{   if (isEmpty(s)) 
       if (isSignedInteger.arguments.length == 1) return defaultEmptyOK;
       else return (isSignedInteger.arguments[1] == true);

    else {
        var startPos = 0;
        var secondArg = defaultEmptyOK;

        if (isSignedInteger.arguments.length > 1)
            secondArg = isSignedInteger.arguments[1];

        // skip leading + or -
        if ( (s.charAt(0) == "-") || (s.charAt(0) == "+") )
           startPos = 1;    
        return (isInteger(s.substring(startPos, s.length), secondArg))
    }
}

// isPositiveInteger (STRING s [, BOOLEAN emptyOK])
// 
// Returns true if string s is an integer > 0.
function isPositiveInteger (s)
{   var secondArg = defaultEmptyOK;

    if (isPositiveInteger.arguments.length > 1)
        secondArg = isPositiveInteger.arguments[1];

    // The next line is a bit byzantine.  What it means is:
    // a) s must be a signed integer, AND
    // b) one of the following must be true:
    //    i)  s is empty and we are supposed to return true for
    //        empty strings
    //    ii) this is a positive, not negative, number

    return (isSignedInteger(s, secondArg)
         && ( (isEmpty(s) && secondArg)  || (parseInt (s) > 0) ) );
}

// isNonnegativeInteger (STRING s [, BOOLEAN emptyOK])
// 
// Returns true if string s is an integer >= 0.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.
function isNonnegativeInteger (s)
{   var secondArg = defaultEmptyOK;

    if (isNonnegativeInteger.arguments.length > 1)
        secondArg = isNonnegativeInteger.arguments[1];

    // The next line is a bit byzantine.  What it means is:
    // a) s must be a signed integer, AND
    // b) one of the following must be true:
    //    i)  s is empty and we are supposed to return true for
    //        empty strings
    //    ii) this is a number >= 0

    return (isSignedInteger(s, secondArg)
         && ( (isEmpty(s) && secondArg)  || (parseInt (s) >= 0) ) );
}

// isNegativeInteger (STRING s [, BOOLEAN emptyOK])
// 
// Returns true if string s is an integer < 0.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.
function isNegativeInteger (s)
{   var secondArg = defaultEmptyOK;

    if (isNegativeInteger.arguments.length > 1)
        secondArg = isNegativeInteger.arguments[1];

    // The next line is a bit byzantine.  What it means is:
    // a) s must be a signed integer, AND
    // b) one of the following must be true:
    //    i)  s is empty and we are supposed to return true for
    //        empty strings
    //    ii) this is a negative, not positive, number

    return (isSignedInteger(s, secondArg)
         && ( (isEmpty(s) && secondArg)  || (parseInt (s) < 0) ) );
}

// isNonpositiveInteger (STRING s [, BOOLEAN emptyOK])
// 
// Returns true if string s is an integer <= 0.
function isNonpositiveInteger (s)
{   var secondArg = defaultEmptyOK;

    if (isNonpositiveInteger.arguments.length > 1)
        secondArg = isNonpositiveInteger.arguments[1];

    // The next line is a bit byzantine.  What it means is:
    // a) s must be a signed integer, AND
    // b) one of the following must be true:
    //    i)  s is empty and we are supposed to return true for
    //        empty strings
    //    ii) this is a number <= 0

    return (isSignedInteger(s, secondArg)
         && ( (isEmpty(s) && secondArg)  || (parseInt (s) <= 0) ) );
}

// isFloat (STRING s [, BOOLEAN emptyOK])
// 
// True if string s is an unsigned floating point (real) number. 
//
// Also returns true for unsigned integers. If you wish
// to distinguish between integers and floating point numbers,
// first call isInteger, then call isFloat.
//
// Does not accept exponential notation.
function isFloat (s)

{   if (isEmpty(s)) 
       if (isFloat.arguments.length == 1) return defaultEmptyOK;
       else return (isFloat.arguments[1] == true);

    return reFloat.test(s)
}

// isSignedFloat (STRING s [, BOOLEAN emptyOK])
// 
// True if string s is a signed or unsigned floating point 
// (real) number. First character is allowed to be + or -.
//
// Also returns true for unsigned integers. If you wish
// to distinguish between integers and floating point numbers,
// first call isSignedInteger, then call isSignedFloat.
//
// Does not accept exponential notation.
function isSignedFloat (s)
{   if (isEmpty(s)) 
       if (isSignedFloat.arguments.length == 1) return defaultEmptyOK;
       else return (isSignedFloat.arguments[1] == true);

    else {
        var startPos = 0;
        var secondArg = defaultEmptyOK;

        if (isSignedFloat.arguments.length > 1)
            secondArg = isSignedFloat.arguments[1];

        // skip leading + or -
        if ( (s.charAt(0) == "-") || (s.charAt(0) == "+") )
           startPos = 1;    
        return (isFloat(s.substring(startPos, s.length), secondArg))
    }
}

function isAmount(s) {
   if (isEmpty(s)) 
       if (isAmount.arguments.length == 1) return defaultEmptyOK;
       else return (isAmount.arguments[1] == true);
    return reAmount.test(s)
}

function isSignedAmount(s) {
   if (isEmpty(s)) 
       if (isSignedAmount.arguments.length == 1) return defaultEmptyOK;
       else return (isSignedAmount.arguments[1] == true);
    else {
        var startPos = 0;
        var secondArg = defaultEmptyOK;

        if (isSignedAmount.arguments.length > 1)
            secondArg = isSignedAmount.arguments[1];

        // skip leading + or -
        if ( (s.charAt(0) == "-") || (s.charAt(0) == "+") )
           startPos = 1;    
        return (isAmount(s.substring(startPos, s.length), secondArg))
    }
}

// isAlphabetic (STRING s [, BOOLEAN emptyOK])
// 
// Returns true if string s is English letters 
// (A .. Z, a..z) only.
function isAlphabetic (s)
{   var i;

    if (isEmpty(s)) 
       if (isAlphabetic.arguments.length == 1) return defaultEmptyOK;
       else return (isAlphabetic.arguments[1] == true);

    else {
       return reAlphabetic.test(s)
    }
}

// isAlphanumeric (STRING s [, BOOLEAN emptyOK])
// 
// Returns true if string s is English letters 
// (A .. Z, a..z) and numbers only.
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)
    }
}

// isEmail (STRING s [, BOOLEAN emptyOK])
// 
// Email address must be of form a@b.c -- in other words:
// * there must be at least one character before the @
// * there must be at least one character before and after the .
// * the characters @ and . are both required
function isEmail (s)
{   if (isEmpty(s)) 
       if (isEmail.arguments.length == 1) return defaultEmptyOK;
       else return (isEmail.arguments[1] == true);
    
    else {
       return reEmail.test(s)
    }
}


// isUSPhoneNumber (STRING s [, BOOLEAN emptyOK])
// 
// isUSPhoneNumber returns true if string s is a valid U.S. Phone
// Number.  Must be 10 digits.
//
// NOTE: Strip out any delimiters (spaces, hyphens, parentheses, etc.)
// from string s before calling this function.
function isUSPhoneNumber (s)
{   if (isEmpty(s)) 
       if (isUSPhoneNumber.arguments.length == 1) return defaultEmptyOK;
       else return (isUSPhoneNumber.arguments[1] == true);
    return (isInteger(s) && s.length == digitsInUSPhoneNumber)
}

// isInternationalPhoneNumber (STRING s [, BOOLEAN emptyOK])
// 
// isInternationalPhoneNumber returns true if string s is a valid 
// international phone number.  Must be digits only; any length OK.
// May be prefixed by + character.
//
// NOTE: A phone number of all zeros would not be accepted.
// I don't think that is a valid phone number anyway.
//
// NOTE: Strip out any delimiters (spaces, hyphens, parentheses, etc.)
// from string s before calling this function.  You may leave in 
// leading + character if you wish.
function isInternationalPhoneNumber (s)
{   if (isEmpty(s)) 
       if (isInternationalPhoneNumber.arguments.length == 1) return defaultEmptyOK;
       else return (isInternationalPhoneNumber.arguments[1] == true);
    return (isPositiveInteger(s))
}

// isZIPCode (STRING s [, BOOLEAN emptyOK])
// 
// isZIPCode returns true if string s is a valid 
// U.S. ZIP code.  Must be 5 or 9 digits only.
//
// NOTE: Strip out any delimiters (spaces, hyphens, etc.)
// from string s before calling this function.  
function isZIPCode (s)
{  if (isEmpty(s)) 
       if (isZIPCode.arguments.length == 1) return defaultEmptyOK;
       else return (isZIPCode.arguments[1] == true);
   return (isInteger(s) && 
            ((s.length == digitsInZIPCode1) ||
             (s.length == digitsInZIPCode2)))
}

// Check whether string s is empty.
function isEmpty(s)
{   return ((s == null) || (s.length == 0))
}

// Returns true if string s is empty or 
// whitespace characters only.
function isWhitespace (s)
{   // Is s empty?
    return (isEmpty(s) || reWhitespace.test(s));
}

// isYear (STRING s [, BOOLEAN emptyOK])
// 
// isYear returns true if string s is a valid 
// Year number.  Must be 2 or 4 digits only.
// 
// For Year 2000 compliance, you are advised
// to use 4-digit year numbers everywhere.
//
// And yes, this function is not Year 10000 compliant, but 
// because I am giving you 8003 years of advance notice,
// I don't feel very guilty about this ...
function isYear (s)
{   if (isEmpty(s)) 
       if (isYear.arguments.length == 1) return defaultEmptyOK;
       else return (isYear.arguments[1] == true);
    if (!isNonnegativeInteger(s)) return false;
    return ((s.length == 2) || (s.length == 4));
}

// 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.
function isIntegerInRange (s, a, b)
{   if (isEmpty(s)) 
       if (isIntegerInRange.arguments.length == 1) return defaultEmptyOK;
       else return (isIntegerInRange.arguments[1] == 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));
}

// isMonth (STRING s [, BOOLEAN emptyOK])
// 
// isMonth returns true if string s is a valid 
// month number between 1 and 12.
function isMonth (s)
{   if (isEmpty(s)) 
       if (isMonth.arguments.length == 1) return defaultEmptyOK;
       else return (isMonth.arguments[1] == true);
    return isIntegerInRange (s, 1, 12);
}

// isDay (STRING s [, BOOLEAN emptyOK])
// 
// isDay returns true if string s is a valid 
// day number between 1 and 31.
function isDay (s)
{   if (isEmpty(s)) 
       if (isDay.arguments.length == 1) return defaultEmptyOK;
       else return (isDay.arguments[1] == true);   
    return isIntegerInRange (s, 1, 31);
}

// daysInFebruary (INTEGER year)
// 
// Given integer argument year,
// returns number of days in February of that year.
function daysInFebruary (year)
{   // February has 29 days in any year evenly divisible by four,
    // EXCEPT for centurial years which are not also divisible by 400.
    return (  ((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0) ) ) ? 29 : 28 );
}

// 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;
}

// Strip functions

// Removes all characters which appear in regexp bag from string s.
// NOTES:
// 1) bag must be a regexp which matches single characters in isolation,
//    i.e. A or B or C or D or 1 or 2 ...
//    e.g. /\d/g  or /[a-zA-Z]/g
// 2) make sure to append the 'g' modifier (for global search & replace)
//    at the end of the regexp
//    e.g. /\d/g  or /[a-zA-Z]/g
function stripCharsInRE (s, bag)
{       return s.replace(bag, "")
}

// Removes all characters which appear in string bag from string s.
function stripCharsInBag (s, bag)
{   var i;
    var returnString = "";

    // Search through string's characters one by one.
    // If character is not in bag, append to returnString.

    for (i = 0; i < s.length; i++)
    {   
        // Check that current character isn't whitespace.
        var c = s.charAt(i);
        if (bag.indexOf(c) == -1) returnString += c;
    }

    return returnString;
}

// Removes all characters which do NOT appear in string bag 
// from string s.
function stripCharsNotInBag (s, bag)
{   var i;
    var returnString = "";

    // Search through string's characters one by one.
    // If character is in bag, append to returnString.

    for (i = 0; i < s.length; i++)
    {   
        // Check that current character isn't whitespace.
        var c = s.charAt(i);
        if (bag.indexOf(c) != -1) returnString += c;
    }

    return returnString;
}

// Removes all whitespace characters from s.
// Global variable whitespace (see above)
// defines which characters are considered whitespace.
function stripWhitespace (s)
{   return stripCharsInBag (s, whitespace)
}

// WORKAROUND FUNCTION FOR NAVIGATOR 2.0.2 COMPATIBILITY.
//
// The below function *should* be unnecessary.  In general,
// avoid using it.  Use the standard method indexOf instead.
//
// However, because of an apparent bug in indexOf on 
// Navigator 2.0.2, the below loop does not work as the
// body of stripInitialWhitespace:
//
// while ((i < s.length) && (whitespace.indexOf(s.charAt(i)) != -1))
//   i++;
//
// ... so we provide this workaround function charInString
// instead.
//
// charInString (CHARACTER c, STRING s)
//
// Returns true if single character c (actually a string)
// is contained within string s.
function charInString (c, s)
{   for (i = 0; i < s.length; i++)
    {   if (s.charAt(i) == c) return true;
    }
    return false
}

// Removes initial (leading) whitespace characters from s.
// Global variable whitespace (see above)
// defines which characters are considered whitespace.
function stripInitialWhitespace (s)
{   var i = 0;

    while ((i < s.length) && charInString (s.charAt(i), whitespace))
       i++;
    
    return s.substring (i, s.length);
}

// Removes initial (leading) whitespace characters from s.
// Global variable whitespace (see above)
// defines which characters are considered whitespace.
function stripTrailingWhitespace (s)
{   var i = s.length - 1;

    while ((i > 0) && charInString (s.charAt(i), whitespace))
       i--;

    if (i == 0)
	  return "";
    else
    	  return s.substring (0, i+1);
}

// reformat functions

// takes ZIPString, a string of 5 or 9 digits;
// if 9 digits, inserts separator hyphen
function reformatZIPCode (ZIPString)
{   if (ZIPString.length == 5) return ZIPString;
    else return (reformat (ZIPString, "", 5, "-", 4));
}

// takes USPhone, a string of 10 digits
// and reformats as (123) 456-789
function reformatUSPhone (USPhone)
{   return (reformat (USPhone, "(", 3, ") ", 3, "-", 4))
}

// reformat (TARGETSTRING, STRING, INTEGER, STRING, INTEGER ... )       
//
// Handy function for arbitrarily inserting formatting characters
// or delimiters of various kinds within TARGETSTRING.
//
// reformat takes one named argument, a string s, and any number
// of other arguments.  The other arguments must be integers or
// strings.  These other arguments specify how string s is to be
// reformatted and how and where other strings are to be inserted
// into it.
//
// reformat processes the other arguments in order one by one.
// * If the argument is an integer, reformat appends that number 
//   of sequential characters from s to the resultString.
// * If the argument is a string, reformat appends the string
//   to the resultString.
//
// NOTE: The first argument after TARGETSTRING must be a string.
// (It can be empty.)  The second argument must be an integer.
// Thereafter, integers and strings must alternate.  This is to
// provide backward compatibility to Navigator 2.0.2 JavaScript
// by avoiding use of the typeof operator.
//
// It is the caller's responsibility to make sure that we do not
// try to copy more characters from s than s.length.
//
// EXAMPLES:
//
// * To reformat a 10-digit U.S. phone number from "1234567890"
//   to "(123) 456-7890" make this function call:
//   reformat("1234567890", "(", 3, ") ", 3, "-", 4)
//
// * To reformat a 9-digit U.S. Social Security number from
//   "123456789" to "123-45-6789" make this function call:
//   reformat("123456789", "", 3, "-", 2, "-", 4)
//
// HINT:
//
// If you have a string which is already delimited in one way
// (example: a phone number delimited with spaces as "123 456 7890")
// and you want to delimit it in another way using function reformat,
// call function stripCharsNotInBag to remove the unwanted 
// characters, THEN call function reformat to delimit as desired.
//
// EXAMPLE:
//
// reformat (stripCharsNotInBag ("123 456 7890", digits),
//           "(", 3, ") ", 3, "-", 4)
function reformat (s)
{   var arg;
    var sPos = 0;
    var resultString = "";

    for (var i = 1; i < reformat.arguments.length; i++) {
       arg = reformat.arguments[i];
       if (i % 2 == 1) resultString += arg;
       else {
           resultString += s.substring(sPos, sPos + arg);
           sPos += arg;
       }
    }
    return resultString;
}

function reformatDate(validDate) {
	var fix;
	fix = padout(Math.abs(validDate[0])) + "/" + padout(Math.abs(validDate[1])) + "/" + y2k(validDate[2])
	return fix;
}
// isValidTime( fieldName, field )
// desc: determines whether the incoming field is a valid Time. 
// Examples of valid time: 9:9, 09:09, 9.9 09.09 
// out: If it is valid then return true else false 
// This method will go ahead and throw an alert popup if field is invalid
// this method also goes ahead and reformats the value in the field to
// the format hh:mm
function isValidTime(fieldname, field){
	var inTime=field.value;
	var ret = true;

	if (inTime.indexOf(".")!=-1){
		var sTime = inTime.split(".")
	}
	else {
		var sTime = inTime.split(":")
	}

	if ( !isInteger(sTime[0]) || !isInteger(sTime[1]) ||
		!isIntegerInRange(sTime[0], 0, 23) || !isIntegerInRange(sTime[1], 0, 59)){
		warnInvalid(field, fieldname + " value: " + field.value + iTime);
		ret = false;	
	}
	else {
		field.value = reformatTime(sTime);
	}
	return ret;


}			

function reformatTime(validTime) {
	var fix;
	fix = padout(Math.abs(validTime[0])) + ":" + padout(Math.abs(validTime[1]))
	return fix;
}


// controlMaxTextAreaLength
// Limit the length of textarea.
// first arg is the TEXTAREA itself.  
// second arg is the max length of text
function controlMaxTextAreaLength( item, maxlen ) {
	if ( item.value.length > maxlen - 1 )
   		if ( event.keyCode != 8 && event.keyCode <= 32 || event.keyCode > 46 ) 
	   		event.returnValue = false;
}
function checkAmountValue(fieldname,field,length,decimal) {
	var amount = field.value;
	if (isWhitespace(amount))
		return true;
	var maxValue = "";
	maxValue = pad(maxValue,length - decimal,'9')
   	if (decimal > 0) {
   		maxValue = maxValue + "."
		maxValue = pad(maxValue,decimal,'9')
		if (amount.indexOf(".") == -1) {
			amount = amount + "."
			amount = pad(amount,decimal,'0')
		}
		else if ((amount.length  - 1 - amount.indexOf(".")) <= decimal)
			amount = pad(amount,decimal - (amount.length - 1 - amount.indexOf(".")),'0')
		else return false;
	}
	if (Math.abs(amount) > maxValue) {
		warnInvalid(field,fieldname + iAmountValue + "-" + maxValue + " and " + maxValue);
		return false;
	}
	field.value = amount	
	return true;
}
function pad(str,lengthToPad,padChar) {
	var newStr = str;
	var initLength = str.length.valueOf();
	for (var i = initLength; i < (Math.abs(initLength) + Math.abs(lengthToPad)); i++) {
		newStr = newStr + padChar;
	}
	return newStr
}
function checkForSelectedValue(fieldname, field) {
	if (isWhitespace(field.options[field.selectedIndex].value)) 
		return warnEmpty(field,fieldname)
	return true;
}

// this function makes sure something is selected in a radio button set. If nothing
// is selected then an alert is created which states that a selection must be made from
// the radio button set inorder to do a specified function.
// AK 3/2/00
function checkForSelection(field,fieldnamePlural,functionname) {
	var selection = getSelectedButtonValue(field);
	if (selection < 1) {
		alert(mpSelection + functionname + msSelection + fieldnamePlural);
	}
	return selection;
}

// this function is also defined in jslibrary.js as makeArray but since I can't 
// get to it from this file, I had to create a version here. Some jsp's also have their own
// definition of this same function called xmakeArray
// AK 3/8/00
function myMakeArray() {
	for (i = 0; i<myMakeArray.arguments.length; i++) {
		this[i] = myMakeArray.arguments[i];
	}
}

// TimeZone Array
var timezones = new myMakeArray(["GM",0],["ET",-5],["CT",-6],["MT",-7],["PT",-8],["AT",-9],["HT",-10],["LT",99]);
var timezonesLength = 8

// this function adjusts an incoming date with the incoming timezone. It basically 
// adjusts the date so that it is in GMT.
// AK 3/8/00
function adjustTime(dateToAdjust,timezone) {
    var TimezoneOffset = dateToAdjust.getTimezoneOffset();
    for (var i = 0; i < timezonesLength; i++) {
    	if (timezones[i][0] == timezone) {
//    		alert("dateToAdjust=" + dateToAdjust);
//    		alert("GetTime=" + dateToAdjust.getTime());
//    		alert("timezoneoffset=" + TimezoneOffset);
//   		alert("adjustment=" + timezones[i][1]);
    		dateToAdjust.setTime(dateToAdjust.getTime() - timezones[i][1]*60*60*1000)
    		break;
    	}
    }
}

// this function takes two dateTimes (date, time, and time zone) and compares them.
// The first dateTime must be less than the second. otherwise an invalid message
// is displayed and false is returned.  
// AK 3/8/00
function thisDateTimeLessThanThatDateTime(thisDateField, thisTimeField,  thisTZField, thisName, thatDateField, thatTimeField, thatTZField, thatName) {
     var ret = true;
     var thisDate = new Date(Date.parse(thisDateField.value + " " + thisTimeField.value));
     var thatDate = new Date(Date.parse(thatDateField.value + " " + thatTimeField.value));
     adjustTime(thisDate,thisTZField.options[thisTZField.selectedIndex].value);
     adjustTime(thatDate,thatTZField.options[thatTZField.selectedIndex].value);
	//  alert(thisName + "=" + thisDate);
	//  alert(thatName + "=" + thatDate); 
     if(thisDate.getTime() >= thatDate.getTime()) {
        warnInvalid(thisDateField, thatName + iRange + thisName);
        ret = false;
    }
     return ret;
} 


//This function is used in lane analysis reports for calendar period not 
// greater than days
function checkDateRange(thisDateField,  thatDateField,days) {
     var ret = true;
     

     var thisDate = new Date(Date.parse(thisDateField.value));
     var thatDate = new Date(Date.parse(thatDateField.value));
     
    
     if ( (thatDate.getTime() - thisDate.getTime()) > (days*86400000)) 
     {
        alert("Date range cannot be more than 31 days");
        ret = false;
    }
        return ret;
     
}


// desc: determines whether the incoming field is a valid positive integer including zero. 
// out: If it is valid then return true else false 
// If a third parameter is sent in (this is optional) then check if the field is 
// empty, and return the third parameter. 
// This method will go ahead and throw an alert popup if field is invalid
function checkNonNegIntOrZero(fieldname, field) {
   if (isEmpty(field.value)) { 
       if ((checkNonNegIntOrZero.arguments.length == 2 && defaultEmptyOK == false) || 
	   (checkNonNegIntOrZero.arguments.length > 2 && checkNonNegIntOrZero.arguments[2] == false)) 
		return warnInvalid(field, fieldname + iAmount);
       else 
		return true;
   }
   else {
	if (isNonnegativeInteger(field.value))
		return true;
	else
		return warnInvalid(field, fieldname + iNonNegIntOrZero);
   }
}

// desc: determines whether the incoming field is a valid positive integer including zero. 
// out: If it is valid then return true else false 
// If a third parameter is sent in (this is optional) then check if the field is 
// empty, and return the third parameter. 
// This method will go ahead and throw an alert popup if field is invalid
function checkNonNegIntOrZeroValue(fieldname,field,length) {
	var amount = field.value;
	if (isWhitespace(amount))
		return true;
	var maxValue = "";
	maxValue = pad(maxValue,length,'9')
	if (!(isNonnegativeInteger(field.value)) || Math.abs(amount) > maxValue) {
		warnInvalid(field,fieldname + iNonNegIntOrZeroValue + maxValue);
		return false;
	}
	field.value = amount	
	return true;
}

function padRefNbr(refNbr) {
    while (refNbr.length < 8)
        refNbr = '0' + refNbr;
    return refNbr;
}
function ValidateRefNumbers(theForm)
{
  var atLeastOneValueEntered = false;
  var refNumberWidget = 'theForm.ref1';
  var widgetValue = eval(refNumberWidget).value;
  if (widgetValue.length > 0)
  {
    	atLeastOneValueEntered = true;
  }
  if (!atLeastOneValueEntered)
  {
    alert("Please enter a Forward Air Airbill number.");
    theForm.ref1.focus();
    return (false);
  }
  eval(refNumberWidget).value = padRefNbr(eval(refNumberWidget).value);
  return (true);
}


// This method validates a user's attempt to login it assumes that the form being passed
// as a parameter has two text inputs called
// * UserName
// * password
function isValidLogin(theForm)
{
  if (!checkForValue("User Id",theForm.UserName))
    return (false);
  if (!checkForValue("Password",theForm.Password))
    return (false);
//  if (theForm.UserName.value.length < 5)
//  {
//    alert("User Id must be at least 5 characters");
//    theForm.UserName.focus();
//    return (false);
//  }
//  if (!isAlphanumeric(theForm.UserName.value)) {
//    warnInvalid (theForm.UserName, s)
//    return (false);
//  }
  return (true);
}

function check_empty(text)
{
  	return (text.length > 0);
}

function getSecureURL(url) {
    host = "";
    if (location.host.substr(0,18).toUpperCase() == "WWW.FORWARDAIR.COM")
        host = "https://" + location.host;	
    else if (location.host.substr(0,14).toUpperCase() == "FORWARDAIR.COM")
        host = "https://www." + location.host;
    url = host + url;
    return url;
}

// AKildea 04/16/2010
// check if this browser supports innerText. Firefox does not.
function checkForInnerTextFeature()
{
	var obj = (document.getElementsByTagName("body")[0].innerText != undefined) ? true : false;
	return obj;
}
// Akildea 04/16/2010
// this method should be called instead of changing innertext directly. This will work these browsers:
// Linux: 
//   Konqueror 3.5.2 
//   Firefox 1.5.0.1 
// Mac X: 
//   Safari 2.0.3 
//   Camino 1.0 
// Windows: 
//  Firefox 1.5.0.2 
//  Opera 8.54 
//  Internet Explorer 6 
//  Internet Explorer 7.0.5346.5 Beta 2 
function changeInnerText(elem,changeVal){
    if(!checkForInnerTextFeature()){
        elem.textContent = changeVal;
    }else{
        elem.innerText = changeVal;
    }
}
// Akildea 04/16/2010
// this method should be called instead of .innertext directly. This will work these browsers:
// Linux: 
//   Konqueror 3.5.2 
//   Firefox 1.5.0.1 
// Mac X: 
//   Safari 2.0.3 
//   Camino 1.0 
// Windows: 
//  Firefox 1.5.0.2 
//  Opera 8.54 
//  Internet Explorer 6 
//  Internet Explorer 7.0.5346.5 Beta 2 

function getInnerText(elem){
    if(!checkForInnerTextFeature()){
        return elem.textContent;
    }else{
        return elem.innerText;
    }
}