///////////////////////////////////////////////////////////////////////////////
//  HANG WIRE JAVASCRIPT CALENDAR OBJECT

window.HW_cal_day_click = function ()
{
	if(this.has_event)
	{
		this.cal.ondayclick(this.cal.year, this.cal.month, this.day);
	}
}

window.HW_cal_day_set_event_status = function (whether)
{
	if(this.day)
	{
		// There's a day number in this cell... set standard class name, or set today as class name
		if((this.cal.year == this.cal.current_year) && (this.cal.month == this.cal.current_month) && (this.day == this.cal.current_day))
		{
			// it's today
			this.td.className = whether ? this.cal.day_event_css_class_name : this.cal.today_css_class_name;
		}
		else
		{
			// it's not today
			this.td.className = whether ? this.cal.day_event_css_class_name : this.cal.day_standard_css_class_name;
		}
	}
	else
	{
		// The cell is empty
		this.td.className = this.cal.day_empty_css_class_name;
	}
//testing
//if(this.day && this.td.className == "HW_cal_day_event_class_name"){
//	window.alert("day = "+this.day+"\nclass name = "+this.td.className);
//}

	this.has_event = whether ? true : false;
	return this;
}

window.HW_cal_day_add_event = function (what)
{
	this.set_event_status(true);
	this.cal.how_to_do_event_layout(this.day, this.eventsdiv, what);
}

window.HW_cal_day_clear = function ()
{
	this.events = new Array();
	this.set_event_status(false);
	for(var i=this.eventsdiv.childNodes.length-1; i>=0; i--)
	{
		this.eventsdiv.removeChild(this.eventsdiv.childNodes[i]);
	}
	this.eventsdiv.appendChild(this.a);
}

window.HW_cal_day_set_day = function (day)
{
	// Displays a day number or clears the display
	if(!day || day=='')
	{
		day = window.HangWire.nbsp;
		this.day = false;
	}
	else
	{
		this.day = day;
	}
	this.text.data = day;
	this.set_event_status(this.has_event);			// don't change this.has_event; this is just to make sure the correct CSS class is applied
	return this;
}

window.HW_cal_Day = function (wk, dy, cal)
{
	// Parameters & Properties
	this.wk = wk;
	this.dy = dy;
	this.cal = cal;
	this.has_event = false;
	this.events = new Array();
	this.day = false;

	// Methods
	this.set_day = HW_cal_day_set_day;
	this.set_event_status = HW_cal_day_set_event_status;
	this.day_click = HW_cal_day_click;
	this.clear = HW_cal_day_clear;
	this.add_event = HW_cal_day_add_event;

	// Layout
	var t = this;
	this.td = this.cal.w.document.createElement('td');
	this.td.className = this.cal.day_standard_css_class_name;
	this.td.setAttribute('id', this.cal.jsidbase + '_HW_cal_daycell_w' + this.wk + 'd' + this.dy);
	this.td.style.overflow = 'hidden';
	this.a = this.cal.w.document.createElement('a');
	this.a.setAttribute('id', this.cal.jsidbase + '_HW_cal_day_w' + this.wk + 'd' + this.dy);
	this.a.onclick = function () { t.day_click(); }
	this.text = this.cal.w.document.createTextNode(window.HangWire.nbsp);
	this.a.appendChild(this.text);
	this.td.appendChild(this.a);
	this.eventsdiv = this.cal.w.document.createElement('div');		// event info will go here
	this.td.appendChild(this.eventsdiv);
}

window.HW_cal_do_layout = function ()
{
	var tr = null;
	var td = null;
	var tn = null;
	var tb = null;

	// Start title row
	this.element_to_append.style.textAlign = 'center';
	var tt = this.w.document.createElement('table');
	tt.width = '100%';
	var ttb = this.w.document.createElement('tbody');
	var ttr = this.w.document.createElement('tr');

	// Left nav button
	td = this.w.document.createElement('td');
	td.style.textAlign = 'left';
	td.appendChild(this.left_month_nav);
	ttr.appendChild(td);

	// Title cell
	this.title_td.style.textAlign = 'center';
	ttr.appendChild(this.title_td);

	// Right nav button
	td = this.w.document.createElement('td');
	td.style.textAlign = 'right';
	td.appendChild(this.right_month_nav);
	ttr.appendChild(td);

	// Finish title row
	ttb.appendChild(ttr);
	tt.appendChild(ttb);
	this.element_to_append.appendChild(tt);

	// Start table
	this.table.style.width = '100%';
	tb = this.w.document.createElement('tbody');

	// Week headings
	tr = this.w.document.createElement('tr');
	for(var i=0; i<7; i++)
	{
//		this.day_headings[i].appendChild(this.w.document.createTextNode(this.day_names.abbreviated[i]));
		this.day_headings[i].appendChild(this.w.document.createTextNode(this.calendar_systems[this.calendar_system].day_names[this.day_name_mode][i]));
		tr.appendChild(this.day_headings[i]);
	}
	tb.appendChild(tr);

	// Day grid
	for(var wk in this.days)
	{
		tr = this.w.document.createElement('tr');
		for(var dy in this.days[wk])
		{
			tr.appendChild(this.days[wk][dy].td);
		}
		tb.appendChild(tr);
	}

	// Finish
	this.table.appendChild(tb);
	this.element_to_append.appendChild(this.table);
}

window.HW_cal_change_layout = function (how_to_do_layout)
{
	if(how_to_do_layout)
	{
		this.how_to_do_layout = how_to_do_layout;
	}
	for(i=0; i<this.element_to_append.children.length; i++)
	{
		HangWire.remove_all_children(this.element_to_append);
	}
	this.how_to_do_layout();
	return this;
}

window.HW_cal_set_css = function (tbl, mnav, title, dayhead, day, dayev, today, daymouse, dayempty)
{
	var t = this;
	if(tbl)
	{
		this.table_css_class_name = tbl;
		this.table.className = tbl;
	}
	if(mnav)
	{
		this.month_nav_css_class_name = mnav;
		this.left_month_nav.className = mnav;
		this.right_month_nav.className = mnav;
	}
	if(title)
	{
		this.title_css_class_name = title;
		this.title_td.className = title;
	}
	if(dayhead)
	{
		this.day_heading_css_class_name = dayhead;
		for(var i in this.day_headings)
		{
			this.day_headings[i].className = dayhead;
		}
	}
	if(day || dayev || today || daymouse)
	{
		if(day)
		{
			this.day_standard_css_class_name = day;
		}
		if(dayev)
		{
			this.day_event_css_class_name = dayev;
		}
		if(today)
		{
			this.today_css_class_name = today;
		}
		if(daymouse)
		{
			this.day_mouseover_css_class_name = daymouse;
		}
		for(var i in this.days) for(var j in this.days[i])
		{
			this.days[i][j].tdclass = ((this.days[i][j].day == this.day) && today ? today : (this.days[i][j].has_event ? dayev : day));
			this.days[i][j].td.className = this.days[i][j].tdclass;
			if(daymouse)
			{
				this.days[i][j].td.onmouseover = function () { this.className = daymouse; }
				this.days[i][j].td.onmouseout = function () { this.className = t.days[i][j].tdclass; }
			}
		}
		if(dayempty)
		{
			this.day_empty_css_class_name = dayempty;
		}
		else
		{
			this.day_empty_css_class_name = day;				// default empty days to standard day style if dayempty not given
		}
	}
}

window.HW_cal_calsys_add_leap_alternative = function (leap_id, is_leap_year, fullmonths, leapmonthlengths, abbmonths, maptoregular)
{
	// Default is no abbreviations
	if(!abbmonths)
	{
		abbmonths = fullmonths;
	}

	// Default is identity map
	if(!maptoregular)
	{
		maptoregular = function (m) { return m; }
	}

	this.leap[leap_id] = new Object();
	this.leap[leap_id].isleap = is_leap_year;
	this.leap[leap_id].months = new Array();
	for(i in fullmonths)
	{
		this.leap[leap_id].months[i] = new Object();
		this.leap[leap_id].months[i].full = fullmonths[i];
		this.leap[leap_id].months[i].abbreviated = abbmonths[i];
		this.leap[leap_id].months[i].month_length = leapmonthlengths[i];
		this.leap[leap_id].months[i].maptoregular = maptoregular;
	}
	return this;
}

window.HW_cal_calsys_months_in_year = function (year)
{
	var leapid = this.isleap(year);
	if(leapid)
	{
		return this.leap[leapid].months;
	}
	else
	{
		return this.months;
	}
}

window.HW_cal_Calendar_System = function (fullmonths, monthlengths, abbmonths, daynames, abbdaynames, fldaynames)
{
	// Default is no abbreviations
	if(!abbmonths)
	{
		abbmonths = fullmonths;
	}
	this.day_names = new Object();
	this.day_names.full = daynames;												// Full day names ("Sunday")
	this.day_names.abbreviated = abbdaynames = abbdaynames || daynames;			// Abbreviated day names ("Sun")
	this.day_names.first_letter = fldaynames || abbdaynames || daynames;		// First-letter day names ("S")

	this.leap = new Object();

	this.months = new Array();
	for(i in fullmonths)
	{
		this.months[i] = new Object();
		this.months[i].full = fullmonths[i];
		this.months[i].abbreviated = abbmonths[i];
		this.months[i].month_length = monthlengths[i];
	}

	this.months_in_year = HW_cal_calsys_months_in_year;
	this.add_leap_alternative = HW_cal_calsys_add_leap_alternative;
	
	this.isleap = function (year)
	{
		var result = false;
		for(var lid in this.leap)
		{
			if(this.leap[lid].isleap(year))
			{
				result = lid;
				break;
			}
		}
		return result;
	}
}

window.HW_cal_set_calendar_system = function (id)
{
	this.calendar_system = id;
}

window.HW_cal_add_calendar_system = function (id, fullmonths, monthlengths, abbmonths, daynames, abbdaynames, fldaynames)
{
	this.calendar_systems[id] = new HW_cal_Calendar_System(fullmonths, monthlengths, abbmonths, daynames, abbdaynames, fldaynames);
	return this;
}

window.HW_cal_current_month_system = function (year)
{
	year = year || this.year;
	var leapid = this.calendar_systems[this.calendar_system].isleap(this.year);
	return leapid ? this.calendar_systems[this.calendar_system].leap[leapid].months : this.calendar_systems[this.calendar_system].months;
}

window.HW_cal_display_month_title = function (abbrev, month, year)
{
	var abbr = abbrev ? 'abbreviated' : 'full';
	month = month || this.month;
	year = year || this.year;
	this.title_text.data = this.current_month_system()[month - 1][abbr] + ' ' + year;
}

window.HW_cal_clear_events = function ()
{
	for(i in this.days) for(j in this.days[i])
	{
		this.days[i][j].clear();
	}
}

window.HW_cal_add_event = function (day, what)
{
	this.monthdays[day].add_event(what);
}

window.HW_cal_set_month = function (year, month)
{
	this.year = year;
	this.month = month;
	this.monthdays = new Array(' ');

	// Clear old events
	this.clear_events();

	// Month title
	this.display_month_title(this.month_abbreviation);

	// Get day of week of first day of selected month
	this.d.setFullYear(this.year, this.month - 1, 1);
	var day = this.d.getDay();

	// Display days of this month
	var dt = 0;
	var ml = this.current_month_system(year)[month - 1].month_length;
	var daylabel = 0;
	for(var wk = 0; wk < 6; wk++)
	{
		for(var dy = 0; dy < 7; dy++)
		{
			this.days[wk][dy].set_event_status(false);
			daylabel = (wk==0 && dy < day) || (++dt <= ml) ? dt : false;
			this.days[wk][dy].set_day(daylabel);
			if(daylabel)
			{
				this.monthdays[daylabel] = this.days[wk][dy];
			}
		}
	}

	// Add events for this month
	this.how_to_get_events(this.year, this.month);
}

window.HW_cal_move_month = function (offset)
{
	this.month = this.month + offset;
	while(this.month <= 0)
	{
		this.year -= 1;
		this.month += this.calendar_systems[this.calendar_system].months_in_year(this.year).length;
	}
	while(this.month > this.calendar_systems[this.calendar_system].months_in_year(this.year).length)
	{
		this.month -= this.calendar_systems[this.calendar_system].months_in_year(this.year).length;
		this.year += 1;
	}
	this.set_month(this.year, this.month);
	return this;
}

window.HW_cal_move_year = function (offset)
{
	var leap_formerly = this.calendar_systems[this.calendar_system].isleap(this.year);
	this.year += offset;
	if(leap_formerly && !this.calendar_systems[this.calendar_system].isleap(this.year))
	{
		this.month = this.calendar_systems[this.calendar_system].leap[leap_formerly].maptoregular(this.month);
	}
	this.set_month(this.year, this.month);
	return this;
}

function HW_cal_use_rss(rssobj)
{
	var t = this;

	// Set record handler
	rssobj.record_handler = function (rec) {

		// Parse time out of date
		if(rec.pubdate) {
			var d = new Date();
			d.setTime(Date.parse(rec.pubdate));
			var h = d.getHours();
			var m = d.getMinutes();
			if(h>0 && m>0 || (rec.all_day && parseInt(rec.all_day)==0)) {		// add date only if it exists; if it's midnight check all_day exists and is false
				rec.time = (h % 12 ? h % 12 : 12) + ':' + (m < 10 ? '0' : '') + m + ' ' + (h < 12 ? 'am' : 'pm');
			}

		}
//window.alert("t.month = "+t.month+"\nd.getMonth = "+(1+d.getMonth()));
//window.alert("t.year = "+t.year+"\nd.getFullYear = "+(d.getFullYear()));

		// Add event if month and year match
		if(t.month==(1+d.getMonth()) && t.year==d.getFullYear()) {
//window.alert("add event = "+t.month+", "+t.year+"\n"+rec.title);
			t.add_event(d.getDate(), rec);
		}

		//var str = '';
		//for(var i in rec) {
		//	str = str + i + ' => ' + rec[i] + "\n";
		//}
		//window.alert(str + "\n" + t.month + ' ' + d.getMonth() + ' | ' + t.year + ' ' + d.getYear());
	}

	this.how_to_get_events = function (year, month) {
		rssobj.read();
	}

}

window.HW_cal_refresh = function ()
{
//	this.change_layout();
	if(!this.layout_done)
	{
		this.do_layout();
	}
	this.set_month(this.year, this.month);
}


///////////////// LAYOUT LIBRARY

function HW_cal_event_layout_day_cells_with_summaries(day, cell, info) {
	// Calendar layout with summaries
	// Result will be:	<div class="event_details">
	//						<div><a class="event_title">Title</a></div>
	//						<div class="event_summary">Summary</div>
	//						<div class="event_time">Time</div>
	//						<div class="event_price">Price</div>
	//					</div>
	var divs = new Object();
	var eventdiv = document.createElement('div');
	eventdiv.className = 'event_details';										// NOTE css class name

	// Title div with link
	divs.title = document.createElement('div');
	var a = document.createElement('a');
	a.setAttribute('href', info.link);
	a.className = 'event_title';												// NOTE css class name
	a.appendChild(document.createTextNode(info.title));
	divs.title.appendChild(a);
	eventdiv.appendChild(divs.title);

	// Floating box
	var fbox = new HW_Floating_Box(divs.title, 'mouseover', [10,2]);
	fbox.box.className = 'event_popup_box';										// NOTE css class name

	// Other divs
	if(info.summary)
	{
		divs.summary = document.createElement('div');
		divs.summary.className = 'event_summary';								// NOTE css class name
		divs.summary.appendChild(document.createTextNode(info.summary));
		fbox.box.appendChild(divs.summary);
	}
	if(info.time)
	{
		divs.time = document.createElement('div');
		divs.time.className = 'event_time';										// NOTE css class name
		divs.time.appendChild(document.createTextNode(info.time));
		fbox.box.appendChild(divs.time);
	}
	if(info.cost)
	{
		divs.price = document.createElement('div');
		divs.price.className = 'event_price';									// NOTE css class name
		divs.price.appendChild(document.createTextNode(info.cost));
		fbox.box.appendChild(divs.price);
	}

	// Append the event
	cell.appendChild(eventdiv);
}

function HW_cal_event_layout_day_cells_small(day, cell, info) {
	// Calendar layout with just date displayed by default

	var divs = new Object();
	var eventdiv = document.createElement('div');
	eventdiv.className = 'event_details';										// NOTE css class name

/*	// Title div with link
	divs.title = document.createElement('div');
	var a = document.createElement('a');
	a.setAttribute('href', info.link);
	a.className = 'event_title';												// NOTE css class name
	a.appendChild(document.createTextNode(info.title));
	divs.title.appendChild(a);
	eventdiv.appendChild(divs.title);

	// Floating box
	var fbox = new HW_Floating_Box(divs.title, 'mouseover', [10,2]);
	fbox.box.className = 'event_popup_box';										// NOTE css class name

	// Other divs
	if(info.summary)
	{
		divs.summary = document.createElement('div');
		divs.summary.className = 'event_summary';								// NOTE css class name
		divs.summary.appendChild(document.createTextNode(info.summary));
		fbox.box.appendChild(divs.summary);
	}
	if(info.time)
	{
		divs.time = document.createElement('div');
		divs.time.className = 'event_time';										// NOTE css class name
		divs.time.appendChild(document.createTextNode(info.time));
		fbox.box.appendChild(divs.time);
	}
	if(info.cost)
	{
		divs.price = document.createElement('div');
		divs.price.className = 'event_price';									// NOTE css class name
		divs.price.appendChild(document.createTextNode(info.cost));
		fbox.box.appendChild(divs.price);
	}

	// Append the event
	cell.appendChild(eventdiv);*/
}


/////////////////// CONSTRUCTOR ////////////////////////

window.HW_Calendar = function (element_to_append, ondayclick, css, day_name_mode)
{
	// Explanation of Parameters:
	//		element_to_append ..... is an element on the page.  The calendar will be placed within this element.
	//								Typically, this is a blank DIV element that's defined and positioned in the page HTML.
	//		ondayclick ............ is a function that gives you the ability to make the calendar do something when the user clicks
	//								on a day in the calendar.  It is given in the form:
	//									function ondayclick (year, month, day) {
	//										// execute something that may use the year, month, day variables
	//										// for example, you could set document.location
	//									}
	//								THEN call the constructor and pass ondayclick as the second parameter.  Remember to just use the
	//								function name.  RIGHT:		new HW_Calendar(element_to_append, ondayclick, css)
	//												WRONG:		new HW_Calendar(element_to_append, ondayclick(), css)
	//								           ALSO RIGHT:		new HW_Calendar(element_to_append, function (y, m, d) { /*execute*/ }, css)
	//		css ................... is a 9-element array containing the CSS class names for various things on the calendar.  See the
	//								default value below on line 608 for an example.
	//		day_name_mode ......... tells the calendar how to display the names of the days of the week.  Options are:
	//								'full' | 'abbreviated' | 'first_letter'.  The default is 'abbreviated'.

	// Parameters
	var t = this;
	this.element_to_append = element_to_append;
	this.ondayclick = function (year, month, day) {}
	if(ondayclick)
	{
		this.ondayclick = ondayclick;						// function (year, month, day) {...}
	}
	css = css || ['HW_cal_table_class_name', 'HW_cal_month_nav_class_name', 'HW_cal_title_class_name', 'HW_cal_day_heading_class_name', 'HW_cal_day_standard_class_name', 'HW_cal_day_event_class_name', 'HW_cal_day_today_class_name', 'HW_cal_day_mouseover_class_name', 'HW_cal_day_empty_class_name'];
	
	this.day_name_mode = day_name_mode || 'abbreviated';

	// Properties
	this.table = null;
	this.days = new Array();
	this.left_td = null;
	this.title_td = null;
	this.right_td = null;
	this.day_headings = new Array();
	this.error = false;
	this.month_abbreviation = false;
	this.table_css_class_name = null;
	this.month_nav_css_class_name = null;
	this.title_css_class_name = null;
	this.day_heading_css_class_name = null;
	this.day_standard_css_class_name = null;
	this.day_event_css_class_name = null;
	this.day_empty_css_class_name = null;
	this.d = new Date();
	this.current_year = this.d.getFullYear();
	this.current_month = this.d.getMonth() + 1;
	this.current_day = this.d.getDate();

	// Default properties
	this.w = window;
	this.jsidbase = 'HW_cal_' + window.HangWire.unique_number();
	this.year = this.current_year;
	this.month = this.current_month;
	this.day = this.current_day;
	this.calendar_system = null;
	this.calendar_systems = new Object();
	this.numbering_system = false;				// default to using numbers
//	this.day_names = new Object();
//	this.day_names.full = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
//	this.day_names.abbreviated = new Array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
	this.monthdays = new Array();
	this.layout_done = false;

	// Methods
	this.add_calendar_system = HW_cal_add_calendar_system;
	this.add_leap_alternative = function (id, lid, ily, fm, lml, am) { this.calendar_systems[id].add_leap_alternative(lid, ily, fm, lml, am); }
	this.set_css = HW_cal_set_css;
	this.set_calendar_system = HW_cal_set_calendar_system;
	this.display_month_title = HW_cal_display_month_title;
	this.current_month_system = HW_cal_current_month_system;
	this.how_to_do_layout = HW_cal_do_layout;
	this.do_layout = function () { t.how_to_do_layout(); t.layout_done = true; }		// for public use
	this.change_layout = HW_cal_change_layout;
	this.set_month = HW_cal_set_month;
	this.move_month = HW_cal_move_month;
	this.move_year = HW_cal_move_year;
	this.clear_events = HW_cal_clear_events;
	this.add_event = HW_cal_add_event;
	this.use_rss = HW_cal_use_rss;
	this.how_to_get_events = function (year, month) {}
	this.how_to_do_event_layout = function (day, eventsdiv, what) {		// what is an object (associative array) of data
	}
	this.refresh = HW_cal_refresh;

	// Set Gregorian calendar system
	var fullmonths = new Array('January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December');
	var abbmonths = new Array('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec');
	var mlengths = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
	var lmlengths = new Array(31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
	var daynames = new Array('Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday');
	var abbdaynames = new Array('Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat');
	var fldaynames = new Array('S', 'M', 'T', 'W', 'T', 'F', 'S');
	this.add_calendar_system('gregorian:en', fullmonths, mlengths, abbmonths, daynames, abbdaynames, fldaynames);
	this.add_leap_alternative('gregorian:en', 'leap', function (year) { return ((year % 4 == 0) && (year % 400 != 0)); }, fullmonths, lmlengths, abbmonths);
	this.set_calendar_system('gregorian:en');

	// Create day objects
	for(var i=0; i<6; i++)
	{
		this.days[i] = new Array();
		for(var j=0; j<7; j++)
		{
			this.days[i][j] = new HW_cal_Day(i, j, this);
		}
	}

	// Create left month nav object: defaults to anchor with '<<'
	this.left_month_nav = this.w.document.createElement('a');
	this.left_month_nav.appendChild(this.w.document.createTextNode('<<'));
	this.left_month_nav.setAttribute('href', 'javascript://');
	this.left_month_nav.setAttribute('id', this.jsidbase + '_HW_cal_left');
	this.left_month_nav.onclick = function () { t.move_month(-1); }

	// Create title cell and title text objects
	this.title_td = this.w.document.createElement('td');
	this.title_td.setAttribute('id', this.jsidbase + '_HW_cal_title');
	this.title_text = this.w.document.createTextNode(window.HangWire.nbsp);
	this.title_td.appendChild(this.title_text);

	// Create right month nav object: defaults to anchor with '>>'
	this.right_month_nav = this.w.document.createElement('a');
	this.right_month_nav.appendChild(this.w.document.createTextNode('>>'));
	this.right_month_nav.setAttribute('href', 'javascript://');
	this.right_month_nav.setAttribute('id', this.jsidbase + '_HW_cal_right');
	this.right_month_nav.onclick = function () { t.move_month(1); }

	// Table for calendar
	this.table = this.w.document.createElement('table');
	this.table.setAttribute('id', this.jsidbase + '_HW_cal_table');

	// Week headings
	this.day_headings = new Array();
	for(var i=0; i<7; i++)
	{
		this.day_headings[i] = this.w.document.createElement('td');
		this.day_headings[i].setAttribute('id', this.jsidbase + '_HW_cal_day_heading_' + i);
	}

	// Layout libraries
	this.event_layouts = new Object();
	this.event_layouts.monthly_with_popup_summaries = HW_cal_event_layout_day_cells_with_summaries;
	this.event_layouts.monthly_small = HW_cal_event_layout_day_cells_small;
	this.select_event_layout = function (layout) { if(this.event_layouts[layout]) { this.how_to_do_event_layout = this.event_layouts[layout]; } }
	this.select_event_layout('monthly_with_popup_summaries');

	// Do layout, set CSS, set month and finish
	this.set_css(css[0], css[1], css[2], css[3], css[4], css[5], css[6], css[7], css[8]);
	this.set_month(this.year, this.month); /**/
}
