//
// Enhanced JavaScript Event Calendar
//
// Author:  Rick Pike
// Website: http://calendar.pikesys.com
// Email: calendar@pikesys.com
//'Version 0.3 - (07-May-2004)
// based on an earlier script by Kevin Ilsen (http://calendar.ilsen.net or kevin@ilsen.net)
// updated by Michael Dunn - 2008 - css and database driven

// Configurable values are set to defaults here; you can override them before calling Calendar( ) from your HTML page

var SpecialDay=0;	// 1=Sunday, 2=Monday, . . . 7=Saturday
var showAltDate = false;  	// add display of alternate date using results from user supplied "getAltMonth(dy, mo, yr, last)" and "getAltDate(dy, mo, yr)" functions
var showHolidays = false; 	// add display of holidays using result from user supplied "holidays(dy, mo, yr)" function
var showAltHoly = false; 	// add display of alternate holidays using result from user supplied "getAltHoly(dy, mo, yr)" function
var showNav = true; 		// enable month navigation (might disable for print version)
var showImages = true; 	// enable event images (might disable for print version)
var showLinks = true; 		// enable event hyperlinks (might disable for print version)
var imageAlign = "left"; 	// default event image alignment
var imageScale = 100;		// percent scale factor for images
var altAlign = true; 		// alternate left/right alignment of event images on same date for readability
var DefaultFormat = "custom"; // for compatibility; set to "layer" to simplify formatting
var ExportPage = ""; 		// name of html page for displaying event text for export
var PrintPage = ""; 		// name of html page for printer-friendly format
var printing = false;
var msgBoxBorder = 0;
// all format codes must have "|" to separate before and after tags
var DateFontSize=5;
var AltDateFormat = "<font color=#999999 size=2>|</font>";
var MonthFormat = "<font size=" + DateFontSize + "><b>|</b></font>";
var AltMonthFormat = "<br><font color=#999999 size=" + DateFontSize/2 + ">|</font>";
var HolidayFormat = "<font color=#999999 size=2><b><center>|</center></b></font>";
var AltHolyFormat = "<font  size=2><b><center>|</center></b></font>";
var defaultMsgBox = "";
var courses = new Array();

// Initialize the range of the calendar to Jan - Dec of the current year.
// Event definitions will change this as needed; or it can be explicitly
// overridden before calling Calendar( ) from the HTML page.

var today = new Date();
var FirstMonth=GetFullYear(today) * 100 + 1;
var LastMonth=FirstMonth + 200; //100 = 1 year

// Events[] is a SPARSE array; Call AddEvent( ) to populate it or DefineEvent( ) for
// compatibility with existing calendar definition scripts.

var Events = new Array;

// Each event is defined by calling the AddEvent( ) routine with the following parameters:
//
//   AddEvent(Date, Description, Layer, Format, Link, Image, Width, Height, Align, Alt)
//        Date is a numeric value in the format YYYYMMDD
//        Description is a string (may include embedded HTML tags such as <BR>, <strong>, etc.)
//        Layer is an event category whose display on the calendar can be toggled on/off by the user
//        Format specifies the source of the format info for Description. Note that any embedded
//        formats in Description will still be applied; this argument is primarily to provide
//        a more convenient way to specify formats. 
//            "layer" = use default format from layer definition (plus any embedded tags!)
//            "custom" = only use format tags embedded in Description string
//            "<...>|</...>" = series of before and after tags separated by a "|" to wrap around
//               Description (plus any embedded tags!)  
//        Link is the URL of the target page if a hyperlink is desired from this event entry
//        Image is the URL of the image if you want to display an image with this event
//        Width is the width of the image in pixels
//        Height is the height of the image in pixels
//        Align is the alignment of the image such as "left", or "right"
//        Alt is the alternate text of the image (for mouseover or non-graphic browser)

// The function DefineEvent(Date, Description, Link, Image, Width, Height) is used
// for compatibility with previous calendar definition scripts

// Event constructor
function Event(description, layer, format, link, image, width, height, align, alt) {

	this.description = description;
	if (link) this.link = link;
	if (image) {
	   this.image = image;
	   if (width) this.width = width;
	   if (height) this.height = height;
	   if (align) this.align = align;
	   if (alt) this.alt = alt;
	   //alert("Event: ("+this.width+","+this.height+")");
	}
	
	if (format) {
	   if (CheckFormat(format)) this.format = format;
	}
}

// Compatibility function for existing calendar definition scripts
function DefineEvent(Date, Description, Link, Image, Width, Height) {
	AddEvent(Date, Description, "", "", Link, Image, Width, Height, "", "");
}

function AddEvent(Date, Description, Link)
{
	AddEvent(Date, Description, '', '', Link, '', 0, 0, '', ''); 
}

function AddEvent(Date, Description, Layer, Format, Link, Image, Width, Height, Align, Alt) {
	var i;
	if (!Events[Date]) Events[Date] = new Array;
	i = Events[Date].length;
	Events[Date][i] = new Event(Description, Layer, Format, Link, Image, Width, Height, Align, Alt);

	// Adjust the minimum and maximum month & year to include this date
	tmp = Math.floor(Date / 100);
	if (tmp < FirstMonth) FirstMonth = tmp;
	if (tmp > LastMonth) LastMonth = tmp;
}

// Utility function to populate an array with values
function arr() {
	for (var n=0;n<arr.arguments.length;n++) {
		this[n+1] = arr.arguments[n];
	}
}

// Create the array of month names (used in various places)
var months = new arr("January","February","March","April","May","June","July","August","September","October","November","December");

// Calendar( ) is the only routine that needs to be called to display the calendar
var cookieName = "AgamaCalendar";
var pre, post, tmp, gloMo, gloYr, gloYearmonth;

function Calendar( ) {
	var curdy, curmo, curyr, yr, mo, dy, firstday, yearmonth, bgn, lastdate, jump;
	var weekdays = new arr("Sun","Mon","Tue","Wed","Thu","Fri","Sat");
	var thispage = window.location.pathname;
	var myMsgBox = "";

	// Save current day and month for comparison
	curdy = today.getDate();
	curmo = today.getMonth()+1;
	curyr = today.getFullYear();
	
	initCal(curmo);
	mo = gloMo; yr = gloYr; yearmonth = gloYearmonth;
	
	// Create a date object for the first day of the desired month
	bgn = new Date(months[mo] + " 1," + yr);
	// Get the day-of-week of the first day, and the # days in the month
	firstday = bgn.getDay();
	lastdate = NumDaysIn(mo,yr);
	lastday = 1+(firstday + lastdate - 1)%7;
	prev = next = "&nbsp;";
	if (showNav) {
		if (yearmonth > FirstMonth)
			prev = '<a class="navlink" href="' + thispage + '?'+PrevYearMonth(yearmonth)+'">View '+months[PrevMonth(mo)]+'</a>';
		if (yearmonth < LastMonth)
			next += '<a class="navlink" href="' + thispage + '?'+NextYearMonth(yearmonth)+'">View '+months[NextMonth(mo)]+'</a>';
	}

	parseFormat(MonthFormat);
	tmp = "<TABLE CLASS=mainTable><TR CLASS=nav>";
	tmp += "<TD ALIGN=CENTER CLASS=nav>" + prev + "</TD>";
	tmp += "<TD ALIGN=CENTER COLSPAN=5 CLASS='title'>" + months[mo] + " " + yr;
	/*
	if (showAltDate) {
		parseFormat(AltMonthFormat);
		altMonth = getAltMonth(1, mo, yr, lastdate);
		tmp += pre + (altMonth ? altMonth : "") + post;
	}*/
	tmp += "</TD><TD ALIGN=CENTER CLASS=nav>" + next + "</TD></TR>";
	document.write(tmp);
	document.write("<TR CLASS=nav>");
	
	for (var i=1;i<=7;i++){
		document.write("<TD ALIGN=CENTER WIDTH=14% CLASS=wkdays>"+weekdays[i]+"</TD>");
	}
	dy = 1;
	document.write("</TR><TR>");

	while (dy <= lastdate) {
		for (var i=1; i<=7; i++) {
			
			// If the day cell is before the first day of the month, print a miniMonth display of previous month in the first cell, 
			// otherwise print a space in this cell of the table.
			if (dy == 1 && i <= firstday) {
				if (i == 1) {
							document.write("<TD>");
					
				} 
				else {
					document.write("<TD>");
				}
				document.write("</TD>");

			// If the day cell is after the last day of the month, print a miniMonth display of following month in the last cell, 
			// otherwise print a space in this cell of the table.
			} else if (dy > lastdate) {
				if (i == 7) {
					document.write("<TD>");
				} 
				else {
					document.write("<TD>");
				}
				document.write("</TD>");

			// Otherwise, write date and the event, if any, in this cell of the table.
			} else {
				if((dy == curdy) && (mo == curmo))
					document.write("<TD CLASS=todayCell VALIGN=TOP>");
				else
					document.write("<TD CLASS=cell VALIGN=TOP><div class=cellContent id=cell"+dy+">");
				ShowDate(yr,mo,dy,i,curmo,curdy);
				document.write("</div></TD>");				
				dy++;
			}
		}
		document.write("</TR>");
	}

	//var moTmp = (gloYr - curyr)*12 + mo; alert (gloYr);
	var moTmp = (gloYr - Math.floor(FirstMonth/100))*12 + mo;
	if(moTmp > 0)
	{
		tmp = "<TR CLASS=NAV><TD COLSPAN=7 VALIGN=MIDDLE><div class=coursesoffered><p align=center>Courses offered this month: "+courses[moTmp]+"</p></div></TD><TR>";
	}
	else { tmp = "<TR CLASS=NAV><TD COLSPAN=7 VALIGN=MIDDLE></TD><TR>"; }
	document.write(tmp);
	
	if (showNav) {
		prev = next = "";
		if (yearmonth > FirstMonth)
			prev = '<a class="navlink" href="' + thispage + '?'+PrevYearMonth(yearmonth)+'">View '+months[PrevMonth(mo)]+'</a>';
		if (yearmonth < LastMonth)
			next += '<a class="navlink" href="' + thispage + '?'+NextYearMonth(yearmonth)+'">View '+months[NextMonth(mo)]+'</a>';
		tmp = "<TR CLASS=nav><TD VALIGN=bottom ALIGN=CENTER CLASS=nav><div class='bottomNav'>" + prev + "</div></TD>";
		tmp += "<TD colspan=5 align=center VALIGN=bottom><div class='bottomNav'><FORM>";
		/*if (ExportPage) tmp += '<a class="navlink" href="' + ExportPage + '?'+yearmonth+'">Export Events Displayed</a>|';*/
		tmp += '<span class=navlink>Jump to month: ';
		document.write(tmp);
		BuildSelectionList(yearmonth, thispage);
		if (PrintPage) document.write(' | <a target="_blank" href="' + PrintPage + '?'+yearmonth+'">Print-friendly</a> | <a  href="http://www.agamayoga.com/calendar/index.htm">List View</a> | <a href="/">Back to Homepage</a></span>');
		tmp = "</FORM></div></TD><TD VALIGN=bottom ALIGN=CENTER CLASS=nav><div class='bottomNav'>" + next + "</div></TD>";
		document.write(tmp + "</TR>");
		
	}
	document.write("</TABLE>");
}

// Display a date in the appropriate color, with events (if there are any)

function ShowDate(yr, mo, dy, dayofweek, currentmonth, currentday) {

	var ind, DayHighlighted, tmp, event;

	tmp = "<TABLE><TR VALIGN=TOP><TD ALIGN=LEFT WIDTH=10%";
	
	DayHighlighted = false;
	var spanClass = 'normalDate';
	
	if ((mo == currentmonth) && (dy == currentday)) {
		DayHighlighted = true;
		spanClass = 'todayClass';
		
	} else if (dayofweek == SpecialDay) {
		DayHighlighted = true;
	}

	ind = (((yr * 100) + mo) * 100) + dy;
	if (Events[ind]) {
		//event = Events[ind];
		if (!DayHighlighted) spanClass = 'event';
//	} else {
//		event = "&nbsp;<BR>&nbsp;";
	}
	
	
	tmp += "><B><span class='"+spanClass+"'>" + dy + (dy<10 ? "" : "") +"</span>" + "</B></TD>";	 	// close tag
	document.write(tmp);
	
	if (showAltDate) {
		altDate = getAltDate(dy, mo, yr);
		parseFormat(AltDateFormat);
		document.write("<TD ALIGN=RIGHT>" + pre + altDate + post + "</TD>");
	}
	document.write("</TR></TABLE>");

	if (showAltHoly) {
		tmp = getAltHoly(dy,mo,yr);
		if (tmp) {
			parseFormat(AltHolyFormat);
			document.write(pre + tmp + post + "<BR>");
		}
	}
	
	if (showHolidays) {
		tmp = holidays(dy,mo,yr);
		if (tmp) {
			parseFormat(HolidayFormat);
			document.write(pre + tmp + post + "<BR>");
		}
	}
//	document.write("<P><FONT SIZE=1>" + event + "</FONT>");

	images=0;
	for (j in Events[ind]) {
		ev = Events[ind][j];
		// with(Events[ind][j]) { // greatly improves readability of following
		//for (k in ev) { alert("ev["+k+"]="+ev[k]) }
		//  document.write("Events[" + ind + "][" + j + "][" + k + "] = " + EscapeLtGt(Events[ind][j][k]), "<br>");
		
		tmp = "";		
		// Build the HTML string for this event
		tmp += (j>0 ? "<br>" : "");
			if (ev.image && showImages) {
				if (ev.align) {
					align = ev.align;
				} else if (altAlign && images>0) {
					align = (lastAlign=="left" ? "right" : "left");
				} else {
					align = imageAlign;
				}
				tmp += '<img src="' + ev.image + 
					   (ev.width ? '"  width="' + ev.width*imageScale/100 : '') +
					   (ev.height ? '" height="' + ev.height*imageScale/100 : '') +
					   (ev.alt ? '" alt="' + ev.alt : '') +					   
					   '" align="' + align + '" valign="top">';
				lastAlign = align;
				images++;
			}
			format = "";
			if (ev.format == "custom") { // use only embedded tags
				format = "";
			} else if (ev.format) { 	// format string?
				if (CheckFormat(ev.format)) format = ev.format;
			}
			parseFormat(format);
			
			if((currentday == dy)&&(currentmonth == mo)&&(!printing))	{
				tmp += pre + (ev.link && showLinks ? "<a style='color:FFFFFF' href="+ev.link+">"+ev.description+"</a>" : "<span style='color:FFFFFF'>"+ ev.description + "</span>") + post + "<br>";
			}
			
			else {
				tmp += pre + (ev.link && showLinks ? "<a style='color:000000' href="+ev.link+">"+ev.description+"</a>" : ev.description) + post + "<br>"; 
			}
			
		
		
	document.write("<span class='eventDescription'>"+tmp+"</span>");
	}
}

function initCal(curmo) {

	// Default to current month and year
	mo = curmo;
	yr = GetFullYear(today);
	yearmonth = (yr * 100) + mo;

	// If querystring parameter is present, get the month/year ("calendar.php?YYYYMM")
	if (location.search.length > 1) {
		yearmonth = parseInt(location.search.substring(1,location.search.length));
		if ((""+yearmonth).length == 6) {
			mo = yearmonth % 100;
			yr = (yearmonth - mo) / 100;
		}
	}

	// Constrain to the range of months with events
	if (yearmonth < FirstMonth) {
		mo = FirstMonth % 100;
		yr = (FirstMonth - mo) / 100;
		yearmonth = FirstMonth;
	}
	if (yearmonth > LastMonth) {
		mo = LastMonth % 100;
		yr = (LastMonth - mo) / 100;
		yearmonth = LastMonth;
	}
	gloMo = mo; gloYr = yr; gloYearmonth = yearmonth;
}

function qw(string) {
	return "\"" + string + "\"";
}

// Remaining routines are utilities used above

function NumDaysIn(mo,yr) {
	if (mo==4 || mo==6 || mo==9 || mo==11) return 30;
	else if ((mo==2) && LeapYear(yr)) return 29;
	else if (mo==2) return 28;
	else return 31;
}

function LeapYear(yr) {
	return ( (yr%4 == 0 && yr%100 != 0) || yr % 400 == 0 ? true : false );
}

// fixes a Netscape 2 and 3 bug
function GetFullYear(d) { // d is a date object
	var yr = d.getYear();
	return ( yr < 1000 ? yr + 1900 : yr );
}

function PrevMonth(mth) {
	return ( mth == 1 ? 12 : mth - 1 );
}

function NextMonth(mth) {
	return ( mth == 12 ? 1 : mth + 1 );
}

function PrevYearMonth(yrmth) {
	return ( yrmth%100 == 1 ? yrmth-100+11 : yrmth-1 );
}

function NextYearMonth(yrmth) {
	return ( yrmth%100 == 12 ? yrmth-11+100 : yrmth+1 );
}

function JumpTo(calendar, thispage) {
	var sel, yrmo;

	sel = calendar.selectedIndex;
	yrmo = calendar.form.jumpmonth[sel].value;
	document.location = thispage + "?" + yrmo;
}

function BuildSelectionList(current, thispage) {
	var mo, yr, yearmonth;

	yearmonth = FirstMonth;
	tmp = "<select name=\"jumpmonth\" size=1 onchange=\"JumpTo(this,'" + thispage + "')\">";
	while (yearmonth <= LastMonth) {
		mo = yearmonth % 100;
		yr = (yearmonth - mo) / 100;
		selected = (yearmonth == current ? " selected" : "");
		tmp += "<option value=" + yearmonth + selected + ">" + months[mo]+" "+yr;
		yearmonth = NextYearMonth(yearmonth);
	}

	document.write(tmp + "</select>");
}

// Utility routines

function escramVal(j,k){var a,b,c,d,e;a='<a href=\"mai';c='\">';a+='lto:';b=j+'@';e='</a>';b+=k;d=b;return(a+b+c+d+e);}

function parseFormat(format) {
	// pre and post are globals
	pre = post = "";
	if (format) {		
		var sep = format.indexOf("|");
		if (sep > 0) {  // split format into pre and post strings
			pre = format.substring(0, sep);
			post= format.substring(1+sep, format.length);
		}
	}
}

function CheckFormat(String) {
	var okay;
	okay =(String == "custom" || String.indexOf("|")>0);
	if (!okay) alert("Invalid Calendar Format String: " + String);
	return okay;
}

			
							   