function Calendar(target) {

 this.toString	= function() { return "[object Calendar]"; };
 this.target	= target;
 this.TODAY;
 this.MONTH;
 this.DATE;
 this.YEAR;
 this.todaystr;
 this.size	= 10;

 this.months	= new Array();
 this.monthdisplay;
 this.calbody;
 this.dragable	= 0;
 this.closeable	= 0;
 this.style	= "small";

 this.statusXML		= "";
 this.events		= new Array();
 this.excludes		= new Array();

 this.statusClasses	= new Array();

 // define standard tagName default values
 this.tags	= new Array();
 this.tags["status"]	= "Status";
 this.tags["date"]		= "Date";
 this.tags["event"]		= "Event";

 this.onClickDate	= function() {};
 this.loadDateData	= function() {};
 this.onLoad	= function() {};


 this.Month		= function(name,days) {
	this.name	= name;
	this.ds		= days;
	this.days	= function(year) {
					if (this.name == "February") {
						var tYear = year/4;
						if (tYear == parseInt(tYear)) {
							return this.ds + 1;
						}
					}
					return this.ds;
				  };
	return this;
 };

 // add Status data in XML format
 this.addStatusXML	= function(xmlfile) {
	this.xml	= xmlfile;
	var events  = this.xml.responseXML.getElementsByTagName(this.tags["event"]);
	for (var oIdx = 0; oIdx < events.length; oIdx++) {
		var include	= 1;
		for (var etag in this.excludes) {
			var eval	= this.excludes[etag];
			var oval	= getElementValue(events[oIdx],etag,"");
			if (eval.match(oval)) {
				include	= 0;
				break;
			} 
		}
		if (include) {
			this.events.push(events[oIdx]);
		}
	}
	return this.events;
 };


 // sets the target DIV for the calendar to appear
 this.setTarget	= function(target) {
	this.target	= target;
 };

 // sets the XML data that contains status info
 this.setStatusXML	= function(xml) {
	this.statusXML	= xml;
 };

 // sets the tagnames for various fields
 this.setTag	= function(tag,name) {
	this.tags[tag]	= name;
 };

 this.setStatusClasses	= function(status,className) {
	this.statusClasses[status]	= className;
 };

 this.getCells	= function() {
	var cArr	= new Array();
	for (var rIdx = 0; rIdx < this.calbody.rows.length; rIdx++) {
		var row	= this.calbody.rows[rIdx];
		for (var cIdx = 0; cIdx < row.cells.length; cIdx++) {
			var cell	= row.cells[cIdx];
			if (cell.className.match("calendarcell")) {
				cArr.push(cell);
			}
		}
	}
	return cArr;
 };

 this.buildCalendar	= function(cellSize) {
	if (this.MONTH > 12) { this.MONTH = 1; this.YEAR++; }
	if (this.MONTH < 1) { this.MONTH = 12; this.YEAR--; }
	var calendar	= this.calbody;
	var oldRows		= calendar.rows.length;
	for (var rIdx = 0; rIdx < oldRows; rIdx++) {
		calendar.deleteRow(0);
	}
	this.monthdisplay.innerHTML = this.months[this.MONTH].name + " " + this.YEAR;
	var startDate	= new Date(this.MONTH + "/01/" + this.YEAR);
	var currDate	= 1;
	var currWeek	= 1;
	var currRow		= calendar.insertRow(-1);
	for (var d = 0; d < startDate.getDay(); d++) {
		currRow.insertCell(d).bgColor = "#FFFFFF";
	}
	for (var d = startDate.getDay(); d < 7; d++) {
		var currCell = currRow.insertCell(d);
		this.createCell(currCell,currDate++);
	}
	while (currDate < this.months[this.MONTH].days(this.YEAR) + 1) {
		currWeek++;
		var currRow	= calendar.insertRow(-1);
		for (var d = 0; d < 7; d++) {
			if (currDate > this.months[this.MONTH].days(this.YEAR)) { continue; }
			var currCell	= currRow.insertCell(-1);
			this.createCell(currCell,currDate++);
		}
	}
	this.onLoad(this);
	return this;
 };

 this.createTable	= function() {
	var calHead		= document.createElement("THEAD");
	    calHead.style.textAlign	= "center";
	    calHead.style.fontWeight	= "bold";
	var calTab		= document.createElement("TABLE");
	    calTab.className	= "Calendar";
//	    calTab.bgColor	= "#FF0000";
	    calTab.appendChild(calHead);
	    calTab.cellSpacing	= 0;
//	    calTab.cellPadding	= 0;
	    calTab.style.backgroundColor	= "white";
	    calTab.style.border	= "solid thin";
	this.target.appendChild(calTab);
	var mRow	= calHead.insertRow(-1);
	    mRow.bgColor	= "#F0F0F0";
	var closeCell	= mRow.insertCell(-1);
	var prevCell	= mRow.insertCell(-1);
	var nextCell;
	var monthCell;
	if (navigator.userAgent.toLowerCase().indexOf("safari") != -1) {
		nextCell	= mRow.insertCell(-1);
		monthCell	= mRow.insertCell(-1);
	} else {
		monthCell	= mRow.insertCell(-1);
		nextCell	= mRow.insertCell(-1);
	}
	// Build Close Cell
	if (this.closeable) {
		var closeIMG	= document.createElement("IMG");
			closeIMG.target	= this.target;
			closeIMG.className	= "clickable";
		    closeIMG.src	= "/Icons/close.png";
		    closeIMG.closeCalendar	= this.closeCalendar;
		    closeIMG.onclick= function() {
				this.closeCalendar();
			};
		closeCell.appendChild(closeIMG);
	}
	// Build Previous Month Cell
	prevCell.title	= "prev month";
	prevCell.className	= "clickable";
	prevCell.obj	= this;
	prevCell.onclick	= function() {
		this.obj.MONTH--;
		this.obj.buildCalendar();
	};
	prevCell.innerHTML	= "&lt;";
	// Build Next Month Cell
	nextCell.title	= "next month";
	nextCell.className	= "clickable";
	nextCell.obj	= this;
	nextCell.onclick	= function() {
		this.obj.MONTH++;
		this.obj.buildCalendar();
	};
	nextCell.innerHTML	= "&gt;";
	nextCell.style.display = "inline";
	// Build Current Month Cell
	monthCell.colSpan	= 4;
	monthCell.id	= this.target.id + "Handle";
	this.monthdisplay	= monthCell;
	if (this.dragable) {
	   	calTab.className	+= " drag"
		monthCell.className	+= "draghandle";
	}
	//
	// Create Month Row
	//
	var wRow	= calHead.insertRow(-1);
	    wRow.bgColor	= "#F0F0F0";
//	    wRow.style.color	= "#FF0000";
	var sunCell	= wRow.insertCell(-1);
	var monCell	= wRow.insertCell(-1);
	var tueCell	= wRow.insertCell(-1);
	var wedCell	= wRow.insertCell(-1);
	var thuCell	= wRow.insertCell(-1);
	var friCell	= wRow.insertCell(-1);
	var satCell	= wRow.insertCell(-1);
	sunCell.innerHTML	= "S";
	monCell.innerHTML	= "M";
	tueCell.innerHTML	= "T";
	wedCell.innerHTML	= "W";
	thuCell.innerHTML	= "T";
	friCell.innerHTML	= "F";
	satCell.innerHTML	= "S";
	var calBody	= document.createElement("TBODY");
	calTab.appendChild(calBody);
	this.calbody	= calBody;
	calTab.style.fontSize	= this.size + "px";
	calTab.style.fontFamily	= "monospace";
	return calTab;
 };

 this.closeCalendar	= function() {
	this.target.style.display	= "none";
 };

 this.createCell	= function(thisCell,thisDate) {
	var datestr	= parseInt(this.YEAR*10000) + parseInt(this.MONTH*100) + parseInt(thisDate);
	var cellid	= this.target.id + datestr;
	thisCell.calendar	= this;
	thisCell.id	= cellid;
	thisCell.width	= this.size * 2;
//	thisCell.width	= 22;
	thisCell.height	= thisCell.width;
	thisCell.date	= new Date(this.MONTH + "/" + thisDate + "/" + this.YEAR);
	thisCell.innerHTML	= thisDate;
//	thisCell.align	= "center";
//	thisCell.bgColor	= "#FFFFFF";
	thisCell.className	= "clickable calendarcell";
	thisCell.datestr	= datestr;
	thisCell.target		= this.target;
	thisCell.onClickDate	= this.onClickDate;
//	thisCell.onclick		= function() { this.onClickDate(this); }
	thisCell.onclick		= thisCell.onClickDate;
//	thisCell.onmouseover	= function() { this.bgColor = "#D0D0D0"; }
//	thisCell.onmouseout		= function() { this.bgColor = ""; }
//	thisCell.onmouseover	= function() { this.style.border = "solid thin #FF0000"; }
//	thisCell.onmouseout		= function() { this.style.border = ""; }
	if (thisCell.datestr == this.todaystr) {
		thisCell.className	+= " todaycell";
	}
	return thisCell;
 };

 this.str2date		= function(dateStr) {
	if (!dateStr) { return ""; }
	if (dateStr.match("/")) {
		return dateStr;
	}
    var y   = dateStr.substring(0,4);
    var m   = dateStr.substring(4,6);
    var d   = dateStr.substring(6,8);
    var slashdate   = m + "/" + d + "/" + y;
    return slashdate;
 };

 this.date2str		= function(slashdate) {
	if (!slashdate) { return ""; }
	if (slashdate.match(/^\d+$/)) { return slashdate; }
	var dparts	= slashdate.split("/");
	if (dparts.length == 0) {
		return slashdate;
	}
	var m		= dparts[0];
	var d		= dparts[1];
	var y		= dparts[2];
	var dateStr	= (y*10000) + (m*100) + (d*1);
	return dateStr;
 };

 this.init		= function() {
	// set Globals
	this.TODAY	= new Date();
	this.MONTH	= this.TODAY.getMonth() + 1;
	this.DATE	= this.TODAY.getDate();
	this.YEAR	= this.TODAY.getFullYear();
	if (this.YEAR < 1900) { this.YEAR += 1900; }
	var todaystr	= (this.YEAR*10000) + (this.MONTH*100) + (this.DATE*1);
	this.todaystr	= todaystr.toString();
	// init Month Array
	this.months		= new Array();
	this.months[1]	= new this.Month("January",31);
	this.months[2]	= new this.Month("February",28);
	this.months[3]	= new this.Month("March",31);
	this.months[4]	= new this.Month("April",30);
	this.months[5]	= new this.Month("May",31);
	this.months[6]	= new this.Month("June",30);
	this.months[7]	= new this.Month("July",31);
	this.months[8]	= new this.Month("August",31);
	this.months[9]	= new this.Month("September",30);
	this.months[10]	= new this.Month("October",31);
	this.months[11]	= new this.Month("November",30);
	this.months[12]	= new this.Month("December",31);
	if (this.months[this.MONTH].days() == this.DATE) { this.MONTH++; }
	this.createTable();
	this.buildCalendar();
	return this;
 };

 return this;

}

