/**
 * Global variables
 */
months = new Array(12);
months[0] = "Jan";
months[1] = "Feb";
months[2] = "Mar";
months[3] = "Apr";
months[4] = "May";
months[5] = "Jun";
months[6] = "Jul";
months[7] = "Aug";
months[8] = "Sep";
months[9] = "Oct";
months[10] = "Nov";
months[11] = "Dec";


/**
 * Function called by onLoad event of the body tag.
 * Add extra functionality by supplying .js file that implements customLoad.
 */
function generalLoad() {
	var i = 0;

	// set focus on the first element of the first form
	if (document.forms.length > 0) {
		firstForm = document.forms[0];
		if (firstForm.elements.length > 0) {
			for (i = 0; i < firstForm.elements.length; i++) {
				thisElement = firstForm.elements[i];
				if (thisElement.id != "Hidden") {
					thisElement.focus();
					break;
				}
			}
		}
	}

	// then invoke the customised load processing
	customLoad();
}

/**
 * Function called each time a form element loses focus.
 * The element in question is passed in as a parameter.
 * Element data type is checked here based on the content of the id attribute of the input tag.
 * Add extra functionality by supplying .js file that implements customBlur.
 */
function generalBlur(thisElement) {
	var i = 0;

	// check date data types
	if (thisElement.id == "MandatoryDate" || thisElement.id == "OptionalDate") {
		if (!isValidDate(thisElement)) {
			if (thisElement.title == "") {
				alert("This is not a recognised date (try dd/mm/yy).");
			} else {
				alert(thisElement.title + 
					" is not a recognised date (try dd/mm/yy).");
			}
			thisElement.focus();
			return false;
		}
	}

	// check time data types
	if (thisElement.id == "MandatoryTime" || thisElement.id == "OptionalTime") {
		if (!isValidTime(thisElement)) {
			alert(thisElement.title + 
				" is not a recognised 24-hour time (try hh:mm).");
			thisElement.focus();
			return false;
		}
	}

	// check currency data types
	if (thisElement.id == "MandatoryCurrency" || thisElement.id == "OptionalCurrency") {
		if (!isValidCurrency(thisElement)) {
			alert(thisElement.title + 
				" is not a recognised amount (try 9999.99).");
			thisElement.focus();
			return false;
		}
	}

	// check number data types
	if (thisElement.id == "MandatoryNumber" || thisElement.id == "OptionalNumber") {
		if (!isValidNumber(thisElement)) {
			alert(thisElement.title + 
				" is not a recognised number.");
			thisElement.focus();
			return false;
		}
	}

	// if all ok, invoke customised onBlur processing
	return customBlur(thisElement);
}

/**
 * Function called each time a form element changes value.
 * The element in question is passed in as a parameter.
 * Add extra functionality by supplying .js file that implements customBlur.
 */
function generalChange(thisElement) {

	// if all ok, invoke customised onBlur processing
	return customChange(thisElement);
}


/**
 * Function called each time a checkbox is clicked.
 * The element in question is passed in as a parameter.
 * Add extra functionality by supplying .js file that implements customClick.
 */
function generalClick(thisElement) {

	// if all ok, invoke customised onClick processing
	return customClick(thisElement);
}


/**
 * Function called each time a select box value changes.
 * The element in question is passed in as a parameter.
 * Add extra functionality by supplying .js file that implements customChange.
 */
function generalChange(thisElement) {

	// if all ok, invoke customised onChange processing
	return customChange(thisElement);
}


/**
 * Function called each time a form is submitted.
 * The form in question is passed in as a parameter.
 * Element data type is re-checked here as is the presence of mandatory fields.
 * Add extra functionality by supplying .js file that implements customSubmit.
 */
function generalSubmit(thisForm) {
	var i = 0;

	// check for mandatory fields
	for (i = 0; i < thisForm.elements.length; i++) {
		thisElement = thisForm.elements[i];
		if (!generalBlur(thisElement)) {
			return false;
		}
		if (thisElement.id.substring(0,9) == "Mandatory") { 
			if (isEmpty(thisElement)) {
				alert(thisElement.title + " is required.");
				thisElement.focus();
				return false;
			}
		}
	}

	// if all ok, invoke customised submit processing
	return customSubmit(thisForm);
}

/**
 * Tests if a text input is empty.
 */
function isEmpty(thisElement) {
	if (thisElement.value.length == 0) { 
		return true;
	}
	return false;
}

/**
 * Tests if the contents of an element constitutes a valid date.
 */
function isValidDate(thisElement) {

	if (isEmpty(thisElement)) { 
		return true;
	}

	// parse the date
	thisDate = parseDate(thisElement);

	// if not a valid date, get out
	if (isNaN(thisDate)) {
		return false;
	}

	// reformat the date
	year = thisDate.getFullYear() + "";
	day = thisDate.getDate() + "";
	if (day.length == 1) {
		day = "0" + day;
	}
	thisElement.value = 
		day + "-" + 
		months[thisDate.getMonth()] + "-" + 
		year;

	// all ok
	return true;
}

/**
 * Takes a user entered date and converts it to a Date object.
 */
function parseDate(thisElement) {
	var i = 0;
	var j = 0;

	today = new Date();

	// first split the string
	input = thisElement.value;
	bits = new Array(3);
	bits = input.split("/");
	if (bits.length == 1) {
		bits = input.split("-");
	}
	if (bits.length == 1) {
		bits = input.split(".");
	}
	if (bits.length == 1) {
		bits = input.split(" ");
	}

	if (bits.length == 1) {
		if (input.length > 4) {
			// no separators
			bits[0] = input.substring(0,2);
			bits[1] = input.substring(2,4);
			bits[2] = input.substring(4,8);
		} else if (input.length > 2) {
			bits[0] = input.substring(0,2);
			bits[1] = input.substring(2,4);
			bits[2] = today.getFullYear();
		} else {
			bits[0] = input.substring(0,2);
			bits[1] = today.getMonth() + 1;
			bits[2] = today.getFullYear();
		}
	}

	if (bits.length == 2) {
		bits[2] = today.getFullYear();
	}

	// sort out alpha months
	for (i = 0; i < bits.length; i++) {
		if (isNaN(bits[i])) {
			for (j = 0; j < 12; j++) {
				if (bits[i].toUpperCase() == months[j].toUpperCase()) {
					bits[i] = (j + 1) + "";
					break;
				}
			}
		}
	}

	// sort out 2 digit years
	if (bits[2].length < 4) {
		if (bits[2] < 30) {
			bits[2] = "20" + bits[2];
		}
	}
	
	// preliminary sensibility checks on day and month
	if (bits[0].length > 2) {
		bits[0] = "?";
	}
	if (bits[0].length == 2 && bits[0] > "31") {
		bits[0] = "?";
	}
	if (bits[1].length > 2) {
		bits[1] = "?";
	}
	if (bits[1].length == 2 && bits[1] > "12") {
		bits[1] = "?";
	}
	

	// parse the date to check validity
	yankDate = bits[1] + "/" + bits[0] + "/" + bits[2];
	thisDate = new Date(Date.parse(yankDate));

	return thisDate;
}

/**
 * Tests if the contents of an element constitutes a valid time.
 */
function isValidTime(thisElement) {

	var pos = 0;
	var isPM = false;

	if (isEmpty(thisElement)) { 
		return true;
	}

	// check for am/pm
	input = thisElement.value;
	input = input.toUpperCase();
	pos = input.indexOf("AM");
	if (pos > 0) {
		input = input.substring(0,pos);
	}
	pos = input.indexOf("PM");
	if (pos > 0) {
		isPM = true;
		input = input.substring(0,pos);
	}


	// first split the string
	bits = new Array(2);
	bits = input.split(":");
	if (bits.length == 1) {
		bits = input.split("-");
	}
	if (bits.length == 1) {
		bits = input.split(".");
	}
	if (bits.length == 1) {
		bits = input.split(" ");
	}

	if (bits.length == 1) {
		// no separators
		bits[0] = input.substring(0,2);
		bits[1] = input.substring(2,4);
	}
	if (bits[0] == "24") {
		bits[0] = "23";
		bits[1] = "59";
	}


	// parse the time to check validity
	thisTime = new Date();
	thisTime.setHours(bits[0]);
	thisTime.setMinutes(bits[1]);
	if (isNaN(thisTime)) {
		return false;
	}

	// allow for AM/PM
	if (isPM) {
		thisTime.setHours(thisTime.getHours() + 12);
	}

	// now reformat the date
	hour = thisTime.getHours() + "";
	min = thisTime.getMinutes() + "";
	if (hour.length == 1) {
		hour = "0" + hour;
	}
	if (min.length == 1) {
		min = "0" + min;
	}
	thisElement.value = hour + ":" + min;
	return true;
}

/**
 * Tests if the contents of an element constitutes a valid number.
 */
function isValidNumber(thisElement) {
	var i = 0;

	if (isEmpty(thisElement)) { 
		return true;
	}

	// first remove any spurious dollar sign
	input = thisElement.value;
	if (input.charAt(0) == "$") {
		input = input.substring(1);
	}
	if (input.charAt(0) == " ") {
		input = input.substring(1);
	}
	if (input.charAt(input.length - 1) == "%") {
		input = input.substring(0, input.length - 1);
	}

	// now remove any commas
	bits = new Array(9);
	bits = input.split(",");
	amount = bits.join("");

	// now check for validity
	if (isNaN(amount)) {
		return false;
	}

	// format and return
	thisElement.value = amount;
	return true;
}

/**
 * Tests if the contents of an element constitutes a valid currency amount.
 */
function isValidCurrency(thisElement) {
	var i = 0;

	if (isEmpty(thisElement)) { 
		return true;
	}

	amount = parseCurrency(thisElement);

	// now check for validity
	if (isNaN(amount)) {
		return false;
	}

	// format the currency and return
	thisElement.value = formatCurrency(amount);
	return true;
}

function parseCurrency(thisElement) {

	//strip commas			
	var anum0 = /,/g;
	var val = thisElement.value.replace(anum0, "");
	
	var anum1 = /^([-\(])?\$?([0-9]+)(\.[0-9]{0,2})?\)?$/;
	
	var arr = anum1.exec(val);
	if (arr != null) {
		var sign = arr[1];		
		var cents = arr[3];
		if (sign == null) {
			sign = "";		
		} else if (sign == "(") {
			sign = "-";			
		}
		if (cents == null) {
			return parseFloat(sign + arr[2]);
		} else {
			return parseFloat(sign + arr[2] + cents);
		}
	}
		
	return parseFloat("NaN");
	
}

/**
 * Parse a currency object into a number
 */
function oldParseCurrency(thisElement) {

	var negative = false;

	var amount = thisElement.value;

	// remove leading minus signs
	if (amount.charAt(0) == '-') {
		amount = amount.substring(1);
		negative = true;
	}
	if (amount.charAt(0) == '(') {
		var pos = amount.indexOf(')');
		if (pos >= 0) {
			amount = amount.substring(1, pos);
			negative = true;
		}
	}

	// first remove the dollar sign
	if (amount.charAt(0) == "$") {
		amount = amount.substring(1);
	}
	while (amount.charAt(0) == " ") {
		amount = amount.substring(1);
	}

	// now remove any commas
	if (amount.indexOf(",") >= 0) {
		amount = amount.split(",").join("");
	}

	// now add the negative
	if (negative) {	
		return parseFloat("-" + amount);
	} 
	return parseFloat(amount);
}


/**
 * Formats a currency object into a format suitable for display
 */
function formatCurrency(currency) {
	
	var anum1 = /^(-)?([0-9]+)(\.[0-9]{0,2})?$/;
	
	//floating point numbers need to be rounded to 2 decimal places
	var arr = anum1.exec(Math.round(currency * 100) / 100);
	if (arr != null) {
	
		var dollars = "" + arr[2];						
		var dollars2 = "";				
		for (var i = dollars.length; i > 0; i = i - 3) {
			if (i > 3) {
				dollars2 = "," + dollars.substring(i-3, i) + dollars2;
			} else {
				dollars2 = dollars.substring(0, i) + dollars2;
			}
		}					
		dollars = "$" + dollars2;
		
		var cents = arr[3];
		if (cents == null || cents.length == 0) cents = ".00";
		while (cents.length < 3) cents = cents + "0";		

		dollars = dollars + cents;		
	
		if (arr[1] == "-") {
			return "(" + dollars + ")";
		}
		return dollars;
	}		
	return "NaN";

}

/**
 * Formats a currency object into a format suitable for display
 */
function oldFormatCurrency(currency) {
	var i = 0;
	var negative = false;

	// round to 2 decimal places
	rounded = Math.round(currency * 100) / 100;
	if (rounded < 0) {
		negative = true;
	}
	
	// make sure we have a String object
	amount = rounded + "";
	if (amount.charAt(0) == '-') {
		amount = amount.substring(1);
	}

	// now add the decimal point
	point = amount.indexOf(".");
	if (point < 0) {
		amount = amount + ".00";
	}
	if (point == amount.length - 1) {
		amount = amount + "00";
	}
	if (point == amount.length - 2) {
		amount = amount + "0";
	}

	// now put back the commas
	point = amount.indexOf(".");
	display = amount.substring(point);
	for (i = point; i > 0; i = i - 3) {
		if (i > 3) {
			display = "," + amount.substring(i-3, i) + display;
		} else {
			display = amount.substring(i-3, i) + display;
		}
	}

	// and add the dollar sign
	display = "$" + display;

	// now add the negative
	if (negative) {
		display = "-" + display;
	}

	// return the formatted value
	return display;
}