// ===================================================================
// Author: Matt Kruse <matt@mattkruse.com>
// WWW: http://www.mattkruse.com/
//
// NOTICE: You may use this code for any purpose, commercial or
// private, without any further permission from the author. You may
// remove this notice from your final code if you wish, however it is
// appreciated by the author if at least my web site address is kept.
//
// You may *NOT* re-distribute this code in any way except through its
// use. That means, you can include it in your product, or your web
// site, or any other form where the code is actually being used. You
// may not put the plain javascript up on your site for download or
// include it in your javascript libraries for download.
// If you wish to share this code with others, please just point them
// to the URL instead.
// Please DO NOT link directly to my .js files from your site. Copy
// the files to your server and use them there. Thank you.
// ===================================================================

/* SOURCE FILE: AnchorPosition.js */

/*
 AnchorPosition.js
 Author: Matt Kruse
 Last modified: 10/11/02

 DESCRIPTION: These functions find the position of an <A> tag in a document,
 so other elements can be positioned relative to it.

 COMPATABILITY: Netscape 4.x,6.x,Mozilla, IE 5.x,6.x on Windows. Some small
 positioning errors - usually with Window positioning - occur on the
 Macintosh platform.

 FUNCTIONS:
 getAnchorPosition(anchorname)
 Returns an Object() having .x and .y properties of the pixel coordinates
 of the upper-left corner of the anchor. Position is relative to the PAGE.

 getAnchorWindowPosition(anchorname)
 Returns an Object() having .x and .y properties of the pixel coordinates
 of the upper-left corner of the anchor, relative to the WHOLE SCREEN.

 NOTES:

 1) For popping up separate browser windows, use getAnchorWindowPosition.
 Otherwise, use getAnchorPosition

 2) Your anchor tag MUST contain both NAME and ID attributes which are the
 same. For example:
 <A NAME="test" ID="test"> </A>

 3) There must be at least a space between <A> </A> for IE5.5 to see the
 anchor tag correctly. Do not do <A></A> with no space.
 */

// getAnchorPosition(anchorname)
//   This function returns an object having .x and .y properties which are the coordinates
//   of the named anchor, relative to the page.
function getAnchorPosition(anchorname)
{
	// This function will return an Object with x and y properties
	var useWindow=false;
	var coordinates=new Object();
	var x=0, y=0;
	// Browser capability sniffing
	var use_gebi=false, use_css=false, use_layers=false;
	if (document.getElementById)
		use_gebi=true;
	else if (document.all)
		use_css=true;
	else if (document.layers)
		use_layers=true;
	
	// Logic to find position
	if (use_gebi && document.all)
	{
		x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);
		y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);
	}
	else if (use_gebi)
	{
		var o=document.getElementById(anchorname);
		x=AnchorPosition_getPageOffsetLeft(o);
		y=AnchorPosition_getPageOffsetTop(o);
	}
	else if (use_css)
	{
		x=AnchorPosition_getPageOffsetLeft(document.all[anchorname]);
		y=AnchorPosition_getPageOffsetTop(document.all[anchorname]);
	}
	else if (use_layers)
	{
		var found=0;
		for( var i=0;i < document.anchors.length;i++)
		{
			if (document.anchors[i].name == anchorname)
			{
				found=1;
				break;
			}
		}
		if (found == 0)
		{
			coordinates.x=0;
			coordinates.y=0;
			return coordinates;
		}
		x=document.anchors[i].x;
		y=document.anchors[i].y;
	}
	else
	{
		coordinates.x=0;
		coordinates.y=0;
		return coordinates;
	}
	coordinates.x=x;
	coordinates.y=y;
	return coordinates;
}

// getAnchorWindowPosition(anchorname)
// This function returns an object having .x and .y properties which are the
// coordinates
// of the named anchor, relative to the window
function getAnchorWindowPosition(anchorname)
{
	var coordinates=getAnchorPosition(anchorname);
	var x=0;
	var y=0;
	if (document.getElementById)
	{
		if (isNaN(window.screenX))
		{
			x=coordinates.x - document.body.scrollLeft + window.screenLeft;
			y=coordinates.y - document.body.scrollTop + window.screenTop;
		}
		else
		{
			x=coordinates.x + window.screenX
					+ (window.outerWidth - window.innerWidth)
					- window.pageXOffset;
			y=coordinates.y + window.screenY
					+ (window.outerHeight - 24 - window.innerHeight)
					- window.pageYOffset;
		}
	}
	else if (document.all)
	{
		x=coordinates.x - document.body.scrollLeft + window.screenLeft;
		y=coordinates.y - document.body.scrollTop + window.screenTop;
	}
	else if (document.layers)
	{
		x=coordinates.x + window.screenX
				+ (window.outerWidth - window.innerWidth) - window.pageXOffset;
		y=coordinates.y + window.screenY
				+ (window.outerHeight - 24 - window.innerHeight)
				- window.pageYOffset;
	}
	coordinates.x=x;
	coordinates.y=y;
	return coordinates;
}

// Functions for IE to get position of an object
function AnchorPosition_getPageOffsetLeft(el)
{
	var ol=el.offsetLeft;
	while ((el=el.offsetParent) != null)
		ol+=el.offsetLeft;
	return ol;
}

function AnchorPosition_getWindowOffsetLeft(el)
{
	return AnchorPosition_getPageOffsetLeft(el) - document.body.scrollLeft;
}

function AnchorPosition_getPageOffsetTop(el)
{
	var ot=el.offsetTop;
	while ((el=el.offsetParent) != null)
		ot+=el.offsetTop;
	return ot;
}

function AnchorPosition_getWindowOffsetTop(el)
{
	return AnchorPosition_getPageOffsetTop(el) - document.body.scrollTop;
}

/* SOURCE FILE: date.js */

// HISTORY
// ------------------------------------------------------------------
// May 17, 2003: Fixed bug in parseDate() for dates <1970
// March 11, 2003: Added parseDate() function
// March 11, 2003: Added "NNN" formatting option. Doesn't match up
// perfectly with SimpleDateFormat formats, but
// backwards-compatability was required.
// ------------------------------------------------------------------
// These functions use the same 'format' strings as the
// java.text.SimpleDateFormat class, with minor exceptions.
// The format string consists of the following abbreviations:
//
// Field | Full Form | Short Form
// -------------+--------------------+-----------------------
// Year | yyyy (4 digits) | yy (2 digits), y (2 or 4 digits)
// Month | MMM (name or abbr.)| MM (2 digits), M (1 or 2 digits)
// | NNN (abbr.) |
// Day of Month | dd (2 digits) | d (1 or 2 digits)
// Day of Week | EE (name) | E (abbr)
// Hour (1-12) | hh (2 digits) | h (1 or 2 digits)
// Hour (0-23) | HH (2 digits) | H (1 or 2 digits)
// Hour (0-11) | KK (2 digits) | K (1 or 2 digits)
// Hour (1-24) | kk (2 digits) | k (1 or 2 digits)
// Minute | mm (2 digits) | m (1 or 2 digits)
// Second | ss (2 digits) | s (1 or 2 digits)
// AM/PM | a |
//
// NOTE THE DIFFERENCE BETWEEN MM and mm! Month=MM, not mm!
// Examples:
// "MMM d, y" matches: January 01, 2000
// Dec 1, 1900
// Nov 20, 00
// "M/d/yy" matches: 01/20/00
// 9/2/00
// "MMM dd, yyyy hh:mm:ssa" matches: "January 01, 2000 12:30:45AM"
// ------------------------------------------------------------------
var MONTH_NAMES=new Array('January', 'February', 'March', 'April', 'May',
		'June', 'July', 'August', 'September', 'October', 'November',
		'December', 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug',
		'Sep', 'Oct', 'Nov', 'Dec');
var DAY_NAMES=new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday',
		'Friday', 'Saturday', 'Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');

function LZ(x)
{
	return (x < 0 || x > 9?"":"0") + x;
}

// ------------------------------------------------------------------
// isDate ( date_string, format_string )
// Returns true if date string matches format of format string and
// is a valid date. Else returns false.
// It is recommended that you trim whitespace around the value before
// passing it to this function, as whitespace is NOT ignored!
// ------------------------------------------------------------------
function isDate(val, format)
{
	var date=getDateFromFormat(val, format);
	if (date == 0)
		return false;
	return true;
}

// -------------------------------------------------------------------
// compareDates(date1,date1format,date2,date2format)
// Compare two date strings to see which is greater.
// Returns:
// 1 if date1 is greater than date2
// 0 if date2 is greater than date1 of if they are the same
// -1 if either of the dates is in an invalid format
// -------------------------------------------------------------------
function compareDates(date1, dateformat1, date2, dateformat2)
{
	var d1=getDateFromFormat(date1, dateformat1);
	var d2=getDateFromFormat(date2, dateformat2);
	if (d1 == 0 || d2 == 0)
		return -1;
	else 
	if (d1 > d2)
		return 1;
	return 0;
}

// ------------------------------------------------------------------
// formatDate (date_object, format)
// Returns a date in the output format specified.
// The format string uses the same abbreviations as in getDateFromFormat()
// ------------------------------------------------------------------
function formatDate(date, format)
{
	format=format + "";
	var result="";
	var i_format=0;
	var c="";
	var token="";
	var y=date.getYear() + "";
	var M=date.getMonth() + 1;
	var d=date.getDate();
	var E=date.getDay();
	var H=date.getHours();
	var m=date.getMinutes();
	var s=date.getSeconds();
	var yyyy, yy, MMM, MM, dd, hh, h, mm, ss, ampm, HH, H, KK, K, kk, k;
	// Convert real date parts into formatted versions
	var value=new Object();
	if (y.length < 4)
		y="" + (y - 0 + 1900);

	value["y"]="" + y;
	value["yyyy"]=y;
	value["yy"]=y.substring(2, 4);
	value["M"]=M;
	value["MM"]=LZ(M);
	value["MMM"]=MONTH_NAMES[M - 1];
	value["NNN"]=MONTH_NAMES[M + 11];
	value["d"]=d;
	value["dd"]=LZ(d);
	value["E"]=DAY_NAMES[E + 7];
	value["EE"]=DAY_NAMES[E];
	value["H"]=H;
	value["HH"]=LZ(H);
	if (H == 0)
		value["h"]=12;
	else if (H > 12)
		value["h"]=H - 12;
	else
		value["h"]=H;
	
	value["hh"]=LZ(value["h"]);
	
	if (H > 11)
		value["K"]=H - 12;
	else
		value["K"]=H;
	
	value["k"]=H + 1;
	value["KK"]=LZ(value["K"]);
	value["kk"]=LZ(value["k"]);

	if (H > 11)
		value["a"]="PM";
	else
		value["a"]="AM";

	value["m"]=m;
	value["mm"]=LZ(m);
	value["s"]=s;
	value["ss"]=LZ(s);
	while (i_format < format.length)
	{
		c=format.charAt(i_format);
		token="";
		while ((format.charAt(i_format) == c) && (i_format < format.length))
			token+=format.charAt(i_format++);
		
		if (value[token] != null)
			result=result + value[token];
		else
			result=result + token;
	}
	return result;
}

// Formats the date according to PHP standard (http://no.php.net/manual/en/function.strftime.php)
function phpFormatDate(date, format)
{
	format=format + "";
	var result="";
	var i_format=0;
	var c="";
	var token="";
	var y=date.getYear() + "";
	var M=date.getMonth() + 1;
	var d=date.getDate();
	var E=date.getDay();
	var H=date.getHours();
	var m=date.getMinutes();
	var s=date.getSeconds();
	var yyyy, yy, MMM, MM, dd, hh, h, mm, ss, ampm, HH, H, KK, K, kk, k;
	// Convert real date parts into formatted versions
	var value=new Object();
	if (y.length < 4)
		y="" + (y - 0 + 1900);

	value["%Y"]=y;
	value["%y"]=y.substring(2, 4);
//	value["n"]=M;
	value["%m"]=LZ(M);
	value["%B"]=MONTH_NAMES[M - 1];
	value["%b"]=MONTH_NAMES[M + 11];
	value["%e"]=d;
	value["%d"]=LZ(d);
	value["%a"]=DAY_NAMES[E + 7];
	value["%A"]=DAY_NAMES[E];
//	value["G"]=H;
	value["%H"]=LZ(H);
	if (H == 0)
		value["%l"]=12;
	else if (H > 12)
		value["%l"]=H - 12;
	else
		value["%l"]=H;
	
	value["%I"]=LZ(value["%l"]);
	
	if (H > 11)
		value["%p"]="PM";
	else
		value["%p"]="AM";

	if (H > 11)
		value["%P"]="pm";
	else
		value["%P"]="am";

	value["%M"]=LZ(m);
	value["%S"]=LZ(s);
	while (i_format < format.length)
	{
		token=format.charAt(i_format);
		if (token== "%")
			token+=format.charAt(++i_format);
		
		if (value[token] != null)
			result=result + value[token];
		else
			result=result + token;
		i_format++;
	}
	return result;
}

// ------------------------------------------------------------------
// Utility functions for parsing in getDateFromFormat()
// ------------------------------------------------------------------
function _isInteger(val)
{
	var digits="1234567890";
	for( var i=0;i < val.length;i++)
	{
		if (digits.indexOf(val.charAt(i)) == -1)
			return false;
	}
	return true;
}
function _getInt(str, i, minlength, maxlength)
{
	for( var x=maxlength;x >= minlength;x--)
	{
		var token=str.substring(i, i + x);
		if (token.length < minlength)
			return null;
		if (_isInteger(token))
			return token;
	}
	return null;
}

// ------------------------------------------------------------------
// getDateFromFormat( date_string , format_string )
//
// This function takes a date string and a format string. It matches
// If the date string matches the format string, it returns the
// getTime() of the date. If it does not match, it returns 0.
// ------------------------------------------------------------------
function getDateFromFormat(val, format)
{
	val=val + "";
	format=format + "";
	var i_val=0;
	var i_format=0;
	var c="";
	var token="";
	var token2="";
	var x, y;
	var now=new Date();
	var year=now.getYear();
	var month=now.getMonth() + 1;
	var date=1;
	var hh=now.getHours();
	var mm=now.getMinutes();
	var ss=now.getSeconds();
	var ampm="";

	while (i_format < format.length)
	{
		// Get next token from format string
		c=format.charAt(i_format);
		token="";
		while ((format.charAt(i_format) == c) && (i_format < format.length))
		{
			token+=format.charAt(i_format++);
		}
		// Extract contents of value based on format token
		if (token == "yyyy" || token == "yy" || token == "y")
		{
			if (token == "yyyy")
			{
				x=4;
				y=4;
			}
			if (token == "yy")
			{
				x=2;
				y=2;
			}
			if (token == "y")
			{
				x=2;
				y=4;
			}
			year=_getInt(val, i_val, x, y);
			if (year == null)
				return 0;
			
			i_val+=year.length;
			if (year.length == 2)
			{
				if (year > 70)
					year=1900 + (year - 0);
				else
					year=2000 + (year - 0);
			}
		}
		else if (token == "MMM" || token == "NNN")
		{
			month=0;
			for( var i=0;i < MONTH_NAMES.length;i++)
			{
				var month_name=MONTH_NAMES[i];
				if (val.substring(i_val, i_val + month_name.length)
						.toLowerCase() == month_name.toLowerCase())
				{
					if (token == "MMM" || (token == "NNN" && i > 11))
					{
						month=i + 1;
						if (month > 12)
							month-=12;

						i_val+=month_name.length;
						break;
					}
				}
			}
			if ((month < 1) || (month > 12))
				return 0;

		}
		else if (token == "EE" || token == "E")
		{
			for( var i=0;i < DAY_NAMES.length;i++)
			{
				var day_name=DAY_NAMES[i];
				if (val.substring(i_val, i_val + day_name.length).toLowerCase() == day_name
						.toLowerCase())
				{
					i_val+=day_name.length;
					break;
				}
			}
		}
		else if (token == "MM" || token == "M")
		{
			month=_getInt(val, i_val, token.length, 2);
			if (month == null || (month < 1) || (month > 12))
				return 0;

			i_val+=month.length;
		}
		else if (token == "dd" || token == "d")
		{
			date=_getInt(val, i_val, token.length, 2);
			if (date == null || (date < 1) || (date > 31))
				return 0;

			i_val+=date.length;
		}
		else if (token == "hh" || token == "h")
		{
			hh=_getInt(val, i_val, token.length, 2);
			if (hh == null || (hh < 1) || (hh > 12))
				return 0;

			i_val+=hh.length;
		}
		else if (token == "HH" || token == "H")
		{
			hh=_getInt(val, i_val, token.length, 2);
			if (hh == null || (hh < 0) || (hh > 23))
				return 0;

			i_val+=hh.length;
		}
		else if (token == "KK" || token == "K")
		{
			hh=_getInt(val, i_val, token.length, 2);
			if (hh == null || (hh < 0) || (hh > 11))
				return 0;

			i_val+=hh.length;
		}
		else if (token == "kk" || token == "k")
		{
			hh=_getInt(val, i_val, token.length, 2);
			if (hh == null || (hh < 1) || (hh > 24))
				return 0;

			i_val+=hh.length;
			hh--;
		}
		else if (token == "mm" || token == "m")
		{
			mm=_getInt(val, i_val, token.length, 2);
			if (mm == null || (mm < 0) || (mm > 59))
				return 0;

			i_val+=mm.length;
		}
		else if (token == "ss" || token == "s")
		{
			ss=_getInt(val, i_val, token.length, 2);
			if (ss == null || (ss < 0) || (ss > 59))
				return 0;

			i_val+=ss.length;
		}
		else if (token == "a")
		{
			if (val.substring(i_val, i_val + 2).toLowerCase() == "am")
				ampm="AM";
			else if (val.substring(i_val, i_val + 2).toLowerCase() == "pm")
				ampm="PM";
			else
				return 0;
			
			i_val+=2;
		}
		else
		{
			if (val.substring(i_val, i_val + token.length) != token)
				return 0;
			else
				i_val+=token.length;
		}
	}
	// If there are any trailing characters left in the value, it doesn't match
	if (i_val != val.length)
		return 0;

	// Is date valid for month?
	if (month == 2)
	{
		// Check for leap year
		if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))
		{ // leap year
			if (date > 29)
				return 0;
		}
		else
		{
			if (date > 28)
				return 0;
		}
	}
	if ((month == 4) || (month == 6) || (month == 9) || (month == 11))
	{
		if (date > 30)
			return 0;
	}
	// Correct hours value
	if (hh < 12 && ampm == "PM")
		hh=hh - 0 + 12;
	else if (hh > 11 && ampm == "AM")
		hh-=12;
	
	var newdate=new Date(year, month - 1, date, hh, mm, ss);
	return newdate.getTime();
}

// ------------------------------------------------------------------
// parseDate( date_string [, prefer_euro_format] )
//
// This function takes a date string and tries to match it to a
// number of possible date formats to get the value. It will try to
// match against the following international formats, in this order:
// y-M-d MMM d, y MMM d,y y-MMM-d d-MMM-y MMM d
// M/d/y M-d-y M.d.y MMM-d M/d M-d
// d/M/y d-M-y d.M.y d-MMM d/M d-M
// A second argument may be passed to instruct the method to search
// for formats like d/M/y (european format) before M/d/y (American).
// Returns a Date object or null if no patterns match.
// ------------------------------------------------------------------
function parseDate(val)
{
	var preferEuro=(arguments.length == 2)?arguments[1]:false;
	generalFormats=new Array('y-M-d', 'MMM d, y', 'MMM d,y', 'y-MMM-d',
			'd-MMM-y', 'MMM d');
	monthFirst=new Array('M/d/y', 'M-d-y', 'M.d.y', 'MMM-d', 'M/d', 'M-d');
	dateFirst=new Array('d/M/y', 'd-M-y', 'd.M.y', 'd-MMM', 'd/M', 'd-M');
	var checkList=new Array('generalFormats', preferEuro?'dateFirst'
			:'monthFirst', preferEuro?'monthFirst':'dateFirst');
	var d=null;
	for( var i=0;i < checkList.length;i++)
	{
		var l=window[checkList[i]];
		for( var j=0;j < l.length;j++)
		{
			d=getDateFromFormat(val, l[j]);
			if (d != 0) {
				return new Date(d);
			}
		}
	}
	return null;
}

/* SOURCE FILE: PopupWindow.js */

/*
 * PopupWindow.js Author: Matt Kruse Last modified: 02/16/04
 * 
 * DESCRIPTION: This object allows you to easily and quickly popup a window in a
 * certain place. The window can either be a DIV or a separate browser window.
 * 
 * COMPATABILITY: Works with Netscape 4.x, 6.x, IE 5.x on Windows. Some small
 * positioning errors - usually with Window positioning - occur on the Macintosh
 * platform. Due to bugs in Netscape 4.x, populating the popup window with
 * <STYLE> tags may cause errors.
 * 
 * USAGE: // Create an object for a WINDOW popup var win = new PopupWindow();
 *  // Create an object for a DIV window using the DIV named 'mydiv' var win =
 * new PopupWindow('mydiv');
 *  // Set the window to automatically hide itself when the user clicks //
 * anywhere else on the page except the popup win.autoHide();
 *  // Show the window relative to the anchor name passed in
 * win.showPopup(anchorname);
 *  // Hide the popup win.hidePopup();
 *  // Set the size of the popup window (only applies to WINDOW popups
 * win.setSize(width,height);
 *  // Populate the contents of the popup window that will be shown. If you //
 * change the contents while it is displayed, you will need to refresh()
 * win.populate(string);
 *  // set the URL of the window, rather than populating its contents //
 * manually win.setUrl("http://www.site.com/");
 *  // Refresh the contents of the popup win.refresh();
 *  // Specify how many pixels to the right of the anchor the popup will appear
 * win.offsetX = 50;
 *  // Specify how many pixels below the anchor the popup will appear
 * win.offsetY = 100;
 * 
 * NOTES: 1) Requires the functions in AnchorPosition.js
 * 
 * 2) Your anchor tag MUST contain both NAME and ID attributes which are the
 * same. For example: <A NAME="test" ID="test"> </A>
 * 
 * 3) There must be at least a space between <A> </A> for IE5.5 to see the
 * anchor tag correctly. Do not do <A></A> with no space.
 * 
 * 4) When a PopupWindow object is created, a handler for 'onmouseup' is
 * attached to any event handler you may have already defined. Do NOT define an
 * event handler for 'onmouseup' after you define a PopupWindow object or the
 * autoHide() will not work correctly.
 */

// Set the position of the popup window based on the anchor
function PopupWindow_getXYPosition(anchorname)
{
	var coordinates;
	if (this.type == "WINDOW")
		coordinates=getAnchorWindowPosition(anchorname);
	else
		coordinates=getAnchorPosition(anchorname);

	this.x=coordinates.x;
	this.y=coordinates.y;
}
// Set width/height of DIV/popup window
function PopupWindow_setSize(width, height)
{
	this.width=width;
	this.height=height;
}
// Fill the window with contents
function PopupWindow_populate(contents)
{
	this.contents=contents;
	this.populated=false;
}
// Set the URL to go to
function PopupWindow_setUrl(url)
{
	this.url=url;
}
// Set the window popup properties
function PopupWindow_setWindowProperties(props)
{
	this.windowProperties=props;
}
// Refresh the displayed contents of the popup
function PopupWindow_refresh()
{
	if (this.divName != null)
	{
		// refresh the DIV object
		if (this.use_gebi)
			document.getElementById(this.divName).innerHTML=this.contents;
		else if (this.use_css)
			document.all[this.divName].innerHTML=this.contents;
		else if (this.use_layers)
		{
			var d=document.layers[this.divName];
			d.document.open();
			d.document.writeln(this.contents);
			d.document.close();
		}
	}
	else
	{
		if (this.popupWindow != null && !this.popupWindow.closed)
		{
			if (this.url != "")
				this.popupWindow.location.href=this.url;
			else
			{
				this.popupWindow.document.open();
				this.popupWindow.document.writeln(this.contents);
				this.popupWindow.document.close();
			}
			this.popupWindow.focus();
		}
	}
}
// Position and show the popup, relative to an anchor object
function PopupWindow_showPopup(anchorname)
{
	this.getXYPosition(anchorname);
//	this.x+=this.offsetX;
	this.y+=this.offsetY;
	if (!this.populated && (this.contents != ""))
	{
		this.populated=true;
		this.refresh();
	}
	if (this.divName != null)
	{
		// Show the DIV object
		if (this.use_gebi)
		{
			document.getElementById(this.divName).style.left=this.x + "px";
			document.getElementById(this.divName).style.top=this.y + "px";
			document.getElementById(this.divName).style.visibility="visible";
		}
		else if (this.use_css)
		{
			document.all[this.divName].style.left=this.x;
			document.all[this.divName].style.top=this.y;
			document.all[this.divName].style.visibility="visible";
		}
		else if (this.use_layers)
		{
			document.layers[this.divName].left=this.x;
			document.layers[this.divName].top=this.y;
			document.layers[this.divName].visibility="visible";
		}
	}
	else
	{
		if (this.popupWindow == null || this.popupWindow.closed)
		{
			// If the popup window will go off-screen, move it so it doesn't
			if (this.x < 0)
				this.x=0;

			if (this.y < 0)
				this.y=0;

			if (screen && screen.availHeight)
			{
				if ((this.y + this.height) > screen.availHeight)
					this.y=screen.availHeight - this.height;
			}
			if (screen && screen.availWidth)
			{
				if ((this.x + this.width) > screen.availWidth)
					this.x=screen.availWidth - this.width;
			}
			var avoidAboutBlank=window.opera
					|| (document.layers && !navigator.mimeTypes['*'])
					|| navigator.vendor == 'KDE'
					|| (document.childNodes && !document.all && !navigator.taintEnabled);
			this.popupWindow=window.open(avoidAboutBlank?"":"about:blank",
					"window_" + anchorname, this.windowProperties + ",width="
							+ this.width + ",height=" + this.height
							+ ",screenX=" + this.x + ",left=" + this.x
							+ ",screenY=" + this.y + ",top=" + this.y + "");
		}
		this.refresh();
	}
}
// Hide the popup
function PopupWindow_hidePopup()
{
	if (this.divName != null)
	{
		if (this.use_gebi)
			document.getElementById(this.divName).style.visibility="hidden";
		else if (this.use_css)
			document.all[this.divName].style.visibility="hidden";
		else if (this.use_layers)
			document.layers[this.divName].visibility="hidden";
	}
	else
	{
		if (this.popupWindow && !this.popupWindow.closed)
		{
			this.popupWindow.close();
			this.popupWindow=null;
		}
	}
}
// Pass an event and return whether or not it was the popup DIV that was clicked
function PopupWindow_isClicked(e)
{
	if (this.divName != null)
	{
		if (this.use_layers)
		{
			var clickX=e.pageX;
			var clickY=e.pageY;
			var t=document.layers[this.divName];
			if ((clickX > t.left) && (clickX < t.left + t.clip.width)
					&& (clickY > t.top) && (clickY < t.top + t.clip.height))
				return true;
		}
		else if (document.all)
		{ // Need to hard-code this to trap IE for error-handling
			var t=window.event.srcElement;
			while (t.parentElement != null)
			{
				if (t.id == this.divName)
					return true;

				t=t.parentElement;
			}
		}
		else if (this.use_gebi && e)
		{
			var t=e.originalTarget;
			while (t.parentNode != null)
			{
				if (t.id == this.divName)
					return true;

				t=t.parentNode;
			}
		}
	}
	return false;
}

// Check an onMouseDown event to see if we should hide
function PopupWindow_hideIfNotClicked(e)
{
	if (this.autoHideEnabled && !this.isClicked(e))
	{
		this.hidePopup();
		return true;
	}
	return false;
}
// Call this to make the DIV disable automatically when mouse is clicked outside
// it
function PopupWindow_autoHide()
{
	this.autoHideEnabled=true;
}
// This global function checks all PopupWindow objects onmouseup to see if they
// should be hidden
function PopupWindow_hidePopupWindows(e)
{
	for( var i=0;i < popupWindowObjects.length;i++)
	{
		if (popupWindowObjects[i] != null)
		{
			var p=popupWindowObjects[i];
			if (p.hideIfNotClicked(e))
				popupWindowObjects[i]=null;
		}
	}
//	document.onmouseup=window.popupWindowOldEventListener;
//	window.listenerAttached=false;
}
// Run this immediately to attach the event listener
function PopupWindow_attachListener()
{
	if (document.layers)
		document.captureEvents(Event.MOUSEUP);

	window.popupWindowOldEventListener=document.onmouseup;
	if (window.popupWindowOldEventListener != null)
		document.onmouseup=new Function(
				"window.popupWindowOldEventListener(); PopupWindow_hidePopupWindows();");
	else
		document.onmouseup=PopupWindow_hidePopupWindows;
}
// CONSTRUCTOR for the PopupWindow object
// Pass it a DIV name to use a DHTML popup, otherwise will default to window
// popup
function PopupWindow()
{
	if (!window.popupWindowIndex)
		window.popupWindowIndex=0;
	
	if (!window.popupWindowObjects)
		window.popupWindowObjects=new Array();

	if (!window.listenerAttached)
	{
		window.listenerAttached=true;
		PopupWindow_attachListener();
	}
	this.index=popupWindowIndex++;
	popupWindowObjects[this.index]=this;
	this.divName=null;
	this.popupWindow=null;
	this.width=0;
	this.height=0;
	this.populated=false;
	this.visible=false;
	this.autoHideEnabled=false;

	this.contents="";
	this.url="";
	this.windowProperties="toolbar=no,location=no,status=no,menubar=no,scrollbars=auto,resizable,alwaysRaised,dependent,titlebar=no";
	if (arguments.length > 0)
	{
		this.type="DIV";
		this.divName=arguments[0];
	}
	else
		this.type="WINDOW";
	this.use_gebi=false;
	this.use_css=false;
	this.use_layers=false;
	if (document.getElementById)
		this.use_gebi=true;
	else if (document.all)
		this.use_css=true;
	else if (document.layers)
		this.use_layers=true;
	else
		this.type="WINDOW";

	this.offsetX=0;
	this.offsetY=0;
	// Method mappings
	this.getXYPosition=PopupWindow_getXYPosition;
	this.populate=PopupWindow_populate;
	this.setUrl=PopupWindow_setUrl;
	this.setWindowProperties=PopupWindow_setWindowProperties;
	this.refresh=PopupWindow_refresh;
	this.showPopup=PopupWindow_showPopup;
	this.hidePopup=PopupWindow_hidePopup;
	this.setSize=PopupWindow_setSize;
	this.isClicked=PopupWindow_isClicked;
	this.autoHide=PopupWindow_autoHide;
	this.hideIfNotClicked=PopupWindow_hideIfNotClicked;
}

/* SOURCE FILE: CalendarPopup.js */

// HISTORY
// ------------------------------------------------------------------
// Feb 7, 2005: Fixed a CSS styles to use px unit
// March 29, 2004: Added check in select() method for the form field
// being disabled. If it is, just return and don't do anything.
// March 24, 2004: Fixed bug - when month name and abbreviations were
// changed, date format still used original values.
// January 26, 2004: Added support for drop-down month and year
// navigation (Thanks to Chris Reid for the idea)
// September 22, 2003: Fixed a minor problem in YEAR calendar with
// CSS prefix.
// August 19, 2003: Renamed the function to get styles, and made it
// work correctly without an object reference
// August 18, 2003: Changed showYearNavigation and
// showYearNavigationInput to optionally take an argument of
// true or false
// July 31, 2003: Added text input option for year navigation.
// Added a per-calendar CSS prefix option to optionally use
// different styles for different calendars.
// July 29, 2003: Fixed bug causing the Today link to be clickable
// even though today falls in a disabled date range.
// Changed formatting to use pure CSS, allowing greater control
// over look-and-feel options.
// June 11, 2003: Fixed bug causing the Today link to be unselectable
// under certain cases when some days of week are disabled
// March 14, 2003: Added ability to disable individual dates or date
// ranges, display as light gray and strike-through
// March 14, 2003: Removed dependency on graypixel.gif and instead
// / use table border coloring
// March 12, 2003: Modified showCalendar() function to allow optional
// start-date parameter
// March 11, 2003: Modified select() function to allow optional
// start-date parameter
/*
 * DESCRIPTION: This object implements a popup calendar to allow the user to
 * select a date, month, quarter, or year.
 * 
 * COMPATABILITY: Works with Netscape 4.x, 6.x, IE 5.x on Windows. Some small
 * positioning errors - usually with Window positioning - occur on the Macintosh
 * platform. The calendar can be modified to work for any location in the world
 * by changing which weekday is displayed as the first column, changing the
 * month names, and changing the column headers for each day.
 * 
 * USAGE: // Create a new CalendarPopup object of type WINDOW var cal = new
 * CalendarPopup();
 *  // Create a new CalendarPopup object of type DIV using the DIV named 'mydiv'
 * var cal = new CalendarPopup('mydiv');
 *  // Easy method to link the popup calendar with an input box.
 * cal.select(inputObject, anchorname, dateFormat); // Same method, but passing
 * a default date other than the field's current value cal.select(inputObject,
 * anchorname, dateFormat, '01/02/2000'); // This is an example call to the
 * popup calendar from a link to populate an // input box. Note that to use
 * this, date.js must also be included!! <A HREF="#"
 * onClick="cal.select(document.forms[0].date,'anchorname','MM/dd/yyyy'); return
 * false;">Select</A>
 *  // Set the type of date select to be used. By default it is 'date'.
 * cal.setDisplayType(type);
 *  // When a date, month, quarter, or year is clicked, a function is called and //
 * passed the details. You must write this function, and tell the calendar //
 * popup what the function name is. // Function to be called for 'date' select
 * receives y, m, d cal.setReturnFunction(functionname); // Function to be
 * called for 'month' select receives y, m
 * cal.setReturnMonthFunction(functionname); // Function to be called for
 * 'quarter' select receives y, q cal.setReturnQuarterFunction(functionname); //
 * Function to be called for 'year' select receives y
 * cal.setReturnYearFunction(functionname);
 *  // Show the calendar relative to a given anchor
 * cal.showCalendar(anchorname);
 *  // Hide the calendar. The calendar is set to autoHide automatically
 * cal.hideCalendar();
 *  // Set the month names to be used. Default are English month names
 * cal.setMonthNames("January","February","March",...);
 *  // Set the month abbreviations to be used. Default are English month
 * abbreviations cal.setMonthAbbreviations("Jan","Feb","Mar",...);
 *  // Show navigation for changing by the year, not just one month at a time
 * cal.showYearNavigation();
 *  // Show month and year dropdowns, for quicker selection of month of dates
 * cal.showNavigationDropdowns();
 *  // Set the text to be used above each day column. The days start with //
 * sunday regardless of the value of WeekStartDay
 * cal.setDayHeaders("S","M","T",...);
 *  // Set the day for the first column in the calendar grid. By default this //
 * is Sunday (0) but it may be changed to fit the conventions of other //
 * countries. cal.setWeekStartDay(1); // week is Monday - Sunday
 *  // Set the weekdays which should be disabled in the 'date' select popup. You
 * can // then allow someone to only select week end dates, or Tuedays, for
 * example cal.setDisabledWeekDays(0,1); // To disable selecting the 1st or 2nd
 * days of the week
 *  // Selectively disable individual days or date ranges. Disabled days will
 * not // be clickable, and show as strike-through text on current browsers. //
 * Date format is any format recognized by parseDate() in date.js // Pass a
 * single date to disable: cal.addDisabledDates("2003-01-01"); // Pass null as
 * the first parameter to mean "anything up to and including" the // passed
 * date: cal.addDisabledDates(null, "01/02/03"); // Pass null as the second
 * parameter to mean "including the passed date and // anything after it:
 * cal.addDisabledDates("Jan 01, 2003", null); // Pass two dates to disable all
 * dates inbetween and including the two cal.addDisabledDates("January 01,
 * 2003", "Dec 31, 2003");
 *  // When the 'year' select is displayed, set the number of years back from
 * the // current year to start listing years. Default is 2. // This is also
 * used for year drop-down, to decide how many years +/- to display
 * cal.setYearSelectStartOffset(2);
 *  // Text for the word "Today" appearing on the calendar
 * cal.setTodayText("Today");
 *  // The calendar uses CSS classes for formatting. If you want your calendar
 * to // have unique styles, you can set the prefix that will be added to all
 * the // classes in the output. // For example, normal output may have this: //
 * <SPAN CLASS="cpTodayTextDisabled">Today<SPAN> // But if you set the prefix
 * like this: cal.setCssPrefix("Test"); // The output will then look like: //
 * <SPAN CLASS="TestcpTodayTextDisabled">Today<SPAN> // And you can define that
 * style somewhere in your page.
 *  // When using Year navigation, you can make the year be an input box, so //
 * the user can manually change it and jump to any year
 * cal.showYearNavigationInput();
 *  // Set the calendar offset to be different than the default. By default it //
 * will appear just below and to the right of the anchorname. So if you have //
 * a text box where the date will go and and anchor immediately after the //
 * text box, the calendar will display immediately under the text box.
 * cal.offsetX = 20; cal.offsetY = 20;
 * 
 * NOTES: 1) Requires the functions in AnchorPosition.js and PopupWindow.js
 * 
 * 2) Your anchor tag MUST contain both NAME and ID attributes which are the
 * same. For example: <A NAME="test" ID="test"> </A>
 * 
 * 3) There must be at least a space between <A> </A> for IE5.5 to see the
 * anchor tag correctly. Do not do <A></A> with no space.
 * 
 * 4) When a CalendarPopup object is created, a handler for 'onmouseup' is
 * attached to any event handler you may have already defined. Do NOT define an
 * event handler for 'onmouseup' after you define a CalendarPopup object or the
 * autoHide() will not work correctly.
 * 
 * 5) The calendar popup display uses style sheets to make it look nice.
 * 
 */

var DEFAULT_MONTH_NAME=new Array("January", "February", "March", "April", "May",
		"June", "July", "August", "September", "October", "November",
		"December");
var DEFAULT_MONTH_ABBR=new Array("Jan", "Feb", "Mar", "Apr", "May", "Jun",
		"Jul", "Aug", "Sep", "Oct", "Nov", "Dec");
var DEFAULT_DAY_HEADER=new Array("S", "M", "T", "W", "T", "F", "S");
var DEFAULT_TODAY_TEXT="Today";
var DEFAULT_CLEAR_TEXT="Clear";

function CP_setDefaultText(type,value)
{
	switch (type)
	{
		case 1: DEFAULT_MONTH_NAME=value; break;
		case 2: DEFAULT_MONTH_ABBR=value; break;
		case 3: DEFAULT_DAY_HEADER=value; break;
		case 4: DEFAULT_TODAY_TEXT=value; break;
		case 5: DEFAULT_CLEAR_TEXT=value; break;
	}
}

// Quick fix for FF3
function CP_stop(e)
{
	if (e && e.stopPropagation)
		e.stopPropagation();
}

// CONSTRUCTOR for the CalendarPopup Object
function CalendarPopup()
{
	var c;
	if (arguments.length > 0)
		c=new PopupWindow(arguments[0]);
	else
	{
		c=new PopupWindow();
		c.setSize(150, 175);
	}
	c.offsetX=-152;
	c.offsetY=25;
	c.autoHide();
	// Calendar-specific properties
	c.monthNames=DEFAULT_MONTH_NAME;
	c.monthAbbreviations=DEFAULT_MONTH_ABBR;
	c.dayHeaders=DEFAULT_DAY_HEADER;
	c.returnFunction="CP_tmpReturnFunction";
	c.returnMonthFunction="CP_tmpReturnMonthFunction";
	c.returnQuarterFunction="CP_tmpReturnQuarterFunction";
	c.returnYearFunction="CP_tmpReturnYearFunction";
	c.weekStartDay=1;
	c.isShowYearNavigation=false;
	c.displayType="date";
	c.disabledWeekDays=new Object();
	c.disabledDatesExpression="";
	c.yearSelectStartOffset=2;
	c.currentDate=null;
	c.todayText=DEFAULT_TODAY_TEXT;
	c.clearText=DEFAULT_CLEAR_TEXT;
	c.cssPrefix="";
	c.isShowNavigationDropdowns=false;
	c.isShowYearNavigationInput=false;
	window.CP_calendarObject=null;
	window.CP_targetInput=null;
	window.CP_dateFormat="MM/dd/yyyy";
	// Method mappings
	c.copyMonthNamesToWindow=CP_copyMonthNamesToWindow;
	c.setReturnFunction=CP_setReturnFunction;
	c.setReturnMonthFunction=CP_setReturnMonthFunction;
	c.setReturnQuarterFunction=CP_setReturnQuarterFunction;
	c.setReturnYearFunction=CP_setReturnYearFunction;
	c.setMonthNames=CP_setMonthNames;
	c.setMonthAbbreviations=CP_setMonthAbbreviations;
	c.setDayHeaders=CP_setDayHeaders;
	c.setWeekStartDay=CP_setWeekStartDay;
	c.setDisplayType=CP_setDisplayType;
	c.setDisabledWeekDays=CP_setDisabledWeekDays;
	c.addDisabledDates=CP_addDisabledDates;
	c.setYearSelectStartOffset=CP_setYearSelectStartOffset;
	c.setTodayText=CP_setTodayText;
	c.showYearNavigation=CP_showYearNavigation;
	c.showCalendar=CP_showCalendar;
	c.hideCalendar=CP_hideCalendar;
	c.getStyles=getCalendarStyles;
	c.refreshCalendar=CP_refreshCalendar;
	c.getCalendar=CP_getCalendar;
	c.select=CP_select;
	c.setCssPrefix=CP_setCssPrefix;
	c.showNavigationDropdowns=CP_showNavigationDropdowns;
	c.showYearNavigationInput=CP_showYearNavigationInput;
	c.copyMonthNamesToWindow();
	// Return the object
	return c;
}
function CP_copyMonthNamesToWindow()
{
	// Copy these values over to the date.js
	if (typeof (window.MONTH_NAMES) != "undefined"
			&& window.MONTH_NAMES != null)
	{
		window.MONTH_NAMES=new Array();
		for( var i=0;i < this.monthNames.length;i++)
			window.MONTH_NAMES[window.MONTH_NAMES.length]=this.monthNames[i];
		
		for( var i=0;i < this.monthAbbreviations.length;i++)
			window.MONTH_NAMES[window.MONTH_NAMES.length]=this.monthAbbreviations[i];
	}
}
// Temporary default functions to be called when items clicked, so no error is
// thrown
function CP_tmpReturnFunction(y, m, d)
{
	if (window.CP_targetInput != null)
	{
		var dt=new Date(y, m - 1, d, 0, 0, 0);
		if (window.CP_calendarObject != null)
			window.CP_calendarObject.copyMonthNamesToWindow();

		window.CP_targetInput.value=formatDate(dt, window.CP_dateFormat);
	}
	else
		alert('Use setReturnFunction() to define which function will get the clicked results!');
}
function CP_tmpReturnMonthFunction(y, m)
{
	alert('Use setReturnMonthFunction() to define which function will get the clicked results!\nYou clicked: year='
			+ y + ' , month=' + m);
}
function CP_tmpReturnQuarterFunction(y, q)
{
	alert('Use setReturnQuarterFunction() to define which function will get the clicked results!\nYou clicked: year='
			+ y + ' , quarter=' + q);
}
function CP_tmpReturnYearFunction(y)
{
	alert('Use setReturnYearFunction() to define which function will get the clicked results!\nYou clicked: year=' + y);
}

// Set the name of the functions to call to get the clicked item
function CP_setReturnFunction(name)
{
	this.returnFunction=name;
}
function CP_setReturnMonthFunction(name)
{
	this.returnMonthFunction=name;
}
function CP_setReturnQuarterFunction(name)
{
	this.returnQuarterFunction=name;
}
function CP_setReturnYearFunction(name)
{
	this.returnYearFunction=name;
}

// Over-ride the built-in month names
function CP_setMonthNames()
{
	for( var i=0;i < arguments.length;i++)
	{
		this.monthNames[i]=arguments[i];
	}
	this.copyMonthNamesToWindow();
}

// Over-ride the built-in month abbreviations
function CP_setMonthAbbreviations()
{
	for( var i=0;i < arguments.length;i++)
		this.monthAbbreviations[i]=arguments[i];
	
	this.copyMonthNamesToWindow();
}

// Over-ride the built-in column headers for each day
function CP_setDayHeaders()
{
	for( var i=0;i < arguments.length;i++)
		this.dayHeaders[i]=arguments[i];
}

// Set the day of the week (0-7) that the calendar display starts on
// This is for countries other than the US whose calendar displays start on
// Monday(1), for example
function CP_setWeekStartDay(day)
{
	this.weekStartDay=day;
}

// Show next/last year navigation links
function CP_showYearNavigation()
{
	this.isShowYearNavigation=(arguments.length > 0)?arguments[0]:true;
}

// Which type of calendar to display
function CP_setDisplayType(type)
{
	if (type != "date" && type != "week-end" && type != "month"
			&& type != "quarter" && type != "year")
	{
		alert("Invalid display type! Must be one of: date,week-end,month,quarter,year");
		return false;
	}
	this.displayType=type;
}

// How many years back to start by default for year display
function CP_setYearSelectStartOffset(num)
{
	this.yearSelectStartOffset=num;
}

// Set which weekdays should not be clickable
function CP_setDisabledWeekDays()
{
	this.disabledWeekDays=new Object();
	for( var i=0;i < arguments.length;i++)
		this.disabledWeekDays[arguments[i]]=true;
}

// Disable individual dates or ranges
// Builds an internal logical test which is run via eval() for efficiency
function CP_addDisabledDates(start, end)
{
	if (arguments.length == 1)
		end=start;

	if (start == null && end == null)
		return;

	if (this.disabledDatesExpression != "")
		this.disabledDatesExpression+="||";

	if (start != null)
	{
		start=parseDate(start);
		start="" + start.getFullYear() + LZ(start.getMonth() + 1)
				+ LZ(start.getDate());
	}
	if (end != null)
	{
		end=parseDate(end);
		end="" + end.getFullYear() + LZ(end.getMonth() + 1) + LZ(end.getDate());
	}
	if (start == null)
		this.disabledDatesExpression+="(ds<=" + end + ")";
	else if (end == null)
		this.disabledDatesExpression+="(ds>=" + start + ")";
	else
		this.disabledDatesExpression+="(ds>=" + start + "&&ds<=" + end + ")";
}

// Set the text to use for the "Today" link
function CP_setTodayText(text)
{
	this.todayText=text;
}

// Set the prefix to be added to all CSS classes when writing output
function CP_setCssPrefix(val)
{
	this.cssPrefix=val;
}

// Show the navigation as an dropdowns that can be manually changed
function CP_showNavigationDropdowns()
{
	this.isShowNavigationDropdowns=(arguments.length > 0)?arguments[0]:true;
}

// Show the year navigation as an input box that can be manually changed
function CP_showYearNavigationInput()
{
	this.isShowYearNavigationInput=(arguments.length > 0)?arguments[0]:true;
}

// Hide a calendar object
function CP_hideCalendar()
{
	if (arguments.length > 0)
		window.popupWindowObjects[arguments[0]].hidePopup();
	else
		this.hidePopup();
}

// Refresh the contents of the calendar display
function CP_refreshCalendar(index)
{
	var calObject=window.popupWindowObjects[index];
	if (arguments.length > 1)
		calObject.populate(calObject.getCalendar(arguments[1], arguments[2],
				arguments[3], arguments[4], arguments[5]));
	else
		calObject.populate(calObject.getCalendar());

	calObject.refresh();
}

// Populate the calendar and display it
function CP_showCalendar(anchorname)
{
	if (arguments.length > 1)
	{
		if (arguments[1] == null || arguments[1] == "")
			this.currentDate=new Date();
		else
			this.currentDate=new Date(parseDate(arguments[1]));
	}
	this.populate(this.getCalendar());
	this.showPopup(anchorname);
}

// Simple method to interface popup calendar with a text-entry box
function CP_select(inputobj, linkname, format)
{
	var selectedDate=(arguments.length > 3)?arguments[3]:null;
	if (!window.getDateFromFormat)
	{
		alert("calendar.select: To use this method you must also include 'date.js' for date formatting");
		return;
	}
	if (this.displayType != "date" && this.displayType != "week-end")
	{
		alert("calendar.select: This function can only be used with displayType 'date' or 'week-end'");
		return;
	}
	if (inputobj.type != "text" && inputobj.type != "hidden"
			&& inputobj.type != "textarea")
	{
		alert("calendar.select: Input object passed is not a valid form input object");
		window.CP_targetInput=null;
		return;
	}
	if (inputobj.disabled)
		return;
	// Can't use calendar input on disabled form input!
	window.CP_targetInput=inputobj;
	window.CP_calendarObject=this;
	this.currentDate=null;
	var time=0;
	if (selectedDate != null)
	{
		time=getDateFromFormat(selectedDate, format)
	}
	else if (inputobj.value != "")
	{
		time=getDateFromFormat(inputobj.value, format);
	}
	if (selectedDate != null || inputobj.value != "")
	{
		if (time == 0)
		{
			this.currentDate=null;
		}
		else
		{
			this.currentDate=new Date(time);
		}
	}
	window.CP_dateFormat=format;
	this.showCalendar(linkname);
}

// Get style block needed to display the calendar correctly
function getCalendarStyles()
{
	var result="";
	var p="";
	if (this != null && typeof (this.cssPrefix) != "undefined"
			&& this.cssPrefix != null && this.cssPrefix != "")
	{
		p=this.cssPrefix;
	}
	result+="<STYLE>\n";
	result+="." + p + "cpYearNavigation,." + p + "cpMonthNavigation { background-color:#C0C0C0; text-align:center; vertical-align:center; text-decoration:none; color:#000000; font-weight:bold; }\n";
	result+="." + p + "cpDayColumnHeader, ." + p + "cpYearNavigation,." + p
			+ "cpMonthNavigation,." + p + "cpCurrentMonthDate,." + p
			+ "cpCurrentMonthDateDisabled,." + p + "cpOtherMonthDate,." + p
			+ "cpOtherMonthDateDisabled,." + p + "cpCurrentDate,." + p
			+ "cpCurrentDateDisabled,." + p + "cpTodayText,." + p
			+ "cpTodayTextDisabled,." + p
			+ "cpText { font-family:arial; font-size:8pt; }\n";
	result+="TD."
			+ p
			+ "cpDayColumnHeader { text-align:right; border:solid thin #C0C0C0;border-width:0px 0px 1px 0px; }\n";
	result+="." + p + "cpCurrentMonthDate, ." + p + "cpOtherMonthDate, ." + p
			+ "cpCurrentDate  { text-align:right; text-decoration:none; }\n";
	result+="."
			+ p
			+ "cpCurrentMonthDateDisabled, ."
			+ p
			+ "cpOtherMonthDateDisabled, ."
			+ p
			+ "cpCurrentDateDisabled { color:#D0D0D0; text-align:right; text-decoration:line-through; }\n";
	result+="." + p + "cpCurrentMonthDate, .cpCurrentDate { color:#000000; }\n";
	result+="." + p + "cpOtherMonthDate { color:#808080; }\n";
	result+="TD."
			+ p
			+ "cpCurrentDate { color:white; background-color: #C0C0C0; border-width:1px; border:solid thin #800000; }\n";
	result+="TD."
			+ p
			+ "cpCurrentDateDisabled { border-width:1px; border:solid thin #FFAAAA; }\n";
	result+="TD." + p + "cpTodayText, TD." + p + "cpTodayTextDisabled { border:solid thin #C0C0C0; border-width:1px 0px 0px 0px;}\n";
	result+="A." + p + "cpTodayText, SPAN." + p
			+ "cpTodayTextDisabled { height:20px; }\n";
	result+="A." + p + "cpTodayText { color:black; }\n";
	result+="." + p + "cpTodayTextDisabled { color:#D0D0D0; }\n";
	result+="." + p + "cpBorder { border:solid thin #808080; }\n";
	result+="</STYLE>\n";
	return result;
}

// Return a string containing all the calendar code to be displayed
function CP_getCalendar()
{
	var now=new Date();
	// Reference to window
	if (this.type == "WINDOW")
		var windowref="window.opener.";
	else
		var windowref="";
	var result="";
	// If POPUP, write entire HTML document
	if (this.type == "WINDOW")
	{
		result+="<HTML><HEAD><TITLE>Calendar</TITLE>"
				+ this.getStyles()
				+ "</HEAD><BODY MARGINWIDTH=0 MARGINHEIGHT=0 TOPMARGIN=0 RIGHTMARGIN=0 LEFTMARGIN=0>\n";
		result+='<CENTER><TABLE WIDTH=100% BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>\n';
	}
	else
	{
		result+='<TABLE CLASS="' + this.cssPrefix + 'cpBorder" WIDTH=144 BORDER=1 BORDERWIDTH=1 CELLSPACING=0 CELLPADDING=1>\n';
		result+='<TR><TD ALIGN=CENTER>\n';
		result+='<CENTER>\n';
	}
	// Code for DATE display (default)
	// -------------------------------
	if (this.displayType == "date" || this.displayType == "week-end")
	{
		if (this.currentDate == null)
			this.currentDate=now;

		if (arguments.length > 0)
			var month=arguments[0];
		else
			var month=this.currentDate.getMonth() + 1;

		if (arguments.length > 1 && arguments[1] > 0
				&& arguments[1] - 0 == arguments[1])
			var year=arguments[1];
		else
			var year=this.currentDate.getFullYear();

		var daysinmonth=new Array(0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31,
				30, 31);
		if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0))
			daysinmonth[2]=29;

		var current_month=new Date(year, month - 1, 1);
		var display_year=year;
		var display_month=month;
		var display_date=1;
		var weekday=current_month.getDay();
		var offset=0;

		offset=(weekday >= this.weekStartDay)?weekday - this.weekStartDay:7
				- this.weekStartDay + weekday;
		if (offset > 0)
		{
			display_month--;
			if (display_month < 1)
			{
				display_month=12;
				display_year--;
			}
			display_date=daysinmonth[display_month] - offset + 1;
		}
		var next_month=month + 1;
		var next_month_year=year;
		if (next_month > 12)
		{
			next_month=1;
			next_month_year++;
		}
		var last_month=month - 1;
		var last_month_year=year;
		if (last_month < 1)
		{
			last_month=12;
			last_month_year--;
		}
		var date_class;
		if (this.type != "WINDOW")
			result+="<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";
		result+='<TR>\n';
		var refresh=windowref + 'CP_refreshCalendar';
		var refreshLink='javascript:' + refresh;
		if (this.isShowNavigationDropdowns)
		{
			result+='<TD CLASS="'
					+ this.cssPrefix
					+ 'cpMonthNavigation" WIDTH="78" COLSPAN="3"><select CLASS="'
					+ this.cssPrefix
					+ 'cpMonthNavigation" name="cpMonth" onmouseup="CP_stop(event)" onChange="'
					+ refresh + '(' + this.index
					+ ',this.options[this.selectedIndex].value-0,' + (year - 0)
					+ ');">';
			for( var monthCounter=1;monthCounter <= 12;monthCounter++)
			{
				var selected=(monthCounter == month)?'SELECTED':'';
				result+='<option value="' + monthCounter + '" ' + selected
						+ '>' + this.monthNames[monthCounter - 1] + '</option>';
			}
			result+='</select></TD>';
			result+='<TD CLASS="' + this.cssPrefix + 'cpMonthNavigation" WIDTH="10">&nbsp;</TD>';

			result+='<TD CLASS="'
					+ this.cssPrefix
					+ 'cpYearNavigation" WIDTH="56" COLSPAN="3"><select CLASS="'
					+ this.cssPrefix
					+ 'cpYearNavigation" name="cpYear" onmouseup="CP_stop(event)" onChange="'
					+ refresh + '(' + this.index + ',' + month
					+ ',this.options[this.selectedIndex].value-0);">';
			for( var yearCounter=year - this.yearSelectStartOffset;yearCounter <= year 
					+ this.yearSelectStartOffset;yearCounter++)
			{
				var selected=(yearCounter == year)?'SELECTED':'';
				result+='<option value="' + yearCounter + '" ' + selected + '>'
						+ yearCounter + '</option>';
			}
			result+='</select></TD>';
		}
		else
		{
			if (this.isShowYearNavigation)
			{
				result+='<TD CLASS="' + this.cssPrefix
						+ 'cpMonthNavigation" WIDTH="10"><A CLASS="'
						+ this.cssPrefix + 'cpMonthNavigation" HREF="'
						+ refreshLink + '(' + this.index + ',' + last_month
						+ ',' + last_month_year + ');">&lt;</A></TD>';
				result+='<TD CLASS="' + this.cssPrefix
						+ 'cpMonthNavigation" WIDTH="58"><SPAN CLASS="'
						+ this.cssPrefix + 'cpMonthNavigation">'
						+ this.monthNames[month - 1] + '</SPAN></TD>';
				result+='<TD CLASS="' + this.cssPrefix
						+ 'cpMonthNavigation" WIDTH="10"><A CLASS="'
						+ this.cssPrefix + 'cpMonthNavigation" HREF="'
						+ refreshLink + '(' + this.index + ',' + next_month
						+ ',' + next_month_year + ');">&gt;</A></TD>';
				result+='<TD CLASS="' + this.cssPrefix + 'cpMonthNavigation" WIDTH="10">&nbsp;</TD>';

				result+='<TD CLASS="' + this.cssPrefix
						+ 'cpYearNavigation" WIDTH="10"><A CLASS="'
						+ this.cssPrefix + 'cpYearNavigation" HREF="'
						+ refreshLink + '(' + this.index + ',' + month + ','
						+ (year - 1) + ');">&lt;</A></TD>';
				if (this.isShowYearNavigationInput)
				{
					result+='<TD CLASS="'
							+ this.cssPrefix
							+ 'cpYearNavigation" WIDTH="36"><INPUT NAME="cpYear" CLASS="'
							+ this.cssPrefix
							+ 'cpYearNavigation" SIZE="4" MAXLENGTH="4" VALUE="'
							+ year + '" onBlur="' + refresh + '(' + this.index
							+ ',' + month + ',this.value-0);"></TD>';
				}
				else
				{
					result+='<TD CLASS="' + this.cssPrefix
							+ 'cpYearNavigation" WIDTH="36"><SPAN CLASS="'
							+ this.cssPrefix + 'cpYearNavigation">' + year
							+ '</SPAN></TD>';
				}
				result+='<TD CLASS="' + this.cssPrefix
						+ 'cpYearNavigation" WIDTH="10"><A CLASS="'
						+ this.cssPrefix + 'cpYearNavigation" HREF="'
						+ refreshLink + '(' + this.index + ',' + month + ','
						+ (year + 1) + ');">&gt;</A></TD>';
			}
			else
			{
				result+='<TD CLASS="' + this.cssPrefix
						+ 'cpMonthNavigation" WIDTH="22"><A CLASS="'
						+ this.cssPrefix + 'cpMonthNavigation" HREF="'
						+ refreshLink + '(' + this.index + ',' + last_month
						+ ',' + last_month_year + ');">&lt;&lt;</A></TD>\n';
				result+='<TD CLASS="' + this.cssPrefix
						+ 'cpMonthNavigation" WIDTH="100"><SPAN CLASS="'
						+ this.cssPrefix + 'cpMonthNavigation">'
						+ this.monthNames[month - 1] + ' ' + year
						+ '</SPAN></TD>\n';
				result+='<TD CLASS="' + this.cssPrefix
						+ 'cpMonthNavigation" WIDTH="22"><A CLASS="'
						+ this.cssPrefix + 'cpMonthNavigation" HREF="'
						+ refreshLink + '(' + this.index + ',' + next_month
						+ ',' + next_month_year + ');">&gt;&gt;</A></TD>\n';
			}
		}
		result+='</TR></TABLE>\n';
		result+='<TABLE WIDTH=120 BORDER=0 CELLSPACING=0 CELLPADDING=1 ALIGN=CENTER>\n';
		result+='<TR>\n';
		for( var j=0;j < 7;j++)
		{

			result+='<TD CLASS="' + this.cssPrefix
					+ 'cpDayColumnHeader" WIDTH="14%"><SPAN CLASS="'
					+ this.cssPrefix + 'cpDayColumnHeader">'
					+ this.dayHeaders[(this.weekStartDay + j) % 7] + '</TD>\n';
		}
		result+='</TR>\n';
		for( var row=1;row <= 6;row++)
		{
			result+='<TR>\n';
			for( var col=1;col <= 7;col++)
			{
				var disabled=false;
				if (this.disabledDatesExpression != "")
				{
					var ds="" + display_year + LZ(display_month)
							+ LZ(display_date);
					eval("disabled=(" + this.disabledDatesExpression + ")");
				}
				var dateClass="";
				if ((display_month == this.currentDate.getMonth() + 1)
						&& (display_date == this.currentDate.getDate())
						&& (display_year == this.currentDate.getFullYear()))
					dateClass="cpCurrentDate";
				else if (display_month == month)
					dateClass="cpCurrentMonthDate";
				else
					dateClass="cpOtherMonthDate";

				if (disabled || this.disabledWeekDays[col - 1])
				{
					result+='	<TD CLASS="' + this.cssPrefix + dateClass
							+ '"><SPAN CLASS="' + this.cssPrefix + dateClass
							+ 'Disabled">' + display_date + '</SPAN></TD>\n';
				}
				else
				{
					var selected_date=display_date;
					var selected_month=display_month;
					var selected_year=display_year;
					if (this.displayType == "week-end")
					{
						var d=new Date(selected_year, selected_month - 1,
								selected_date, 0, 0, 0, 0);
						d.setDate(d.getDate() + (7 - col));
						selected_year=d.getYear();
						if (selected_year < 1000)
							selected_year+=1900;
						
						selected_month=d.getMonth() + 1;
						selected_date=d.getDate();
					}
					result+='	<TD CLASS="' + this.cssPrefix + dateClass
							+ '"><A HREF="javascript:' + windowref
							+ this.returnFunction + '(' + selected_year + ','
							+ selected_month + ',' + selected_date + ');'
							+ windowref + 'CP_hideCalendar(\'' + this.index
							+ '\');" CLASS="' + this.cssPrefix + dateClass
							+ '">' + display_date + '</A></TD>\n';
				}
				display_date++;
				if (display_date > daysinmonth[display_month])
				{
					display_date=1;
					display_month++;
				}
				if (display_month > 12)
				{
					display_month=1;
					display_year++;
				}
			}
			result+='</TR>';
		}
		var current_weekday=now.getDay() - this.weekStartDay;
		if (current_weekday < 0)
			current_weekday+=7;

		result+='<TR>\n';
		result+='	<TD COLSPAN=7 ALIGN=CENTER CLASS="' + this.cssPrefix + 'cpTodayText">\n';
		if (this.disabledDatesExpression != "")
		{
			var ds="" + now.getFullYear() + LZ(now.getMonth() + 1)
					+ LZ(now.getDate());
			eval("disabled=(" + this.disabledDatesExpression + ")");
		}
		if (disabled || this.disabledWeekDays[current_weekday + 1])
		{
			result+='		<SPAN CLASS="' + this.cssPrefix
					+ 'cpTodayTextDisabled">' + this.todayText + '</SPAN>\n';
		}
		else
		{
			result+='		<A CLASS="' + this.cssPrefix
					+ 'cpTodayText" HREF="javascript:' + windowref
					+ this.returnFunction + '(\'' + now.getFullYear() + '\',\''
					+ (now.getMonth() + 1) + '\',\'' + now.getDate() + '\');'
					+ windowref + 'CP_hideCalendar(\'' + this.index + '\');">'
					+ this.todayText + '</A>\n';
			result+='&nbsp;&nbsp;&nbsp;<A CLASS="' + this.cssPrefix
					+ 'cpTodayText" HREF="javascript:' + windowref
					+ this.returnFunction + '(0,0,0);'
					+ windowref + 'CP_hideCalendar(\'' + this.index + '\');">'
					+ this.clearText + '</A>\n';
		}
		result+='		<BR>\n';
		result+='	</TD></TR></TABLE></CENTER></TD></TR></TABLE>\n';
	}

	// Code common for MONTH, QUARTER, YEAR
	// ------------------------------------
	if (this.displayType == "month" || this.displayType == "quarter"
			|| this.displayType == "year")
	{
		if (arguments.length > 0)
			var year=arguments[0];
		else
		{
			if (this.displayType == "year")
				var year=now.getFullYear() - this.yearSelectStartOffset;
			else
				var year=now.getFullYear();
		}
		if (this.displayType != "year" && this.isShowYearNavigation)
		{
			result+="<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";
			result+='<TR>\n';
			result+='	<TD CLASS="' + this.cssPrefix
					+ 'cpYearNavigation" WIDTH="22"><A CLASS="'
					+ this.cssPrefix + 'cpYearNavigation" HREF="javascript:'
					+ windowref + 'CP_refreshCalendar(' + this.index + ','
					+ (year - 1) + ');">&lt;&lt;</A></TD>\n';
			result+='	<TD CLASS="' + this.cssPrefix
					+ 'cpYearNavigation" WIDTH="100">' + year + '</TD>\n';
			result+='	<TD CLASS="' + this.cssPrefix
					+ 'cpYearNavigation" WIDTH="22"><A CLASS="'
					+ this.cssPrefix + 'cpYearNavigation" HREF="javascript:'
					+ windowref + 'CP_refreshCalendar(' + this.index + ','
					+ (year + 1) + ');">&gt;&gt;</A></TD>\n';
			result+='</TR></TABLE>\n';
		}
	}

	// Code for MONTH display
	// ----------------------
	if (this.displayType == "month")
	{
		// If POPUP, write entire HTML document
		result+='<TABLE WIDTH=120 BORDER=0 CELLSPACING=1 CELLPADDING=0 ALIGN=CENTER>\n';
		for( var i=0;i < 4;i++)
		{
			result+='<TR>';
			for( var j=0;j < 3;j++)
			{
				var monthindex=((i * 3) + j);
				result+='<TD WIDTH=33% ALIGN=CENTER><A CLASS="'
						+ this.cssPrefix + 'cpText" HREF="javascript:'
						+ windowref + this.returnMonthFunction + '(' + year
						+ ',' + (monthindex + 1) + ');' + windowref
						+ 'CP_hideCalendar(\'' + this.index + '\');" CLASS="'
						+ date_class + '">'
						+ this.monthAbbreviations[monthindex] + '</A></TD>';
			}
			result+='</TR>';
		}
		result+='</TABLE></CENTER></TD></TR></TABLE>\n';
	}

	// Code for QUARTER display
	// ------------------------
	if (this.displayType == "quarter")
	{
		result+='<BR><TABLE WIDTH=120 BORDER=1 CELLSPACING=0 CELLPADDING=0 ALIGN=CENTER>\n';
		for( var i=0;i < 2;i++)
		{
			result+='<TR>';
			for( var j=0;j < 2;j++)
			{
				var quarter=((i * 2) + j + 1);
				result+='<TD WIDTH=50% ALIGN=CENTER><BR><A CLASS="'
						+ this.cssPrefix + 'cpText" HREF="javascript:'
						+ windowref + this.returnQuarterFunction + '(' + year
						+ ',' + quarter + ');' + windowref
						+ 'CP_hideCalendar(\'' + this.index + '\');" CLASS="'
						+ date_class + '">Q' + quarter + '</A><BR><BR></TD>';
			}
			result+='</TR>';
		}
		result+='</TABLE></CENTER></TD></TR></TABLE>\n';
	}

	// Code for YEAR display
	// ---------------------
	if (this.displayType == "year")
	{
		var yearColumnSize=4;
		result+="<TABLE WIDTH=144 BORDER=0 BORDERWIDTH=0 CELLSPACING=0 CELLPADDING=0>";
		result+='<TR>\n';
		result+='	<TD CLASS="' + this.cssPrefix
				+ 'cpYearNavigation" WIDTH="50%"><A CLASS="' + this.cssPrefix
				+ 'cpYearNavigation" HREF="javascript:' + windowref
				+ 'CP_refreshCalendar(' + this.index + ','
				+ (year - (yearColumnSize * 2)) + ');">&lt;&lt;</A></TD>\n';
		result+='	<TD CLASS="' + this.cssPrefix
				+ 'cpYearNavigation" WIDTH="50%"><A CLASS="' + this.cssPrefix
				+ 'cpYearNavigation" HREF="javascript:' + windowref
				+ 'CP_refreshCalendar(' + this.index + ','
				+ (year + (yearColumnSize * 2)) + ');">&gt;&gt;</A></TD>\n';
		result+='</TR></TABLE>\n';
		result+='<TABLE WIDTH=120 BORDER=0 CELLSPACING=1 CELLPADDING=0 ALIGN=CENTER>\n';
		for( var i=0;i < yearColumnSize;i++)
		{
			for( var j=0;j < 2;j++)
			{
				var currentyear=year + (j * yearColumnSize) + i;
				result+='<TD WIDTH=50% ALIGN=CENTER><A CLASS="'
						+ this.cssPrefix + 'cpText" HREF="javascript:'
						+ windowref + this.returnYearFunction + '('
						+ currentyear + ');' + windowref + 'CP_hideCalendar(\''
						+ this.index + '\');" CLASS="' + date_class + '">'
						+ currentyear + '</A></TD>';
			}
			result+='</TR>';
		}
		result+='</TABLE></CENTER></TD></TR></TABLE>\n';
	}
	// Common
	if (this.type == "WINDOW")
		result+="</BODY></HTML>\n";

	return result;
}

