/* ============================================================= *//*
 * File     : cal.js
 * Created  : 2008/07/25 [Y/M/D]
 * Author   : Michael Kerr (mkerr@aa.co.nz) 
 * Purpose  : To have an easy to use dynamic calendar.
 * History 
 * 		Date         	Version        	Description 
 * 		2008-07-23		1.0				First version
 *		2008-07-28		1.4				Uber Upgrades!
*//* ============================================================= */

var calDays = {'Sunday': 0, 'Monday': 1, 'Tuesday': 2, 'Wednesday': 3, 'Thursday': 4, 'Friday': 5, 'Saturday': 6};

var Calendar = new Class(
{
	today: null,
	startDate: null,

	Monday : 1,
	Tuesday: 2,
	Wednesday: 3,
	Thursday: 4,
	Friday: 5,
	Saturday: 6,
	Sunday: 0,

	CAL_WEEK: 5,
	DPW: 7,

	DAY_CELLS: 35,
	ONE_DAY: 86400,

	FDOW: null,

	SAT: 0,
	SUN: 0,
	
	opt: 0,
	
	name: '',
	displayCaption: true,
	displayDOW: true,
	displayPast: false,
	
	displayRange: null,
	displayMonths: null,
	DsOI: null,
	
	Days: null,
	
	multiSelect: false,
	selFrom: null,
	selTo: null,
	selWhich: 0,
	
	hideOnClick: true,
	navMonth: true,
	navYear: true,
	
	allowToday: false,

	monthCount: 1,
	
	myCanvas: null,
	
	targetA: '',
	targetB: '',
	
	format: 'yyyy-mm-dd',
	
	initialize: function(O)
	{
		this.opt = O || null;

		this.rootElement = this.opt && this.opt.root != '' ? Utils.$(this.opt.root) : document.body;

			this.myCanvas = document.createElement('DIV');
			this.myCanvas.id = 'calendar-wrap';
			this.myCanvas.className = 'calendar-wrap';
			this.rootElement.appendChild(this.myCanvas);
	
		this.FDOW = calDays['Monday'];
	
		this.setToday();

		this.setStartDate();

		this.displayMonths = {1 : "January", 2 : "Febuary", 3 : "March", 4 : "April", 5 : "May", 6 : "June", 7 : "July", 8 : "August", 9 : "September", 10 : "October", 11 : "November", 12 : "December"};

		this.setupDOW();

		//this.navMonth = this.opt && this.opt.navMonth ? this.opt.navMonth : null;
		//this.navYear = this.opt && this.opt.navYear ? this.opt.navYear : null;
	},

	render: function(A)
	{
		var lmnts = Utils.$$('calendar-wrap');
		for (var i = 0; i < lmnts.length; i++)
		{
			lmnts[i].style.display = 'none';
		}
	
		if (this.myCanvas.style.display == 'none')
			this.myCanvas.style.display = 'block';

		while ( this.myCanvas.hasChildNodes() ) { this.myCanvas.removeChild( this.myCanvas.lastChild ); }

		if (A) this.today = A;

		if (typeof this.CAL_DAYS == 'undefined') { this.setupDays(); }

		var header = this.renderHeader();
		
		var newWidth = 0;
		for (var i = 0; i < this.monthCount; i++)
		{
			var cal = document.createElement('DIV');
			cal.className = 'calendar-block';
			this.myCanvas.appendChild(cal);

			A = this.CAL_DAYS[i].date;

			if (this.displayCaption)
				this.renderCaption(A, cal, i);

			if (this.displayDOW)
				this.renderDOW(A, cal);

			this.renderDays(A, i, cal);
			
			newWidth += cal.offsetWidth;
		}
		

		var footer = this.renderFooter();

		var iframe = document.createElement('IFRAME');
		iframe.className = 'iframe';
		iframe.style.width = (parseInt(newWidth) + 20) + 'px';
		//iframe.style.width = (parseInt(this.myCanvas.offsetWidth) + 20) + 'px';
		iframe.style.filter = 'mask()';
		iframe.src = 'javascript:false;';

		this.myCanvas.appendChild(iframe);
		
		header.style.width = newWidth;
		footer.style.width = newWidth;
		
		/*header.style.width = this.myCanvas.offsetWidth;
		footer.style.width = this.myCanvas.offsetWidth;*/
	},
	
	renderHeader: function()
	{
		var header = document.createElement('DIV');
		header.className = 'calendar-header';
		//header.id = 'calendar-header';
		header.style.display = 'block';

		var leftside = document.createElement('DIV');
		leftside.className = 'calendar-header-left';

		header.appendChild(leftside);
	
		if (this.allowToday)
		{
			var today = document.createElement('DIV');
			today.innerHTML = '<u>Today</u>';
			today.className = 'calendar-header-text';
			Event.attach(today, 'click', function(){ this.selFrom = this.today; Utils.$(this.targetA).value = uDate.formatify(this.selFrom); this.close(); }, this);

			header.appendChild(today);
		}

		var close = document.createElement('DIV');
		close.className = 'calendar-header-close close-norm';

		Event.attach(close, 'click', 	 function(){ this.close(); }, this);
		Event.attach(close, 'mouseover', function(){ Utils.addClass(close, 'close-over'); }, this);
		Event.attach(close, 'mouseout',  function(){ Utils.removeClass(close, 'close-over');  }, this);

		header.appendChild(close);

		this.myCanvas.appendChild(header);

		var clearfix = document.createElement('DIV');
			clearfix.className = 'calendar-clearfix';
			clearfix.innerHTML = '<!-- -->';
		this.myCanvas.appendChild(clearfix);
		
		return header;
	},

	renderFooter: function()
	{
		var clearfix = document.createElement('DIV');
			clearfix.className = 'calendar-clearfix';
			clearfix.innerHTML = '<!-- -->';
		this.myCanvas.appendChild(clearfix);

		var footer = document.createElement('DIV');
		//footer.id = 'calendar-footer';
		footer.className = 'calendar-footer';
		footer.innerHTML = '&nbsp;';

		var l = document.createElement('DIV');
		l.className = 'calendar-footer-left';

		var r = document.createElement('DIV');
		r.className = 'calendar-footer-right';
		
		footer.appendChild(l);
		footer.appendChild(r);

		this.myCanvas.appendChild(footer);
		
		return footer;
	},
	
	renderCaption: function(A, B, C)
	{
		var w = 0;
		if (this.navMonth && C == 0) w += 2;
		if (this.navYear && C == 0) w += 2;
		
		if (this.navYear && C == 0)
		{
			var nav = document.createElement('DIV');
				nav.className = 'calendar-caption-nav calendar-year-nav';
				nav.innerHTML = "&#124;&lt;";
			Event.attach(nav, 'click', function(e) { this.prevYear(); }, this);

			B.appendChild(nav);
		}

		if (this.navMonth && C == 0)
		{
			var nav = document.createElement('DIV');
				nav.className = 'calendar-caption-nav calendar-month-nav';
				nav.innerHTML = "&lt;";
			Event.attach(nav, 'click', function(e) { this.prevMonth(); }, this);

			B.appendChild(nav);
		}

		var title = document.createElement('DIV');
			title.id = 'title';
			title.className = 'calendar-caption';
			title.style.width = ((this.DPW - w) * (ePref == 'on' ? 31 : 25) + (this.DPW - 4) * 2 - 4) + ((w * 5) + 2) +'px';
			title.innerHTML = this.displayMonths[A.M] + ', ' + A.Y;
		B.appendChild(title);

		if (this.navMonth && C == 0)
		{
			var nav = document.createElement('DIV');
				nav.className = 'calendar-caption-nav calendar-month-nav';
				nav.innerHTML = "&gt;";
			Event.attach(nav, 'click', function(e) { this.nextMonth(); }, this);

			B.appendChild(nav);
		}

		if (this.navYear && C == 0)
		{
			var nav = document.createElement('DIV');
				nav.className = 'calendar-caption-nav calendar-year-nav';
				nav.innerHTML = "&gt;&#124;";
			Event.attach(nav, 'click', function(e) { this.nextYear(); }, this);

			B.appendChild(nav);
		}

		var clearfix = document.createElement('DIV');
			clearfix.className = 'calendar-clearfix';
			clearfix.innerHTML = '<!-- -->';
		B.appendChild(clearfix);		
	},

	renderDOW: function(A, B)
	{
		for (day in this.Days)
		{
			var dowBar = document.createElement('DIV');
				dowBar.id = 'dowBar';
				dowBar.className = 'calendar-days-of-week';
				dowBar.innerHTML = this.Days[day];

			B.appendChild(dowBar);
		}

		var clearfix = document.createElement('DIV');
			clearfix.className = 'calendar-clearfix';
			clearfix.innerHTML = '<!-- -->';
		B.appendChild(clearfix);		
	},

	renderDays: function(A, B, C)
	{
		var x = 0;
		for (i = 0; i < this.DAY_CELLS; i++)
		{
			this.CAL_DAYS[B].days[i].render();
			C.appendChild(this.CAL_DAYS[B].days[i].myCanvas);

			if (x == 6) 
			{ 
				var clearfix = document.createElement('DIV');
					clearfix.className = 'calendar-clearfix';
					clearfix.innerHTML = '<!-- -->';
				C.appendChild(clearfix);	x = 0; 
			} else { x += 1; }
		}
	},
	
	nav: function(A, B)
	{
		this.CAL_DAYS = null;
		this.CAL_DAYS = new Array();

		if (A > 0)
		{
			iYearInc = 1;
 			if ((this.startDate.M + A) > 12)
			{
				this.startDate.M = (this.startDate.M + A) - 12;
				this.startDate.Y += iYearInc;
			}
			else
				{ this.startDate.M += A; }
			m = 1;
		}
		else if (A < 0)
		{
			iYearInc = -1;
 			if ((this.startDate.M + A) < 1)
			{
				this.startDate.M = (this.startDate.M + A) + 12;
				this.startDate.Y += iYearInc;
			}
			else
				{ this.startDate.M += A; }
			m = 12;
		}

		if (B != 0)
			this.startDate.Y += B;

		var yearMod = 0, sMonth = this.startDate.M;
		for (var i = 0; i < this.monthCount; i++, sMonth++)
		{
			if ((sMonth % 13) == 0 && i == 0)
			{
				this.startDate.Y += iYearInc;
				this.startDate.M = m;
				yearMod = 0;
				sMonth = m;
			} 
			else if ((sMonth % 13) == 0)
			{
				yearMod += 1;
				sMonth = 1;
			}

			var tmpDate = {'Y': (this.startDate.Y + yearMod), 'M': sMonth};
			this.CAL_DAYS[i] = {'date': tmpDate, 'days': this.setupCalDays(tmpDate.Y, tmpDate.M)};
		}

		this.render();
	},
	
	nextMonth: function() { this.nav( 1, 0); },
	prevMonth: function() { this.nav(-1, 0); },
	
	nextYear: function() { this.nav(0,  1); },
	prevYear: function() { this.nav(0, -1); },
	
	monthPlus: function(A) { A = A ||  1; this.nav(A, 0); },
	yearPlus:  function(A) { A = A ||  1; this.nav(0, A); },
	
	setFormat: function(A) { this.format = A; },

	setupSats: function(A)
	{
		day = this.SAT;
		while (day < this.DAY_CELLS)
			{ A[day].isWeekend = true; day += this.DPW;}
	},

	setupSuns: function(A)
	{
		day = this.SUN;
		while (day < this.DAY_CELLS)
			{ A[day].isWeekend = true; day += this.DPW;}
	},

	setupCalDays: function(y, m)
	{
		y = parseFloat(y); m = parseFloat(m) - 1;

		var cal_days = new Array();
		var days_in_month = uDate.dIM(y, m);
		var display_offset = uDate.fDO(y, m, this.FDOW);

		for (i = 0; i < this.DAY_CELLS; i++)
			{ cal_days[i] = new Day({'Y': y, 'M': m + 1, 'D': ''}, i + 1, this); }

		var wrap_mod = Utils.MAX(0, (days_in_month + display_offset) - this.DAY_CELLS); i = 0;
		while (wrap_mod > 0)
		{
			cal_days[i].myDay = (days_in_month + 1) - wrap_mod;
			cal_days[i].myDate = {'Y': y, 'M': m + 1, 'D': cal_days[i].myDay};
			wrap_mod -= 1; i += 1;
		}

		var a = display_offset;
		while ((a < this.DAY_CELLS) && ((a - display_offset) < days_in_month))
		{ 
			cal_days[a].myDay = (a + 1) - display_offset; 
			cal_days[a].myDate = {'Y': y, 'M': m + 1, 'D': cal_days[a].myDay};
			a += 1;	
		}

		this.setupSats(cal_days);
		this.setupSuns(cal_days);

		for (i = 0; i < this.DAY_CELLS; i++) { cal_days[i].render(); } // cal_days[i].attachEvents(); }

		return cal_days;
	},
	
	foreachRange: function(A, B, C)
	{
		dFrom = A.split('-');
		yF = parseFloat(dFrom[0]); mF = parseFloat(dFrom[1]); dF = parseFloat(dFrom[2]);

		dTo = B.split('-');
		yT = parseFloat(dTo[0]); mT = parseFloat(dTo[1]); dT = parseFloat(dTo[2]);

		var dFrom = new Date();
		dFrom.setFullYear(yF, mF - 1, dF);
		
		var dTo = new Date();
		dTo.setFullYear(yT, mT - 1, dT);

		var dayMod = 1;
		while (dFrom <= dTo)
		{
			cY = dFrom.getFullYear();
			cM = dFrom.getMonth() + 1;
			cD = dFrom.getDate();

			C(Utils.$(cY + '-' + (cM > 9 ? '' : '0') + cM + '-' + (cD > 9 ? '' : '0') + cD));

			dFrom.setFullYear(yF, mF - 1, dF + dayMod);	
			dayMod++;
		}
	},
	
	selectRange: function(A, B)
	{
		this.foreachRange(A, B, function(D) { if (D) Utils.addClass(D, 'selected'); });
	},
	
	deselectRange: function(A, B)
	{
		this.foreachRange(A, B, function(D) { if (D) Utils.removeClass(D, 'selected'); });
	},
	
	close: function(e, A)
	{
		this.myCanvas.style.display = "none";
	},
	
	closeEx: function()
	{
		// overwrite me!
	},
	
	/*=====================================================*/
	
	toggleDisplayPast: function(A)
		{ this.displayPast = A; },

	toggleNavMonth: function(A)
		{ if (typeof A == 'undefined') A = !this.navMonth; this.navMonth = A; },

	toggleNavYear: function(A)
		{ if (typeof A == 'undefined') A = !this.navYear; this.navYear = A; },

	setToday: function(A)
	{
		var tmpDate = new Date();

		this.today = {'Y': 0, 'M': 0, 'D': 0};
		if (A && A.Y)
		{
			var Y = (A.Y != null) ? parseFloat(A.Y) : tmpDate.getFullYear();
			var M = (A.M != null) ? parseFloat(A.M) : tmpDate.getMonth() + 1;
			var D = (A.D != null) ? parseFloat(A.D) : tmpDate.getDate();		
			this.today = {'Y': Y, 'M': M, 'D': D};
		}
		else { this.today = {'Y': tmpDate.getFullYear(), 'M': tmpDate.getMonth() + 1, 'D': tmpDate.getDate()}; }
	},
	
	setStartDate: function(A)
	{
		var tmpDate = new Date();

		this.startDate = {'Y': 0, 'M': 0};
		if (A && A.Y)
		{
			var Y = (A.Y != null) ? parseFloat(A.Y) : tmpDate.getFullYear();
			var M = (A.M != null) ? parseFloat(A.M) : tmpDate.getMonth() + 1;
			this.startDate = {'Y': Y, 'M': M};
		}
		else { this.startDate = {'Y': tmpDate.getFullYear(), 'M': tmpDate.getMonth() + 1}; }
	},
	
	setMonthCount: function(A)
	{
		this.monthCount = parseInt(A) > 0 ? parseInt(A) : 1;
		
		if (typeof this.CAL_DAYS == 'undefined') { this.setupDays(); }
	},
	
	toggleCaption: function(A)
		{ if (typeof A == 'undefined') A = !this.displayCaption; this.displayCaption = A; },
	
	toggleDOW: function(A)
		{ if (typeof A == 'undefined') A = !this.displayDOW; this.displayDOW = A; },
	
	toggleAllowToday: function(A)
		{ if (typeof A == 'undefined') A = !this.allowToday; this.allowToday = A; },
	
	toggleHideOnClick: function(A)
		{ if (typeof A == 'undefined') A = !this.hideOnClick; this.hideOnClick = A; },
		
	setFDOW: function(A)
		{ A = (A >= 0 && A <= 6) ? A : 1; this.FDOW = A; this.setupDOW(); },
		
	setDisplayRange: function(A)
	{
		this.displayRange = A ? A : null;
		if (this.displayRange)
		{
			var t = this.today;
			var dr = this.displayRange;

			dr.sD = {'Y': t.Y, 'M': t.M, 'D': t.D};
			dr.eD = {'Y': 0, 'M': 0, 'D': 0};

			if (dr.f)
				{ dr.sD = {'Y': dr.f.Y, 'M': dr.f.M, 'D': dr.f.D}; }
			
			if (dr.p && dr.p.D)
			{
				dr.eD = {'Y': dr.sD.Y, 'M': dr.sD.M, 'D': dr.sD.D};
				var i = dr.p.D + dr.sD.D;
				var x = uDate.dIM(dr.eD.Y, dr.eD.M);
				while (i > x)
				{
					i -= x;	dr.eD.M += 1;
					if (dr.eD.M > 12)
					{
						dr.eD.M = 1;
						dr.eD.Y += 1;
					}
					x = uDate.dIM(dr.eD.Y, dr.eD.M);
				}
				dr.eD.D = i;
			}

			if (dr.t)
				{ dr.eD = {'Y': dr.t.Y, 'M': dr.t.M, 'D': dr.t.D}; }

			if (!dr.eD.Y)
				dr.eD = {'Y': dr.f.Y + 1000, 'M': dr.f.M, 'D': dr.f.D};

			dr.sD.date = new Date(dr.sD.Y, dr.sD.M - 1, dr.sD.D, 0, 0, 1);
			dr.eD.date = new Date(dr.eD.Y, dr.eD.M - 1, dr.eD.D, 0, 0, 1);
		}
	},

	setReturn: function(A, B)
	{
		this.targetA = A;
		if (typeof B != 'undefined')
		{
			this.multiSelect = true;
			this.targetB = B;
		}

		Utils.addClass(Utils.$(this.targetA), 'calendar-opener');

		Event.attach(Utils.$(this.targetA), 'click', function()
		{
			this.preRender();
			Utils.$(this.targetA).style.position = 'relative';
			this.setPos(Utils.$(this.targetA), 0, 1);
			this.render();
		}, this);
	},

	setupDays: function()
	{
		this.CAL_DAYS = new Array();

		var yearMod = 0, sMonth = this.startDate.M;
		for (var i = 0; i < this.monthCount; i++, sMonth++)
		{
			if ((sMonth % 13) == 0)
			{
				yearMod += 1;
				sMonth = 1;
			}

			var tmpDate = {'Y': (this.startDate.Y + yearMod), 'M': sMonth};
			this.CAL_DAYS[i] = {'date': tmpDate, 'days': this.setupCalDays(tmpDate.Y, tmpDate.M)};
		}
	},

	setupDOW: function()
	{
		if (typeof this.FDOW == 'undefined') this.FDOW = this.Monday;

		this.SAT = (((this.Saturday - this.FDOW) < 0) ? (6 + ((this.Saturday - this.FDOW) + 1)) : this.Saturday - this.FDOW);
		this.SUN = (((this.Sunday - this.FDOW) < 0) ? (6 + ((this.Sunday - this.FDOW) + 1)) : this.Sunday - this.FDOW);

		this.Days = new Array();
		for (var i = 0; i < this.DPW; i++)
		{
			DOW = ((this.FDOW + i) > 6) ? (this.FDOW + i) - this.DPW : this.FDOW + i;
			this.Days[i] = ((DOW == this.Sunday) ? 'S' : ((DOW == this.Monday) ? 'M' : ((DOW == this.Tuesday) ? 'T' : ((DOW == this.Wednesday) ? 'W' : ((DOW == this.Thursday) ? 'T' : ((DOW == this.Friday) ? 'F' : ((DOW == this.Saturday) ? 'S' : '-')))))));
		}
	},

	setPos: function(E, A, B)
	{
		var x = E.offsetLeft;
		var y = E.offsetTop;
		var w = E.offsetWidth;
		var h = E.offsetHeight;

		this.myCanvas.style.left = (A == 0 ? x : (x + w)) + 'px';
		this.myCanvas.style.top = (B == 0 ? y : (y + h)) + 'px';
	},

	preRender: function()
	{
		//overwrite me!!
	}
});


var Day = new Class(
{
	myId: '',
	myValue: '',
	myClass: '',
	myStyles: '',
	myDate: '',
	myDay: '',
	myPosition: 0,
	
	myStatus: 1,
	
	myParent: null,
	myParentObj: null,
	
	myCanvas: null,

	isWeekend: false,

	initialize: function(A, B, C)
	{
		this.myParentObj = C;
		this.myParent = C.myCanvas;
		this.myDate = A ? A : null;
		this.myDay = A && A.D ? A.D : '';
		this.myPosition = B;

		this.myCanvas = document.createElement('DIV');
	},

	render: function()
	{
		var p = this.myParentObj;
		var t = p.today;

		this.myCanvas.id = ((this.myDate != null) ? this.myDate.Y + '-' + uDate.LZ(this.myDate.M) + '-' + uDate.LZ(this.myDay) : rand() % 3);
		
		var currentDate = uDate.make(this.myDate);

		var isEnabled = (this.myDay != null && this.myDay > 0 && (uDate.GE(this.myDate, t) || p.displayPast));
		if (p.displayRange)
		{		
			var dr = p.displayRange;
			isEnabled = ((currentDate >= dr.sD.date || p.displayPast) && currentDate <= dr.eD.date) ? isEnabled : false;
		}

		this.myClass = 'calendar-day';
		this.myClass += (this.isWeekend) ? ' calendar-weekend' : '';
		this.myClass += (isEnabled) ? ' calendar-selectable' : ' calendar-disabled';

		if (uDate.same(this.myDate, t))
		{
			this.myClass += ' calendar-today';
		}
		else if (p.selFrom && p.selTo && uDate.between(this.myDate, p.selFrom, p.selTo))
		{
			this.myClass += ' calendar-selected';
		}		
		else if (p.selFrom && uDate.same(p.selFrom, this.myDate))
		{
			this.myClass += ' calendar-selected';
		}

		this.myStatus = (isEnabled) ? 1 : 0;

		this.myCanvas.className = this.myClass;
		this.myCanvas.innerHTML = ((this.myDay != null) ? this.myDay : ' ');

		this.attachEvents();
	},

	attachEvents: function()
	{
		if (this.myStatus == 1)
		{
			Event.attach(this.myCanvas, 'mouseover', this.dayMouseOver, this);
			Event.attach(this.myCanvas, 'mouseout',  this.dayMouseOut,  this);
			Event.attach(this.myCanvas, 'click',     this.dayClick,     this);
		}
	},

	dayMouseOver: function(e)
	{
		if (this.myStatus == 1)
		{
			var node = Event.target(e);
			Utils.addClass(node, 'calendar-day-hover');
		}
		else
			Event.stop(e);
	},

	dayMouseOut: function(e)
	{
		if (this.myStatus == 1)
		{
			var node = Event.target(e);
			Utils.removeClass(node, 'calendar-day-hover');
		}
		else
			Event.stop(e);		
	},

	dayClick: function(e)
	{
		if (this.myStatus == 1)
		{
			var p = this.myParentObj;
			var node = Event.target(e);

			if (p && p.multiSelect)
			{
				if (!p.selFrom || selWhich == 0)
				{ 
					if (p.selFrom && p.selTo) p.deselectRange(p.selFrom, p.selTo);
					p.selFrom = node.id; selWhich = 1; p.selTo = null; 
					Utils.addClass(Utils.$(p.selFrom), 'selected');

					if (p && p.targetA != '' && Utils.$(p.targetA))	Utils.$(p.targetA).value = uDate.formatify(p.selFrom, p.format);
				}
				else if (!p.selTo || selWhich == 1)
				{
					p.selTo = node.id; selWhich = 0;
					if (p.selTo < p.selFrom)
					{
						var tmp = p.selTo;
						p.selTo = p.selFrom;
						p.selFrom = tmp;

						if (p && p.targetA != '' && Utils.$(p.targetA))	Utils.$(p.targetA).value = uDate.formatify(p.selFrom, p.format);
					}

					if (p && p.targetB != '' && Utils.$(p.targetB))	Utils.$(p.targetB).value = uDate.formatify(p.selTo, p.format);
				}

				if (p.selFrom && p.selTo)
				{
					p.selectRange(p.selFrom, p.selTo);
				}
			}
			else
			{
				var tmp = node.id.split('-');
				p.selFrom = {'Y': tmp[0], 'M': tmp[1], 'D': tmp[2]};

				if (p && p.targetA != '' && Utils.$(p.targetA))	Utils.$(p.targetA).value = uDate.formatify(node.id, p.format);
			}

			if (p && p.hideOnClick)
			{ 
				if (p.multiSelect && selWhich == 1) return;
				this.myParent.style.display = 'none'; p.closeEx();
			}
		}
		else
			Event.stop(e);
	}
});

var uDate = 
{
	same: function(A, B)
	{
		return (A.Y == B.Y && A.M == B.M && A.D == B.D);
	},
	
	GT: function(A, B)
	{
		return (A.Y > B.Y || ((A.Y == B.Y && A.M > B.M) || ((A.Y == B.Y && A.M == B.M && A.D > B.D))));
	},
	
	GE: function(A, B)
	{
		return (A.Y > B.Y || ((A.Y == B.Y && A.M > B.M) || ((A.Y == B.Y && A.M == B.M && A.D >= B.D))));
	},
	
	LT: function(A, B)
	{
		return (A.Y < B.Y || ((A.Y == B.Y && A.M < B.M) || ((A.Y == B.Y && A.M == B.M && A.D < B.D))));
	},
	
	LE: function(A, B)
	{
		return (A.Y < B.Y || ((A.Y == B.Y && A.M < B.M) || ((A.Y == B.Y && A.M == B.M && A.D <= B.D))));
	},
	
	make: function(A)
	{
		var t = new Date();
		t.setFullYear(A.Y, A.M - 1, A.D);
		return t;
	},
	
	LZ: function(A)
	{
		A = parseFloat(A);
		return (A > 0 && A <= 9) ? '0' + A : A;
	},
	
	dIM: function(y, m)
	{
		d = (arguments[3] != null) ? arguments[3] : 30;
		m = parseFloat(m) + 1; y = parseFloat(y);
		switch (m)
		{
			case 2: d -= (((y % 4) == 0) && ((y % 100) != 0)) ? 1 : 2; break;
			case 1: case 3: case 5: case 7: case 8: case 10: case 12: d += 1; break;
		}
		return d;
	},
	
	fDO: function(y, m, A)
	{
		var tmpDate = new Date(y, m, 1, 0, 0, 1); day = tmpDate.getDay();
		return day = ((day - A) < 0) ? day = (6 + ((day - A) +1)) : day - A;
	},
	
	between: function(A, B, C)
	{
		if (A.D)
		{
			B = typeof B == 'string' ? uDate.objectify(B) : B;
			C = typeof C == 'string' ? uDate.objectify(C) : C;
			return (uDate.GE(A, B) && uDate.LE(A, C));
		} else return false;
	},
	
	objectify: function(A)
	{
		if (typeof A == 'string')
		{
			tmp = A.split('-');
			return {'Y': tmp[0], 'M': tmp[1], 'D': tmp[2]};
		}
		else
			return A;
	},
	
	stringify: function(A)
	{
		if (typeof A != 'string')
		{
			A = A.Y + '-' + uDate.LZ(A.M) + '-' + uDate.LZ(A.D);
		}
		return A;
	},
	
	validify: function(A)
	{
		/* =============================================================== */
		//	This function exists to masssage a date until it sits right.
		//	basically if you provide 2008-15-12 you will get 2009-03-12.
		/* =============================================================== */
	
		var y = parseFloat(A.Y);
		var m = parseFloat(A.M);
		var d = parseFloat(A.D);

		var str = {'Y': y, 'M': m, 'D': d};
		
		var ins = 0; // Insurance! :)
		var bOk = true;
		do
		{
			ins++;
			if (ins > 50)
			{
				// no transaction so need more then 50 iterations so if ins hits 50 we pull the plug.
				return {'Y': str.Y, 'M': str.M, 'D': str.D, 'E': 'timed out, oops'};
			}

			bOk = true;

			bOk = (m < 1) ? false : bOk;
			if (!bOk)
			{
				y = y - 1;
				m = 12 + m;
				continue;
			}

			bOk = (m > 12) ? false : bOk;
			if (!bOk)
			{
				y = y + 1;
				m = m - 12;
				continue;
			}

			bOk = (d < 1) ? false : bOk;
			if (!bOk)
			{
				m = m - 1;
				d = uDate.dIM(m) + d;
				continue;
			}

			dm = uDate.dIM(m)
			bOk = (d > dm) ? false : bOk;
			if (!bOk)
			{
				m = m + 1;
				d = d - dm;
				continue;
			}

		} while (bOk === false);

		return {'Y': y, 'M': m, 'D': d};
	},
	
	min: function(A, B)
	{
		var c = uDate.floatify(A);
		var d = uDate.floatify(B);

		if ((c.Y < d.Y) || (c.Y == d.Y && c.M < d.M) || (c.Y == d.Y && c.M == d.M && c.D <= d.D)) return A;
		return B;
	},
	
	max: function(A, B)
	{
		var c = uDate.floatify(A);
		var d = uDate.floatify(B);

		if ((c.Y > d.Y) || (c.Y == d.Y && c.M > d.M) || (c.Y == d.Y && c.M == d.M && c.D >= d.D)) return A;
		return B;	
	},
	
	floatify: function(A)
	{
		var X = parseFloat(A.Y);
		var Y = parseFloat(A.M);
		var Z = parseFloat(A.D);
		return {'Y': X, 'M': Y, 'D': Z};
	},
	
	formatify: function(D, A)
	{
		A = (A != '') ? A : 'yyyy-mm-dd';

		var d = null;
		tD = uDate.objectify(D);

		if (typeof tD.M == 'undefined')
			{ d = new Date(D); }
		else
		{
			d = new Date();
			d.setFullYear(tD.Y, tD.M - 1, tD.D);
		}

		return d.format(A);
	}
}


/*
 * Date Format 1.2.2
 * (c) 2007-2008 Steven Levithan <stevenlevithan.com>
 * MIT license
 * Includes enhancements by Scott Trenda <scott.trenda.net> and Kris Kowal <cixar.com/~kris.kowal/>
 *
 * Accepts a date, a mask, or a date and a mask.
 * Returns a formatted version of the given date.
 * The date defaults to the current date/time.
 * The mask defaults to dateFormat.masks.default.
 */
var dateFormat = function () {

	var token = /d{1,4}|m{1,4}|yy(?:yy)?|([HhMsTt])\1?|[LloSZ]|"[^"]*"|'[^']*'/g,
		timezone = /\b(?:[PMCEA][SDP]T|(?:Pacific|Mountain|Central|Eastern|Atlantic) (?:Standard|Daylight|Prevailing) Time|(?:GMT|UTC)(?:[-+]\d{4})?)\b/g,
		timezoneClip = /[^-+\dA-Z]/g,
		pad = function (val, len) {
			val = String(val);
			len = len || 2;
			while (val.length < len) val = "0" + val;
			return val;
		};

	// Regexes and supporting functions are cached through closure
	return function (date, mask, utc) {
		var dF = dateFormat;

		// You can't provide utc if you skip other args (use the "UTC:" mask prefix)
		if (arguments.length == 1 && (typeof date == "string" || date instanceof String) && !/\d/.test(date)) {
			mask = date;
			date = undefined;
		}

		// Passing date through Date applies Date.parse, if necessary
		date = date ? new Date(date) : new Date();
		if (isNaN(date)) throw new SyntaxError("invalid date");

		mask = String(dF.masks[mask] || mask || dF.masks["default"]);

		// Allow setting the utc argument via the mask
		if (mask.slice(0, 4) == "UTC:") {
			mask = mask.slice(4);
			utc = true;
		}

		var	_ = utc ? "getUTC" : "get",
			d = date[_ + "Date"](),
			D = date[_ + "Day"](),
			m = date[_ + "Month"](),
			y = date[_ + "FullYear"](),
			H = date[_ + "Hours"](),
			M = date[_ + "Minutes"](),
			s = date[_ + "Seconds"](),
			L = date[_ + "Milliseconds"](),
			o = utc ? 0 : date.getTimezoneOffset(),
			flags = {
				d:    d,
				dd:   pad(d),
				ddd:  dF.i18n.dayNames[D],
				dddd: dF.i18n.dayNames[D + 7],
				m:    m + 1,
				mm:   pad(m + 1),
				mmm:  dF.i18n.monthNames[m],
				mmmm: dF.i18n.monthNames[m + 12],
				yy:   String(y).slice(2),
				yyyy: y,
				h:    H % 12 || 12,
				hh:   pad(H % 12 || 12),
				H:    H,
				HH:   pad(H),
				M:    M,
				MM:   pad(M),
				s:    s,
				ss:   pad(s),
				l:    pad(L, 3),
				L:    pad(L > 99 ? Math.round(L / 10) : L),
				t:    H < 12 ? "a"  : "p",
				tt:   H < 12 ? "am" : "pm",
				T:    H < 12 ? "A"  : "P",
				TT:   H < 12 ? "AM" : "PM",
				Z:    utc ? "UTC" : (String(date).match(timezone) || [""]).pop().replace(timezoneClip, ""),
				o:    (o > 0 ? "-" : "+") + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4),
				S:    ["th", "st", "nd", "rd"][d % 10 > 3 ? 0 : (d % 100 - d % 10 != 10) * d % 10]
			};

		return mask.replace(token, function ($0) {
			return $0 in flags ? flags[$0] : $0.slice(1, $0.length - 1);
		});
	};
}();

// Some common format strings
dateFormat.masks = {
	"default":      "ddd mmm dd yyyy HH:MM:ss",
	shortDate:      "m/d/yy",
	mediumDate:     "mmm d, yyyy",
	longDate:       "mmmm d, yyyy",
	fullDate:       "dddd, mmmm d, yyyy",
	shortTime:      "h:MM TT",
	mediumTime:     "h:MM:ss TT",
	longTime:       "h:MM:ss TT Z",
	isoDate:        "yyyy-mm-dd",
	isoTime:        "HH:MM:ss",
	isoDateTime:    "yyyy-mm-dd'T'HH:MM:ss",
	isoUtcDateTime: "UTC:yyyy-mm-dd'T'HH:MM:ss'Z'"
};

// Internationalization strings
dateFormat.i18n = {
	dayNames: [
		"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
		"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
	],
	monthNames: [
		"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec",
		"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"
	]
};

// For convenience...
Date.prototype.format = function (mask, utc) {
	return dateFormat(this, mask, utc);
}
