
/**************************************************************
 *  Calendar code for chris.muellershome.com                  *
 *  all code by Chris Mueller unless otherwise noted          *
 *  January 11, 2005 (the warm heart of a Minnesotan winter)  *
 *                                                            *
 *  Please use for your own non-commerical enterprises.       *
 **************************************************************/

var req; // for XMLHttp requests
var daysOfWeek = ["S","M","T","W","Th","F","S"]
var months = [ "January","February","March","April","May","June","July","August","September","October","Novemeber","December" ]
var cal = new Calendar();
var dataStore = new DataStorage();

function postItem(summaryVal, idVal) {
	this.summary = summaryVal;
	this.id = idVal;
}

// a caching mechanism
function DataStorage() {
	this.dA = new Array();
	this.add = function(year,month,day,summary,id) {
		if(!this.dA[year]) this.dA[year]=new Array();
		if(!this.dA[year][month]) this.dA[year][month]=new Array();
		this.dA[year][month][day] = new postItem(summary,id);
	}
	this.getId = function(year,month,day) {
		if(this.dA[year] && this.dA[year][month] && this.dA[year][month][day]) return this.dA[year][month][day].id;
		else return false;
	}
	this.getSummary = function(year,month,day) {
		if(this.dA[year] && this.dA[year][month] && this.dA[year][month][day]) return this.dA[year][month][day].summary;
		else return false;
	}
	this.monthExists = function(year,month) {
		if(this.dA[year] && this.dA[year][month]) return true;
		else return false;
	}
}

// the calendar gets a date, then it draws the month associated with that date's month
function Calendar() {
	this.d = new Date();
	this.calArray = new Array(6);
	for (i = 0; i < 6; i++)
		this.calArray[i] = new Array(7);
		
	this.init = function() {
		document.write('<table align="center" cellpadding="2" cellspacing="0" id="calendar"><tr id="calHead">'
		 + '<th id="prevCal">&nbsp;</th><th id="monthname" colspan="5"></th><th id="nextCal"></th></tr>');
		for (dayOfWeek = 0; dayOfWeek < 7; dayOfWeek++)
			document.write('<th>' + daysOfWeek[dayOfWeek]  + '</th>');
		document.write('</tr>');
		for (row = 0; row < 6; row++) {
			document.write('<tr>');
			for (col = 0; col < 7; col++) {
					document.write('<td class="gday" id="d' + row + col + '">&nbsp;</td>');
			}
			document.write('</tr>');
		}
		document.write('</table>');
	} // end init
	
	this.make = function() {
		var year = this.d.getFullYear();
		var monthIndex = this.d.getMonth();
		var prevMonth; var nextMonth; var prevYear; var nextYear;
		if(monthIndex != 0) { prevYear = year; prevMonth = monthIndex - 1; }
			else { prevYear = year-1; prevMonth = 11; }
		if(monthIndex != 11) { nextYear = year; nextMonth = monthIndex + 1; }
			else { nextYear = year+1; nextMonth = 0; }

		calHeader = document.getElementById("monthname");
		calHeader.innerHTML = months[this.d.getMonth()] + "&nbsp;" + year;
		prevCalNode = document.getElementById("prevCal");
		nextCalNode = document.getElementById("nextCal");
		prevCalNode.innerHTML = '<a href="javascript:gotoDate('+prevMonth+','+prevYear+');" title="'+months[prevMonth]+' '+prevYear+'">&nbsp;&laquo;&nbsp;</a>';
		nextCalNode.innerHTML = '<a href="javascript:gotoDate('+nextMonth+','+nextYear+');" title="'+months[nextMonth]+' '+nextYear+'">&nbsp;&raquo;&nbsp;</a>';
		for (row = 0; row < 6; row++) {
			for (col = 0; col < 7; col++) {
				a = this.calArray[row][col];
				b = document.getElementById("d" + row + col);
				if (a != 0) {
					b.className = "gday";
					b.innerHTML = a;
				} else {
					b.className = "nday";
					b.innerHTML = "&nbsp;";
				}
			}
		}
	} // end make
	
	this.makeActive = function() {
		year = this.d.getFullYear();
		month = this.d.getMonth();
		for (row = 0; row < 6; row++) {
			for (col = 0; col < 7; col++) {
				day = this.calArray[row][col];
				id = dataStore.getId(year,month,day);
				if(day!=0 && id) {
					summary = dataStore.getSummary(year,month,day);
					b = document.getElementById("d" + row + col);
					b.className = "aday";
					b.innerHTML = '<a href="archive.php?m='+id+'" title="' + summary + '">' + day + '</a>';
				}
			}
		}
	} // end makeActive
	
	this.setDate = function(month,year) {
		this.d.setMonth(month);
		this.d.setYear(year);
		this.d.setDate(1);
		dat = new Date(this.d);
		var i = 1;
		for(row = 0; row < 6; row++) {
			for(col = 0; col < 7; col++) {
				if(dat.getDay() == col && dat.getMonth() == month) {
					this.calArray[row][col] = i;
					i++;
					dat.setDate(i);
				}
				else
					this.calArray[row][col] = 0;
			}
		}
	} // end setDate
}

function loadXMLDoc(url) {
	// code from http://developer.apple.com/internet/webcontent/xmlhttpreq.html
    // branch for native XMLHttpRequest object
    if (window.XMLHttpRequest) {
        req = new XMLHttpRequest();
        req.onreadystatechange = processReqChange;
        req.open("GET", url, true);
        req.send(null);
    // branch for IE/Windows ActiveX version
    } else if (window.ActiveXObject) {
        req = new ActiveXObject("Microsoft.XMLHTTP");
        if (req) {
            req.onreadystatechange = processReqChange;
            req.open("GET", url, true);
            req.send();
        }
    }
}

function processReqChange() {
    if (req.readyState == 4) {
        if (req.status == 200) { 
			processXML();
        } else {
            alert("There was a problem updating the calendar:\n" + req.statusText);
        }
    }
}

function getElementText(tagName, parent, index) {
	// code from http://developer.apple.com/internet/webcontent/xmlhttpreq.html
    var result =  parent.getElementsByTagName(tagName)[index];
    if (result) // get text, accounting for possible whitespace (carriage return) text nodes 
        if (result.childNodes.length > 1) return result.childNodes[1].nodeValue;
		else return result.firstChild.nodeValue;    		
    else return "n/a";
}

function processXML() {
	// update the dataStore and then call cal.makeActive() to update the calendar
	var items = req.responseXML.getElementsByTagName("item");
	for(var i=0;i<items.length;i++) {
		year = getElementText("year",items[i],0);
		month  = getElementText("month",items[i],0);
		day = getElementText("day",items[i],0);
		summary = getElementText("summary",items[i],0);
		id = getElementText("id",items[i],0);
		dataStore.add(year,month,day,summary,id);
		cal.makeActive();
	}
}

function gotoDate(month,year) {
	cal.setDate(month,year);
	cal.make();
	phpMonth = month+1;
	if(!dataStore.monthExists(year,month)) loadXMLDoc("calendar.php?year="+year+"&month="+phpMonth);
	else cal.makeActive();
}

function initCal() {
	// do some checks for browser compatibility as well
	// draw the calendar here the first time using writelns. then we'll modify it using DOM in make()
	cal.init();
	var now = new Date();
	gotoDate(now.getMonth(),now.getFullYear());
}
