function Calendar(id) {
	var objINPUT = null;
	var objCalendar = null;
	var currentDate= {year:null, month:null, day:null};
	var today = {year:null, month:null, day:null};

	var data = {
		week:['Sun','Mon','Tue','Wed','Thu','Fri','Sat'],
		month:['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
		format:'%2 %1', // %1:year, %2:month
		calendarId:'calendar'
	}

	var calendars = new Array();
	var currentCalendarBtnId = null;

	var gLanguageResources = new Array();
	gLanguageResources['ViewPrevMonth'] = 'View the previous month';
	gLanguageResources['ViewNextMonth'] = 'View the forward month';
	gLanguageResources['CloseLayer'] = 'Close Layer';

	var initialize = function () {
		today = getTodayDate();
		createCalendar(currentDate.year, currentDate.month);
	}

	this.setLanguageResources = function (data) {
		for (var key in data) {
			gLanguageResources[key] = data[key];
		}
	}

	this.bind = function (button, target) {
		var objButton = document.getElementById(button);
		objButton.onclick = function () { return toggleCalendar(this, target); }
		var objField = document.getElementById(target);
		objField.readonly = true;

		calendars[button] = target;
	}

	var toggleCalendar = function (obj, target) {
		if (document.getElementById(data.calendarId) && currentCalendarBtnId == obj.id) {
			objCalendar = document.getElementsByTagName('body')[0].removeChild(objCalendar);
			currentCalendarBtnId = null;
		} else {
			var objINPUT = document.getElementById(target);

			if (objINPUT.value != '')
				currentDate = parseDate(objINPUT.value);
			else
				currentDate = getTodayDate();

			printMonthTable(currentDate.year, currentDate.month);
			document.getElementsByTagName('body')[0].appendChild(objCalendar);
			currentCalendarBtnId = obj.id;

			relocate(obj);
		}

		return false;
	}

	var relocate = function (obj) {
		objCalendar.style.left = Object.getOffset(obj.id, true).left + 'px';
		objCalendar.style.top = (Object.getOffset(obj.id, true).top + Object.getOffset(obj.id, true).height + 3) + 'px';
	}

	var getTodayDate = function () {
		var data = {};
		var date = new Date();

		data.year = date.getFullYear();
		data.month = date.getMonth() + 1;
		data.day = date.getDate();

		return data;
	}

	var createCalendar = function (year, month) {
		objCalendar = Object.createHTMLElement('div', {id:data.calendarId});
		var objTemp = Object.createHTMLElement('div', {className:'inner'});
		objCalendar.appendChild(objTemp);
		objTemp.appendChild(Object.createHTMLElement('table'));

		var objButtons = Object.createHTMLElement('div', {className:'buttons'});
		var objPrevLink = Object.createHTMLElement('a', {href:'#', onclick:printPrevMonthTable, className:'button prevbtn'});
		objPrevLink.appendChild(document.createTextNode(gLanguageResources['ViewPrevMonth']));
		objButtons.appendChild(objPrevLink);
		var objNextLink = Object.createHTMLElement('a', {href:'#', onclick:printNextMonthTable, className:'button nextbtn'});
		objNextLink.appendChild(document.createTextNode(gLanguageResources['ViewNextMonth']));
		objButtons.appendChild(objNextLink);
		objTemp.appendChild(objButtons);

		var objCloseLink = Object.createHTMLElement('a', {href:'#', className:'button close'});
		objCloseLink.appendChild(document.createTextNode(gLanguageResources['CloseLayer']));
		objButtons.appendChild(objCloseLink);
		objTemp.appendChild(objButtons);
		objCloseLink.onclick = function () {
			objCalendar = document.getElementsByTagName('body')[0].removeChild(objCalendar);
			return false;
		}

		redrawCalendar(year, month);
	}

	var printPrevMonthTable = function () {
		var tempYear = currentDate.year;
		var tempMonth = currentDate.month - 1;
		if (tempMonth == 0) {
			tempMonth = 12;
			tempYear--;
		}
		return printMonthTable(tempYear, tempMonth);
	}

	var printNextMonthTable = function () {
		var tempYear = currentDate.year;
		var tempMonth = currentDate.month + 1;
		if (tempMonth == 12) {
			tempMonth = 1;
			tempYear++;
		}
		return printMonthTable(tempYear, tempMonth);
	}

	var printMonthTable = function (year, month) {
		if ((year >= 1800 && month >= 1) || (year <= 2101 && month <= 12)) {
			var date = new Date(year, month - 1);
			redrawCalendar(date.getFullYear(), date.getMonth() + 1);
		}

		return false;
	}

	var redrawCalendar = function (year, month) {
		var monthDay = new Array(31, 0, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);

		if (year % 400 == 0)
			monthDay[1] = 29;
		else if (year % 100 == 0)
			monthDay[1] = 28;
		else if (year % 4 == 0)
			monthDay[1] = 29;
		else
			monthDay[1] = 28;

		var date = new Date(year, month - 1, 1);
		var startWeekday = date.getDay();

		var objTABLE = Object.createHTMLElement('table', {className:'calendar'});
		var objCaption = Object.createHTMLElement('caption');
		var objCaptionP = Object.createHTMLElement('span');

		objCaptionP.appendChild(document.createTextNode(printf(data.format, year, data.month[month-1])));
		objTABLE.appendChild(objCaption);
		objCaption.appendChild(objCaptionP);

		var objTHEAD = Object.createHTMLElement('thead');
		var objTR = Object.createHTMLElement('tr');
		objTABLE.appendChild(objTHEAD);
		objTHEAD.appendChild(objTR);

		for (var i=0; i<data.week.length; i++) {
			var objTH = Object.createHTMLElement('th', {className:'item' + (i + 1)});
			objTH.appendChild(document.createTextNode(data.week[i]));
			objTR.appendChild(objTH);
		}

		var objTBODY = Object.createHTMLElement('tbody');
		objTABLE.appendChild(objTBODY);

		for (var i=0; i<monthDay[month - 1]; i++) {
			var index = startWeekday + i;
			var solarDate = {year:year, month:month, day:(i + 1)};

			if (i == 0) {
				var objTR = Object.createHTMLElement('tr');
				objTBODY.appendChild(objTR);

				for (var j=0; j<startWeekday; j++) {
					var objTD = Object.createHTMLElement('td', {className:'empty'});
					objTD.appendChild(document.createTextNode(' '));
					objTR.appendChild(objTD);
				}
			} else if (index % 7 == 0) {
				var objTR = Object.createHTMLElement('tr');
				objTBODY.appendChild(objTR);
			}

			var objTD = Object.createHTMLElement('td', {className:'item' + (index % 7 + 1)});
			var objA = Object.createHTMLElement('a', {href:'#', onclick:select});
			objA.appendChild(document.createTextNode(solarDate.day));
			objTD.appendChild(objA);
			objTR.appendChild(objTD);

			if (today.year == year && today.month == month && today.day == solarDate.day)
				objTD.className = 'today';
		}

		var num = (i + startWeekday) % 7;
		if (num > 0) {
			for (var j=num; j<7; j++) {
				var objTD = Object.createHTMLElement('td', {className:'empty'});
				objTD.appendChild(document.createTextNode(' '));
				objTR.appendChild(objTD);
			}
		}

		objCalendar.firstChild.replaceChild(objTABLE, objCalendar.firstChild.firstChild);

		currentDate.year = year;
		currentDate.month = month;
	}

	var select = function () {
		var date = currentDate.year + '-' + (currentDate.month >= 10 ? currentDate.month : '0' + currentDate.month) + '-' + (this.firstChild.nodeValue >= 10 ? this.firstChild.nodeValue : '0' + this.firstChild.nodeValue);

		var target = calendars[currentCalendarBtnId];
		document.getElementById(target).value = date;

		return false;
	}

	var parseDate = function (date) {
		var temp = date.split(/\-0?/);
		return {year:temp[0], month:parseInt(temp[1]), day:parseInt(temp[2])};
	}

	var printf = function () {
		var text = arguments[0];

		for (var i=1; i<arguments.length; i++) {
			var param = arguments[i];
			if (typeof(param) == 'number')
				param = (param >= 10) ? param : '0' + param;
			text = text.replace('%' + i, param);
		}

		return text;
	}

	initialize();
}