
function NormalizeEvent(e) {
	if (!e) {
		return null;
	}
	
	// Normalize IE-specific attributes
	// --------------------------------
	// IE's srcElement is a better name, but target is the standard
	if (e.srcElement) {
		e.target = e.srcElement;
	}
	
	// Normalize NN6-specific attributes
	// ---------------------------------
	// NN6 (and IE Mac) provides different properties for Unicode vs. keyboard code.  The former 
	// applies to keypress, while the latter applies to keyup and keydown.
	// IE uses keyCode for both (the meaning changes depending on keypress vs. up/down.)
	// W3C is not settled on the standard.  For now, we'll stick with IE.
	// if (e.charCode) {
	// 	e.keyCode = e.charCode; // Unfortunately, can't do this...keyCode is read-only
	// }
	if (e.charCode && e.type == "keypress") {
		e.key = e.charCode;
	}
	else {
		e.key = e.keyCode;
	}
	
	
	/*
	// Normalize NN4-specific attributes
	// ---------------------------------
	// NN4 calls keycode "which"
	if (e.which) {
		e.keyCode = evt.which;
	}
	// NN4 uses bitmasks to indicate modifier keys
	if (e.modifiers) {
		e.altKey = e.modifiers & Event.ALT_MASK;
		e.ctrlKey = e.modifiers & Event.CONTROL_MASK;
		e.shiftKey = e.modifiers & Event.SHIFT_MASK;
	}
	*/
}

function MakeDateInput(elm) {
	elm.onkeypress = DateInput_KeyPress;
	elm.nextDay = DateInput_NextDay;
	elm.prevDay = DateInput_PrevDay;
}

function FormatDate(dt) {
	var DATE_SEPARATOR = "/";
	return ((dt.getMonth() + 1) + DATE_SEPARATOR + dt.getDate() + DATE_SEPARATOR + GetY2KYear(dt));		
}







//
//	OnDateKeyPress()
//	----------------
//	This function pre-processes date input key commands, and is supposed to be hooked
//	up as the KeyPress event of date input controls.
//
//	The event parameter "evt" is automatically passed by NN4, but IE4+ defines the event
//	as a property of the window.  This object is valid only during the life of an event
//	handler, so this function will not work if you call it outside an event handler. The
//	keyCode is extracted based on the browser, as is the reference to the input control.
//
//	After that, it's a simple switch based on the keyCode, and the function returns
//	false if it handles the event and wants to swallow it up, or true if event propagation
//	should continue.
//
//	Netscape Quirks
//	---------------
//	NN4 appears to have a bug in the Date object.  Try holding the plus key down to make
//	the dates increment over a year. There are certain dates (apparently a slightly 
//	different one each year, although apparently consistent from session to session) where 
//	incrementing the date returns the same date.  Why?  Who knows.  Workarounds?  We could 
//	store the value of the date, increment it using Javascript, and if it's the same as the 
//	previous value,	manually construct a new Date object one day higher.  But that can be 
//	a complicated process because of leap years and so on, which is why you want to rely 
//	on a Date subsystem in the first place.  Sigh.  I say if this bothers users, they
//	should switch to a better browser.
//
function DateInput_KeyPress(evt) {
	if (!evt && event) evt = event;
	NormalizeEvent(evt);

	var bContinue = true;	
	var dtElm = evt.target;	
	switch (evt.key) {

		case 61:	// = key
		case 43:	// + key
			dtElm.nextDay();
			bContinue = false;
			break;
		case 45:	// - key
			dtElm.prevDay();
			bContinue = false;
			break;
		//case 84:	// T
		//case 116:	// t
		//	elm.value = Today();
		//	event.returnValue=false;
		//	event.cancelBubble=true;
		//	break;
			
	}
	return bContinue;
}


//
//	UpDate()
//	--------
//	Increments a string representation of a date by one day,
//	and returns the new date as a string.  If no date can be
//	parsed from the input, and the string is not empty, it
//	just returns the original string.  If the input string
//	is empty, it returns today's date as a string.
//
function DateInput_NextDay() {
	var s = this.value;
	var dt = ParseDate(s);

	// If dt is a string, the value must not be valid date.
	if (typeof dt == "string") {
		// If s is just a blank string, set dt to today. 
		// TODO: parameter for initial value? Either a fixed date, or perhaps value from another field.
		if (s.length == 0) {
			s = FormatDate(new Date());
		}
	}
	else {
		// increment
		dt.setDate(dt.getDate() + 1)
		s = FormatDate(dt);
	}
	this.value = s;
}

//
//	DownDate()
//	----------
//	Like UpDate, only it decrements the date by one day.
//
function DateInput_PrevDay() {
	var s = this.value;
	var dt = ParseDate(s);

	// If dt is a string, the value must not be valid date.
	if (typeof dt == "string") {
		// If s is just a blank string, set dt to today. 
		// TODO: parameter for initial value?
		if (s.length == 0) {
			s = FormatDate(new Date());
		}
	}
	else {
		// decrement
		dt.setDate(dt.getDate() - 1);
		s = FormatDate(dt);
	}
	this.value = s;
}

//
//	ParseDate()
//	-----------
//	Attempts to parse a date-time value from a given string.
//	If the parse is not successful, it returns the original
//	string, otherwise it returns the canonical string 
//	representation for the date
//
function ParseDate(sInput) {
	var nMsec = Date.parse(sInput);
	if (isNaN(nMsec)) 
		return sInput;

	return new Date(nMsec);
}

//
//	GetY2KYear()
//	------------
//	Returns the CCYY representation of a year from a Date object.  This is handy
//	because it covers up some strange return values from Javascript's Date.getYear()
//
function GetY2KYear(dt) {
	var yr = dt.getYear();
	if (yr < 1000) yr += 1900;
	return yr;
}

//
//	Today()
//	-------
//	Returns today's date as a string
//
function Today() {
	var dt = new Date();
	return FormatDate(dt);
}
