/**
 * calndar v1.1: dhtml calentar
 *
 * developed by Vlad Gurdiga - gurdiga@gmail.com
 * 
 */
 
var WEEK_LATIN = true; /* week begins on Monday */

var calendar = new Calendar(), body, thisDocument, shield,
	FORCE_VISIBLE = 1,
	NOT_FORCE_VISIBLE = 2;
var mousedowns = new Object(); //object to hold mousedown states for next/prev controls

Date.prototype.getMonthLength = function() {
	switch (this.getMonth()) {
	case 0: case 2: case 4: case 6: case 7: case 9: case 11: return 31;
	case 1: return ((this.getFullYear() % 4) ? 28 : 29);
	case 3: case 5: case 8: case 10: return 30;
	}
}


Date.prototype.getLatinDay = function() {
	return (WEEK_LATIN ? (this.getDay() == 0 ? 6 : this.getDay() - 1) : this.getDay())
}
	


function Calendar() {
	this.date = new Date();
	this.date0;
	this.id = 'calendar' + this.date.getTime();
	this.table;
	this.shield;
	this.element;
	this.event;
	this.visible = false;

	this.create = function() {
		this.table = thisDocument.createElement('table')
		this.table.style.top = (getAbsoluteY(this.element) + this.element.offsetHeight) + 'px';
		this.table.style.left = getAbsoluteX(this.element) + 'px';
		this.table.appendChild(thisDocument.createElement('tbody'));
		this.table.id = this.id;
		this.table.className = 'calendar';
		this.table.cellSpacing = 0;
		this.table.cellPadding = 0;
		

		tr = thisDocument.createElement('tr');
		td = this.createTd(String.fromCharCode(171), 'scroller');
		attachEventHandler(td, 'mousedown', this.goPreviousYear);
		attachEventHandler(td, 'mousemove', this.cancelSelection);
		attachEventHandler(td, 'mouseup', this.clearPreviousYearTimer);
		attachEventHandler(td, 'mouseout', this.clearPreviousYearTimer);
		attachEventHandler(td, 'click', stopPropagation);
		
		tr.appendChild(td);
		td = this.createTd(this.date.getFullYear(), 'year', 5)
		td.id = 'calendarSelectedYearTd';
		tr.appendChild(td);
		td = this.createTd(String.fromCharCode(187), 'scroller');
		attachEventHandler(td, 'mousedown', this.goNextYear);
		attachEventHandler(td, 'mousemove', this.cancelSelection);
		attachEventHandler(td, 'mouseup', this.clearNextYearTimer);
		attachEventHandler(td, 'mouseout', this.clearNextYearTimer);
		attachEventHandler(td, 'click', stopPropagation);
		tr.appendChild(td);
		this.table.tBodies[0].appendChild(tr);

		tr = thisDocument.createElement('tr');
		td = this.createTd(String.fromCharCode(171), 'scroller');
		attachEventHandler(td, 'mousedown', this.goPreviousMonth);
		attachEventHandler(td, 'mousemove', this.cancelSelection);
		attachEventHandler(td, 'mouseup', this.clearPreviousMonthTimer);
		attachEventHandler(td, 'mouseout', this.clearPreviousMonthTimer);
		attachEventHandler(td, 'click', stopPropagation);
		tr.appendChild(td);
		td = this.createTd(LR_MN[this.date.getMonth()], 'month', 5);
		td.id = 'calendarSelectedMonthTd';
		tr.appendChild(td);
		td = this.createTd(String.fromCharCode(187), 'scroller');
		attachEventHandler(td, 'mousedown', this.goNextMonth);
		attachEventHandler(td, 'mousemove', this.cancelSelection);
		attachEventHandler(td, 'mouseup', this.clearNextMonthTimer);
		attachEventHandler(td, 'mouseout', this.clearNextMonthTimer);
		attachEventHandler(td, 'click', stopPropagation);
		tr.appendChild(td);
		this.table.tBodies[0].appendChild(tr);

		tr = thisDocument.createElement('tr');
		tr.className = 'dayMarker';

		for (j = 0; j < 7; j++) {
			tr.appendChild(this.createTd(LR_WD[j].substr(0, 2), (j > 4 ? 'weekEnd' : '')))
		}

		this.table.tBodies[0].appendChild(tr);
		
		body.insertBefore(this.table, body.firstChild);

		if (!(this.shield = thisDocument.getElementById('calendarShield'))) {
			this.shield = thisDocument.getElementById('calendarShield')
		}
		
		this.table.parentNode.insertBefore(this.shield, this.table);
		this.shield.style.top = this.table.style.top;
		this.shield.style.left = this.table.style.left;
		this.shield.style.width = this.table.offsetWidth;
		this.shield.style.height = this.table.offsetHeight;
		this.shield.style.display = 'block';
		
		this.visible = true;
	}

	
	this.display = function(evt, state) {
		if (!this.event) {
			if (thisDocument.all) {
				this.event = event
			} else {
				this.event = evt
			}
		}

		var date = new Date(this.date.getFullYear(), this.date.getMonth(), 1),
			dayCount0 = this.date.getMonthLength(),
			dayCount = dayCount0 + date.getLatinDay(),
			weekCount = Math.ceil(dayCount / 7),
			className = '', tr, td, d,
			firstDatePrec, today = new Date();
	
		if (this.visible == false) this.create();
		this.removeDaysRows();

		firstDatePrec = new Date(this.date.getFullYear(), this.date.getMonth() - 1, 1);
		
		for (i = 0; i < weekCount; i++) {
			tr = thisDocument.createElement('tr');

			for (j = 1; j < 8; j++) {
				className = (j > 5 ? 'weekEnd' : '');

				d = j + i * 7 - date.getLatinDay();

				if (d <= 0) {
					d += firstDatePrec.getMonthLength();
					className = 'previousMonth'
				} else if (d > this.date.getMonthLength()) {
					d -= this.date.getMonthLength();
					className = 'nextMonth'
				}

				if (d == this.date0.getDate()
					&& j + i * 7 - 1 < this.date0.getMonthLength() + date.getLatinDay()
					&& j + i * 7 - 1 > date.getLatinDay() - 1
					&& this.date.getMonth() == this.date0.getMonth()
					&& this.date.getYear() == this.date0.getYear()) {
					className = 'current'
				}

				td = this.createTd(d, className);

				attachEventHandler(td, 'mousedown', dayOnClick);
				attachEventHandler(td, 'mouseover', dayOnMouseOver);
				attachEventHandler(td, 'mouseout', dayOnMouseOut);
				tr.appendChild(td)
			}

			this.table.tBodies[0].appendChild(tr)
		}
		
		document.getElementById('calendarSelectedYearTd').firstChild.data = this.date.getFullYear();
		document.getElementById('calendarSelectedMonthTd').firstChild.data = LR_MN[this.date.getMonth()];
		
		tr = thisDocument.createElement('tr');
		td = this.createTd(LR_TODAY, 'todayButton', 7);
		attachEventHandler(td, 'mousedown', function() {
			var d = new Date(), day = d.getDate(), month = d.getMonth() + 1;

			calendar.element.value = d.getFullYear()
					+ '-' + (month < 10 ? '0' : '') + month
					+ '-' + (day < 10 ? '0' : '') + day;

			if (calendar.element.onchange) {
				calendar.element.onchange()
			}

			calendar.display()
		});
		tr.appendChild(td);
		this.table.tBodies[0].appendChild(tr);

		this.shield.style.width = this.table.offsetWidth;
		this.shield.style.height = this.table.offsetHeight;


		function dayOnClick(evt) {
			var td = getElementByEvent(evt),
				delta = 0, day, month, year;

			if (td.getAttribute('oldClassName') == 'previousMonth') {
				delta = -1
			} else if (td.getAttribute('oldClassName') == 'nextMonth') {
				delta = 1
			}

			year = calendar.date.getFullYear();
			month = (calendar.date.getMonth() + 1 + delta);

			if (month == 0) {
				month = 12;
				year--
			} else if (month == 13) {
				month = 1;
				year++
			}

			day = td.firstChild.data;

			calendar.element.value = year
				+ '-' + (month < 10 ? '0' : '') + month
				+ '-' + (day < 10 ? '0' : '') + day;

			if (calendar.element.onchange) {
				calendar.element.onchange()
			}

			this.date = new Date(year, month - 1, day);
			this.date0 = this.date;
			calendar.remove()
		}

		function dayOnMouseOver(evt) {
			evt = evt || event;
			var td = evt.target || evt.srcElement;

			td.setAttribute('oldClassName', td.className);
			td.className = 'hovered'
		}

		function dayOnMouseOut(evt) {
			evt = evt || event;
			var td = evt.target || evt.srcElement;

			td.className = td.getAttribute('oldClassName');
			td.removeAttribute('oldClassName')
		}
	}

	this.createTd = function(text, className, colSpan) {
		td = thisDocument.createElement('td');
		td.appendChild(thisDocument.createTextNode(text));

		if (className) td.className = className;
		if (colSpan) td.colSpan = colSpan;
		
		return td
	}

	this.remove = function(evt) {
		if (this.table && this.visible == true) {
			this.visible = false;
			body.removeChild(this.table);
			delete this.table;
			delete this.event;
			this.shield.style.display = 'none'
		}
	}
	
	this.removeDaysRows = function() {
		if (this.table && this.table.tBodies[0].rows) {
			var nrRows = this.table.tBodies[0].rows.length;
			for (var crtRow = nrRows-1; crtRow >= 3; crtRow-- ) {
				this.table.tBodies[0].deleteRow(crtRow);
			}
		}
	}


	this.goMonth = function(step) {
		this.date = new Date(
				this.date.getFullYear(),
				this.date.getMonth() + step,
				this.date.getDate());

		this.date0 = this.date;
		this.display(this.event, FORCE_VISIBLE)

		this.element.value =
			this.date.getFullYear()
			+ '-' + (this.date.getMonth() + 1 > 9 ? '' : '0') + (this.date.getMonth() + 1)
			+ '-' + (this.date.getDate() > 9 ? '' : '0') + this.date.getDate();

		if (calendar.element.onchange) {
			calendar.element.onchange()
		}
	}


	this.goYear = function(step) {
		this.date = new Date(
				this.date.getFullYear() + step,
				this.date.getMonth(),
				this.date.getDate());

		this.date0 = this.date;
		this.display(this.event, FORCE_VISIBLE)

		this.element.value =
			this.date.getFullYear()
			+ '-' + (this.date.getMonth() + 1 > 9 ? '' : '0') + (this.date.getMonth() + 1)
			+ '-' + (this.date.getDate() > 9 ? '' : '0') + this.date.getDate();
			
		if (calendar.element.onchange) {
			calendar.element.onchange()
		}
	}


	this.goNextYear = function() {
		this.nextYearTimerID = setInterval("calendar.goYear(1)", 50)
	}
	this.clearNextYearTimer = function() {
		clearInterval(this.nextYearTimerID);
	}

	this.goPreviousYear = function(evt) {
		this.previousYearTimerID = setInterval("calendar.goYear(-1)", 50)
	}
	this.clearPreviousYearTimer = function() {
		clearInterval(this.previousYearTimerID);
	}

	this.goNextMonth = function() {
		this.nextMonthTimerID = setInterval("calendar.goMonth(1)", 50)
	}
	this.clearNextMonthTimer = function() {
		clearInterval(this.nextMonthTimerID);
	}
	
	this.goPreviousMonth = function() {
		this.previousMonthTimerID = setInterval("calendar.goMonth(-1)", 50)
	}
	this.clearPreviousMonthTimer = function() {
		clearInterval(this.previousMonthTimerID);
	}
	
	this.cancelSelection = function() {
		var sel ;
		if (document.selection && document.selection.empty) {
			document.selection.empty() ;
		} else if (window.getSelection) {
			sel=window.getSelection();
			if (sel && sel.removeAllRanges)
				sel.removeAllRanges();
		}
	}
}


function attachCalendar(element) {
	thisDocument = element.ownerDocument;
	if (!body) {
		body = thisDocument.getElementsByTagName('body')[0];
		//shield = top.document.getElementById('calendarShield');

		attachEventHandler(body, 'click', function(evt) {
			//alert(getElementByEvent(evt))
			//debug(evt)
			if (calendar.table && getElementByEvent(evt) != calendar.element) {
				calendar.remove()
			}
		})
	}

	//element.readOnly = true; /* optional input lock on attach */
	attachEventHandler(element, 'click', inputOnClick);
	attachEventHandler(element, 'keyup', function(evt) {
		evt = evt || event;
		if (evt.keyCode == 27) {
			calendar.remove()
		} else {
			inputOnClick(evt)
		}
	});
	attachEventHandler(element, 'keydown', function(evt) {
		evt = evt || event;
		if (evt.keyCode == 9) calendar.remove()
	})
}


function inputOnClick(evt) {
	var date, day = 0, month = 0, year = 0,
		element = getElementByEvent(evt);

	if (element.value) {
		day = element.value.substr(8, 2);
		month = element.value.substr(5, 2);
		year = element.value.substr(0, 4);

		if (day > 0 && day < 32 && month > 0 < 13 && year > 0) {
			date = new Date(year, month - 1, day)
		} else {
			date = new Date()
		}

	} else {
		date = new Date()
	}

	if (calendar.table && element != calendar.element) {
		calendar.remove()
	}

	calendar.date = date;
	calendar.date0 = date;
	calendar.element = element;
	if (calendar.visivle == false) calendar.create();
	calendar.display(evt);
	stopPropagation(evt);
}

