/*
calendar.js

Copyright 2005 Pyramis Studios, Inc. / http://www.pyramis-studios.com

Author: 		Andrew Mace
Created:		20050111
Last Modified:	20050721
Prerequisites:	xhr.js
				calendar.cgi (or source to query calendar xml data)

LEGAL NOTICE:
THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTIES OF ANY KIND EITHER EXPRESS OR IMPLIED. TO THE FULLEST EXTENT POSSIBLE PURSUANT TO THE APPLICABLE LAW, PYRAMIS STUDIOS, INC. DISCLAIMS ALL WARRANTIES, EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT OR OTHER VIOLATION OF RIGHTS. 

LIMITATION OF LIABILITY
UNDER NO CIRCUMSTANCES, INCLUDING, BUT NOT LIMITED TO, NEGLIGENCE, SHALL PYRAMIS STUDIOS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING, BUT NOT LIMITED TO, LOSS OF DATA OR PROFIT, ARISING OUT OF THE USE, OR THE INABILITY TO USE, THE MATERIALS IN THIS FILE, EVEN IF PYRAMIS STUDIOS, INC. OR A PYRAMIS STUDIOS AUTHORIZED REPRESENTATIVE HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. IF YOUR USE OF MATERIALS FROM THIS FILE RESULTS IN THE NEED FOR SERVICING, REPAIR OR CORRECTION OF EQUIPMENT OR DATA, YOU ASSUME ANY COSTS THEREOF. SOME PROVINCES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF INCIDENTAL OR CONSEQUENTIAL DAMAGES OR THE EXCLUSION OF LIABILITY IN CERTAIN CIRCUMSTANCES, SO THE ABOVE LIMITATION OR EXCLUSION MAY NOT APPLY TO YOU.

THIS FILE MAY NOT BE USED IN ANY OTHER WAY THAN ITS EXPRESS PURPOSE. REDISTRIBUTION OF THIS FILE OR THE CREATION OF DERIVATIVE WORKS IS NOT PERMITTED.

COPYRIGHT 2005 PYRAMIS STUDIOS, INC. ALL RIGHTS ARE RESERVED.

MODIFYING OR REMOVING THE CONTENTS OF THIS FILE BEFORE THIS LINE IS NOT PERMITTED.
*/

/* globals */
/* 
	----- Implement these functions/values -----
*/	
var calRange = 2; // 0 = day, 1 = week, 2 = month, also set in body onload handler
var calDataSource = '/rooms/calendar.cgi';
var calPressColor = '#666666'; // the border color around a pressed box
var calTimerLength = 500; // ms

var calSelectState = [0,0,0,calRange,'','']; // [year,month,day,calRange,searchString,calendars]
var calAction = 0; // 0 = select, 1 = unselect
var calTimerId = 0;
var calDetailed = []; // remember which items are expanded for sending and retrieving

function calGrid(n)
{ // open selected calendar in grid view in new window

	var d = new Date();
	var y = d.getFullYear();
	var m = d.getMonth();
	if(m < 10) m = '0' + m;

	window.open('calendar.cgi?c=' + n + '&x=grid&from=' + y + m + '01','_blank','addressbar=no,toolbar=no,status=no,menubar=no,scrollbars=yes,resizable=yes');
}

function calRefresh()
{ // resend the queries
	var f = document.forms.calSearch;
	if(f != null) f.q.value = calSelectState[4];
	calSubmit();
}

function calSubmit()
{ // Send the query to the server - date range, search query
	calTimerId = 0;

	var f = document.forms.calSearch;
	var q = '';
	if(f != null) {
		q = f.q.value;
		f.q.value = '';
	}
	calSelectState[4] = q; // update the search string	
	f = document.forms.calCalendars;
	var c = '';
	if(f != null) {
		var cbs = f.getElementsByTagName('input');
		for(var i = 0; i < cbs.length; i++) {
			if(cbs[i].name == 'c' && cbs[i].checked) {
				c += cbs[i].value;
			}
		}
		calSelectState[5] = c; // update which calendars we're searching
	}
	if(!c.length) {
		alert('Please select at least one calendar to search');
		return(false);
	}
	var d1 = calToYYYYMMDD();
	var d2;
	if(calRange == 0) { // day
		d2 = d1;
	} else if(calRange == 1) { // week
		var tmp = new Date(calSelectState[0],calSelectState[1],calSelectState[2]);
		var n = tmp.getDay();
		var ms = tmp.getTime() + tmp.getTimezoneOffset() * 60000;
		tmp.setTime(ms - (n * 86400000));
		d1 = calToYYYYMMDD(tmp.getFullYear(),tmp.getMonth(),tmp.getDate());
		tmp.setTime(ms + ((6 - n) * 86400000));
		d2 = calToYYYYMMDD(tmp.getFullYear(),tmp.getMonth(),tmp.getDate());
	} else if(calRange == 2) { // month
		d1 = calToYYYYMMDD(calSelectState[0],calSelectState[1],1);
		var nd = Date.monthLengths[calSelectState[1]];
		if(calSelectState[1] == 1 && Date.isLeap(calSelectState[0])) nd++;
		d2 = calToYYYYMMDD(calSelectState[0],calSelectState[1],nd);
	}
	cal_previous_status_msg = '';
	var s = 'c=' + c + '&q=' + encodeURIComponent(q) + '&from=' + d1 + '&to=' + d2;
	// send which ones have been expanded as well
	s += '&d=' + calDetailed.join(',');
	xhr_info_id = 'cal_status'; // set status message area
	xhr_load(calDataSource,'POST',s);
}

/* calDetail functions relevant if not all event data sent initially */
function calDetail(id)
{
	var el = document.getElementById(id + '_detail');
	if(el != null) {
		if(el.style.display != 'block') 
			calDetailShow(id);
		else
			calDetailHide(id);
	}
}
var cal_previous_status_msg;
function calDetailShow(id)
{
	var el = document.getElementById(id + '_detail');
	if(el != null) {
		el.style.display = 'block';
		if(el.innerHTML.length < 8) {
			xhr_info_id = 'cal_status'; // set status message area
			cal_previous_status_msg = document.getElementById(xhr_info_id).innerHTML;
			xhr_serial = false; // allow multiple detail requests
			xhr_load(calDataSource,'POST','x=detail&id=' + id);
		}
		for(var i = 0; i < calDetailed.length; i++) {
			if(calDetailed[i] == id) return;
		}
		calDetailed.push(id);
	}
}
function calDetailHide(id)
{
	var el = document.getElementById(id + '_detail');
	if(el != null) {
		el.style.display = 'none';
		for(var i = 0; i < calDetailed.length; i++) {
			if(calDetailed[i] == id) {
				calDetailed.splice(i, 1);
				return;
			}
		}		
	}
}



/* --------------------------------------------

	----- Standardized code below -----
	----- See also xhr.js for XmlHttpRequest handling ------
	
-------------------------------------------- */

function xhr_error_custom(r)
{
	if(r == -1) { // XMLHttpRequest not supported
		// REDIRECT HERE TO PAGE NOTIFYING USER OF CALENDAR REQUIREMENTS
	} else {
		xhr_info(r.status); // update status message
	}
}

function xhr_process_custom(r)
{
	var doc = r.responseXML;
	var nodes = doc.lastChild.childNodes;
	var id;
	for(var i = 0; i < nodes.length; i++) {		
		if(nodes[i].nodeName == 'ht') {
			id = nodes[i].getAttribute('id');
			var el = document.getElementById(id);
			if(el) { // was id == xhr_info_id
				if(id == 'cal_status' && nodes[i].firstChild.nodeValue.length < 7 && cal_previous_status_msg.length) {
					el.innerHTML = cal_previous_status_msg;
				} else {
					el.innerHTML = nodes[i].firstChild.nodeValue;	
				}
			}
		} else if(nodes[i].nodeName == 'js') { // handle js after all page updates
			xhr_queue_js.push([nodes[i].getAttribute('id'),nodes[i].getAttribute('args')]);
		}
	}
	return(true); // return true to prevent standard xhr_process()ing
}

// xhr_process_js_custom to do custom js calling

/* ---------------------------


DATE AND CALENDAR FUNCTIONS 


--------------------------- */

Date.days 			= ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
Date.months 		= ['January','February','March','April','May','June','July','August','September','October','November','December'];
Date.monthLengths 	= [31,28,31,30,31,30,31,31,30,31,30,31];

Date.isLeap = function(y)
{
	return(((y & 3) == 0) ^ (y % 100 == 0) ^ (y % 400 == 0)); 
}

Date.getDayOfWeek = function(y,m,d)
{
	return((new Date(y,m,d)).getDay());
}

Date.today = function()
{
	var d = new Date();
	return(d.getFullYear() + "_" + d.getMonth() + "_" + d.getDate());
}

function calQueue(n)
{
	if(calTimerId != 0) window.clearTimeout(calTimerId);
	if(n == null) n = calTimerLength;
	calTimerId = window.setTimeout("calSubmit()",n);
}

function calSetRange(n)
{
	if(n < 0 || n > 2 || calRange == n) return;
	calRange = n;
	calSelect();
	if(calSetRange_custom) calSetRange_custom(n);
}

function calFromMilitary(s) 
{
	var h = parseInt(s.slice(0,2));
	var m = s.slice(2);
	var ampm = ' AM';
	if(h >= 12) {
		if(h > 12) h -= 12;
		ampm = ' PM';
	} else if(h == 0) {
		h = 12;
	}
	return(h + ':' + m + ampm);
}

function calFromYYYYMMDD(s,flg)
{ // convert a string like 20050725 into Monday, July 25, 2005
/*
flg & 1 = don't include year
flg & 2 = don't include day of week
*/
	var y = s.slice(0,4);
	var m = parseInt(s.slice(4,6));
	var d = parseInt(s.slice(6));
	var n = Date.getDayOfWeek(y,m,d);
	return(((flg & 2) ? '' : Date.days[n] + ', ') + Date.months[m] + ' ' + d + ((flg & 1) ? '' : ', ' + y));
}

function calToYYYYMMDD(y,m,d)
{ // convert 2005,7,25 into 20050725
	var s;
	if(y == null) {
		y = calSelectState[0];
		m = calSelectState[1];
		d = calSelectState[2];
	}
	s = "" + y;
	if(m < 10) m = '0' + m;
	s += m;
	if(d < 10) d = '0' + d;
	s += d;	
	return(s);
}

function calPress(o)
{ // mouse press on calendar day box, update styles
	var s = o.style;
	s.borderTopColor = s.borderLeftColor = s.borderRightColor = s.borderBottomColor = calPressColor;	
	if(o.onmouseup == null) {
		o.onmouseup = function() {
			this.onmouseout = null;
			var els = this.id.split('_');
			calSelect(els[0],els[1],els[2]);
		}
	}
	if(o.onmouseout == null) {
		o.onmouseout = function() {
			var s = this.style;
			s.borderTopColor = s.borderLeftColor = s.borderRightColor = s.borderBottomColor = "";	
		}	
	}
}

function calUnselect()
{
	if(calSelectState[0] == 0) return;
	var y = calSelectState[0];
	var m = calSelectState[1];
	var d = calSelectState[2];
	var r = calSelectState[3];
	var tmp = calRange;
	calRange = r;
	calAction = 1; // unselect
	_calSelect(y,m,d);
	calRange = tmp;
	calAction = 0; // select re-enabled
}

function calSelect(y,m,d)
{
	calUnselect();
	if(y == null) { // use calSelectState
		y = calSelectState[0];
		m = calSelectState[1];
		d = calSelectState[2];
		if(calSelectState[3] != calRange) calQueue();
	} else {
		if(calSelectState[3] != calRange) calQueue();
		else if(calSelectState[0] != y) calQueue();
		else if(calSelectState[1] != m) calQueue();
		else { // same year and month		
			if(calSelectState[2] != d) { // day changed
				if(calRange == 1) { // determine if the new day is in the same week
					var d1 = new Date(y,m,calSelectState[2]);
					var n = d1.getDay();
					var w0 = calSelectState[2] - n;
					if(d < w0 || d > w0 + 6) calQueue();
				} else if(calRange == 0) calQueue();
			}
		}
		calSelectState[0] = y;
		calSelectState[1] = m;
		calSelectState[2] = d;
	}
	calSelectState[3] = calRange;
	_calSelect(y,m,d);
}

function _calSelect(y,m,d)
{
	var o = document.getElementById(y + '_' + m + '_' + d);
	if(o == null) return;
	
	var s = o.style;
	s.borderTopColor = s.borderLeftColor = s.borderRightColor = s.borderBottomColor = "";	
	
	if(calRange == 0) {
		calSelectDay(y,m,d,o);
	} else if(calRange == 1) {
		calSelectWeek(y,m,d,o.parentNode.parentNode);
	} else if(calRange == 2) {
		calSelectMonth(y,m,d);
	}
}

function calSelectDay(y,m,d,o,flg)
{
	if(o == null) o = document.getElementById(y + '_' + m + '_' + d);
	if(o != null) {
		if(calAction == 0) {
			if(o.className == 'cal_d') o.className = 'cal_d_on';
			else if(o.className == 'cal_dtoday') o.className = 'cal_dtoday_on';
			else if(o.className == 'cal_dx' && !flg) o.className = 'cal_dx_on';
		} else {
			if(o.className == 'cal_d_on') o.className = 'cal_d';
			else if(o.className == 'cal_dtoday_on') o.className = 'cal_dtoday';
			else if(o.className == 'cal_dx_on') o.className = 'cal_dx';
		}
	}
}

function calSelectWeek(y,m,d,o,flg)
{ // get all els in the row
	if(o == null) {
		o = document.getElementById(y + '_' + m + '_' + d);
		if(o == null) return;
		o = o.parentNode.parentNode;
	}
	if(o != null) {
		for(var i = 0; i < o.childNodes.length; i++) {
			if(o.childNodes[i].nodeType == 1 && o.hasChildNodes() && o.childNodes[i].firstChild.nodeType == 1) {
				calSelectDay(y,m,d,o.childNodes[i].firstChild,flg);
			}
		}
	}
}

function calSelectMonth(y,m,d)
{
	for(var i = 1; i < 43; i += 7) {
		calSelectWeek(y,m,i,null,true);
	}
}

function calDrawMonthN(y,m,n)
{
	var m2 = m;
	var y2 = y;
	var e = document.getElementById('cal_months');
	var s = "";
	var flg = 0;
	// flg & 1 = include SMTWTFS; flg & 2 = include previous month; flg & 4 = include next month
	for(var i = 0; i < n; i++) {
		flg = 0;
		if(i == 0) flg = 3;
		if(i == n - 1) flg |= 4;
		s += _calDrawMonth(y,m++,flg,n);
		if(m == 12) {
			y++;
			m = 0;
		}
	}
	e.innerHTML = s;
	calSelect();
}
function calDrawMonthN_queue(y,m,n)
{
	window.setTimeout("calDrawMonthN(" + y + "," + m + "," + n + ")", 5);
}

function calDrawMonth(y,m)
{
	var e = document.getElementById('cal_months');
	var s = _calDrawMonth(y,m);
	e.innerHTML = s;
}

function _calDrawMonth(y,m,flg,q)
{ // flg & 1 = include SMTWTFS; flg & 2 = include previous month; flg & 4 = include next month
	var out = '<div class="cal"><table cellpadding="0" cellspacing="0" border="0" style="width: 100%;">';
	
	if(flg & 2) {
		var m2 = m - 1;
		var y2 = y;
		if(m2 < 0) {
			m2 += 12;
			y2--;
		}
		out += '<tr><td class="cal_tdtl">&nbsp;</td><td colspan="7" class="cal_tdt">&nbsp;</td><td class="cal_tdtr">&nbsp;</td>';
		out += '<tr><td class="cal_tdl">&nbsp;</td><td colspan="7"><div class="cal_jumpt" onMouseUp="calDrawMonthN_queue(' + y2 + ',' + m2 + ',' + q + ')">&laquo;&nbsp;' + Date.months[m2] + " " + y2 + '&nbsp;&nbsp;</div></td><td class="cal_tdr">&nbsp;</td></tr>';
	}
	
	out += '<tr><td class="cal_tdl">&nbsp;</td><td colspan="7"><div class="cal_h">' + Date.months[m] + " " + y + '</div></td><td class="cal_tdr">&nbsp;</td></tr>';

	if(flg && flg & 1) {
		out += '<tr><td class="cal_tdl">&nbsp;</td>';
		for(var i = 0; i < 7; i++) {
			out += '<td><div class="cal_ch">' + Date.days[i].slice(0,1) + "</div></td>";
		}
		out += '<td class="cal_tdr">&nbsp;</td></tr>';
	}

	var first = Date.getDayOfWeek(y,m,1);
	var i = -1;
	var n = Date.monthLengths[m] + first;
	if(m == 1 && Date.isLeap(y)) n++;	
	var total = n;
	if(total % 7 != 0) {
		total += (7 - (total % 7));
	}
	var t = Date.today();

	var k;
	if(m == 0) {
		k = Date.monthLengths[11];
	} else {
		k = Date.monthLengths[m - 1];
		if(m - 1 == 1 && Date.isLeap(y)) k++;
	}
	
	while(++i < n) {
		if(i % 7 == 0) out += '<tr><td class="cal_tdl">&nbsp;</td>';
		if(i < first) {
			out += '<td><div class="cal_dx">' + (k - (first - i) + 1) + '</div></td>';
		} else {
			var c = (t == y + '_' + m + '_' + (i - first + 1)) ? 'cal_dtoday' : 'cal_d';
			out += '<td><div class="' + c + '" id="' + y + '_' + m + '_' + (i - first + 1) + '" onMouseDown="calPress(this)">';
			out += (i - first + 1) + "</div></td>";
		}
		if((i + 1) % 7 == 0) out += '<td class="cal_tdr">&nbsp;</td></tr>';
	}
	if(i < total) {
		k = 1;
		while(i % 7 != 0) {
			out += '<td><div class="cal_dx" id="' + y + '_' + m + '_' + (i - first + 1) + '">' + k + '</div></td>';
			i++;
			k++;
		}
		out += '<td class="cal_tdr">&nbsp;</td></tr>';
	}
	// pad the bottom
	out += '<tr><td class="cal_tdl">&nbsp;</td><td colspan="7">&nbsp;</td><td class="cal_tdr">&nbsp;</td>';
	
	if(flg & 4) {
		var m2 = m + 1;
		var y2 = y;
		if(m2 > 11) {
			m2 -= 12;
			y2++;
		}
		var m3 = m2 - q + 1;
		var y3 = y2;
		if(m3 < 0) {
			m3 += 12;
			y3--;
		}
		out += '<tr><td class="cal_tdl">&nbsp;</td><td colspan="7"><div class="cal_jumpb" onMouseUp="calDrawMonthN_queue(' + y3 + ',' + m3 + ',' + q + ')">&nbsp;&nbsp;' + Date.months[m2] + " " + y2 + '&nbsp;&raquo;</div></td><td class="cal_tdr">&nbsp;</td></tr>';
		out += '<tr><td class="cal_tdbl">&nbsp;</td><td colspan="7" class="cal_tdb">&nbsp;</td><td class="cal_tdbr">&nbsp;</td>';
	}
	out += "</table></div>";
	return(out);
}

