function Calendar(id,config) {
	if (typeof config == "undefined") {
		this.config = new Calendar.Config();
	} else {
		this.config = config;
	};

	this.id = id;
	this.parent = null;
	
	this.calendarDiv = null;
	this.iframeBkg = null;
	this.hideEvent = null;
	
	this.callBack = null;
	
	this.todayDate = new Date();
	this.todayDate.setHours(0);
	this.todayDate.setMinutes(0);
	this.todayDate.setSeconds(0);
	
	if (this.config.selectDate) {
		this.selectDate = this.config.selectDate;
	}else {
		this.selectDate = new Date();
	}
	
	this.selectDate.setHours(0);
	this.selectDate.setMinutes(0);
	this.selectDate.setSeconds(0);

	this.displayMonth = this.selectDate.getMonth();
	this.displayYear = this.selectDate.getFullYear();
	
	this.MonthDays = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
    this.init();
};

Calendar.isMSIE = (navigator.appName == "Microsoft Internet Explorer");
Calendar.isMSIE5 = Calendar.isMSIE && (navigator.userAgent.indexOf('MSIE 5') != -1);
Calendar.isMSIE5_0 = Calendar.isMSIE && (navigator.userAgent.indexOf('MSIE 5.0') != -1);
Calendar.isGecko = navigator.userAgent.indexOf('Gecko') != -1;
Calendar.isMAC = navigator.userAgent.indexOf("Mac") > -1;
Calendar.OneDay = 24 * 60 * 60 * 1000;

Calendar.Config = function () {
	this.version = '0.1';
	
	this.className = 'calendar';
	this.startDate = new Date();
	this.endDate = new Date();
	this.endDate.setMonth(this.endDate.getMonth() + 13);
	
	this.selectDate = new Date();

	this.width = 240;
	
	this.autoHide = false;
	
	//this.Closed = icalendarclose;
	if ((typeof(icalendarclose) != "undefined") && (icalendarclose != null))
	{
	this.Closed = icalendarclose;
	}
	else
	{
	this.Closed = 'Close';
	}
	
	this.displayPosition = 'auto';
	
	this.Caption = new Array('S','M','T','W','T','F','S');

	this.MonthNames = new Array('January','February','March','April','May','June','July','August','September','October','November','December');
	this.ShortMonthNames = new Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sept','Oct','Nov','Dec');
	
	this.isLanguageRightToLeft = false;
	
	this.iconPreviousMonth = "/images/calendar/button-l.gif";
	this.iconNextMonth = "/images/calendar/button-r.gif";
	this.iconSelectMonth = "/images/calendar/button-d.gif";
};

Calendar.prototype.init = function () {
	var obj = this;

	//Create Calendar Div
	this.calendarDiv = document.createElement("DIV");
	this.calendarDiv.id = this.id + '_div';
	this.calendarDiv.style.position = "absolute";
	this.calendarDiv.style.top = '0px';
	this.calendarDiv.style.left = '0px';
	
	if (obj.config.width) {
		this.calendarDiv.style.width = obj.config.width + "px";
	}else {
		this.calendarDiv.style.width = "auto";
	};
	this.calendarDiv.style.visibility = 'hidden';
	this.calendarDiv.style.zIndex = 5000;
	this.calendarDiv.className = this.config.className;
	this.calendarDiv.innerHTML = this.buildCalendar(this.displayMonth,this.displayYear);

	//Prepare DIV Event
	if (this.config.autoHide) {
		Calendar.addEvent(this.calendarDiv,"focus", function (event) {
					 return obj.OnFocus(Calendar.isMSIE ? window.event : event);
				 });
		Calendar.addEvent(this.calendarDiv,"blur", function (event) {
					 return obj.OnBlur(Calendar.isMSIE ? window.event : event);
				 });
	}
	
	document.body.appendChild(this.calendarDiv);

	//Initail IFrame to Fix Overlap with select
	this.iframeBkg = document.createElement("IFRAME");
	this.iframeBkg.id = this.id + '_frame';
	this.iframeBkg.src = 'javascript:false';
	this.iframeBkg.style.position = "absolute";
	this.iframeBkg.style.top = '0px';
	this.iframeBkg.style.left = '0px';
	this.iframeBkg.style.border = 0;

	if (obj.config.width) {
		this.iframeBkg.style.width = obj.config.width + "px";
	}else {
		this.iframeBkg.style.width = this.txt.offsetWidth + "px";
	};

	this.iframeBkg.style.display = 'none';

	document.body.appendChild(this.iframeBkg);
	
	Calendar.addEvent(window,"resize", function (event) {
				 return obj.OnResize(Calendar.isMSIE ? window.event : event);
			 });
}

Calendar.prototype.OnFocus = function (e) {
	var obj = this;
	
	clearTimeout(obj.hideEvent);
};

Calendar.prototype.OnBlur = function (e) {
	var obj = this;

	obj.hideEvent = setTimeout("Calendar.hide('" + obj.id + "');",500);
};

Calendar.prototype.OnResize = function (e){
    if (this.calendarDiv.style.visibility != 'hidden')
	    this.setPosition();
};

Calendar.previousMonth = function(objCal) {
	objCal.displayMonth--;
	if (objCal.displayMonth < 0) {
		objCal.displayMonth = 11;
		objCal.displayYear--;
	}
	
	objCal.calendarDiv.innerHTML = objCal.buildCalendar();
	objCal.iframeBkg.style.height = objCal.calendarDiv.style.height;
};

Calendar.nextMonth = function(objCal) {
	objCal.displayMonth++;
	if (objCal.displayMonth > 11) {
		objCal.displayMonth = 0;
		objCal.displayYear++;
	}
	
	objCal.calendarDiv.innerHTML = objCal.buildCalendar();
	objCal.iframeBkg.height = objCal.calendarDiv.offsetHeight;
};

Calendar.pickedDate = function (source,objCal,iDay,iMonth,iYear) {
	objCal.selectDate = new Date(iYear,iMonth,iDay);
	
	//alert(source.parentNode.parentNode.parentNode.childNodes.length);
	
	if (source.parentNode.parentNode.parentNode.tagName == 'TBODY') {
	    for (var i = 0;i < source.parentNode.parentNode.parentNode.childNodes.length;i++) {
	        for (var j = 0;j < source.parentNode.parentNode.parentNode.childNodes[i].childNodes.length;j++ ) {
	            if (source.parentNode.parentNode.parentNode.childNodes[i].childNodes[j].className == 'select')
	                source.parentNode.parentNode.parentNode.childNodes[i].childNodes[j].className = '';
	        }
	    }
	}
	
	source.parentNode.className = 'select';
	
	if (objCal.config.callBack) {
		objCal.config.callBack(iDay,iMonth,iYear,objCal);
	}
	
	if (objCal.config.autoHide)
    	Calendar.hide(objCal.id);
};

Calendar.prototype.buildCalendar = function() {
	var strCalendar = '';
	var i,j;
	var monthStart = new Date(this.displayYear,this.displayMonth,1);
	var monthEnd = new Date(this.displayYear,this.displayMonth,this.MonthDays[this.displayMonth]);
	var currentDate;
	var numDays;
	var prevMonth,nextMonth;
	
	var FirstDate = new Date(this.displayYear, this.displayMonth, 1);

	var Rows = 6;
	//if (((this.MonthDays[this.displayMonth] == 31) && (FirstDate.getDay() > 4)) || ((this.MonthDays[this.displayMonth] == 30) && (FirstDate.getDay() == 6))) Rows = 6;
	//else if ((this.MonthDays[this.selectDate.getMonth()] == 28) && (FirstDate.getDay() == 0)) Rows = 4;

	strCalendar += '<table width="100%" cellpadding="0" cellspacing="0" border="0"';
	if (this.config.autoHide) {
		strCalendar += ' onmouseover="Calendar.cancelHide(\'' + this.id + '\');" onmouseout="Calendar.setAutoHide(\'' + this.id + '\');"';
	}
	
	prevMonth = (this.displayMonth - 1) >= 0?this.displayMonth - 1:11;
	nextMonth = (this.displayMonth + 1)%12;
	
	strCalendar += '>';
	strCalendar += '<tr><th colspan="2" align="left">';
	
	if (this.config.startDate) {
		if ((this.config.startDate - monthStart) < 0) {
			strCalendar += '<a href="#" onclick="Calendar.previousMonth(eval(' + this.id + '));return false;"><img src="' + this.config.iconPreviousMonth + '" border="0" /></a></th>';
		}else {
			strCalendar += '&nbsp;';
		}
	}else {
		strCalendar += '<a href="#" onclick="Calendar.previousMonth(eval(' + this.id + '));return false;"><img src="' + this.config.iconPreviousMonth + '" border="0" /></a></th>';
	}
	if (this.config.isLanguageRightToLeft)
	    strCalendar += '<th colspan="5">' + this.displayYear + '&nbsp;' + this.config.MonthNames[this.displayMonth] + '<a href="#" onclick="(eval(' + this.id + ')).buildMonthSelection();return false;"><img src="' + this.config.iconSelectMonth + '" border="0" /></a></th><th colspan="2" align="right">';
	else
	    strCalendar += '<th colspan="5">' + this.config.MonthNames[this.displayMonth] + '&nbsp;' + this.displayYear + '<a href="#" onclick="(eval(' + this.id + ')).buildMonthSelection();return false;"><img src="' + this.config.iconSelectMonth + '" border="0" /></a></th><th colspan="2" align="right">';

	if (this.config.endDate) {
		if ((monthEnd - this.config.endDate) < 0) {
			strCalendar += '<a href="#" onclick="Calendar.nextMonth(eval(' + this.id + '));return false;"><img src="' + this.config.iconNextMonth + '" border="0"/></a>';
		}else {
			strCalendar += '&nbsp;';
		}
	}else {
		strCalendar += '<a href="#" onclick="Calendar.nextMonth(eval(' + this.id + '));return false;"><img src="' + this.config.iconNextMonth + '" border="0"/></a>';
	}

	strCalendar += '</th></tr>';
	
	//Generate Calendar Header
	strCalendar += '<tr><td></td>';
	for (i = 0;i < 7;i++) {
		strCalendar += '<td>' + this.config.Caption[i] + '</td>';
	}
	strCalendar += '<td></td></tr>';
	
	//Generate Calendar Body
   numDays = this.MonthDays[this.displayMonth];
   
   //Check LeapYear
   if ((this.displayMonth == 1) && (new Date(this.displayYear,1, 29).getDate() == 29)) numDays++;   
   for (j=0;j<Rows;j++) {
      strCalendar += '<tr><td></td>';
      for (i=1;i<=7;i++) {
         var Day = (j * 7) + (i - FirstDate.getDay());
         if ((Day >= 1) && (Day <= numDays)) {
			currentDate = new Date(this.displayYear,this.displayMonth,Day,0,0,0);
			
		 	if (Math.round((currentDate - this.selectDate)/Calendar.OneDay) == 0) {
	            strCalendar += '<td class="select">';
			}else if (Math.round((currentDate - this.todayDate)/Calendar.OneDay) == 0){
	            strCalendar += '<td class="today">';
			}else {
				strCalendar += '<td>';
			}
			
			if ((currentDate - this.config.startDate >= 0) && (this.config.endDate - currentDate >= 0)) {
				strCalendar += '<a href="#" onclick="Calendar.pickedDate(this,eval(\'' + this.id + '\'),\'' + currentDate.getDate() + '\',\'' + currentDate.getMonth() + '\',\'' + currentDate.getFullYear() + '\');return false;" onmouseover="Calendar.highlightDate(this, true);"  onmouseout="Calendar.highlightDate(this, false);">' + Day + '</a>';
			}else {
				strCalendar +=  Day;
			}
			
			strCalendar += '&nbsp;</td>';
         }
         else strCalendar += '<td>&nbsp;</td>';
      }
      strCalendar += '<td></td></tr>';
   }
	strCalendar += '<tr><td></td><td class="Line">.</td><td class="Line">.</td><td class="Line">.</td><td class="Line">.</td><td class="Line">.</td><td class="Line">.</td><td class="Line">.</td><td></td></tr>';
	strCalendar += '<tr><td colspan="9" class="close"><a href="#" onclick="Calendar.hide(\'' + this.id + '\');return false;">'+this.config.Closed +'</a></td></tr>';
	strCalendar += '</table>';
	
	return strCalendar;
} 

Calendar.setAutoHide = function(id) {
	var obj = eval(id);
	obj.hideEvent = setTimeout("Calendar.hide('" + id + "');",100);
}

Calendar.cancelHide = function(id) {
	clearTimeout(eval(id + '.hideEvent'));
};

Calendar.hide = function(id) {
	// Don't hide if month selection is open
	if (document.getElementById(id + '_months_div') && (document.getElementById(id + '_months_div').style.visibility != 'hidden')) return;
	
	document.getElementById(id + '_div').style.visibility = 'hidden';
	document.getElementById(id + '_frame').style.display = 'none';
};

Calendar.prototype.display = function (obj) {
	if (obj) {
		this.parent = obj;
	}	

	this.calendarDiv.innerHTML = this.buildCalendar();
	
	this.iframeBkg.height = this.calendarDiv.offsetHeight;
	
	this.setPosition();

	this.calendarDiv.style.visibility = 'visible';
	if (Calendar.isMSIE && !Calendar.isMAC) this.iframeBkg.style.display = 'block';
};

Calendar.prototype.setPosition = function () {
	var xPos,yPos;
	
	xPos = this.findPosX();
	yPos = this.findPosY();
	
	if (this.config.displayPosition == 'auto') {
	    this.calendarDiv.style.top = yPos + this.parent.offsetHeight + 'px';
	    this.iframeBkg.style.top = yPos + this.parent.offsetHeight + 'px';

	    if ((xPos + this.calendarDiv.offsetWidth) > document.body.clientWidth) {
		    xPos = document.body.clientWidth - this.calendarDiv.offsetWidth - (Calendar.isMSIE?20:5);
	    };

	    this.calendarDiv.style.left = xPos + 'px';
	    this.iframeBkg.style.left = xPos + 'px';
	}else if (this.config.displayPosition == 'right') {
	    this.calendarDiv.style.top = yPos + 'px';
	    this.iframeBkg.style.top = yPos + 'px';

	    this.calendarDiv.style.left = xPos + this.parent.offsetWidth + 'px';
	    this.iframeBkg.style.left = xPos + this.parent.offsetWidth + 'px';
	}
};

Calendar.prototype.findPosX = function () {
	var obj = this.parent;

    var curleft = 0;
    if (obj.offsetParent) {
        while (obj.offsetParent) {
            curleft += obj.offsetLeft;
            obj = obj.offsetParent;
        };
    } else if (obj.x) {
        curleft += obj.x;
    };
    return curleft;
};

Calendar.prototype.findPosY = function () {
	var obj = this.parent;

    var curtop = 0;
    if (obj.offsetParent) {
        while (obj.offsetParent) {
            curtop += obj.offsetTop;
            obj = obj.offsetParent;
        };
    } else if (obj.y) {
        curtop += obj.y;
    };
    return curtop;
};

Calendar.addEvent = function (obj, name, handler) {
	// Browser check
	if (Calendar.isMSIE)
		if (!Calendar.isMAC) {
			obj.attachEvent("on" + name, handler);
		} else {
			switch (name) {
				case 'load':obj.onload = handler;break;
				case 'focus':obj.onfocus = handler;break;
				case 'blur':obj.onblur = handler;break;
				case 'resize':obj.onresize = handler;break;
			}
		}
	else
		obj.addEventListener(name, handler, false);
};

Calendar.prototype.buildMonthSelection = function() {	
	var MAX_MONTH = 14;	
	var NO_PER_COL = Math.round(MAX_MONTH / 2);
	
	var monthDivName = this.id + "_months_div";
	var monthDiv = document.getElementById(monthDivName);
	
	if (!monthDiv) {
		// Create month list
		var curDate = new Date();		
		var strHTML = "<ul class=\"left\">";
		var strTemplate = "<li><a href=\"#\" onclick=\"(eval('" +this.id + "')).Go2({y}, {m});return false;\">{0}</a></li>";
		
		// Left column
		for(i = 1; i <= NO_PER_COL; i++) {
			strHTML += strTemplate.replace("{0}", this.config.ShortMonthNames[curDate.getMonth()] + " " + curDate.getFullYear()).replace("{m}", curDate.getMonth()).replace("{y}", curDate.getFullYear());			
			curDate.setMonth(curDate.getMonth() + 1);
		}
		strHTML += "</ul><ul class=\"right\">";
		// Right column
		for(i = 1; i <= NO_PER_COL; i++) {
			if ((i * 2) <= MAX_MONTH) {
				strHTML += strTemplate.replace("{0}", this.config.ShortMonthNames[curDate.getMonth()] + " " + curDate.getFullYear()).replace("{m}", curDate.getMonth()).replace("{y}", curDate.getFullYear());
			} else {
				strHTML += "<li>&nbsp;</li>"
			}
			curDate.setMonth(curDate.getMonth() + 1);
		}
		strHTML += "</ul>";
		// Buttom line + Closed
		strHTML += "<div class=\"clear\"></div><ul class=\"Line\"><li><a href=\"#\" onclick=\"document.getElementById('" + monthDivName +  "').style.visibility='hidden';return false;\">" + this.config.Closed + "</a></li></ul>";
						
		// Create container
		var rowHeight = (this.calendarDiv.firstChild.firstChild.rows[0].offsetHeight  > 0)  ? this.calendarDiv.firstChild.firstChild.rows[0].offsetHeight : 30;
		monthDiv = document.createElement("div");
		monthDiv.style.position = "absolute";
		monthDiv.style.width = this.calendarDiv.firstChild.clientWidth + "px";		
		monthDiv.style.height = (this.calendarDiv.firstChild.clientHeight -  rowHeight) + "px";		
		monthDiv.id = monthDivName;
		monthDiv.innerHTML = strHTML;		

		// Set position					
		monthDiv.style.top =  rowHeight + "px";								
		monthDiv.style.left =  "0px";								
		this.calendarDiv.appendChild(monthDiv);		
	}

	monthDiv.style.visibility = "inherit";
}

Calendar.prototype.Go2 = function(pYear, pMonth) {
	this.displayMonth = pMonth;
	this.displayYear = pYear;
	
	this.calendarDiv.innerHTML = this.buildCalendar();
	this.iframeBkg.height = this.calendarDiv.offsetHeight;
};

Calendar.highlightDate = function(obj, flag) {
	if (obj.parentNode.className == "select") return;
	obj.parentNode.className = (flag) ? "over" : "";
}