/*!!
Epoch DHTML JavaScript Calendar - Version 2.0.2
English Edition
Primary JavaScript File
(c) 2006-2007 MeanFreePath
Free for NON-COMMERCIAL use - see website for details and updates
http://www.meanfreepath.com/javascript_calendar/index.html
!!*/

/**
* The main Epoch class.  All publicly-accessible methods and properties are called from this class
*/
function Epoch(name,mode,targetelement,multiselect) {
	var self = this; //workaround due to varying definitions of "this" in variable scopes. see http://www.meanfreepath.com/support/epoch/epoch.html#self for details
	//DEFINE PRIVATE METHODS
	//-----------------------------------------------------------------------------
	/**
	* Declares and initializes the calendar variables.  All the variables here can be safely changed
	* (within reason ;) by the developer
	*/
	function calConfig() {
		self.versionNumber = '2.0.2';
		self.displayYearInitial = self.curDate.getFullYear(); //the initial year to display on load
		self.displayMonthInitial = self.curDate.getMonth(); //the initial month to display on load (0-11)
		self.displayYear = self.displayYearInitial;
		self.displayMonth = self.displayMonthInitial;
		self.minDate = new Date(2006,0,1);
		self.maxDate = new Date(2012,11,31);
		self.startDay = 0; // the day the week will 'start' on: 0(Sun) to 6(Sat)
		self.showWeeks = true; //whether the week numbers will be shown
		self.selCurMonthOnly = true; //allow user to only select dates in the currently displayed month
	}
	//-----------------------------------------------------------------------------
	/**
	* All language settings for Epoch are made here.
	* Check Date.dateFormat() for the Date object's language settings
	*/
	function setLang() {
		self.daylist = new Array('S','M','T','W','T','F','S','S','M','T','W','T','F','S');
		self.months_sh = new Array('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
		self.monthup_title = 'Go to the next month';
		self.monthdn_title = 'Go to the previous month';
		self.clearbtn_caption = 'Clear';
		self.clearbtn_title = 'Clears any dates selected on the calendar';
		self.maxrange_caption = 'This is the maximum range';
		self.closebtn_caption = 'Close';
		self.closebtn_title = 'Close the calendar';
	}
	//-----------------------------------------------------------------------------
	/**
	* Initializes the standard Gregorian Calendar parameters
	*/
	function setDays() {
		self.daynames = new Array();
		var j=0;
		for(var i=self.startDay;i<self.startDay + 7;i++) {
			self.daynames[j++] = self.daylist[i];
		}
		self.monthDayCount = new Array(31,((self.curDate.getFullYear() - 2000) % 4 ? 28 : 29),31,30,31,30,31,31,30,31,30,31);
	}
	//-----------------------------------------------------------------------------
	/**
	* Creates the full DOM implementation of the calendar
	*/
	function createCalendar() {
		var tbody, tr, td;
		self.calendar = document.createElement('table');
		self.calendar.setAttribute('id',self.name+'_calendar');
		setClass(self.calendar,'calendar');
		self.calendar.style.display = 'none'; //default to invisible
		//to prevent IE from selecting text when clicking on the calendar
		addEventHandler(self.calendar,'selectstart', function() {return false;});
		addEventHandler(self.calendar,'drag', function() {return false;});
		tbody = document.createElement('tbody');

		//create the Main Calendar Heading
		tr = document.createElement('tr');
		td = document.createElement('td');
		td.appendChild(createMainHeading());
		tr.appendChild(td);
		tbody.appendChild(tr);

		//create the calendar Day Heading & the calendar Day Cells
		tr = document.createElement('tr');
		td = document.createElement('td');
		self.calendar.celltable = document.createElement('table');
		setClass(self.calendar.celltable,'cells');
		self.calendar.celltable.appendChild(createDayHeading());
		self.calendar.celltable.appendChild(createCalCells());
		td.appendChild(self.calendar.celltable);
		tr.appendChild(td);
		tbody.appendChild(tr);

		//create the calendar footer
		tr = document.createElement('tr');
		td = document.createElement('td');
		td.appendChild(createFooter());
		tr.appendChild(td);
		tbody.appendChild(tr);

		//add the tbody element to the main calendar table
		self.calendar.appendChild(tbody);

		//and add the onmouseover events to the calendar table
		addEventHandler(self.calendar,'mouseover',cal_onmouseover);
		addEventHandler(self.calendar,'mouseout',cal_onmouseout);
	}
	//-----------------------------------------------------------------------------
	/**
	* Creates the primary calendar heading, with months & years
	*/
	function createMainHeading() {
		//create the containing <div> element
		var container = document.createElement('div');
		setClass(container,'mainheading');
		//create the child elements and other variables
		self.monthSelect = document.createElement('select');
		self.yearSelect = document.createElement('select');
		var monthDn = document.createElement('input'), monthUp = document.createElement('input');
		var opt, i;
		//fill the month select box
		for(i=0;i<12;i++) {
			opt = document.createElement('option');
			opt.setAttribute('value',i);
			if(self.displayMonth == i) {
				opt.setAttribute('selected','selected');
			}
			opt.appendChild(document.createTextNode(self.months_sh[i]));
			self.monthSelect.appendChild(opt);
		}
		//and fill the year select box
		var yrMax = self.maxDate.getFullYear(), yrMin = self.minDate.getFullYear();
		for(i=yrMin;i<=yrMax;i++) {
			opt = document.createElement('option');
			opt.setAttribute('value',i);
			if(self.displayYear == i) {
				opt.setAttribute('selected','selected');
			}
			opt.appendChild(document.createTextNode(i));
			self.yearSelect.appendChild(opt);
		}
		//add the appropriate children for the month buttons
		monthUp.setAttribute('type','button');
		monthUp.setAttribute('value','>');
		monthUp.setAttribute('title',self.monthup_title);
		monthDn.setAttribute('type','button');
		monthDn.setAttribute('value','<');
		monthDn.setAttribute('title',self.monthdn_title);
		self.monthSelect.owner = self.yearSelect.owner = monthUp.owner = monthDn.owner = self;  //hack to allow us to access self calendar in the events (<fix>??)

		//assign the event handlers for the controls
		function selectonchange()	{
			if(self.goToMonth(self.yearSelect.value,self.monthSelect.value)) {
				self.displayMonth = self.monthSelect.value;
				self.displayYear = self.yearSelect.value;
			}
			else {
				self.monthSelect.value = self.displayMonth;
				self.yearSelect.value = self.displayYear;
			}
		}
		addEventHandler(monthUp,'click',function(){self.nextMonth();});
		addEventHandler(monthDn,'click',function(){self.prevMonth();});
		addEventHandler(self.monthSelect,'change',selectonchange);
		addEventHandler(self.yearSelect,'change',selectonchange);

		//and finally add the elements to the containing div
		container.appendChild(monthDn);
		container.appendChild(self.monthSelect);
		container.appendChild(self.yearSelect);
		container.appendChild(monthUp);
		return container;
	}
	//-----------------------------------------------------------------------------
	/**
	* Creates the footer of the calendar - goes under the calendar cells
	*/
	function createFooter() {
		var container = document.createElement('div');
		var clearSelected = document.createElement('input');
		clearSelected.setAttribute('type','button');
		clearSelected.setAttribute('value',self.clearbtn_caption);
		clearSelected.setAttribute('title',self.clearbtn_title);
		clearSelected.owner = self;
		addEventHandler(clearSelected,'click',function() {self.resetSelections(false);});
		container.appendChild(clearSelected);
		if(self.mode == 'popup') {
			var closeBtn = document.createElement('input');
			closeBtn.setAttribute('type','button');
			closeBtn.setAttribute('value',self.closebtn_caption);
			closeBtn.setAttribute('title',self.closebtn_title);
			addEventHandler(closeBtn,'click',function(){self.hide();});
			setClass(closeBtn,'closeBtn');
			container.appendChild(closeBtn);
		}
		return container;
	}
	//-----------------------------------------------------------------------------
	/**
	* Creates the heading containing the day names
	*/
	function createDayHeading() {
		//create the table element
		self.calHeading = document.createElement('thead');
		setClass(self.calHeading,'caldayheading');
		var tr = document.createElement('tr'), th;
		self.cols = new Array(false,false,false,false,false,false,false);

		//if we're showing the week headings, create an empty <td> for filler
		if(self.showWeeks) {
			th = document.createElement('th');
			setClass(th,'wkhead');
			tr.appendChild(th);
		}
		//populate the day titles
		for(var dow=0;dow<7;dow++) {
			th = document.createElement('th');
			th.appendChild(document.createTextNode(self.daynames[dow]));
			if(self.selectMultiple) { //if selectMultiple is true, assign the cell a CalHeading Object to handle all events
				th.headObj = new CalHeading(self,th,(dow + self.startDay < 7 ? dow + self.startDay : dow + self.startDay - 7));
			}
			tr.appendChild(th);
		}
		self.calHeading.appendChild(tr);
		return self.calHeading;
	}
	//-----------------------------------------------------------------------------
	/**
	* Creates the table containing the calendar day cells
	*/
	function createCalCells() {
		self.rows = new Array(false,false,false,false,false,false);
		self.cells = new Array();
		var row = -1, totalCells = (self.showWeeks ? 48 : 42);
		var beginDate = new Date(self.displayYear,self.displayMonth,1);
		var endDate = new Date(self.displayYear,self.displayMonth,self.monthDayCount[self.displayMonth]);
		var sdt = new Date(beginDate);
		sdt.setDate(sdt.getDate() + (self.startDay - beginDate.getDay()) - (self.startDay - beginDate.getDay() > 0 ? 7 : 0) );
		//create the table element to hold the cells
		self.calCells = document.createElement('tbody');
		var tr,td;
		var cellIdx = 0, cell, week, dayval;

		for(var i=0;i<totalCells;i++) {
			if(self.showWeeks) { //if we are showing the week headings
				if(i % 8 == 0) {
					row++;
					week = sdt.getWeek(self.startDay);
					tr = document.createElement('tr');
					td = document.createElement('td');
					if(self.selectMultiple) { //if selectMultiple is enabled, create the associated weekObj objects
						td.weekObj = new WeekHeading(self,td,week,row)
					}
					else {//otherwise just set the class of the td for consistent look
						setClass(td,'wkhead');
					}
					td.appendChild(document.createTextNode(week));
					tr.appendChild(td);
					i++;
				}
			}
			else if(i % 7 == 0) { //otherwise, new row every 7 cells
				row++;
				week = sdt.getWeek(self.startDay);
				tr = document.createElement('tr');
			}
			//create the day cells
			dayval = sdt.getDate();
			td = document.createElement('td');
			td.appendChild(document.createTextNode(dayval));
			cell = new CalCell(self,td,sdt,row,week);//,'normal',sdt.getTime() >= self.minDate.getTime() && sdt.getTime() <= self.maxDate.getTime());
			self.cells[cellIdx] = cell;
			td.cellObj = cell;
			tr.appendChild(td);
			self.calCells.appendChild(tr);
			self.reDraw(cellIdx++); //and paint the cell according to its properties
			sdt.setDate(dayval + 1); //increment the date
		}
		return self.calCells;
	}
	//-----------------------------------------------------------------------------
	/**
	* Runs all the operations necessary to change the mode of the calendar
	* @param HTMLInputElement targetelement
	*/
	function setMode(targetelement)	{
		if(self.mode == 'popup') { //set positioning to absolute for popup
			self.calendar.style.position = 'absolute';
		}
		//if a target element has been set, append the calendar to it
		if(targetelement) {
			switch(self.mode) {
				case 'flat':
					self.tgt = targetelement;
					self.tgt.appendChild(self.calendar);
					self.visible = true;
					break;
				case 'popup':
					self.calendar.style.position = 'absolute';
					document.body.appendChild(self.calendar);
					self.setTarget(targetelement,false);
					break;
			}
		}
		else { //otherwise, add the calendar to the document.body (useful if targetelement will not be defined until after the calendar is initialized)
			document.body.appendChild(self.calendar);
			self.visible = false;
		}
	}
	//-----------------------------------------------------------------------------
	/**
	* Removes the calendar table cells from the DOM (does not delete the cell objects associated with them)
	*/
	function deleteCells() {
		self.calendar.celltable.removeChild(self.calendar.celltable.childNodes[1]); //remove the tbody element from the cell table
	}
	//-----------------------------------------------------------------------------
	/**
	* Sets the CSS class of the element, W3C & IE
	* @param HTMLElement element
	* @param string className
	*/
	function setClass(element,className) {
		element.setAttribute('class',className);
		element.setAttribute('className',className); //<iehack>
	}
