DateTime = Date;

DateTime.prototype.addDays = function(days) {
	var tempDay = this.getDate();
	tempDay += days;
	this.setDate(tempDay);
	return this;
}

DateTime.prototype.addMonths = function(months) {
	var tempMonth = this.getMonth();
	tempMonth += months;
	this.setMonth(tempMonth);
	return this;
}

DateTime.prototype.addYears = function(years) {
	var tempYear = this.getFullYear();
	tempYear += years;
	this.setYear(tempYear);
	return this;
}

DateTime.prototype.getDaysInMonth = function(year, month) {
	if (year != null && month == null) {
		month = year;
		year = this.getFullYear();
	}
	else if (year == null && month == null) {
		year = this.getFullYear();
		month = this.getMonth()
	}
	while (month < 0) {
		month += 11;
		year--;
	}
	while (month > 11) {
		month -=11;
		year++;
	}

	switch(month) {
		case 1:
			if ((year % 100 != 0 && year % 4 ==0) || (year % 400 == 0))
				return 29;
			else
				return 28;
			break;
		case 3:
		case 5:
		case 8:
		case 10:
			return 30;
			break;
		default:
			return 31;
			break;
	}
}

DateTime.prototype.isLeapYear = function() {
	var year = this.getFullYear();
	if ((year % 100 != 0 && year % 4 ==0) || (year % 400 == 0))
		return true;
	else
		return false;
}

DateTime.prototype.dayOfYear = function() {
	var year = this.getFullYear();
	if ((year % 100 != 0 && year % 4 ==0) || (year % 400 == 0))
		return 366;
	else
		return 365;
}

DateTime.prototype.isWeekendDay = function() {
	var dayOfWeek = this.getDay();
	if (dayOfWeek == 0 || dayOfWeek == 6)
		return true;
	else
		return false;
}

DateTime.prototype.compare = function(datePart, date) {
	if (!(date instanceof Date)) {
		date = new Date(date);
	}
	if (!isNaN(date)) {
		var temp1 = null, temp2 = null;
		if (datePart.toLowerCase() == "year") {
			temp1 = new Date(this.getFullYear(), 1, 1, 0, 0, 0, 0);
			temp2 = new Date(date.getFullYear(), 1, 1, 0, 0, 0, 0);
		}
		else if (datePart.toLowerCase() == "month") {
			temp1 = new Date(this.getFullYear(), this.getMonth(), 1, 0, 0, 0, 0);
			temp2 = new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0, 0);
		}
		else if (datePart.toLowerCase() == "day") {
			temp1 = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0, 0);
			temp2 = new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0, 0, 0, 0);
		}
		else {
			temp1 = new Date();
			temp2 = temp1;
		}
		if (temp1.getTime() == temp2.getTime())
			return 0;
		else if (temp1.getTime() < temp2.getTime())
			return -1;
		else
			return 1;
	}
	else
		return null;
}

function Style() {
	thisStyle = this;
	thisStyle.width = "";
	thisStyle.height = "";
	thisStyle.borderStyle = "";
	thisStyle.borderWidth = "";
	thisStyle.borderColor = "";
	thisStyle.foreColor = "";
	thisStyle.fontFamily = "";
	thisStyle.fontSize = "";
	thisStyle.backColor  = "";
	thisStyle.bold = false;
	thisStyle.italic = false;
	thisStyle.cssClass = "";
	thisStyle.borderCollapse = "";
	thisStyle.padding = "";

	//this following style should be applied as attributes of the tag instead of style string;
	thisStyle.align = "";
	thisStyle.vAlign = "";
}

Style.prototype.appendStyle = function(styleString, style, value) {
	var thisStyle = this;
	if (styleString == null || styleString == "")
		return style + ": " + value + "; ";
	else
		return styleString + style + ": " + value + "; ";
}

Style.prototype.getRawStyleString = function() {
	var thisStyle = this;
	var styleString = "";
	if (thisStyle.width != null && thisStyle.width != "")
		styleString = thisStyle.appendStyle(styleString, "width", thisStyle.width);
	if (thisStyle.height != null && thisStyle.height != "")
		styleString = thisStyle.appendStyle(styleString, "height", thisStyle.height);
	if (thisStyle.borderStyle != null && thisStyle.borderStyle != "")
		styleString = thisStyle.appendStyle(styleString, "border-style", thisStyle.borderStyle);
	if (thisStyle.borderWidth != null && thisStyle.borderWidth != "")
		styleString = thisStyle.appendStyle(styleString, "border-width", thisStyle.borderWidth);
	if (thisStyle.borderColor != null && thisStyle.borderColor != "")
		styleString = thisStyle.appendStyle(styleString, "border-color", thisStyle.borderColor);
	if (thisStyle.foreColor != null && thisStyle.foreColor != "")
		styleString = thisStyle.appendStyle(styleString, "color", thisStyle.foreColor);
	if (thisStyle.fontFamily != null && thisStyle.fontFamily != "")
		styleString = thisStyle.appendStyle(styleString, "font-family", thisStyle.fontFamily);
	if (thisStyle.fontSize != null && thisStyle.fontSize != "")
		styleString = thisStyle.appendStyle(styleString, "font-size", thisStyle.fontSize);
	if (thisStyle.backColor != null && thisStyle.backColor != "")
		styleString = thisStyle.appendStyle(styleString, "background-color", thisStyle.backColor);
	if (thisStyle.bold)	{
		styleString = thisStyle.appendStyle(styleString, "font-weight", "bold");
	}
	if (thisStyle.italic){
		styleString = thisStyle.appendStyle(styleString, "font-style", "italic");
	}
	if (thisStyle.borderCollapse != null && thisStyle.borderCollapse != "")
		styleString = thisStyle.appendStyle(styleString, "border-collapse", thisStyle.borderCollapse);
	if (thisStyle.padding != null && thisStyle.padding != "")
		styleString = thisStyle.appendStyle(styleString, "padding", thisStyle.padding);
	
	return styleString;
}

Style.prototype.getStyleString = function() {
	var thisStyle = this;
	var rawStyleString = thisStyle.getRawStyleString();
	if (rawStyleString == null || rawStyleString == "")
		return "";
	else
		return "style=\"" + rawStyleString + "\"";
}

Style.prototype.getAlign = function() {
	var thisStyle = this;
	var align = thisStyle.align.toLowerCase();
	if (align == "left" || align == "right" || align == "center") {
		return " align=\"" + align + "\" ";
	}
	else
		return "";
}

Style.prototype.getValign = function() {
	var thisStyle = this;
	var vAlign = thisStyle.vAlign.toLowerCase();
	if (vAlign == "top" || vAlign == "bottom" || vAlign == "middle") {
		return " vAlign=\"" + vAlign + "\" ";
	}
	else
		return "";
}

function CalendarObject(objectName, showDate, selectedDate) {
	var thisCalendarObject = this;
	//properties

	if (objectName == null || objectName == "") {
		alert("Object cannot be created without a valid object name.");
	}
	else {
		thisCalendarObject.objectName = objectName;
	}

	thisCalendarObject.style = new Style();
	thisCalendarObject.style.width = "100%";
	thisCalendarObject.style.height = "100%";
	thisCalendarObject.style.cellSpacing = 0;
	thisCalendarObject.style.cellPadding = 0;
	thisCalendarObject.style.border = 0;
	thisCalendarObject.style.brdrColor = "transparent";
	thisCalendarObject.style.backColor = "white";
	thisCalendarObject.style.borderWidth = "0px";
	thisCalendarObject.style.borderStyle = "solid";
	thisCalendarObject.style.borderColor = "black";
	thisCalendarObject.style.fontSize = "9pt";
	thisCalendarObject.style.fontFamily = "Tahoma";
	thisCalendarObject.style.cssClass = "Calendar";

	thisCalendarObject.style.headerStyle = new Style();
	thisCalendarObject.style.headerStyle.cssClass = "headerStyle";
	thisCalendarObject.style.headerStyle.width = "100%";

	thisCalendarObject.style.headerStyle["previousYear"] = new Style();
	thisCalendarObject.style.headerStyle["previousMonth"] = new Style();
	thisCalendarObject.style.headerStyle["nextYear"] = new Style();
	thisCalendarObject.style.headerStyle["nextMonth"] = new Style();
	thisCalendarObject.style.headerStyle["previousYear"].cssClass = "previousYearTextStyle";
	thisCalendarObject.style.headerStyle["previousMonth"].cssClass = "previousMonthTextStyle";
	thisCalendarObject.style.headerStyle["nextYear"].cssClass = "nextYearTextStyle";
	thisCalendarObject.style.headerStyle["nextMonth"].cssClass = "nextMonthTextStyle";

	thisCalendarObject.style.titleStyle = new Style();
	thisCalendarObject.style.titleStyle.cssClass = "titleStyle";

	thisCalendarObject.style.dayStyle = new Style();
	thisCalendarObject.style.dayStyle["normal"] = new Style();
	thisCalendarObject.style.dayStyle["hover"] = new Style();
	thisCalendarObject.style.dayStyle["selected"] = new Style();

	thisCalendarObject.style.dayStyle.cssClass ="dayStyle";
	thisCalendarObject.style.dayStyle["normal"].cssClass = "dayStyle";
	thisCalendarObject.style.dayStyle["hover"].cssClass = "dayHoverStyle";
	thisCalendarObject.style.dayStyle["selected"].cssClass = "daySelectedStyle";
	thisCalendarObject.style.dayStyle["normal"].align = "center";
	thisCalendarObject.style.dayStyle["normal"].vAlign = "middle";

	thisCalendarObject.style.todayStyle = new Style();
	thisCalendarObject.style.todayStyle["normal"] = new Style();
	thisCalendarObject.style.todayStyle["hover"] = new Style();
	thisCalendarObject.style.todayStyle["selected"] = new Style();
	thisCalendarObject.style.todayStyle.cssClass = "todayStyle";
	thisCalendarObject.style.todayStyle["normal"].align = "center";
	thisCalendarObject.style.todayStyle["normal"].vAlign = "middle";
	thisCalendarObject.style.todayStyle["normal"].cssClass = "todayStyle";
	thisCalendarObject.style.todayStyle["hover"].cssClass = "todayHoverStyle";
	thisCalendarObject.style.todayStyle["selected"].cssClass = "todaySelectedStyle";


	thisCalendarObject.style.previousMonthDayStyle = new Style();
	thisCalendarObject.style.previousMonthDayStyle["normal"] = new Style();
	thisCalendarObject.style.previousMonthDayStyle["hover"] = new Style();
	thisCalendarObject.style.previousMonthDayStyle["selected"] = new Style();
	thisCalendarObject.style.previousMonthDayStyle.cssClass = "previousMonthDayStyle";
	thisCalendarObject.style.previousMonthDayStyle["normal"].align = "center";
	thisCalendarObject.style.previousMonthDayStyle["normal"].vAlign = "middle";
	thisCalendarObject.style.previousMonthDayStyle["normal"].cssClass = "previousMonthDayStyle";
	thisCalendarObject.style.previousMonthDayStyle["hover"].cssClass = "previousMonthDayHoverStyle";
	thisCalendarObject.style.previousMonthDayStyle["selected"].cssClass = "previousMonthDaySelectedStyle";

	thisCalendarObject.style.nextMonthDayStyle = new Style();
	thisCalendarObject.style.nextMonthDayStyle["normal"] = new Style();
	thisCalendarObject.style.nextMonthDayStyle["hover"] = new Style();
	thisCalendarObject.style.nextMonthDayStyle["selected"] = new Style();
	thisCalendarObject.style.nextMonthDayStyle.cssClass = "nextMonthDayStyle";
	thisCalendarObject.style.nextMonthDayStyle["normal"].align = "center";
	thisCalendarObject.style.nextMonthDayStyle["normal"].vAlign = "middle";
	thisCalendarObject.style.nextMonthDayStyle["normal"].cssClass = "nextMonthDayStyle";
	thisCalendarObject.style.nextMonthDayStyle["hover"].cssClass = "nextMonthDayHoverStyle";
	thisCalendarObject.style.nextMonthDayStyle["selected"].cssClass = "nextMonthDaySelectedStyle";

	thisCalendarObject.style.invalidDayStyle = new Style();
	thisCalendarObject.style.invalidDayStyle.cssClass = "invalidDay";
	thisCalendarObject.style.invalidDayStyle.align = "center";
	thisCalendarObject.style.invalidDayStyle.vAlign = "middle";

	thisCalendarObject.style.footerStyle = new Style();
	thisCalendarObject.style.footerStyle["selected"] = new Style();
	thisCalendarObject.style.footerStyle["today"] = new Style();
	thisCalendarObject.style.footerStyle.cssClass = "footerStyle";
	thisCalendarObject.style.footerStyle["selected"].cssClass = "selectedDate";
	thisCalendarObject.style.footerStyle["today"].cssClass = "selectTodayStyle";
	thisCalendarObject.style.footerStyle.cellSpacing = 0;
	thisCalendarObject.style.footerStyle.cellPadding = 0;
	thisCalendarObject.style.footerStyle.border = 0;
	thisCalendarObject.style.footerStyle.brdrColor = "black";
	thisCalendarObject.style.footerStyle.height = "100%";

	thisCalendarObject.style.closeStyle = new Style();
	thisCalendarObject.style.closeStyle.cssClass = "closeStyle";
	thisCalendarObject.style.closeStyle.hover = new Style();
	thisCalendarObject.style.closeStyle.hover.cssClass = "closeHoverStyle";

	thisCalendarObject.style.weekendStyle = {
		"enabled": false, 
		previousMonthDayStyle:  {
			"normal": new Style(),
			"hover": new Style(),
			"selected": new Style()
		},
		dayStyle: {
			"normal": new Style(),
			"hover": new Style(),
			"selected": new Style()
		},
		nextMonthDayStyle: {
			"normal": new Style(),
			"hover": new Style(),
			"selected": new Style()
		},
		todayStyle: {
			"normal": new Style(),
			"hover": new Style(),
			"selected": new Style()
		},
		invalidDayStyle: new Style()
	}
	
	thisCalendarObject.style.weekendStyle.previousMonthDayStyle["normal"].cssClass = "previousMonthWeekendStyle";
	thisCalendarObject.style.weekendStyle.previousMonthDayStyle["normal"].align = "center";
	thisCalendarObject.style.weekendStyle.previousMonthDayStyle["normal"].vAlign = "middle";
	thisCalendarObject.style.weekendStyle.previousMonthDayStyle["hover"].cssClass = "previousMonthWeekendHoverStyle";
	thisCalendarObject.style.weekendStyle.previousMonthDayStyle["selected"].cssClass = "previousMonthWeekendSelectedStyle";

	thisCalendarObject.style.weekendStyle.dayStyle["normal"].cssClass = "weekendStyle";
	thisCalendarObject.style.weekendStyle.dayStyle["normal"].align = "center";
	thisCalendarObject.style.weekendStyle.dayStyle["normal"].vAlign = "middle";
	thisCalendarObject.style.weekendStyle.dayStyle["hover"].cssClass = "weekendHoverStyle";
	thisCalendarObject.style.weekendStyle.dayStyle["selected"].cssClass = "weekendSelectedStyle";

	thisCalendarObject.style.weekendStyle.nextMonthDayStyle["normal"].cssClass = "nextMonthWeekendStyle";
	thisCalendarObject.style.weekendStyle.nextMonthDayStyle["normal"].align = "center";
	thisCalendarObject.style.weekendStyle.nextMonthDayStyle["normal"].vAlign = "middle";
	thisCalendarObject.style.weekendStyle.nextMonthDayStyle["hover"].cssClass = "nextMonthWeekendHoverStyle";
	thisCalendarObject.style.weekendStyle.nextMonthDayStyle["selected"].cssClass = "nextMonthWeekendSelectedStyle";

	thisCalendarObject.style.weekendStyle.todayStyle["normal"].cssClass = "todayWeekendStyle";
	thisCalendarObject.style.weekendStyle.todayStyle["normal"].align = "center";
	thisCalendarObject.style.weekendStyle.todayStyle["normal"].vAlign = "middle";
	thisCalendarObject.style.weekendStyle.todayStyle["hover"].cssClass = "todayWeekendHoverStyle";
	thisCalendarObject.style.weekendStyle.todayStyle["selected"].cssClass = "todayWeekendSelectedStyle";
	
	thisCalendarObject.style.weekendStyle.invalidDayStyle.cssClass = "invalidDayWeekendStyle";

	thisCalendarObject.dynamicPosition = true;

	thisCalendarObject.offsetX = 0;
	thisCalendarObject.offsetY = 0;

	thisCalendarObject.visible = {
		"previousMonth": true,
		"nextMonth": true,
		"previousYear": false,
		"nextYear": false,
		"header": true,
		"title": true,
		"previousMonthDays": false,
		"nextMonthDays": false,
		"footer": true,
		"close": true
	}

	thisCalendarObject.text = {
		"nextYear": "&gt;&gt;",
		"previousYear": "&lt;&lt;",
		"nextMonth": "&gt;",
		"previousMonth": "&lt;",
		"close": "关闭"
	}

	thisCalendarObject.toolTips = {
		"close": "关闭",
		"date": "选择YYYY年MMM%d日",
		"selectToday": "选择今天",
		"nextMonth": "下个月",
		"previousMonth": "上个月",
		"nextYear": "明年",
		"previousYear": "去年",
		"invalidDate": "不能选择日期YYYY年MMM%d日"
	}

	thisCalendarObject.firstDayOfWeek = 0;
	thisCalendarObject.selectableDateRange = {
		"beginDate": "",
		"endDate": ""
	}

	thisCalendarObject.format = {
		"header": "FullMonthYear", //valid format includes "FullMonthYear", "ShortMonthYear", "MonthYear", "FullMonth", "ShortMonth", "Month", by default "Month";
		"title": "Day", //valid format includes "FullDay", "ShortDay", "Day", by default "ShortDay";
		"calendarBody": "%d",
		footer: {
			"selected": "YYYY/%M/%d",
			"today": "YYYY/%M/%d"
		},
		"selected": "YYYY/%M/%d"
	}

	thisCalendarObject.monthNames = ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"];
	thisCalendarObject.abbreviatedMonthNames = ["1月", "2月", "3月", "4月", "5月", "6月", "7月", "8月", "9月", "10月", "11月", "12月"];
	thisCalendarObject.dayNames = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"];
	thisCalendarObject.abbreviatedDayNames = ["日", "一", "二", "三", "四", "五", "六"];
	thisCalendarObject.shortDayNames = ["日", "一", "二", "三", "四", "五", "六"];
	//private properties
	thisCalendarObject.previousSelectedDate = thisCalendarObject.selectedDate;

	//methods
	thisCalendarObject.show = show;
	thisCalendarObject.previousMonth = previousMonth;
	thisCalendarObject.nextMonth = nextMonth;
	thisCalendarObject.previousYear = previousYear;
	thisCalendarObject.nextYear = nextYear;
	thisCalendarObject.hoverPreviousMonthDay = hoverPreviousMonthDay;
	thisCalendarObject.hoverDay = hoverDay;
	thisCalendarObject.hoverNextMonthDay = hoverNextMonthDay;
	thisCalendarObject.hoverToday = hoverToday;
	thisCalendarObject.normalizePreivousMonthDay = normalizePreivousMonthDay;
	thisCalendarObject.normalizeDay = normalizeDay;
	thisCalendarObject.normalizeNextMonthDay = normalizeNextMonthDay;
	thisCalendarObject.normalizeToday = normalizeToday;
	thisCalendarObject.selectDate = selectDate;

	function hoverPreviousMonthDay(obj) {
		if (obj.className == thisCalendarObject.style.previousMonthDayStyle["normal"].cssClass)
			obj.className = thisCalendarObject.style.previousMonthDayStyle["hover"].cssClass;
		else if (obj.className == thisCalendarObject.style.weekendStyle.previousMonthDayStyle["normal"].cssClass)
			obj.className = thisCalendarObject.style.weekendStyle.previousMonthDayStyle["hover"].cssClass;
	}

	function normalizePreivousMonthDay(obj) {
		if (obj.className == thisCalendarObject.style.previousMonthDayStyle["hover"].cssClass)
			obj.className = thisCalendarObject.style.previousMonthDayStyle["normal"].cssClass;
		else if (obj.className == thisCalendarObject.style.weekendStyle.previousMonthDayStyle["hover"].cssClass)
			obj.className = thisCalendarObject.style.weekendStyle.previousMonthDayStyle["normal"].cssClass;
	}

	function hoverDay(obj) {
		if (obj.className == thisCalendarObject.style.dayStyle["normal"].cssClass)
			obj.className = thisCalendarObject.style.dayStyle["hover"].cssClass;
		else if (obj.className == thisCalendarObject.style.weekendStyle.dayStyle["normal"].cssClass)
			obj.className = thisCalendarObject.style.weekendStyle.dayStyle["hover"].cssClass;
	}

	function normalizeDay(obj) {
		if (obj.className == thisCalendarObject.style.dayStyle["hover"].cssClass)
			obj.className = thisCalendarObject.style.dayStyle["normal"].cssClass;
		else if (obj.className == thisCalendarObject.style.weekendStyle.dayStyle["hover"].cssClass)
			obj.className = thisCalendarObject.style.weekendStyle.dayStyle["normal"].cssClass;
	}

	function hoverToday(obj) {
		if (obj.className == thisCalendarObject.style.todayStyle["normal"].cssClass)
			obj.className = thisCalendarObject.style.todayStyle["hover"].cssClass;
		else if (obj.className == thisCalendarObject.style.weekendStyle.todayStyle["normal"].cssClass)
			obj.className = thisCalendarObject.style.weekendStyle.todayStyle["hover"].cssClass;
	}

	function normalizeToday(obj) {
		if (obj.className == thisCalendarObject.style.todayStyle["hover"].cssClass)
			obj.className = thisCalendarObject.style.todayStyle["normal"].cssClass;
		else if (obj.className == thisCalendarObject.style.weekendStyle.todayStyle["hover"].cssClass)
			obj.className = thisCalendarObject.style.weekendStyle.todayStyle["normal"].cssClass;
	}

	function hoverNextMonthDay(obj) {
		if (obj.className == thisCalendarObject.style.nextMonthDayStyle["normal"].cssClass)
			obj.className = thisCalendarObject.style.nextMonthDayStyle["hover"].cssClass;
		else if (obj.className == thisCalendarObject.style.weekendStyle.nextMonthDayStyle["normal"].cssClass)
			obj.className = thisCalendarObject.style.weekendStyle.nextMonthDayStyle["hover"].cssClass;
	}

	function normalizeNextMonthDay(obj) {
		if (obj.className == thisCalendarObject.style.nextMonthDayStyle["hover"].cssClass)
			obj.className = thisCalendarObject.style.nextMonthDayStyle["normal"].cssClass;
		else if (obj.className == thisCalendarObject.style.weekendStyle.nextMonthDayStyle["hover"].cssClass)
			obj.className = thisCalendarObject.style.weekendStyle.nextMonthDayStyle["normal"].cssClass;
	}

	function selectDate(date) {
		var obj = document.getElementById(thisCalendarObject.objectName + "_" + thisCalendarObject.formatDate(new Date(date), "YYYY_MM_dd"));
		if (obj == null)
			return;
		else {
			var thisDate = new DateTime(thisCalendarObject.previousSelectedDate);
			var previousSelectedObject = document.getElementById(thisCalendarObject.objectName + "_" + thisCalendarObject.formatDate(thisCalendarObject.previousSelectedDate, "YYYY_MM_dd"));
			if (previousSelectedObject != null) { //normalize previously selected
				//alert(thisCalendarObject.previousSelectedObject.id);
				if (thisDate.compare("day", new Date()) == 0) {
					if (thisCalendarObject.style.weekendStyle.enabled && thisDate.isWeekendDay()) {
						previousSelectedObject.className = thisCalendarObject.style.weekendStyle.todayStyle["normal"].cssClass;
					}
					else
						previousSelectedObject.className = thisCalendarObject.style.todayStyle["normal"].cssClass;
				}
				else if (thisDate.compare("month", thisCalendarObject.showDate) < 0) {
					if (thisCalendarObject.style.weekendStyle.enabled && thisDate.isWeekendDay()) {
						previousSelectedObject.className = thisCalendarObject.style.weekendStyle.previousMonthDayStyle["normal"].cssClass;
					}
					else {
						previousSelectedObject.className = thisCalendarObject.style.previousMonthDayStyle["normal"].cssClass;
					}
				}
				else if (thisDate.compare("month", thisCalendarObject.showDate) == 0) {
					if (thisCalendarObject.style.weekendStyle.enabled && thisDate.isWeekendDay()) {
						previousSelectedObject.className = thisCalendarObject.style.weekendStyle.dayStyle["normal"].cssClass;
					}
					else {
						previousSelectedObject.className = thisCalendarObject.style.dayStyle["normal"].cssClass;
					}
				}
				else {
					if (thisCalendarObject.style.weekendStyle.enabled && thisDate.isWeekendDay()) {
						previousSelectedObject.className = thisCalendarObject.style.weekendStyle.nextMonthDayStyle["normal"].cssClass;
					}
					else {
						previousSelectedObject.className = thisCalendarObject.style.nextMonthDayStyle["normal"].cssClass;
					}
				}
			}
			thisCalendarObject.previousSelectedDate = new Date(date);
			thisCalendarObject.selectedDate = thisCalendarObject.previousSelectedDate;
			date = new Date(date);
			thisDate = new DateTime(thisCalendarObject.selectedDate);
			//alert(thisCalendarObject.compareDate("month", thisCalendarObject.selectedDate, thisCalendarObject.showDate));
			if (thisDate.compare("day", new Date()) == 0) {
				if (thisCalendarObject.style.weekendStyle.enabled && thisDate.isWeekendDay()) {
					obj.className = thisCalendarObject.style.weekendStyle.todayStyle["selected"].cssClass;
					thisCalendarObject.hoverToday(obj);
				}
				else {
					obj.className = thisCalendarObject.style.todayStyle["selected"].cssClass;
					thisCalendarObject.hoverToday(obj);
				}
			}
			else if (thisDate.compare("month", thisCalendarObject.showDate) < 0) {
				if (thisCalendarObject.style.weekendStyle.enabled && thisDate.isWeekendDay()){
					obj.className = thisCalendarObject.style.weekendStyle.previousMonthDayStyle["selected"].cssClass;
					thisCalendarObject.hoverPreviousMonthDay(obj);
				}
				else {
					obj.className = thisCalendarObject.style.previousMonthDayStyle["selected"].cssClass;
					thisCalendarObject.hoverPreviousMonthDay(obj);
				}
			}
			else if (thisDate.compare("month", thisCalendarObject.showDate) == 0) {
				if (thisCalendarObject.style.weekendStyle.enabled && thisDate.isWeekendDay()) {
					obj.className = thisCalendarObject.style.weekendStyle.dayStyle["selected"].cssClass;
					thisCalendarObject.hoverDay(obj);
				}
				else {
					obj.className = thisCalendarObject.style.dayStyle["selected"].cssClass;
					thisCalendarObject.hoverDay(obj);
				}
			}
			else if (thisDate.compare("month", thisCalendarObject.showDate) > 0){
				if (thisCalendarObject.style.weekendStyle.enabled && thisDate.isWeekendDay()) {
					obj.className = thisCalendarObject.style.weekendStyle.nextMonthDayStyle["selected"].cssClass;
					thisCalendarObject.hoverNextMonthDay(obj);
				}
				else {
					obj.className = thisCalendarObject.style.nextMonthDayStyle["selected"].cssClass;
					thisCalendarObject.hoverNextMonthDay(obj);
				}
			}
			if (document.getElementById(thisCalendarObject.controlToAcceptDate) != null)
				document.getElementById(thisCalendarObject.controlToAcceptDate).value = thisCalendarObject.formatDate(thisCalendarObject.selectedDate, thisCalendarObject.format["selected"]);
			if (document.getElementById(thisCalendarObject.objectName + "_footer")) {
				var footer = "<table align=\"center\" cellspacing=\"" + thisCalendarObject.style.footerStyle.cellSpacing + "\" cellpadding=\"" + thisCalendarObject.style.footerStyle.cellPadding + "\" border=\"" + thisCalendarObject.style.footerStyle.border + "\" bordercolor=\"" + thisCalendarObject.style.footerStyle.brdrColor + "\"" + thisCalendarObject.getClass(thisCalendarObject.style.footerStyle.cssClass) + thisCalendarObject.style.footerStyle.getStyleString() + "><tr><td width=\"50%\" align=\"left\" vAlign=\"middle\"><a href=\"javascript:" + thisCalendarObject.objectName + ".setToVisible('" + thisCalendarObject.formatDate(thisCalendarObject.selectedDate, "YYYY/MM/dd") + "');\"" + thisCalendarObject.getClass(thisCalendarObject.style.footerStyle["selected"].cssClass) + ">" + thisCalendarObject.formatDate(thisCalendarObject.selectedDate, thisCalendarObject.format.footer["selected"]) + "</a></td><td width=\"50%\" align=\"right\" vAlign=\"middle\"><a href=\"javascript:" + thisCalendarObject.objectName + ".selectToday(); " + thisCalendarObject.objectName + ".setToVisible('" + thisCalendarObject.formatDate(new Date(), "YYYY/MM/dd") + "');\"" + thisCalendarObject.getClass(thisCalendarObject.style.footerStyle["today"].cssClass) + " " + thisCalendarObject.style.footerStyle["today"].getStyleString() + " title=\"" + thisCalendarObject.toolTips["selectToday"] + "\">" + thisCalendarObject.formatDate(new Date(), thisCalendarObject.format.footer["today"]) + "</a></td></tr></table>";
				document.getElementById(thisCalendarObject.objectName + "_footer").innerHTML = footer;
			}
		}
		//alert("seletion finished!");
	}

	thisCalendarObject.formatDate = function(date, format) {
		if (date != null && (date instanceof DateTime) && format != null && format != "") {
			var dateString = format;
			dateString = dateString.replace(/YYYY/g, date.getFullYear());
			dateString = dateString.replace(/YY/g, date.getYear());
			dateString = dateString.replace(/MMMM/g, thisCalendarObject.monthNames[date.getMonth()]);
			dateString = dateString.replace(/MMM/g, thisCalendarObject.abbreviatedMonthNames[date.getMonth()]);
			dateString = dateString.replace(/MM/g, ((date.getMonth() + 1) > 9 ? (date.getMonth() + 1) : "0" + (date.getMonth() + 1)));
			dateString = dateString.replace(/%M/g, date.getMonth() + 1);
			dateString = dateString.replace(/dddd/g, thisCalendarObject.dayNames[date.getDay()]);
			dateString = dateString.replace(/ddd/g, thisCalendarObject.abbreviatedDayNames[date.getDay()]);
			dateString = dateString.replace(/dd/g, (date.getDate()> 9 ? date.getDate() : "0" + date.getDate()));
			dateString = dateString.replace(/%d/g, date.getDate());
			return dateString;
		}
		else
			return "";
	}

	function previousMonth() {
		thisCalendarObject.showDate.addMonths(-1);
		thisCalendarObject.show();
	}

	function nextMonth() {
		thisCalendarObject.showDate.addMonths(1);
		thisCalendarObject.show();
	}

	function previousYear() {
		thisCalendarObject.showDate.addYears(-1);
		thisCalendarObject.show();
	}

	function nextYear() {
		thisCalendarObject.showDate.addYears(1);
		thisCalendarObject.show();
	}

	function show(e) {
		//do validation here
		if (thisCalendarObject.showDate == null || thisCalendarObject.showDate == "")
			thisCalendarObject.showDate = new DateTime();
		else
			thisCalendarObject.showDate = new DateTime(thisCalendarObject.showDate.toString());
		if (thisCalendarObject.selectedDate == null || thisCalendarObject.selectedDate == "")
			thisCalendarObject.selectedDate = new DateTime();
		else
			thisCalendarObject.selectedDate = new DateTime(thisCalendarObject.selectedDate);
		if (!isNaN(Date.parse(thisCalendarObject.selectableDateRange["beginDate"])) && !isNaN(Date.parse(thisCalendarObject.selectableDateRange["endDate"]))) {
			if (new DateTime(thisCalendarObject.selectableDateRange["beginDate"]).compare("day", thisCalendarObject.selectableDateRange["endDate"]) == 1 ) {
				var tempDate = thisCalendarObject.selectableDateRange["beginDate"];
				thisCalendarObject.selectableDateRange["beginDate"] = thisCalendarObject.selectableDateRange["endDate"];
				thisCalendarObject.selectableDateRange["endDate"] = tempDate;
			}
		}
		thisCalendarObject.firstDayOfWeek = thisCalendarObject.firstDayOfWeek % 7;
		//validation ends
		var calendar = "";
		var x, y;
		if (window.event) {
			x = parseInt(window.event.clientX) + parseInt(thisCalendarObject.offsetX) + parseInt(document.documentElement.scrollLeft) + parseInt(document.body.scrollLeft);
			y = parseInt(window.event.clientY) + parseInt(thisCalendarObject.offsetY) + parseInt(document.documentElement.scrollTop) + parseInt(document.body.scrollTop);
		}
		else if (e) {
			x = parseInt(e.clientX) + parseInt(window.scrollX);
			y = parseInt(e.clientY) + parseInt(window.scrollY);
		}

		//for the first time, create div object
		if (document.getElementById(thisCalendarObject.objectName + "_div") == null) {
			var oDiv = document.createElement("div");
			oDiv.id = thisCalendarObject.objectName + "_div";
			if ((typeof(x) != "undefined" || typeof(y) != "undefined") && thisCalendarObject.dynamicPosition) {
				oDiv.style.position = "absolute";
			}
			if (thisCalendarObject.style.cssClass != null && thisCalendarObject.style.cssClass != "")
				oDiv.className = thisCalendarObject.style.cssClass;
			if (document.getElementById(thisCalendarObject.controlToDisplayCalendar) == null || thisCalendarObject.dynamicPosition){
				document.body.appendChild(oDiv);
			}
			else {
				document.getElementById(thisCalendarObject.controlToDisplayCalendar).appendChild(oDiv);
			}
		}

		if (typeof(x) != "undefined" && document.getElementById(thisCalendarObject.objectName + "_div") && thisCalendarObject.dynamicPosition) {
			document.getElementById(thisCalendarObject.objectName + "_div").style.position = "absolute";
			document.getElementById(thisCalendarObject.objectName + "_div").style.left = x + "px";
		}
		if (typeof(y) != "undefined" && document.getElementById(thisCalendarObject.objectName + "_div") && thisCalendarObject.dynamicPosition) {
			document.getElementById(thisCalendarObject.objectName + "_div").style.position = "absolute";
			document.getElementById(thisCalendarObject.objectName + "_div").style.top = y + "px";
		}

		//begin drawing calendar
		calendar += "<table align=\"center\" cellspacing=\"" + thisCalendarObject.style.cellSpacing + "\" cellpadding=\"" + thisCalendarObject.style.cellPadding + "\" bordercolor=\"" + thisCalendarObject.style.brdrColor + "\" border=\"" + thisCalendarObject.style.border + "\" " +  thisCalendarObject.style.getStyleString() + ">";
		// drawing header
		if (thisCalendarObject.visible["header"]) {
			
			calendar += "<tr><td align=\"center\" colSpan=\"7\" " + thisCalendarObject.getClass(thisCalendarObject.style.headerStyle.cssClass) + " " + thisCalendarObject.style.headerStyle.getStyleString() + "><table align=\"center\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\" style=\"width: 100%; height: 100%;\"><tr>";
			//var tempCol = 7;
			//alert(calendar);
			if (thisCalendarObject.visible["previousYear"]) {
				//tempCol--;
				calendar += "<td align=\"left\" valign=\"middle\" style=\"width:1px\"><a href=\"javascript:" + thisCalendarObject.objectName + ".previousYear();\"" + thisCalendarObject.getClass(thisCalendarObject.style.headerStyle["previousYear"].cssClass) + " " + thisCalendarObject.style.headerStyle["previousYear"].getStyleString() + " title=\"" + thisCalendarObject.toolTips["previousYear"] + "\">" + thisCalendarObject.text["previousYear"] + "</a></td>";
			}
			if (thisCalendarObject.visible["previousMonth"]) {
				//tempCol--;
				calendar += "<td align=\"left\" valign=\"middle\" style=\"width:1px\"><a href=\"javascript:" + thisCalendarObject.objectName + ".previousMonth();\"" + thisCalendarObject.getClass(thisCalendarObject.style.headerStyle["previousMonth"].cssClass) + " " + thisCalendarObject.style.headerStyle["previousMonth"].getStyleString() + " title=\"" + thisCalendarObject.toolTips["previousMonth"] + "\">" + thisCalendarObject.text["previousMonth"] + "</a></td>";
			}
			var header = "";
			switch (thisCalendarObject.format["header"]) {
				case "FullMonthYear":
				case "":
					header = thisCalendarObject.monthNames[thisCalendarObject.showDate.getMonth()] + " " + thisCalendarObject.showDate.getFullYear();
					break;
				case "ShortMonthYear":
					header = thisCalendarObject.abbreviatedMonthNames[thisCalendarObject.showDate.getMonth()] + " " + thisCalendarObject.showDate.getFullYear();
					break;
				case "FullMonth":
					header = thisCalendarObject.monthNames[thisCalendarObject.showDate.getMonth()];
					break;
				case "ShortMonth":
					header = thisCalendarObject.abbreviatedMonthNames[thisCalendarObject.showDate.getMonth()];
					break;
				case "Month":
					header = parseInt(thisCalendarObject.showDate.getMonth()) + 1;
					break;
				case "YearFullMonth":
					header = thisCalendarObject.showDate.getFullYear() + " " + thisCalendarObject.monthNames[thisCalendarObject.showDate.getMonth()];
					break;
				case "YearShortMonth":
					header = thisCalendarObject.showDate.getFullYear() + " " +  thisCalendarObject.abbreviatedMonthNames[thisCalendarObject.showDate.getMonth()];
					break;
				case "YearMonth":
					header =thisCalendarObject.showDate.getFullYear() + " " + (parseInt(thisCalendarObject.showDate.getMonth()) + 1);
					break;
				case "MonthYear":
					header = (parseInt(thisCalendarObject.showDate.getMonth()) + 1) + " " + thisCalendarObject.showDate.getFullYear();
				default:
					header = thisCalendarObject.formatDate(thisCalendarObject.showDate, thisCalendarObject.format["header"]);
					break;
			}
			calendar += "<td align=\"center\" valign=\"middle\">" + header + "</td>";
			if (thisCalendarObject.visible["nextMonth"]) {
				//tempCol--;
				calendar += "<td align=\"right\" valign=\"middle\" style=\"width:1px\"><a href=\"javascript:" + thisCalendarObject.objectName + ".nextMonth();\"" + thisCalendarObject.getClass(thisCalendarObject.style.headerStyle["nextMonth"].cssClass) + " " + thisCalendarObject.style.headerStyle["nextMonth"].getStyleString() + " title=\"" + thisCalendarObject.toolTips["nextMonth"] + "\">" + thisCalendarObject.text["nextMonth"] + "</a></td>";
			}
			if (thisCalendarObject.visible["nextYear"]) {
				//tempCol--;
				calendar += "<td align=\"right\" valign=\"middle\" style=\"width:1px\"><a href=\"javascript:" + thisCalendarObject.objectName + ".nextYear();\"" + thisCalendarObject.getClass(thisCalendarObject.style.headerStyle["nextYear"].cssClass) + " " + thisCalendarObject.style.headerStyle["nextYear"].getStyleString() + " title=\"" + thisCalendarObject.toolTips["nextYear"] + "\">" + thisCalendarObject.text["nextYear"] + "</a></td>";
			}
			calendar += "</tr></table></td></tr>";
		}
		// show header ends

		// show title
		if (thisCalendarObject.visible["title"]) {
			calendar += "<tr>";
			var temp = null;
			switch (thisCalendarObject.format["title"]) {
				case "FullDay":
					temp = thisCalendarObject.dayNames;
					break;
				case "Day":
					temp = thisCalendarObject.shortDayNames;
					break;
				default:
					temp = thisCalendarObject.abbreviatedDayNames;
					break;
			}
			for (var i = 0; i < temp.length; i++) {
				calendar += "<td align=\"center\" valign=\"middle\" " + thisCalendarObject.getClass(thisCalendarObject.style.titleStyle.cssClass) + " " + thisCalendarObject.style.titleStyle.getStyleString() + ">" + temp[(thisCalendarObject.firstDayOfWeek + i) % temp.length] + "</td>";
			}
			calendar += "</tr>";
		}
		var index = 0, firstDay = 0, firstDate = null, currentState = "CURRENTMONTH";
		firstDay = new DateTime(thisCalendarObject.showDate.getFullYear(), thisCalendarObject.showDate.getMonth(), 1).getDay() - thisCalendarObject.firstDayOfWeek;
		firstDate = new DateTime(thisCalendarObject.showDate.getFullYear(), thisCalendarObject.showDate.getMonth(), 1);

		if (firstDay < 0)
			firstDay += 7;
		
		var lastMonthDate = new DateTime(thisCalendarObject.showDate.toString());
		lastMonthDate.addMonths(-1);
		//has previous month
		if (firstDay != 0) {
			firstDay = lastMonthDate.getDaysInMonth() - firstDay;
			firstDate = new Date(lastMonthDate.getFullYear(), lastMonthDate.getMonth(), firstDay + 1);
			currentState = "PREVIOUSMONTH";
		}
		//alert(firstDate.toString());
		var currentDay = firstDay;
		calendar += "<tr>";
		while (currentState != "FINISHED") {
			var before = -1, after = -1; //check if the to-be-showed day is in the range
			if (thisCalendarObject.selectableDateRange["beginDate"] == null || thisCalendarObject.selectableDateRange["beginDate"] == "") {
				before = -1;
			}
			else {
				before = new DateTime(thisCalendarObject.selectableDateRange["beginDate"]).compare("day", firstDate);
			}
			if (thisCalendarObject.selectableDateRange["endDate"] == null || thisCalendarObject.selectableDateRange["endDate"] == "") {
				after = -1;
				
			}
			else {
				after = firstDate.compare("day", thisCalendarObject.selectableDateRange["endDate"]);
			}
			if (!(before != 1 && after != 1) && ((currentState == "PREVIOUSMONTH" && thisCalendarObject.visible["previousMonthDays"]) || (currentState == "NEXTMONTH" && thisCalendarObject.visible["nextMonthDays"]) || currentState == "CURRENTMONTH")) {
				//out of range
				if (thisCalendarObject.style.weekendStyle.enabled && firstDate.isWeekendDay()) {
					calendar += "<td width=\"14%\" " + thisCalendarObject.style.weekendStyle.invalidStyle.getAlign() + thisCalendarObject.style.weekendStyle.invalidStyle.getValign() + " id=\"" + thisCalendarObject.objectName + "_" + thisCalendarObject.formatDate(firstDate, "YYYY_MM_dd") + "\" onmouseover=\"javascript:" + thisCalendarObject.objectName + ".hoverDay(this);\" onmouseout=\"javascript:" + thisCalendarObject.objectName + ".normalizeDay(this);\" title=\"" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.toolTips["invalidDate"]) + "\"" + thisCalendarObject.getClass(thisCalendarObject.style.weekendStyle.invalidStyle.cssClass) + " " + thisCalendarObject.style.weekendStyle.invalidDayStyle.getStyleString() + ">" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.format["calendarBody"]) + "</td>";
				}
				else {
					calendar += "<td width=\"14%\" " + thisCalendarObject.style.invalidDayStyle.getAlign() + thisCalendarObject.style.invalidDayStyle.getValign() + " id=\"" + thisCalendarObject.objectName + "_" + thisCalendarObject.formatDate(firstDate, "YYYY_MM_dd") + "\" onmouseover=\"javascript:" + thisCalendarObject.objectName + ".hoverDay(this);\" onmouseout=\"javascript:" + thisCalendarObject.objectName + ".normalizeDay(this);\" title=\"" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.toolTips["invalidDate"]) + "\"" + thisCalendarObject.getClass(thisCalendarObject.style.invalidDayStyle.cssClass) + " " + thisCalendarObject.style.invalidDayStyle.getStyleString() + ">" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.format["calendarBody"]) + "</td>";
				}
			}
			else {
				if (firstDate.compare("day", new Date()) == 0 ) {
					if ((currentState == "PREVIOUSMONTH" && thisCalendarObject.visible["previousMonthDays"]) || (currentState == "NEXTMONTH" && thisCalendarObject.visible["nextMonthDays"]) || currentState == "CURRENTMONTH") {					
						if (thisCalendarObject.style.weekendStyle.enabled && firstDate.isWeekendDay()) {
							calendar += "<td " + thisCalendarObject.style.weekendStyle.todayStyle["normal"].getAlign() + thisCalendarObject.style.weekendStyle.todayStyle["normal"].getValign() + " id=\"" + thisCalendarObject.objectName + "_" + thisCalendarObject.formatDate(firstDate, "YYYY_MM_dd") + "\" onmouseover=\"javascript:" + thisCalendarObject.objectName + ".hoverToday(this);\" onmouseout=\"javascript:" + thisCalendarObject.objectName + ".normalizeToday(this);\" onclick=\"javascript:" + thisCalendarObject.objectName + ".selectDate('" + thisCalendarObject.formatDate(firstDate, "YYYY/MM/dd") + "');\"" + thisCalendarObject.getClass(thisCalendarObject.style.weekendStyle.todayStyle["normal"].cssClass) + " " + thisCalendarObject.style.weekendStyle.todayStyle["normal"].getStyleString() + " title=\"" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.toolTips["date"]) + "\">" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.format["calendarBody"]) + "</td>";
						}
						else {
							calendar += "<td " + thisCalendarObject.style.weekendStyle.todayStyle["normal"].getAlign() + thisCalendarObject.style.weekendStyle.todayStyle["normal"].getValign() + " id=\"" + thisCalendarObject.objectName + "_" + thisCalendarObject.formatDate(firstDate, "YYYY_MM_dd") + "\" onmouseover=\"javascript:" + thisCalendarObject.objectName + ".hoverToday(this);\" onmouseout=\"javascript:" + thisCalendarObject.objectName + ".normalizeToday(this);\" onclick=\"javascript:" + thisCalendarObject.objectName + ".selectDate('" + thisCalendarObject.formatDate(firstDate, "YYYY/MM/dd") + "');\"" + thisCalendarObject.getClass(thisCalendarObject.style.todayStyle["normal"].cssClass) + " " + thisCalendarObject.style.todayStyle["normal"].getStyleString() + " title=\"" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.toolTips["date"]) + "\">" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.format["calendarBody"]) + "</td>";
						}
					}
					else
						calendar += "<td>&nbsp;</td>";
				}
				else if (currentState == "PREVIOUSMONTH") {
					if (thisCalendarObject.visible["previousMonthDays"]) {
						if (thisCalendarObject.style.weekendStyle.enabled && firstDate.isWeekendDay()) {
							//alert("IsWeekend!" + firstDate);
							calendar += "<td width=\"14%\" " + thisCalendarObject.style.weekendStyle.previousMonthDayStyle["normal"].getAlign() + thisCalendarObject.style.weekendStyle.previousMonthDayStyle["normal"].getValign() + " id=\"" + thisCalendarObject.objectName + "_" + thisCalendarObject.formatDate(firstDate, "YYYY_MM_dd") + "\" onmouseover=\"javascript:" + thisCalendarObject.objectName + ".hoverPreviousMonthDay(this);\" onmouseout=\"javascript:" + thisCalendarObject.objectName + ".normalizePreivousMonthDay(this);\" onclick=\"javascript:" + thisCalendarObject.objectName + ".selectDate('" + thisCalendarObject.formatDate(firstDate, "YYYY/MM/dd") + "');\"" + thisCalendarObject.getClass(thisCalendarObject.style.weekendStyle.previousMonthDayStyle["normal"].cssClass) + " " + thisCalendarObject.style.weekendStyle.previousMonthDayStyle["normal"].getStyleString() + " title=\"" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.toolTips["date"]) + "\">" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.format["calendarBody"]) + "</td>";
						}
						else {
							calendar += "<td width=\"14%\" " + thisCalendarObject.style.previousMonthDayStyle["normal"].getAlign() + thisCalendarObject.style.previousMonthDayStyle["normal"].getValign() + " id=\"" + thisCalendarObject.objectName + "_" + thisCalendarObject.formatDate(firstDate, "YYYY_MM_dd") + "\" onmouseover=\"javascript:" + thisCalendarObject.objectName + ".hoverPreviousMonthDay(this);\" onmouseout=\"javascript:" + thisCalendarObject.objectName + ".normalizePreivousMonthDay(this);\" onclick=\"javascript:" + thisCalendarObject.objectName + ".selectDate('" + thisCalendarObject.formatDate(firstDate, "YYYY/MM/dd") + "');\"" + thisCalendarObject.getClass(thisCalendarObject.style.previousMonthDayStyle["normal"].cssClass) + " " + thisCalendarObject.style.previousMonthDayStyle["normal"].getStyleString() + " title=\"" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.toolTips["date"]) + "\">" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.format["calendarBody"]) + "</td>";
						}
					}
					else {
						if (thisCalendarObject.style.weekendStyle.enabled && firstDate.isWeekendDay()) {
							//alert("IsWeekend!" + firstDate);
							calendar += "<td width=\"14%\"" + thisCalendarObject.getClass(thisCalendarObject.style.weekendStyle.previousMonthDayStyle["normal"].cssClass) + " " + thisCalendarObject.style.weekendStyle.previousMonthDayStyle["normal"].getStyleString() + ">&nbsp;</td>";
						}
						else {
							calendar += "<td width=\"14%\"" + thisCalendarObject.getClass(thisCalendarObject.style.previousMonthDayStyle["normal"].cssClass) + " " + thisCalendarObject.style.previousMonthDayStyle["normal"].getStyleString() + ">&nbsp;</td>";
						}
					}
				}
				else if (currentState == "CURRENTMONTH") {
					if (thisCalendarObject.style.weekendStyle.enabled && firstDate.isWeekendDay()) {
						calendar += "<td " + thisCalendarObject.style.weekendStyle.dayStyle["normal"].getAlign() + thisCalendarObject.style.weekendStyle.dayStyle["normal"].getValign() + " id=\"" + thisCalendarObject.objectName + "_" + thisCalendarObject.formatDate(firstDate, "YYYY_MM_dd") + "\" onmouseover=\"javascript:" + thisCalendarObject.objectName + ".hoverDay(this);\" onmouseout=\"javascript:" + thisCalendarObject.objectName + ".normalizeDay(this);\" onclick=\"javascript:" + thisCalendarObject.objectName + ".selectDate('" + thisCalendarObject.formatDate(firstDate, "YYYY/MM/dd") + "');\"" +  thisCalendarObject.getClass(thisCalendarObject.style.weekendStyle.dayStyle["normal"].cssClass) + " " + thisCalendarObject.style.weekendStyle.dayStyle["normal"].getStyleString() + " title=\"" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.toolTips["date"]) + "\">" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.format["calendarBody"]) + "</td>";
					}
					else {
						calendar += "<td " + thisCalendarObject.style.dayStyle["normal"].getAlign() + thisCalendarObject.style.dayStyle["normal"].getValign() + " id=\"" + thisCalendarObject.objectName + "_" + thisCalendarObject.formatDate(firstDate, "YYYY_MM_dd") + "\" onmouseover=\"javascript:" + thisCalendarObject.objectName + ".hoverDay(this);\" onmouseout=\"javascript:" + thisCalendarObject.objectName + ".normalizeDay(this);\" onclick=\"javascript:" + thisCalendarObject.objectName + ".selectDate('" + thisCalendarObject.formatDate(firstDate, "YYYY/MM/dd") + "');\"" +  thisCalendarObject.getClass(thisCalendarObject.style.dayStyle["normal"].cssClass) + " " + thisCalendarObject.style.dayStyle["normal"].getStyleString() + " title=\"" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.toolTips["date"]) + "\">" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.format["calendarBody"]) + "</td>";
					}
				}
				else {
					if (thisCalendarObject.visible["nextMonthDays"]) {
						if (thisCalendarObject.style.weekendStyle.enabled && firstDate.isWeekendDay()) {
							//alert("IsWeekend!" + firstDate);
							calendar += "<td width=\"14%\" " + thisCalendarObject.style.weekendStyle.dayStyle["normal"].getAlign() + thisCalendarObject.style.weekendStyle.dayStyle["normal"].getValign() + " id=\"" + thisCalendarObject.objectName + "_" + thisCalendarObject.formatDate(firstDate, "YYYY_MM_dd") + "\" onmouseover=\"javascript:" + thisCalendarObject.objectName + ".hoverNextMonthDay(this);\" onmouseout=\"javascript:" + thisCalendarObject.objectName + ".normalizeNextMonthDay(this);\" onclick=\"javascript:" + thisCalendarObject.objectName + ".selectDate('" + thisCalendarObject.formatDate(firstDate, "YYYY/MM/dd") + "');\"" +  thisCalendarObject.getClass(thisCalendarObject.style.weekendStyle.nextMonthDayStyle["normal"].cssClass) + " " +  thisCalendarObject.style.weekendStyle.nextMonthDayStyle["normal"].getStyleString() + " title=\"" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.toolTips["date"]) + "\">" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.format["calendarBody"]) + "</td>";
						}
						else {
							calendar += "<td width=\"14%\" " + thisCalendarObject.style.nextMonthDayStyle["normal"].getAlign() + thisCalendarObject.style.nextMonthDayStyle["normal"].getValign() + " id=\"" + thisCalendarObject.objectName + "_" + thisCalendarObject.formatDate(firstDate, "YYYY_MM_dd") + "\" onmouseover=\"javascript:" + thisCalendarObject.objectName + ".hoverNextMonthDay(this);\" onmouseout=\"javascript:" + thisCalendarObject.objectName + ".normalizeNextMonthDay(this);\" onclick=\"javascript:" + thisCalendarObject.objectName + ".selectDate('" + thisCalendarObject.formatDate(firstDate, "YYYY/MM/dd") + "');\"" +  thisCalendarObject.getClass(thisCalendarObject.style.nextMonthDayStyle["normal"].cssClass) + " " +  thisCalendarObject.style.nextMonthDayStyle["normal"].getStyleString() + " title=\"" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.toolTips["date"]) + "\">" + thisCalendarObject.formatDate(firstDate, thisCalendarObject.format["calendarBody"]) + "</td>";
						}
					}
					else {
						if (thisCalendarObject.style.weekendStyle.enabled && firstDate.isWeekendDay()) {
							//alert("IsWeekend!" + firstDate);
							calendar += "<td width=\"14%\"" + thisCalendarObject.getClass(thisCalendarObject.style.weekendStyle.nextMonthDayStyle["normal"].cssClass) + " " + thisCalendarObject.style.weekendStyle.nextMonthDayStyle["normal"].getStyleString() + ">&nbsp;</td>";
						}
						else {
							calendar += "<td width=\"14%\"" + thisCalendarObject.getClass(thisCalendarObject.style.nextMonthDayStyle["normal"].cssClass) + " " + thisCalendarObject.style.nextMonthDayStyle["normal"].getStyleString() + ">&nbsp;</td>";
						}
					}
				}
			}
			firstDate.addDays(1);

			currentDay++;
			index++;
			
			//change state
			if (currentState == "PREVIOUSMONTH" && currentDay >= lastMonthDate.getDaysInMonth()) {
				currentState = "CURRENTMONTH";
				currentDay = 0;
			}
			if (currentState == "CURRENTMONTH" && currentDay >= new Date(thisCalendarObject.showDate).getDaysInMonth()) {
				currentState = "NEXTMONTH";
				currentDay = 0;
			}
			
			if (index % 7 == 0) {
				calendar += "</tr><tr>";
				if (currentState == "NEXTMONTH")
				currentState = "FINISHED";
			}
		}
		calendar += "</tr>";
		calendar = calendar.replace("<tr></tr>", ""); //clear the last formed tempty <tr></tr>
		//alert(calendar);

		if (thisCalendarObject.visible["footer"]) {
			calendar += "<tr><td colSpan=\"7\" id=\"" + thisCalendarObject.objectName + "_footer\">";
			var footer = "<table align=\"center\" cellspacing=\"" + thisCalendarObject.style.footerStyle.cellSpacing + "\" cellpadding=\"" + thisCalendarObject.style.footerStyle.cellPadding + "\" border=\"" + thisCalendarObject.style.footerStyle.border + "\" bordercolor=\"" + thisCalendarObject.style.footerStyle.brdrColor + "\"" + thisCalendarObject.getClass(thisCalendarObject.style.footerStyle.cssClass) + thisCalendarObject.style.footerStyle.getStyleString() + "><tr><td width=\"50%\" align=\"left\" vAlign=\"middle\"><a href=\"javascript:" + thisCalendarObject.objectName + ".setToVisible('" + thisCalendarObject.formatDate(thisCalendarObject.selectedDate, "YYYY/MM/dd") + "');\"" + thisCalendarObject.getClass(thisCalendarObject.style.footerStyle["selected"].cssClass) + ">" + thisCalendarObject.formatDate(thisCalendarObject.selectedDate, thisCalendarObject.format.footer["selected"]) + "</a></td><td width=\"50%\" align=\"right\" vAlign=\"middle\"><a href=\"javascript:" + thisCalendarObject.objectName + ".selectToday(); " + thisCalendarObject.objectName + ".setToVisible('" + thisCalendarObject.formatDate(new Date(), "YYYY/MM/dd") + "');\"" + thisCalendarObject.getClass(thisCalendarObject.style.footerStyle["today"].cssClass) + " " + thisCalendarObject.style.footerStyle["today"].getStyleString() + " title=\"" + thisCalendarObject.toolTips["selectToday"] + "\">" + thisCalendarObject.formatDate(new Date(), thisCalendarObject.format.footer["today"]) + "</a></td></tr></table>";
			calendar += footer;
			calendar += "</td></tr>";
			//alert(footer);
		}

		//close
		if (thisCalendarObject.visible["close"]){
			calendar += "<tr><td colSpan=\"7\" align=\"center\" vAlign=\"middle\" " + thisCalendarObject.getClass(thisCalendarObject.style.closeStyle.cssClass) + " " + thisCalendarObject.style.closeStyle.getStyleString() + " onclick=\"javascript:" + thisCalendarObject.objectName + ".hide();\" " + (thisCalendarObject.getClass(thisCalendarObject.style.closeStyle.cssClass) != "" && thisCalendarObject.getClass(thisCalendarObject.style.closeStyle.hover.cssClass) != "" ? "onmouseover=\"javascript:this.className='" + thisCalendarObject.style.closeStyle.hover.cssClass + "';\" onmouseout=\"javascript:this.className='" + thisCalendarObject.style.closeStyle.cssClass + "';\"" : "") + " title=\"" + thisCalendarObject.toolTips["close"] + "\">" + thisCalendarObject.text["close"] + "</td></tr>";
		}

		calendar += "</table>";
		document.getElementById(thisCalendarObject.objectName + "_div").innerHTML = calendar;
		document.getElementById(thisCalendarObject.objectName + "_div").style.display = "block";
		thisCalendarObject.previousSelectedDate = thisCalendarObject.selectedDate;
		thisCalendarObject.selectDate(thisCalendarObject.selectedDate);
		//document.getElementById("htmlDoc").value = calendar;
	}

	thisCalendarObject.hide = function() {
		if (document.getElementById(thisCalendarObject.objectName + "_div") != null) {
			document.getElementById(thisCalendarObject.objectName + "_div").style.display = "none";
			//document.removeChild(document.getElementById(thisCalendarObject.objectName + "_div"));
		}
	}

	thisCalendarObject.getClass = function(cssClass) {
		if (cssClass == null || cssClass == "")
			return "";
		else
			return " class=\"" + cssClass + "\" ";
	}

	thisCalendarObject.setToVisible = function(date) {
		if (new Date(date).compare("month", thisCalendarObject.showDate) == 0)
			return;
		else {
			thisCalendarObject.showDate = new Date(date);
			thisCalendarObject.show();
		}
	}

	thisCalendarObject.selectToday = function () {
		thisCalendarObject.setToVisible(thisCalendarObject.formatDate(new Date(), "YYYY/MM/dd"));
		thisCalendarObject.selectDate(thisCalendarObject.formatDate(new Date(), "YYYY/MM/dd"));
	}
}

function Calendar() {
	var thisCalendar = this;
	thisCalendar.showDate = ""; 
	thisCalendar.selectedDate = ""; 
	thisCalendar.dateFormat = "YYYY/MM/dd"; 
	thisCalendar.controlToDisplayCalendar = ""; 
	thisCalendar.displayCalendarEvent = ""; 
	thisCalendar.controlToAcceptDate = "";
	thisCalendar.style = new Style();
	thisCalendar.initialize = initialize;
	thisCalendar.bind = bind;
	thisCalendar.initialize();

	function initialize() {
		if (thisCalendar.showDate == null || thisCalendar.showDate == "" || isNaN(Date.parse(thisCalendar.showDate)))
			thisCalendar.showDate = new Date();
		if (thisCalendar.selectedDate == null || thisCalendar.showDate == "" || isNaN(Date.parse(thisCalendar.selectedDate)))
			thisCalendar.selectedDate = new Date();
		if (thisCalendar.dateFormat == null || thisCalendar.dateFormat == "")
			thisCalendar.dateFormat = "YYYY/MM/dd";
		var name = "";
		var ch = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
		for (var i = 0; i < 16; i++) {
			var c = Math.round(Math.random() * 52);
			name += ch.charAt(c);
		}
		thisCalendar.objectName = "CalendarObject_" + name;

		eval("" + thisCalendar.objectName + " = new CalendarObject('" + thisCalendar.objectName + "', '" + thisCalendar.showDate.toString() + "', '" + thisCalendar.selectedDate.toString() + "', '" + thisCalendar.dateFormat + "');");

		//link all references to the new created calendar object;
		thisCalendar.style = eval(thisCalendar.objectName + ".style");
		thisCalendar.offsetX = 0;
		thisCalendar.offsetY = 0;
		thisCalendar.visible = eval(thisCalendar.objectName + ".visible");
		thisCalendar.firstDayOfWeek = eval(thisCalendar.objectName + ".firstDayOfWeek");
		thisCalendar.selectableDateRange = eval(thisCalendar.objectName + ".selectableDateRange");

		//this has something to do with localization
		thisCalendar.text = eval(thisCalendar.objectName + ".text");
		thisCalendar.toolTips = eval(thisCalendar.objectName + ".toolTips");
		thisCalendar.monthNames = eval(thisCalendar.objectName + ".monthNames");
		thisCalendar.abbreviatedMonthNames = eval(thisCalendar.objectName + ".abbreviatedMonthNames");
		thisCalendar.dayNames = eval(thisCalendar.objectName + ".dayNames");
		thisCalendar.abbreviatedDayNames = eval(thisCalendar.objectName + ".abbreviatedDayNames");
		thisCalendar.shortDayNames = eval(thisCalendar.objectName + ".shortDayNames");
		thisCalendar.format = eval(thisCalendar.objectName + ".format");
	}

	function bind() {
		//since there are not references, so we have to hook them separatedly
		if (document.getElementById(thisCalendar.controlToDisplayCalendar)) {
			eval(thisCalendar.objectName + ".monthNames = thisCalendar.monthNames");
			eval(thisCalendar.objectName + ".abbreviatedMonthNames = thisCalendar.abbreviatedMonthNames");
			eval(thisCalendar.objectName + ".dayNames = thisCalendar.dayNames");
			eval(thisCalendar.objectName + ".abbreviatedDayNames = thisCalendar.abbreviatedDayNames");
			eval(thisCalendar.objectName + ".shortDayNames = thisCalendar.shortDayNames");
			eval(thisCalendar.objectName + ".offsetX = thisCalendar.offsetX");
			eval(thisCalendar.objectName + ".offsetY = thisCalendar.offsetY");
			eval(thisCalendar.objectName + ".showDate = thisCalendar.showDate;");
			eval(thisCalendar.objectName + ".selectedDate = thisCalendar.selectedDate;");
			eval(thisCalendar.objectName + ".format = thisCalendar.format;");
			eval(thisCalendar.objectName + ".controlToAcceptDate = thisCalendar.controlToAcceptDate;");
			eval(thisCalendar.objectName + ".controlToDisplayCalendar = thisCalendar.controlToDisplayCalendar;");
			if (thisCalendar.displayCalendarEvent != null && thisCalendar.displayCalendarEvent != ""){
				eval("document.getElementById(\"" + thisCalendar.controlToDisplayCalendar + "\")." + thisCalendar.displayCalendarEvent + " = " + thisCalendar.objectName + ".show;");
			}
			else {
				eval(thisCalendar.objectName + ".dynamicPosition = false;");
				eval(thisCalendar.objectName + ".visible[\"close\"] = false;");
				eval("" + thisCalendar.objectName + ".show();");
			}
		}
	}
}
