/* Copyright 2006 ChrisPhillipsLLC.com */

/*
 * Usage:
 *

<link rel="stylesheet" type="text/css" href="datechooser.css"></link>
<script type="text/javascript" src="datechooser.js">
</script>
<script type="text/javascript">
var datechooser;
function init()
{
return;
	// Recall that January is month 0 in Date constructor
	datechooser = new DateChooser({start: new Date(2005,1,1),
	  end: new Date(2007,1,1), varname: "datechooser",
	  textelem: "gamedate"});
}
</script>
<body onload="init();">
<form>
<input type="text" name="ugh" id="gamedate" autocomplete="off" onchange="datechooser.checkDate();"/>
<img class="calendargraphic" src="images/calendar.gif" onclick="datechooser.goCalendar();"></img>
</form>
</body>
</html>

 *
 */

function DateChooser(o)
{
	var now = new Date();
	this.start = o["start"];
	this.end = o["end"];
	this.end.setDate(this.end.getDate() + 1);
	this.end.setSeconds(this.end.getSeconds() - 1);
	this.varname = o["varname"];

	this.textelem = o["textelem"];
	if (typeof this.textelem == "string")
		this.textelem = document.getElementById(this.textelem);

	if (typeof o["current"] == "object")
		this.current = o["current"];
	else
		this.setCurrent();

	if (document.all) {
		this.iframe = document.createElement("iframe");
		this.iframe.scrolling = "no";
		this.iframe.style.position = "absolute";
		this.iframe.style.border = "none";
		this.iframe.style.visibility = "hidden";
		this.iframe.src = "empty.html";
		document.body.appendChild(this.iframe);
	}
	this.div = document.createElement("div");
	document.body.appendChild(this.div);
	this.div.className = "calendar";
	this.div.style.position = "absolute";
	this.hideCalendar();
	this.showMonth();
	this.moveCalendar();
}

DateChooser.prototype.moveCalendar = function()
{
	var left = this.getLeft(this.textelem);
	var top = this.getTop(this.textelem);
	var width = this.getWidth(this.textelem);

	if (this.iframe) {
		this.setXY(this.iframe, left + width + 5, top);
		this.iframe.style.width = this.getWidth(this.div) + "px";
		this.iframe.style.height = this.getHeight(this.div) + "px";
	}
	this.setXY(this.div, left + width + 5, top);
}

DateChooser.prototype.goCalendar = function()
{
	this.setCurrent();
	if (this.inRange()) {
		this.showMonth();
		this.showCalendar();
	}
}

DateChooser.prototype.setCurrent = function()
{
	var re = /^\s*(\d{4})\D+(\d{1,2})\D+(\d{1,2})\s*$/;
	var arr = re.exec(this.textelem.value);

	if (arr && arr.length && arr.length == 4) {
		var year = parseInt(arr[1], 10);
		var month = parseInt(arr[2], 10);
		var day = parseInt(arr[3], 10);

		this.current = new Date(year, month - 1, day);
		if (!this.inRange()) {
			this.textelem.select();
			this.textelem.focus();
			alert("Date must be between "
			  + this.formatDate(this.start) + " and "
			  + this.formatDate(this.end) + " inclusive.");
		}
	} else {
		this.current = new Date();
		if (!this.inRange())
			this.current.setTime(this.start.getTime());
	}
};

DateChooser.prototype.getNewRow = function()
{
	var className = arguments[0];

	var tr = document.createElement("tr");
	tr.className = className;
	return tr;
};

DateChooser.prototype.getNewCell = function()
{
	var className = arguments[0];
	var text = arguments[1];
	var onclick = arguments[2];

	var td = document.createElement("td");
	td.className = className;
	if (text) {
		var node;
		if (onclick) {
			node = document.createElement("a");
			//node.onclick = onclick;
			var node2 = document.createTextNode(text);
			node.appendChild(node2);
			node.setAttribute("href", onclick);
		} else {
			node = document.createTextNode(text);
		}
		td.appendChild(node);
	}
	return td;
};

DateChooser.prototype.showCalendar = function()
{
	this.div.style.visibility = "visible";
	if (this.iframe)
		this.iframe.style.visibility = "visible";
};

DateChooser.prototype.hideCalendar = function()
{
	this.div.style.visibility = "hidden";
	if (this.iframe)
		this.iframe.style.visibility = "hidden";
};

DateChooser.prototype.dateChosen = function()
{
	var day = arguments[0];

	this.current.setDate(day);
	if (this.textelem) {
		var month = this.current.getMonth() + 1;
		this.textelem.value = this.current.getFullYear() + "-"
		  + (month < 10 ? "0" : "") + month + "-"
		  + (day < 10 ? "0" : "") + day;
		this.textelem.onchange();
	}
	if (this.div) {
		//this.removeChildren(this.div);
		this.hideCalendar();
	}
};

DateChooser.prototype.removeChildren = function()
{
	var elem = arguments[0];

	while (elem.hasChildNodes())
		elem.removeChild(elem.lastChild);
};

DateChooser.prototype.showPrevMonth = function()
{
	this.current.setMonth(this.current.getMonth() - 1);
	this.showMonth();
};

DateChooser.prototype.showNextMonth = function()
{
	this.current.setMonth(this.current.getMonth() + 1);
	this.showMonth();
};

DateChooser.prototype.showMonth = function()
{
	var year = this.current.getFullYear();
	var month = this.current.getMonth();

	// month=0 is January
	// day=0 is Sunday

	var days = ["Sunday", "Monday", "Tuesday",
	  "Wednesday", "Thursday", "Friday", "Saturday"];

	var months = ["January", "February", "March", 
	  "April", "May", "June", "July", "August", "September", 
	  "October", "November", "December"];

	if (!this.div)
		return;
	if (!this.textelem)
		return;

	this.removeChildren(this.div);

	var date = new Date(year, month, 1);
	var firstday = date.getDay();
	var ndays = (new Date(year, month+1, 0)).getDate();

	var table = document.createElement("table");
	table.setAttribute("cellspacing", "1px");
	var tbody = document.createElement("tbody");
	table.appendChild(tbody);

	// Month line
	var currentrow = this.getNewRow("row", tbody);

	var td;
	if (this.start.getTime() < date.getTime())
		td = this.getNewCell("prevmonth", "<",
		  "javascript:" + this.varname + ".showPrevMonth();");
	else
		td = this.getNewCell("prevmonth");
	currentrow.appendChild(td);
	td = this.getNewCell("monthyear",
	  months[month].substring(0,3) + " " + date.getFullYear());
	td.setAttribute("colSpan", 4);
	td.setAttribute("colspan", 4);
	currentrow.appendChild(td);
	if ((new Date(year, month+1, 1)).getTime() < this.end.getTime())
		td = this.getNewCell("nextmonth", ">",
		  "javascript:" + this.varname + ".showNextMonth();");
	else
		td = this.getNewCell("nextmonth");
	currentrow.appendChild(td);
	td = this.getNewCell("close", "X",
	  "javascript:" + this.varname + ".hideCalendar();");
//	td = this.getNewCell("close");
//	var img = document.createElement("img");
//	td.appendChild(img);
//	img.setAttribute("src", "images/close.gif");
//	img.setAttribute("onclick",
//	  "javascript:" + this.varname + ".hideCalendar();");
	currentrow.appendChild(td);
	tbody.appendChild(currentrow);

	// Headings (day names)
	var currentrow = this.getNewRow("row", tbody);
	for (var day in days)
		currentrow.appendChild(this.getNewCell("daynames",
		  days[day].substring(0,2)));
	tbody.appendChild(currentrow);

	// Nondays before the first day of the month
	var currentrow = this.getNewRow("row", tbody);
	for (var i = 0; i < firstday; i++)
		currentrow.appendChild(this.getNewCell("nonday"));
	tbody.appendChild(currentrow);

	var today = new Date();
//alert("today.getFullYear() = " + today.getFullYear() + "\n"
// + "today.getMonth() = " + today.getMonth() + "\n"
// + "today.getDate() = " + today.getDate());

	// The days of the month
	for (var i = 1; i <= ndays; i++) {
		if ((i + firstday) % 7 == 1) {
			currentrow = this.getNewRow("row");
			tbody.appendChild(currentrow);
		}
		var thisday = new Date(year, month, i);
		var classes = "";
		if (today.getFullYear() == year
		  && today.getMonth() == month
		  && today.getDate() == i)
		  	classes = "today ";
		if (this.start.getTime() <= thisday.getTime()
		  && thisday.getTime() <= this.end.getTime())
			td = this.getNewCell(classes + "day", i, "javascript:"
			  + this.varname + ".dateChosen(" + i + ");");
		else
			td = this.getNewCell(classes + "unchooseableday", i);
		currentrow.appendChild(td);
	}

	// Nondays after the last day of the month
	for (var i = ndays + 1; i < ndays + 7; i++)
		if ((i + firstday) % 7 == 1)
			break;
		else
			currentrow.appendChild(this.getNewCell("nonday"));
			
	this.div.appendChild(table);

	if (this.iframe)
		this.moveCalendar();
};

DateChooser.prototype.getWidth = function()
{
	var elem = arguments[0];
	var result = 0;

	if (elem.clientWidth)
		result = elem.clientWidth;
	else if (elem.offsetWidth) {
		if (elem.scrollWidth && elem.offsetWidth != elem.scrollWidth)
			result = elem.scrollWidth;
		else
			result = elem.offsetWidth;
	} else if (elem.clip && elem.clip.width)
		result = elem.clip.width;
	else if (elem.style && elem.style.pixelWidth)
		result = elem.style.pixelWidth;
	else if (elem.style && elem.style.posWidth)
		result = elem.style.posWidth;
	else if (elem.style && elem.style.width)
		result = elem.style.width;

	return parseInt(result);
};

DateChooser.prototype.getHeight = function()
{
	var elem = arguments[0];
	var result = 0;

	//if (document.offsetHeight)
	if (elem.offsetHeight)
		result = elem.offsetHeight;
	else if (elem.clip && elem.clip.height)
		result = elem.clip.height;
	else if (elem.style && elem.style.pixelHeight)
		result = elem.style.pixelHeight;

	return parseInt(result);
};

DateChooser.prototype.getLeft = function()
{
	var elem = arguments[0];
	var result = elem.offsetLeft;

	while ((elem = elem.offsetParent) != null)
		result += elem.offsetLeft;
	return result;
};

DateChooser.prototype.getTop = function()
{
	var elem = arguments[0];
	var result = elem.offsetTop;

	while ((elem = elem.offsetParent) != null)
		result += elem.offsetTop;
	return result;
};

DateChooser.prototype.setXY = function()
{
	var elem = arguments[0];
	var x = arguments[1];
	var y = arguments[2];

	if (elem && elem.style) {
		if (x)
			elem.style.left = x + "px";
		if (y)
			elem.style.top = y + "px";
	}
};

DateChooser.prototype.setZIndex = function()
{
	var elem = arguments[0];
	var value = arguments[1];

	elem.style.zindex = value;
};

DateChooser.prototype.formatDate = function()
{
	var year;
	var month;
	var day;

	if (arguments.length == 1) {
		var date = arguments[0];

		year = date.getFullYear();
		month = date.getMonth() + 1;
		day = date.getDate();
	} else {
		year = arguments[0];
		month = arguments[1];
		day = arguments[2];
	}

	return year + "-"
	  + (month < 10 ? "0" : "") + month + "-"
	  + (day < 10 ? "0" : "") + day;
}

DateChooser.prototype.inRange = function()
{
	return !(this.current.getTime() < this.start.getTime()
	  || this.current.getTime() > this.end.getTime());
}

DateChooser.prototype.checkDate = function()
{
	var re = /^\s*(\d{4})\D+(\d{1,2})\D+(\d{1,2})\s*$/;
	var arr = re.exec(this.textelem.value);

	if (arr && arr.length && arr.length == 4) {
		var year = parseInt(arr[1], 10);
		var month = parseInt(arr[2], 10);
		var day = parseInt(arr[3], 10);

		this.textelem.value = this.formatDate(year, month, day);

		this.current = new Date(year, month - 1, day);
		if (!this.inRange()) {
			this.textelem.select();
			this.textelem.focus();
			alert("Date must be between "
			  + this.formatDate(this.start) + " and "
			  + this.formatDate(this.end) + " inclusive.");
			return false;
		}
	} else {
		this.textelem.select();
		this.textelem.focus();
		alert("Date must be in yyyy-mm-dd format.");
		return false;
	}
	return true;
};

