/**
 * @author Mike Bradford <mike at mikebradford dot org>
 * @version 0.10
 * @todo Employ the XmlHttpRequst(?) object to store weblog posting dates, but keep the use of the date list javascript file as an option 
 */
/**
 * Creates an HTML calendar used to browse postings to my weblog
 * @return void
 * @param string instanceName A string value of the calendar instance. Used in the links that scroll through months
 * @param string containerId The id attribute of the HTML container in which the calendar resides. An element with this id must be present in the HTML document
 *
 * A quick example of how to use this calendar
 *
 * Create a calendar object in the <head> portion of your HTML document:
 * Don't forget to link to the Calendar class file.
 * 
 * <script type="text/javascript" src="js_file_location/calendar.class.js"></script>
 * <script>
 *  myCal = new Calendar('myCal','containerId');
 *  myCal.initMonth(3,2007);
 *  myCal.addDate(2007,4,12);
 *  myCal.addDate(2007,7,2);
 *  myCal.addDate(2007,12,16);
 * </script>
 * 
 * Set the print method of myCal to execute once the page is loaded.
 * 
 * <body onload="myCal.print()">
 * 
 * An HTML element must be present where the calendar will reside. Its id attribute should be 
 * set to the third parameter in your object instantiation.
 * 
 * <div id="containerId"><!-- No markup should go here --></div>
 *
 * Customizing the calendar
 * 
 * You can customize the markup that the calendar object outputs using CSS. The following 
 * is a list of elements and attributes that can be customized.
 *
 * id					explanation
 * ------------------------------------------------------------------------------------
 * containerId			The id of the HTML element where the table markup resides
 *
 * element	class				explanation
 * ------------------------------------------------------------------------------------
 * th		cal-prev-month		The cell that holds the arrow to the previous month
 * th		cal-next-month		The cell that holds the arrow to the next month
 * th		cal-month			The cell of the month and year text in the calendar header
 * td		cal-prev-day		The cells of the days before the current calendar month
 * td		cal-next-day		The cells of the days following the current calendar month
 * td		cal-day-name		The cells containing names of days
 * td		cal-day				The cells containing calendar days
 * td		cal-highlighted-day	The cells containing highlighted calendar days
 *
 * element				explanation
 * ------------------------------------------------------------------------------------
 * table
 * thead
 * tr
 * th
 * tbody
 * td
 *
 * You can customize the month and day headers displayed in the calendar by modifiying
 * the monthList and dayList properties of a calendar object.
 * 
 * //Assuming an object called myCal already exists
 * myCal.monthList = new Array("janvier","février","mars","avril","mai","juin","juillet","août","septembre","octobre","novembre","décembre")
 * mycal.dayList = new Array("di","lu","ma","me","je","ve","sa")
 * mycal.fullDayList = new Array("dimanche","lundi","mardi","mercredi","jeudi","vendredi","samedi")
 */
function Calendar (instanceName, containerId) {
	//Calendar properties;
	this.instanceName = instanceName;
	this.containerId = containerId;
	this.dateArray = new Array();
	this.dayURL = null;
	this.highlightedDayURL = null;
	this.monthURL = null;
	this.yearURL = null;
	this.yearAttr = new Array();
	this.monthAttr = new Array();
	this.dayAttr = new Array();
	this.highlightedDayAttr = new Array();
	this.linkAttr = new Array();
	var date = new Date ();
	this.curDate = new Date(date.getFullYear(),date.getMonth(),1);
	this.monthList = new Array("January","February","March","April","May","June","July","August","September","October","November","December");
	this.dayList = new Array("Su","Mo","Tu","We","Th","Fr","Sa");
	this.fullDayList = new Array("Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday");
	//Calendar methods
	this.print = print;
	this.nextMonth = nextMonth;
	this.prevMonth = prevMonth;
	this.searchDate = searchDate;
	this.searchMonth = searchMonth;
	this.addDate = addDate;
	this.initMonth = initMonth;
	this.addYearAttr = addYearAttr;
	this.addMonthAttr = addMonthAttr;
	this.addDayAttr = addDayAttr;
	this.addHighlightedDayAttr = addHighlightedDayAttr;
	this.addLinkAttr = addLinkAttr;
	this.setDayURL = setDayURL;
	this.setHighlightedDayURL = setHighlightedDayURL;
	this.setMonthURL = setMonthURL;
	this.setYearURL = setYearURL;
}
/**
 * Sets the innerHTML of the HTML container where the calendar resides the calendar markup
 */
function print () {
	var printDate = new Date (this.curDate.getFullYear(),this.curDate.getMonth(),1);
	var monthEvent = '';
	var dateEvent = '';
	var html = '<table>';
	html += '<thead>';
	html += '<tr>';
	html += '<th class="cal-prev-month"><a href="javascript:'+ this.instanceName +'.prevMonth()" title="Go to ' + this.monthList[printDate.getMonth()-1] + ' ' + printDate.getFullYear() + '">&laquo;</a></th>'
	if (this.monthURL != null) {
		var monthAttrs = '';
		for (var m=0; m<this.monthAttr.length; m++) {
			monthAttrs += " " + this.monthAttr[m][0] + '="' + this.monthAttr[m][1] + '"';
		}
		var month = '<a'+monthAttrs+' href="'+this.monthURL+'/'+printDate.getFullYear()+'/'+(printDate.getMonth()+1)+'">'+this.monthList[printDate.getMonth()]+'</a>';
	} else {
		var month = this.monthList[printDate.getMonth()];
	}
	if (this.yearURL != null) {
		var yearAttrs = '';
		for (var y=0; y<this.yearAttr.length; y++) {
			yearAttrs += " " + this.yearAttr[y][0] + '="' + this.yearAttr[y][1] + '"';
		}
		var year = '<a'+yearAttrs+' href="'+this.yearURL+'/'+printDate.getFullYear()+'">'+printDate.getFullYear()+'</a>';
	} else {
		var year = printDate.getFullYear();
	}
	html += '<th class="cal-month" colspan="5">' + month + ' ' + year + '</th>';
	html += '<th class="cal-next-month"><a href="javascript:'+ this.instanceName +'.nextMonth()" title="Go to ' + this.monthList[printDate.getMonth()+1] + ' ' + printDate.getFullYear() + '">&raquo;</a></th>'
	html += '</tr>';
	html += '<tr>';
	for (var i=0; i<7; i++) {
		html += '<th class="cal-day-name"><abbr title="'+ this.fullDayList[i] +'">'+ this.dayList[i] +'</abbr></th>';
	}
	html += '</tr>';
	html += '</thead>';
	html += '<tbody>';
	for (var i=0; i<7; i++) {
		if (printDate.getDay() == i) {
			printDate.setDate(printDate.getDate() - i);
			break;
		}
	}
	for (var i=0; i<6; i++) {
		html += '<tr>';
		var cellClass = '';
		for (var j=0; j<7; j++) {
			day = ''
			if (printDate.getMonth() < this.curDate.getMonth()) {
				if (printDate.getFullYear() == this.curDate.getFullYear()) {
					cellClass = 'cal-prev-day';
				} else {
					cellClass = 'cal-next-day';
				}
			}
			if (printDate.getMonth() > this.curDate.getMonth()) {
				if (printDate.getFullYear() == this.curDate.getFullYear()) {
					cellClass = 'cal-next-day';
				} else {
					cellClass = 'cal-prev-day';
				}
			}
			if (printDate.getMonth() == this.curDate.getMonth()) {
				if (this.searchDate(printDate)) {
					cellClass = 'cal-highlighted-day';
					if (this.highlightedDayURL != null) {
						day = '<a href="'+this.highlightedDayURL+'/'+printDate.getFullYear()+'/'+(printDate.getMonth()+1)+'/'+printDate.getDate()+'">'+printDate.getDate()+'</a>';
					} else {
						day = printDate.getDate()
					}
					for (var k=0; k<this.highlightedDayAttr.length; k++) {
						dateEvent += " " + this.dayAttr[k][0] + '="' + this.dayAttr[k][1] + '"';
					}
				} else {
					cellClass = 'cal-day';
					if (this.dayURL != null) {
						day = '<a href="'+this.dayURL+'/'+printDate.getFullYear()+'/'+(printDate.getMonth()+1)+'/'+printDate.getDate()+'">'+printDate.getDate()+'</a>';
					} else {
						day = printDate.getDate()
					}
					for (var k=0; k<this.dayAttr.length; k++) {
						dateEvent += " " + this.dayAttr[k][0] + '="' + this.dayAttr[k][1] + '"';
					}
				}
			}
			html += '<td class="' + cellClass + '">' + day + '</td>';
			printDate.setDate(printDate.getDate() + 1);
		}
		html += '</tr>';
		if (cellClass == 'cal-next-day') {
			break;	
		}
	}
	html += '</tbody>';
	html += '</table>';
	document.getElementById(this.containerId).innerHTML = html;
}
/**
 * Adds an attribute of the a element for the year if it links to a URL
 * 
 * @return void
 * @param string attr The attribute name
 * @param mixed val The attribute value
 */
function addYearAttr (attr,val) {
	this.yearAttr[this.yearAttr.length] = new Array(attr,val);
}
/**
 * Adds an attribute of the a element for the month if it links to a URL
 * 
 * @return void
 * @param string attr The attribute name
 * @param mixed val The attribute value
 */
function addMonthAttr (attr,val) {
	this.monthAttr[this.monthAttr.length] = new Array(attr,val);
}
/**
 * Adds an attribute of the td element where each non-hightlighted day of the 
 * current month is printed
 * 
 * @return void
 * @param string attr The attribute name
 * @param mixed val The attribute value
 */
function addDayAttr (attr,val) {
	this.dayAttr[this.dayAttr.length] = new Array(attr,val);
}
/**
 * Adds an attribute of the td element where each highlighted day of the current 
 * month is printed
 * 
 * @return void
 * @param string attr The attribute name
 * @param mixed val The attribute value
 */
function addHighlightedDayAttr (attr,val) {
	this.highlightedDayAttr[this.highlightedDayAttr.length] = new Array(attr,val);
}
/**
 * Adds an attribute of the a element where each highlighted day of the current
 * month is printed
 * 
 * @return void
 * @param string attr The attribute name
 * @param mixed val The attribute value
 */
function addLinkAttr (attr,val) {
	this.linkAttr[this.linkAttr.length] = new Array(attr,val);
}
/**
 * Sets the URL for a highlighted day. A string of the pattern "/year/month/day"
 * will be appended to this URL if it is set.
 * 
 * @return void
 * @param string url
 */
function setDayURL (url) {
	this.dayURL = url;
}
/**
 * Sets the URL for a non-highlighted day. A string of the pattern 
 * "/year/month/day" will be appended to this URL if it is set.
 * 
 * @return void
 * @param string url
 */
function setDayURL (url) {
	this.dayURL = url;
}
/**
 * Sets the URL for a highlighted day. A string of the pattern "/year/month/day" 
 * will be appended to this URL if it is set.
 * 
 * @return void
 * @param string url
 */
function setHighlightedDayURL (url) {
	this.highlightedDayURL = url;
}
/**
 * Sets the URL for the current month text. A string of the pattern "/year/month" 
 * will be appended to this URL if it is set.
 * 
 * @return void
 * @param string url
 */
function setMonthURL (url) {
	this.monthURL = url;
}
/**
 * Sets the URL for the current year text. A string of the pattern "/year" will 
 * be appended to this URL if it is set.
 * 
 * @return void
 * @param string url
 */
function setYearURL (url) {
	this.yearURL = url;
}
/**
 * Sets the month that the calendar prints initially
 * 
 * @return void
 * @param int month The integer representation of the month, from 0 to 11
 * @param int year The four-digit year
 */
function initMonth (month,year) {
	this.curDate = new Date(year,month,1);
}
/**
 * Adds a selected date to the calendar
 * 
 * @author Mike Bradford <mike at mikebradford dot info>
 */
function addDate (year,month,day) {
	this.dateArray[this.dateArray.length] = new Date(year,month,day)
}
/**
 * Switches the calendar to the following month
 */
function nextMonth () {
	this.curDate.setMonth(this.curDate.getMonth() + 1)
	this.print()
}
/**
 * Switches the calendar to the previous month
 */
function prevMonth () {
	this.curDate.setMonth(this.curDate.getMonth() - 1)
	this.print()
}
/**
 * Searches for a date
 * 
 * @access private
 * @return boolean
 */
function searchDate (thisDate) {
	for (var i = 0; i < this.dateArray.length; i++) {
		if (this.dateArray[i].getYear() == thisDate.getYear() && this.dateArray[i].getMonth() == thisDate.getMonth() && this.dateArray[i].getDate() == thisDate.getDate()) {
			return true
		}
	}
	return false
}
/**
 * @access private
 * @return boolean
 */
function searchMonth (thisMonth, thisYear, dateArray) {
	for (var i in dateArray) {
		if (dateArray[i].getMonth() == thisMonth && dateArray[i].getFullYear() == thisYear) {
			return true
		}
	}
	return false
}