// dateTimePicker.js
// Last change by: $Author: ara $
// Last changed: $Date: 2006-10-18 08:55:39 +0100 (Wed, 18 Oct 2006) $
// This file @ sub rev: $Rev: 3204 $

// This script relies on functions from DOMFunctions 
// This script turns any select box of class 'datetime' into a DHTML datetime picker widget

// To use exclusions:
//  Import a script which creates an array of the form shown below, where 'startdate' is the name of the id
// of the calendar the exclusions apply to
// var startdate_exclusions= new Array("2006-05-25 00:00:00", "2006-05-21 00:00:00");

var activeDTPs=Array();
var daysInMonth=[0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var months=['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
var DTPExclusions=new Array();
var DTPStartDates=new Array(); // First allowed date for each calendar

function initialiseCalendars() {
	dts=getElementsByClassName(document, "datetime");
	for (var i=0; i<dts.length; i++) {
		// Set up all the datetime fields
		var t=dts[i];
		if (t.id=="") {
			alert('Please assign an id to all datetime elements');
			return false;
		}
		activeDTPs[t]=false;
		addEvent(t, 'click', popDTPicker, false);		

		// Prepare exclusions array
		var exclusionsArray=false;
		var hasExclusions=true;
		try {
			exclusionsArray=eval(''+t.id+'_exclusions');
		} catch (e) {
			hasExclusions=false;
		}
		if (hasExclusions) {
			// Prepare array indexed by id/y/m/d/h/m/s
			DTPExclusions[t.id]=new Array();
			for (var j=0; j<exclusionsArray.length; j++) {
				var parts=getDateParts(exclusionsArray[j]);
				if (! DTPExclusions[t.id][ parts[0] ]) {DTPExclusions[t.id][ parts[0] ]=new Array(); }
				if (! DTPExclusions[t.id][ parts[0] ][ parts[1] ]) {DTPExclusions[t.id][ parts[0] ][ parts[1] ]=new Array(); }
				DTPExclusions[t.id][ parts[0] ][ parts[1] ][ parts[2] ]=new Array(true);
			}
		}

		// Start dates
		var startDate=false;
		var hasStartDate=true;
		try {
			startDate=eval(''+t.id+'_startdate');
		} catch (e) {
			hasExclusions=false;
		}
		if (hasStartDate) {
			if (startDate=="today") {
				dateInt=new Date();
				if (! isIE) {
					year=dateInt.getYear()+1900;
				} else {
					year=dateInt.getYear();
				}
				dateInt=new Date( year, dateInt.getMonth(), dateInt.getDate() );
			} else {
				parts=getDateParts(startDate);
				dateInt=new Date( parts[0], parts[1]-1, parts[2] );
			}

			// Turn start date into integer
			DTPStartDates[t.id]=dateInt.getTime();
		} else {
			DTPStartDates[t.id]=0;
		}
	}
}

function popDTPicker(e) {
	if (isIE) {e=window.event};
	var item=findTarget(e);
	if (activeDTPs[item]==true) {return;}

	// Create the DIV
	var d=document.createElement('div');

	// Work out what classes have been applied to it

	// Work out what day to show initially - default to today
	today=new Date();
	day=today.getDate();
	m=today.getMonth()+1;
	y=today.getYear();
	if (y<1900) {
		y+=1900;
	}
	if (false!=(dateParts=getDateParts(item.value))) {
		day=dateParts[2];		
		m=dateParts[1];
		y=dateParts[0];
	}

	// Create content
	bodyHTML=monthNav(m, y, item.id)+displayMonth(m, y, day, item.id);

	// Set DIV up
	d.className='datetimepicker';
	d.style['zIndex']=20;
	d.style.visibility='hidden';
	d.id=item.id+'_picker';
	d.innerHTML=bodyHTML;

	// Insert into document
	document.body.appendChild(d);

	// Find the position of the date/time element
	var screenWidth=document.body.offsetWidth;
	var screenHeight=window.innerHeight;
	var x=findPosX(item)+3;
	var y=findPosY(item)+item.offsetHeight+3;

	// Work out where to put the div
	d.style.position="absolute";
	var pickerWidth=200; //TODO make this work
	var pickerHeight=d.offsetHeight;
	d.style.left=x+'px';
	d.style.top=y+'px';
	//	Display the div
	d.style.visibility='visible';
	activeDTPs[item]=true;
}

// Function returns HTML for displaying the specified month in the specified year.
// If d>0 that day is preselected
function displayMonth(m, y, d, itemid) {
	m=parseInt(m);
	y=parseInt(y);
	d=parseInt(d);
	if (y<99) { y+=2000;};
	calHTML='';

	var dob=new Date();
	dob.setFullYear(y);
	dob.setMonth(m-1);
	dob.setDate(1);
	var startDay=dob.getDay();
	var endDate=daysInMonth[m];
	if (m==1 && (y%4==0)) {endDate=29;};
	var padCells=7-(endDate+startDay-1)%7;
	if (padCells<0) {padCells=0;};

	calHTML='<table class="datetimepickerdisplay">';
	calHTML+='<tr class=""><th>S</th><th>M</th><th>T</th><th>W</th><th>Th</th><th>F</th><th>Sa</th></tr>';
	for (i=(0-startDay),j=0; i<(endDate+padCells); i++,j++) {
		if (j%7==0) {
			calHTML+='<tr>';
		}
		dayClass='day paddingday';
		cellContents='';
		if (i==(d-1)) {dayClass='day chosenday'}
		if (i>=0 && i<endDate) {
			var dateInt=new Date( y, m-1, i+1);
			dateInt=dateInt.getTime();
			// Check to see if we've got any dates to exclude
			if ( 
					DTPExclusions[itemid] &&
					DTPExclusions[itemid][y] &&
					DTPExclusions[itemid][y][m] &&
					DTPExclusions[itemid][y][m][i+1]
					) {
				dayClass='day excludedday';
				cellContents+=(i+1);
			} else if (dateInt<DTPStartDates[itemid]) {
				// check to see if date is before start date
				dayClass='day excludedday';
				cellContents+=(i+1);
			} else {
				dayClass='day';
				cellContents+='<a class="caldaylink" href="javascript:chooseDate(\''+itemid+'\', \''+(i+1)+'\', \''+m+'\',\''+y+'\')">';
				cellContents+=(i+1);
				cellContents+='</a>';
			} 
		}
		calHTML+='<td class="'+dayClass+'">'+cellContents;
		calHTML+='</td>';
		if (j%7==6) {
			calHTML+='</tr>\n';
		}
	}
	calHTML+='</table>';

	return calHTML;
}

function monthNav(m, y, itemid) {
	m=parseInt(m);
	y=parseInt(y);
	prevMonth=(m==1)?12:m-1;
	nextMonth=(m==12)?1:m+1;
	py=ny=y;
	if (nextMonth==1) {
		ny=y+1;
	}
	if (prevMonth==12) {
		py=y-1;
	}
	calHTML='<table class="datetimemonthnav" width="200">';
	calHTML+='<tr><td class="datetimemonthnavl">';
	calHTML+='<a href="javascript:updatePicker('+prevMonth+', '+py+', \''+itemid+'\');" class="actionLink">'+months[prevMonth-1]+'</a>';
	calHTML+='</td>';
	calHTML+='<td class="datetimemonthnavc"><b>'+months[m-1]+' '+y+'</b></td>';
	calHTML+='<td class="datetimemonthnavr"><a class="actionLink" href="javascript:updatePicker('+nextMonth+', '+ny+', \''+itemid+'\')">'+months[nextMonth-1]+'</a></td></tr>';
	calHTML+='</table>';
	return calHTML;
}

// Update picker
function updatePicker(m, y, itemid) {
	m=parseInt(m);
	y=parseInt(y);
	display=findDOM(itemid+'_picker', 0);
	display.innerHTML=monthNav(m, y, itemid)+displayMonth(m, y, -50, itemid);
}

// Update a calendar control to reflect a chosen date
function chooseDate(ctrl, d, m, y) {
	m=parseInt(m);
	d=parseInt(d);
	y=parseInt(y);
	var picker=findDOM(ctrl+'_picker' ,0);
	var control=findDOM(ctrl ,0);
	activeDTPs[control]=false;	
	picker.parentNode.removeChild(picker);
	control.value=formatDate(d, m, y);
}

function formatDate(d, m, y) {
	return d+'/'+m+'/'+y;
}

function getDateParts(date) {
	// Array indexed in order of parts in ISO standard date
	var parts=new Array(0, 0, 0, 0, 0, 0);
	if (date=="") {
		return false;
	}
	var simpleReg = new RegExp("^[0-9]*/[0-9]*/[0-9]*$");
	var isoReg = new RegExp('^([0-9]+)-([0-9]+)-([0-9]+) +([0-9]+):([0-9]+):([0-9]+)');
	if (simpleReg.test(date)) {
		temp=Array();
		temp=date.split("/");
		parts[0]=parseInt(temp[2], 10);
		parts[1]=parseInt(temp[1], 10);
		parts[2]=parseInt(temp[0], 10);
		return parts;
	} else if (matches=isoReg.exec(date)) {
		parts[0]=parseInt(matches[1], 10);
		parts[1]=parseInt(matches[2], 10);
		parts[2]=parseInt(matches[3], 10);
		parts[3]=parseInt(matches[4], 10);
		parts[4]=parseInt(matches[5], 10);
		parts[5]=parseInt(matches[6], 10);
		parts[6]=parseInt(matches[7], 10);
		return parts;
	}
	return false;
}

addEvent(window, 'load', initialiseCalendars, false);

