﻿/*
 * jQuery.calendar - A calendar plugin for jQuery.
 *
 * Copyright (c) 2007 Dave Stewart <dave@yesterdave.com>, http://www.yesterdave.com
 * Licensed under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 * 
 * $Version: 2007.05.16 +r6
 */
(function($) {
	$.fn.calendar = function(onSelect, options){
		return this.each(function(){
			var me = this;
			var fn = onSelect;
			if ($.isFunction(fn)) {
				fn = function(date, addToHistory){
					onSelect(date, addToHistory, me);
				};
			}
			this.calendar = new $.calendar(me, fn, options);
		});
	};

	$.calendar = function(container, onSelect, options){
		var me = this;
		var calDiv = $(container);
		if (!$.isFunction(onSelect))
			onSelect = function(){};
		var s = {
			days: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
			sdays: ['Su', 'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa'],
			months: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
			tableTitle: 'Calendar',
			lastRowHidden: true,
			disabledDays: [],
			specialDates: [],
			prevImg: null, nextImg: null,
			prevImgDis: null, nextImgDis: null,
			startDate: null, endDate: null,
			selDate: null, today: null
		};
		$.extend(s, options || {});
		var daysDisabled = new Array(7);
		$.each(s.disabledDays, function(i, d){
			daysDisabled[d] = true;
		});
		var fixDate = function(d){
			return d instanceof Date ? new Date(d.getFullYear(), d.getMonth(), d.getDate()) : null;
		};
		s.startDate = fixDate(s.startDate) || new Date(0);
		s.endDate = fixDate(s.endDate);
		s.selDate = fixDate(s.selDate);
		s.today = fixDate(s.today) || fixDate(new Date());
		var selCell, monthShown, monthSpecials;
		var addToHistory = false;
		this.getSelectedDate = function(){
			return s.selDate;
		};
		this.setSelectedDate = function(date, changeMonth, keepHistory){
			if (!date) {
				s.selDate = null;
				selCell.removeClass('Selected');
				selCell = $('notfound');
				return;
			}
			var inMonth = (monthShown.getMonth() == date.getMonth() && monthShown.getFullYear() == date.getFullYear());
			if (!inMonth && !changeMonth)
				s.selDate = fixDate(date);
			else {
				if (!inMonth && changeMonth)
					me.build(date);
				if (keepHistory)
					addToHistory = true;
				calDiv.find("td.Day").each(function(){
					if ($(this).html() == "" + date.getDate())
						$(this).click();
				});
			}
		};
		var dayClick = function(e){
			selCell.removeClass('Selected');
			selCell = $(this).addClass('Selected');
			var dayNum = $(this).html() - 0;
			var month = monthShown.getMonth();
			var year = monthShown.getFullYear();
			s.selDate = new Date(year, month, dayNum);
			var specials = [];
			if (monthSpecials[dayNum]) {
				$.each(s.specialDates, function(i, d){
					if (dayNum == d.getDate() && month == d.getMonth() && year == d.getFullYear())
						specials.push(d);
				});
			}
			var trueClick = e.clientX ? true : false;
			var keepHistory = addToHistory;
			addToHistory = false;
			onSelect(s.selDate, (trueClick || keepHistory), specials);
		};
		var fixMonth = function(y, m, d){ // Necessary for Safari only
			if (m < 0)
				return new Date(y - 1, 11, d);
			else if (m > 11)
				return new Date(y + 1, 0, d);
			else
				return new Date(y, m, d);
		};
		var $$ = function(el){
			return $(document.createElement(el));
		};
		this.init = function(){
			calDiv.empty().append('<div class="calHeader"><div class="calPrev"></div><div class="calNext"></div><span class="calTitle"></span></div>');
			var headerRow = '<tr>';
			for (var i = 0; i < 7; i++) {
				var day = s.days[i];
				var sday = s.sdays[i];
				headerRow += '<th scope="col" abbr="' + day + '" title="' + day + '">' + sday + '</th>';
			}
			headerRow += '</tr>';

			calDiv.append('<table title="' + s.tableTitle + '"><thead>' + headerRow + '</thead><tbody></tbody></table>');
		};
		this.build = function(input){
			input = fixDate(input) || s.today;
			if (s.startDate && input < s.startDate)
				input = s.startDate;
			else if (s.endDate && input > s.endDate)
				input = s.endDate;
			var year = input.getFullYear();
			var month = input.getMonth();

			monthShown = input;

			monthSpecials = {};
			$.each(s.specialDates, function(i, d){
				if (month == d.getMonth() && year == d.getFullYear())
					monthSpecials[d.getDate()] = true;
			});

			var calPrev = calDiv.find('> div > .calPrev').empty();
			if (s.startDate && month == s.startDate.getMonth() && year == s.startDate.getFullYear())
				calPrev.append(s.prevImgDis ? '<img src="' + s.prevImgDis + '" alt="" />' : '&lt;');
			else {
				var lastMonth = fixMonth(year, month - 1, 1);
				var monthName = s.months[lastMonth.getMonth()];
				calPrev.append(
					$$('a').attr({ href: '#', title: monthName }).click(function(){
						me.build(lastMonth);
						return false;
					}).append(s.prevImg ? '<img src="' + s.prevImg + '" alt="' + monthName + '" />' : '&lt;')
				);
			}

			var calNext = calDiv.find('> div > .calNext').empty();
			if (s.endDate && month == s.endDate.getMonth() && year == s.endDate.getFullYear())
				calNext.append(s.nextImgDis ? '<img src="' + s.nextImgDis + '" alt="" />' : '&gt;');
			else {
				var nextMonth = fixMonth(year, month + 1, 1);
				var monthName = s.months[nextMonth.getMonth()];
				calNext.append(
					$$('a').attr({ href: '#', title: monthName }).click(function(){
						me.build(nextMonth);
						return false;
					}).append(s.nextImg ? '<img src="' + s.nextImg + '" alt="' + monthName + '" />' : '&lt;')
				);
			}

			calDiv.find('> div > .calTitle').html(s.months[month] + ' ' + year)

			var first = new Date(year, month, 1);
			var last = new Date(year, month + 1, 0);
			var iDate = new Date(year, month, 1 - first.getDay());

			var tBody = calDiv.find('> table > tbody').empty();

			for (var w = 0; w < 6; w++) {
				var hiddenRow = (s.lastRowHidden && w == 5 && iDate.getMonth() != month);
				var row = '<tr>';
				for (var i = 0; i < 7; i++) {
					var cell = '<td class="';
					var dayNum = iDate.getDate();
					if (hiddenRow) {
						cell += 'Hidden';
					} else if (iDate < first) {
						cell += 'PrevMonth';
						if (iDate.getDate() == (new Date(year, month, 0)).getDate())
							cell += ' PrevMonthLast';
					} else if (iDate > last) {
						cell += 'NextMonth';
						if (dayNum == 1)
							cell += ' NextMonthFirst';
					} else if (daysDisabled[i] || (s.startDate && iDate < s.startDate) || (s.endDate && iDate > s.endDate)) {
						cell += 'Disabled';
					} else {
						cell += 'Day';
					}
					if (monthSpecials[dayNum])
						cell += ' Special';
					if (iDate.valueOf() == s.today.valueOf())
						cell += ' Today';
					if (s.selDate && iDate.valueOf() == s.selDate.valueOf())
						cell += ' Selected';
					iDate.setDate(iDate.getDate() + 1);
					row += cell + '">' + dayNum + '</td>';
				}
				tBody.append(row + '</tr>');
			}
			tBody.children().children(".Day").click(dayClick).hover(function(){
				$(this).addClass('Over');
			}, function() {
				$(this).removeClass('Over');
			});
			selCell = $("td.Selected", tBody);
		};
		me.init();
		me.build(s.selDate);
	};
})(jQuery);