/* Debugging */

// assert function
function assert(fact) {
     if (!fact) {
          alert("Assert failure!");
     }
}


// show all the properties of the current window in a new window
function showProperties() {
	win2=open("",'window2');
	win2.document.open('text/plain');
	win2.document.writeln('Window Properties');
	for (property in window) {
		win2.document.write('<p><b>' + property + ':</b><br>' + window[property] + '</p>')
	}			
}



/* Misc. functions */

// return date & time formatted m/d/yyyy h:m:s A.M./P.M.

function today() {
	var date = new Date()
	
	var day = date.getDate()
	var month = date.getMonth() + 1
	var year = date.getFullYear()
	var dateF = "" + month + "/" +  day + "/" + year
	
	var hour = date.getHours()
	var minute = date.getMinutes()
	var second = date.getSeconds()
	var timeF = "" + ((hour > 12) ? hour - 12 :  hour)
	if (hour == 0)
	timeF = "12";
	timeF += ((minute < 10) ? ":0" : ":") +  minute
	timeF += ((second < 10) ? ":0" : ":") +  second
	timeF += (hour >= 12) ? " P.M." : " A.M."
	return dateF + " - " + timeF
} 


// create a one dimensional js array from comma delimited list of items

function createArray() {
	this.length = createArray.arguments.length;
	for (var i = 0; i < this.length; i++) {
	this[i] = createArray.arguments[i];
	}
}


// create JS associative array from comma delimited strings of keys & corresponding values

function createObject(keys, values) {
	this.length = values.length;
	for (var i = 0; i < this.length; i++) {
	this[i] = keys[i] + ":" + values[i];
	}
}


// Shadowed Text

function shadText(text,font,color,size) {
	window.document.write("<font color='#999999' style=' font-size: " + size + "; font-family: " + font + "'><b>" + text + "</b></font><br><font color='" + color + "' style='position: relative; left: -.15em; top: -1.25em; font-size: " + size + "; font-family: " + font + "'><b>" + text + "</b></font>");
	window.document.write("<p>");
}


// create new window with all forms data

function displayFormData() {
	win2=open("",'window2');
	win2.document.open('text/plain');
	win2.document.writeln('This document has '+ document.forms.length+'forms.<br>');
	for(i=0;i<document.forms.length;++i) {
		win2.document.writeln('form '+i+' has '+document.forms[i].elements.length+' elements.<br>');
		for(j=0;j<document.forms[i].elements.length;++j) {
			win2.document.writeln((j+1)+' A '+document.forms[i].elements[j].type+' element: '+document.forms[i].elements[j].name+' - value: '+document.forms[i].elements[j].value+'<br>');
		}
	}
	win2.document.close()
	return false	
} // end displayFormData


/* popups */

// Popup Image - requires dummy img named popup
function imgPopUp( curimage ) { 
	document.popup.src = curimage; 
} 


// Popup Image in new window

function winPopUp(source,theTitle,NOwidth,NOheight) { 
	var win0 = window.open("",theTitle,"left=100,top=150,toolbar=no,dependent=yes,directories=no,menubar=no,scrollbars=no,resizable=no,dependent,width=0,height=0");
	win0.opener.focus();
	
	var d = win0.document;
	d.write("<html><head><title>" + theTitle + "</title></head>");
	d.write("<body onclick=self.close();onblur=self.close();>");
	d.write('<img src="' + source + '" onload="window.resizeTo(this.width+25, this.height+40);">');
	d.write("</body></html>");
	d.close();
	win0.focus();
} 


/* Forms Validation */

// DEFAULTS

var defaultEmptyOK = false

// VARIABLE DECLARATIONS

var digits = "0123456789";

var lowercaseLetters = "abcdefghijklmnopqrstuvwxyz"

var uppercaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"

// whitespace characters as defined by this sample code
var whitespace = " \t\n\r";


// non-digit characters which are allowed in phone numbers
var phoneNumberDelimiters = "()- ";


// characters which are allowed in US phone numbers
var validUSPhoneChars = digits + phoneNumberDelimiters;


// characters which are allowed in international phone numbers
// (a leading + is OK)
var validWorldPhoneChars = digits + phoneNumberDelimiters + "+";

// REGULAR EXPRESSION DECLARATIONS

// BOI, followed by one of these two patterns:    [trk 10/17/03]
// (a) zero or more digits, followed by ., followed by 2 digits
// (b) zero or more digits
// ... followed by EOI.

// (Rick) BOI, followed by 0 or more digits followed by either nothing or a decimal and 2 digits, followed by EOI.
//var reMoney = /^(\d*(\.\d{2})?)$/ // no commas
var reMoney = /^(((\d{0,3}(,\d\d\d)*)|((\d*)))(\.\d{2})?)$/ // with commas


// CONSTANT STRING DECLARATIONS
// (grouped for ease of translation and localization)

// m is an abbreviation for "missing"

var mPrefix = "You did not enter a value into the "
var mSuffix = " field. This is a required field. Please enter it now."

// i is an abbreviation for "invalid"

var iStateCode = "This field must be a valid two character U.S. state abbreviation (like CA for California). Please reenter it now."
var iZIPCode = "This field must be a 5 or 9 digit U.S. ZIP Code (like 94043). Please reenter it now."
var iUSPhone = "This field must be a 10 digit U.S. phone number (like 415 555 1212). Please reenter it now."
var iWorldPhone = "This field must be a valid international phone number. Please reenter it now."
var iSSN = "This field must be a 9 digit U.S. social security number (like 123 45 6789). Please reenter it now."
var iEmail = "This field must be a valid email address (like foo@bar.com). Please reenter it now."
var iCreditCardPrefix = "This is not a valid "
var iCreditCardSuffix = " credit card number. (Click the link on this form to see a list of sample numbers.) Please reenter it now."
var iDay = "This field must be a day number between 1 and 31.  Please reenter it now."
var iMonth = "This field must be a month number between 1 and 12.  Please reenter it now."
var iYear = "This field must be a 2 or 4 digit year number.  Please reenter it now."
var iDatePrefix = "The Day, Month, and Year for "
var iDateSuffix = " do not form a valid date.  Please reenter them now."
var iMoney = " must be in money format with no non-numeric characters except the decimal point."
var iPhone = " must be 8 to 11 digits."


// p is an abbreviation for "prompt"

var pEntryPrompt = "Please enter a "
var pStateCode = "2 character code (like CA)."
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 pSSN = "9 digit U.S. social security number (like 123 45 6789)."
var pEmail = "valid email address (like foo@bar.com)."
var pCreditCard = "valid credit card number."
var pDay = "day number between 1 and 31."
var pMonth = "month number between 1 and 12."
var pYear = "2 or 4 digit year number."
var pUSD = "US dollar amount in dollars or dollars and cents (without the dollar sign)."


// Check that string theField.value is in money format, with or without 2 decimals places [trk 10/17/03].
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.

// Check whether string s is empty.

function isEmpty(s)
{   return ((s == null) || (s.length == 0))
}

function checkMoney (theField, emptyOK)
{  
if (checkMoney.arguments.length == 1) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    if (!isMoney(theField.value)) 
      return warnInvalid(theField, theField.name + " " + iMoney);
    else return true;
}



// isMoney (STRING s [, BOOLEAN emptyOK])
// 
// True if string s is an unsigned floating point (real) number with two decimal places or none. 
//
// Does not accept exponential notation.
//
// For explanation of optional argument emptyOK,
// see comments of function isInteger.

function isMoney (s)

{   if (isEmpty(s)) 
       if (isMoney.arguments.length == 1) return defaultEmptyOK;
       else return (isMoney.arguments[1] == true);

    else {
	    return reMoney.test(s)
    }
}


// roundMoney (STRING s) (Rick)
//
// rounds amt to 2 decimal places 

function roundMoney(amt) {		
	num = (Math.round(amt*100)/100).toString();
	while(num.indexOf(".") + 3 > num.length) num += "0"; 
	return num
}


function checkPhone(theField) {

	formatPhone(theField)
}

// formatPhone (STRING s) (Rick)
// strips non-digits & requires 8-11 digits
// formats 8-11 digits with dashes as follows:
// 8: xx-xxx-xxx
// 9: xxx-xxx-xxx
// 10: xxx-xxx-xxxx
// 11: xxx-xxxx-xxxx

function formatPhone(theField) {

	var strippedFld = stripCharsNotInBag(theField.value, digits);
	var l = strippedFld.length;
	
	if(l > 0 && ((l < 8) || (l > 11)))
		return warnInvalid(theField, theField.name + " " + iPhone);
		
	if(l == 8) theField.value = reformat(strippedFld,"",2,"-",3,"-",3);
	if(l == 9) theField.value = reformat(strippedFld,"",3,"-",3,"-",3);
	if(l == 10) theField.value = reformat(strippedFld,"",3,"-",3,"-",4);
	if(l == 11) theField.value = reformat(strippedFld,"",3,"-",4,"-",4);
	
	return true;
}


// Display data entry prompt string s in status bar.

function promptEntry (s)
{   window.status = pEntryPrompt + s
}


// Notify user that contents of field theField are invalid.
// String s describes expected contents of theField.value.
// Put select theField, pu focus in it, and return false.

function warnInvalid (theField, s)
{   theField.focus()
    theField.select()
    alert(s)
    return false
}


// 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;
}



// Removes all whitespace characters from s.
// Global variable whitespace (see above)
// defines which characters are considered whitespace.

function stripWhitespace (s)

{   return stripCharsInBag (s, whitespace)
}


// 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 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;
}
