/***************************************************************************
 * mootools-moocalendar.event-2.0.js
 * ---------------
 *   author		-> Chris Colborne
 *   author		-> Andrew Taylor
 *   started	-> Monday, Oct 4th, 2010
 *   modified	-> Tuesday, Mar 1st, 2011
 *   copyright	-> 
 *   email     	-> chris.c@brightlabs.com.au
 *   version    -> 2.0.1
 *
 * file description
 * ------------------
 * Extends mooCalendar2 to provide an events calendar
 * 
 * Based on Mootable 2.0 and Mootools Calendar code by Tyson Cox
 *
 * provides
 * ------------------
 * mooCalendar2.Event
 * 
 * 
 * requires
 * ------------------
 * mooCalendar2
 * core:1.2.4
 * more:1.2.4.4
 * functions
 * JustTheTip
 * 
 * 
 * change log
 * ------------------
 * 2.0			Initial development
 * 2.0.1		Added ability to perform multiple filter searching
 *
 ***************************************************************************/


mooCalendar2.Event = new Class({

	Extends: mooCalendar2,
	
	options: {	'viewTitle': 'View by',
				'filterOptionTitle': 'Show',
				'weekTitleText': 'Week ',

				'eventFrame': null,
				'viewFrame': null,
				'filterFrame': null, 
				'weekFrame': null,
				
				'spinnerElement': null,

				'multipleFilters': false,

				'filterOptions': {},
				
				'initialView': 'month',
				'initialFilters': [],

				'showAllEventsFilter': true,
				'allEventsFilterName': 'All Events',
				
				'eventLinkText': 'view event &gt;',
				'noEventMsg': 'There are no events for your selection',
				
				'requestUrl': null,
				
				'showTooltips': true,
				'linkTooltipTitle': true
								
				// Callback functions
				// 'onFilterChange': $empty,
				// 'onViewChange': $empty,
				// 'onWeekChange': $empty,
				
				// Ajax callback functions
				// 'onDataRequest': $empty,
				// 'onDataComplete': $empty,
				// 'onDataSuccess': $empty,
				// 'onDataFailure': $empty,
					
				// Callback functions from mooCalendar2
				// 'onCreate': $empty,
				// 'onRender': $empty,
				// 'onDayClick': $empty
				// 'onMonthChange': $empty
	},
	
					/*--------------------------------------------------------o
	----------------\                     Member Variables                    |
		variables    \-------------------------------------------------------*/
					
	eventList: [],
	
	week: 0,
	
	filters: [],
	view: '',
	
	hovers: null,
	
	errorMessage: null,
	
	
					/*--------------------------------------------------------o
	----------------\                    Internal Functions                   |
		 internal    \-------------------------------------------------------*/
		
	initialize: function(elem, options) {
		this.setOptions(options);		
				
		if (this.options.initialView == 'month' || this.options.initialView == 'week' || this.options.initialView == 'day') {
			this.view = this.options.initialView;
		} else {
			this.view = 'month';
		}
		
		if (this.options.initialFilters != undefined && this.options.initialFilters.length != 0) {
			this.filters = this.options.initialFilters;	
		} else {
			this.filters = [];	
		}

		if (this.options.eventFrame != null) {
			this.options.eventFrame.addClass('event-holder');
		}
		
		if (this.options.viewFrame != null) {
			this.options.viewFrame.addClass('calViewHolder');			
		}
		
		if (this.options.filterFrame != null) {
			this.options.filterFrame.addClass('calFilterOptionHolder');
		}
		
		if (this.options.weekFrame != null) {
			this.options.weekFrame.addClass('calWeekHolder');
		}
		
		this.parent(elem, options);			

		this.week = this.curDate.getWeekOfMonth();
		
		// Hide or show week holder
		if (this.view == 'week') {
			this.options.weekFrame.show();		
		} else {
			this.options.weekFrame.hide();		
		}
		
		if (this.options.showTooltips) {
			this.hovers = new JustTheTip($('calendarInner'), {	
				tip_html   : '<div class="event-cal-tip-top"></div><div class="event-cal-tip"></div><div class="event-cal-tip-bottom"></div>', 
				tip_class  : 'event-cal-tip-wrap', 
				show_delay : 100, 
				show_event : 'mouseover:relay(.calDayFilled)', 
				position: { position: 'bottomRight', edge: 'topLeft', offset: {x: -5, y: -5} }, 

				onTipShown: function(tip, elem, jtt) { 
					tip.getFirst('.event-cal-tip').set('html', elem.get('tooltipText')); 
				} 
															
			});
		}
	},

					/*--------------------------------------------------------o
	----------------\                   Setup Functions                       |
		  setup      \-------------------------------------------------------*/
	
	create: function() {
		// Add all events filter item
		if (!this.options.multipleFilters && !this.isEmptyObject(this.options.filterOptions) && this.options.showAllEventsFilter) {
			if (this.options.allEventsFilterName == '') {
				this.options.allEventsFilterName = 'All Events';
			}
			var allEvents = {'': this.options.allEventsFilterName};
			this.options.filterOptions = $extend(allEvents, this.options.filterOptions);
		}
		
		// Add default view event text
		if (this.options.eventLinkText == '') {
			this.options.eventLinkText = 'view event &gt;';	
		}
		
		this.createView();
		
		if (this.options.filterFrame != null && !this.isEmptyObject(this.options.filterOptions)) {
			this.createFilters();
		}
		
		if (this.options.requestUrl) {
			this.updateData();
		}
	},
	
	render: function() {
		this.parent();
		if (this.options.weekFrame) {
			this.updateWeekButtons();
		}
		
		if (this.view == 'day') {
			// Highlight on click
			$$('.calDayCell.selected').each(function(elem, idx) {
				elem.removeClass('selected');	
			});
			$$('.calDate' + this.curDate.get('date')).addClass('selected');
		}
		
		if (this.options.eventFrame) {
			this.updateEventFrame();
		}
		
		this.onRender();
		
	},
	

	createView: function() {
		var mooCalendar2 = this;
		
		var viewContain = this.options.viewFrame;
		
		var viewTitle = new Element('div', {'class': 'calViewTitle', 'html': this.options.viewTitle});
		
		viewContain.adopt(viewTitle);
		

		// Create filter buttons (month, week, day)
		var filterButtons = new Element('ul', {'class': 'calFilterButtons'});
	
		var filterDay = new Element('li', {'class': 'calFilterBtn calFilterDay' + ((this.view == 'day')?' selected':''), 'html': 'Day'});
		filterDay.addEvent('click', function(event) {
			mooCalendar2.setView((this.innerHTML).toLowerCase());		
		});		
		filterButtons.adopt(filterDay);

		var filterWeek = new Element('li', {'class': 'calFilterBtn calFilterWeek' + ((this.view == 'week')?' selected':''), 'html': 'Week'});
		filterWeek.addEvent('click', function(event) {
			mooCalendar2.setView((this.innerHTML).toLowerCase());		
		});		
		filterButtons.adopt(filterWeek);
		
		var filterMonth = new Element('li', {'class': 'calFilterBtn calFilterMonth' + ((this.view == 'month')?' selected':''), 'html': 'Month'});
		filterMonth.addEvent('click', function(event) {
			mooCalendar2.setView((this.innerHTML).toLowerCase());	
		});		
		filterButtons.adopt(filterMonth);
		
		viewContain.adopt(filterButtons);
		
	},
	
	createFilters: function() {		
		var mooCalendar2 = this;

		var filterOptionContain = this.options.filterFrame;
		
		// Create filter options
		var filterOptionTitle = new Element('div', {'class': 'calFilterOptionTitle', 'html': this.options.filterOptionTitle});
		
		filterOptionContain.adopt(filterOptionTitle);
		
		var filterOptions = new Element('ul', {'class': 'calFilterOptions'});
	
		for (i in this.options.filterOptions) {
			
			var checked = false;
			
			// Find out if the filter is one of the initial filters now so it doesn't bug out IE7
			if (!this.options.multipleFilters && this.filters.length == 0 && i == '') {
				checked = true;
			} else {
				for (var j=0; j < this.filters.length; j++) {
					if (this.filters[j] == i) {
						checked = true;
					}
				}
			}
			
			if (this.options.multipleFilters) {
				if (checked) {
					var filterInput = new Element('input', {'type': 'checkbox', 'name': 'filter', 'value': i, 'class': 'filter_'+i, 'checked': checked});
				} else {
					// Fix for IE7
					var filterInput = new Element('input', {'type': 'checkbox', 'name': 'filter', 'value': i, 'class': 'filter_'+i});
				}
			} else {
				if (checked) {
					var filterInput = new Element('input', {'type': 'radio', 'name': 'filter', 'value': i, 'class': 'filter_'+i, 'checked': checked});
				} else {
					// Fix for IE7
					var filterInput = new Element('input', {'type': 'radio', 'name': 'filter', 'value': i, 'class': 'filter_'+i});
				}
			}
			
			filterInput.addEvent('click', function(event) {
				if (mooCalendar2.options.multipleFilters) {
					if (this.checked == true) {
						mooCalendar2.addFilter(this.value);
					} else {
						mooCalendar2.removeFilter(this.value);
					}
				} else {
					mooCalendar2.clearFilters();
					mooCalendar2.addFilter(this.value);
				}
			});
			
			var label_text = new Element('span', {'class': 'filter_label_text filter_label_text_'+i, 'html': this.options.filterOptions[i]})
			var label = new Element('label', {'class': 'filter_label filter_label_'+i});
			
			label.adopt(filterInput);
			label.adopt(label_text);
			
			var filter = new Element('li', {'class': 'calFilterOption'});
			filter.adopt(label);
			filterOptions.adopt(filter);
		}
		
		filterOptionContain.adopt(filterOptions);		
	},
	
	updateWeekButtons: function() {
		var weekHolder = this.options.weekFrame;
		var mooCalendar2 = this;
		
		this.weeksInMonth = this.curDate.getWeeksInMonth();
		
		weekHolder.empty();
		
		for (var week=1; week <= this.weeksInMonth; week++) {
			var weekBtn = new Element('li', {'class': 'calWeekBtn calWeekBtn_' + week + ((this.week == week)?' selected':''), 'html': this.options.weekTitleText + week});
			weekBtn.addEvent('click', function(event) {
				if (!this.hasClass('selected')) {
					$$('.calWeekBtn').each( function(elem, idx) {
						elem.removeClass('selected');
					});
					
					this.addClass('selected');
					mooCalendar2.setWeek((this.innerHTML).substr((this.innerHTML).indexOf(' ')));
				}
				
			});
			weekHolder.adopt(weekBtn);
		}
		
	},
	
	
	createDayElement: function (dayNum, day) { 
		mooCalendar2 = this;
		
		var todayClass = '';
		 
		// Today Class
		if ( this.todayDate.get('year') == this.curDate.get('year') && 
				this.todayDate.get('month') == this.curDate.get('month') && 
				this.todayDate.get('date') == dayNum ) {
			todayClass = ' today';
		}
		
		var selectedClass = '';
		var tooltipText = '';
		var first = true;
		var hasEvents = false;
		
		fullDate = this.curDate.format('%Y-%m-' + this.str_pad(dayNum, 2, '0', 'STR_PAD_LEFT'));
		
		if (this.eventList[fullDate] != undefined) {		
			$each(this.eventList[fullDate], function(event, idx) {			
				if (event != undefined) {
					var includeEvent = false;
					
					for (var i=0; i < mooCalendar2.filters.length; i++) {
						if ((!mooCalendar2.options.multipleFilters && mooCalendar2.filters[i] == "") || mooCalendar2.filters[i] == event.filter) {
							includeEvent = true;
							break;
						}
					}
					
					if ((!mooCalendar2.options.multipleFilters && (mooCalendar2.filters == undefined || mooCalendar2.filters.length == 0)) || includeEvent) {
						selectedClass = 'calDayFilled';
						
						// If there is a link, and the option is true, title is a link, otherwise not
						tooltipTitle = (event.link && mooCalendar2.options.linkTooltipTitle ? '<a class="event-cal-tooltip-event-title" href=" ' + event.link + '">' : '<span class="event-cal-tooltip-event-title">') + event.title + (event.link && mooCalendar2.options.linkTooltipTitle ? '</a>' : '</span>');
						
						tooltipText += '<span class="event-cal-tooltip-event' + ((first)?' first':'') + '"><span class="event-cal-tooltip-event-time">' + Date.parse(event.date).format('%I:%M %p') + '</span> - ' + tooltipTitle + '<br /><span class="event-cal-tooltip-event-location">' + event.location + '</span></span>\n';
						first = false;
					}
				}
			});
		}

		var li = new Element('li', {	'class': 'calDayCell calDay' + day + ' calDate' + dayNum + todayClass + ' ' + selectedClass,
										text: dayNum,
										dayNum: dayNum,
										tooltipText: tooltipText
									});		
		return li;
	},
	
					/*--------------------------------------------------------o
	----------------\                    Event Creation Functions
		 events      \-------------------------------------------------------*/

	
	updateEventFrame: function () { 
		mooCalendar2 = this;
		this.options.eventFrame.empty();
		
		year = this.curDate.get('year');
		month = this.str_pad(this.curDate.get('month') + 1, 2, '0', 'STR_PAD_LEFT');
		
		// Decide on dates to iterate through
		switch (this.view) {
			default:
			case 'month':
				startDay = 1;
				endDay = this.curDate.getLastDayOfMonth();
				break;
			
			case 'week':				
				days = this.curDate.getWeekDatesOfMonth(this.week);
				startDay = days[0];
				endDay = days[1];
				break;
				
			case 'day':
				startDay = this.curDate.get('date');
				endDay = this.curDate.get('date');
				break;			
		}
		
		// Iterate through dates looking for events
		var hasEvents = false;
		for (day = startDay; day <= endDay; day++) {
			day = this.str_pad(day, 2, '0', 'STR_PAD_LEFT');	
			if (this.eventList[year + '-' + month + '-' + day] != undefined) {
				$each(this.eventList[year + '-' + month + '-' + day], function (event, idx) {
					if (event != undefined && event.date != undefined) {
						// Check for filter
						if (mooCalendar2.filters == undefined || (!mooCalendar2.options.multipleFilters && mooCalendar2.filters.length == 0)) {
							mooCalendar2.createEventRow(event);
							hasEvents = true;
						} else {
							for (var i = 0; i < mooCalendar2.filters.length; i++) {
								if (mooCalendar2.filters[i] == event.filter || mooCalendar2.filters[i] == "") {
									mooCalendar2.createEventRow(event);
									hasEvents = true;
									break;
								}
							}
						}
					}
				});
			}
		}
		
		if (!hasEvents) {
			this.createNoEventRow();
		}
				
	},

	createEventRow: function (event) {
		eventDate = Date.parse (event.date);

		if (event.link != '') {
			// Event Row
			listrow = new Element('li', {'class': 'event-row filter_' + event.filter});
			row = new Element('a', {'class': 'event-link', 'href': event.link});
		} else {
			listrow = false; /*for checking later on*/
			row = new Element('li', {'class': 'event-row filter_' + event.filter});			
		}
		
		// Event Date
		eventDateHolder = new Element('span', {'class': 'event-date-holder'});
		eventMonth = new Element('span', {'class': 'event-month', 'html': eventDate.format('%b')});
		eventDateDiv = new Element('span', {'class': 'event-date', 'html': eventDate.get('date')});
		eventYear = new Element('span', {'class': 'event-year', 'html': eventDate.format('%Y')});
		
		eventDateHolder.adopt(eventDateDiv);
		eventDateHolder.adopt(eventMonth);
		eventDateHolder.adopt(eventYear);
		
		row.adopt(eventDateHolder);
		
		// Event Details
		eventDetailsHolder = new Element('span', {'class': 'event-details'});
		eventTitle = new Element('span', {'class': 'event-title', 'html': event.title + ' ' + event.location});
		eventDesc = new Element('span', {'class': 'event-desc', 'html': event.description});
		
		eventDetailsHolder.adopt(eventTitle);
		eventDetailsHolder.adopt(eventDesc);
		
		row.adopt(eventDetailsHolder);		
		
		if (listrow) {
			listrow.adopt(row);
			this.options.eventFrame.adopt(listrow);
		} else {
			this.options.eventFrame.adopt(row);
		}
				
	},
	
	createNoEventRow: function (event) {
		// Event Row
		row = new Element('li', {'class': 'event-row no-events', 'html': this.options.noEventMsg});
		
		this.options.eventFrame.adopt(row);
			
	},
	
	
					/*--------------------------------------------------------o
	----------------\                    Ajax Data Handling                   |
		   ajax      \-------------------------------------------------------*/
	
	updateData: function() {
		var mooCalendar2 = this;
		var data = null;
		
		mooCalendar2.errorMessage = null;
		
		var json_request = new Request.JSON({	'url':				this.options.requestUrl,
												'method':			'post',
												'data':				'',
												'onRequest':		function() {
																		mooCalendar2.createSpinner(mooCalendar2.options.spinnerElement)
																		mooCalendar2.onDataRequest();
																	},
												'onComplete':		function() {
																		mooCalendar2.destroySpinner(mooCalendar2.options.spinnerElement)
																		mooCalendar2.onDataComplete();
																	},
												'onSuccess':		function(data, raw) {
																		mooCalendar2.onDataSuccess(data);
																	},
												'onFailure':		function(response) {
																		mooCalendar2.onDataFailure(response);
																	}
											});
		json_request.send();
	
	},
	
	
	parseResponse: function(data) {
		if ( data && data.results ) {
			for (i in data.results) {
				// This solves the hanging comma iCMS issue - simply discard any empty result
				if (i != "" && data.results[i].date) {
					eventDate = Date.parse(data.results[i].date);
					eventDateFormatted = eventDate.format('%Y-%m-%d');
					if (!this.eventList[eventDateFormatted]) {
						this.eventList[eventDateFormatted] = [];
					}
					
					this.eventList[eventDateFormatted][i] = data.results[i];
				}
			}

		} else {
			this.errorMessage = 'Malformed response received.';	
		}
		
		this.render();
	},
	
	
	
					/*--------------------------------------------------------o
	----------------\                   Event Functions                       |
		  event      \-------------------------------------------------------*/
	
	onFilterChange: function () {
		this.fireEvent('filterChange', this.filters);
	},
	
	onViewChange: function () {
		this.fireEvent('viewChange', this.view);
	},
	
	onWeekChange: function () {
		this.fireEvent('weekChange', this.week);
	},
	
	onDayClick: function (elem) {
		// Hide the tip when clicked to fix bug where it stays open
		$$('.event-cal-tip-wrap').each( function(elem) { elem.hide() });
		
		this.setView('day');
		
		// Set the week to the selected date's week
		this.week = this.curDate.getWeekOfMonth();

		this.parent();		
	},
	
	onMonthChange: function () {
		this.curDate.set('date', 1);
		this.week = 1;
		this.setView('month');
	},
	
	// Ajax Events
	
	onDataRequest: function () { 
		this.fireEvent('dataRequest');
	},
	
	onDataComplete: function () {
		this.fireEvent('dataComplete');
	},
	
	onDataSuccess: function (data) {
		this.parseResponse(data);
		this.fireEvent('dataSuccess');		
	},
	
	onDataFailure: function (response) {
		this.errorMessage = 'Unable to retrieve data. - ' + response;
		this.fireEvent('dataFailure', this.errorMessage);
	},
	
	
					/*--------------------------------------------------------o
	----------------\                   Setter Functions                      |
		  setters    \-------------------------------------------------------*/
	
	setWeek: function(w) { 
		this.week = w; 
		this.render();
		this.onWeekChange();
	},
	
	addFilter: function(f) {
		this.filters[this.filters.length] = f;
		this.render();
		this.onFilterChange();
	},
	
	clearFilters: function() {
		this.filters = []; 
	},
	
	removeFilter: function(f) {
		var newFilters = [];
		
		for (var i=0; i < this.filters.length; i++) {
			if (this.filters[i] != f) {
				newFilters[newFilters.length] = this.filters[i];
			}
		}
		this.filters = newFilters;
		this.render();
		this.onFilterChange();
	},
	
	setView: function (view) {
		$$('.calFilterButtons .selected').each(function(elem, idx) {
			elem.removeClass('selected');
		});
		
		$$('.calFilter' + this.ucfirst(view)).addClass('selected');	
		
		if (view == 'week') {
			this.options.weekFrame.show();		
		} else {
			this.options.weekFrame.hide();				
		}
		
		this.view = view;
		this.render();
		this.onViewChange();
	},
	
	
	ucfirst: function(str) {
		// Makes a string's first character uppercase  
		// 
		// version: 1008.1718
		// discuss at: http://phpjs.org/functions/ucfirst
		// +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// +   bugfixed by: Onno Marsman
		// +   improved by: Brett Zamir (http://brett-zamir.me)
		// *     example 1: ucfirst('kevin van zonneveld');
		// *     returns 1: 'Kevin van zonneveld'
		str += '';
		var f = str.charAt(0).toUpperCase();
		return f + str.substr(1);
	},

	str_pad: function(input, pad_length, pad_string, pad_type) {
		// Returns input string padded on the left or right to specified length with pad_string  
		// 
		// version: 1008.1718
		// discuss at: http://phpjs.org/functions/str_pad
		// +   original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
		// + namespaced by: Michael White (http://getsprink.com)
		// +      input by: Marco van Oort
		// +   bugfixed by: Brett Zamir (http://brett-zamir.me)
		// *     example 1: str_pad('Kevin van Zonneveld', 30, '-=', 'STR_PAD_LEFT');
		// *     returns 1: '-=-=-=-=-=-Kevin van Zonneveld'
		// *     example 2: str_pad('Kevin van Zonneveld', 30, '-', 'STR_PAD_BOTH');
		// *     returns 2: '------Kevin van Zonneveld-----'
		var half = '', pad_to_go;
	 
		var str_pad_repeater = function (s, len) {
			var collect = '', i;
	 
			while (collect.length < len) {collect += s;}
			collect = collect.substr(0,len);
	 
			return collect;
		};
	 
		input += '';
		pad_string = pad_string !== undefined ? pad_string : ' ';
		
		if (pad_type != 'STR_PAD_LEFT' && pad_type != 'STR_PAD_RIGHT' && pad_type != 'STR_PAD_BOTH') { pad_type = 'STR_PAD_RIGHT'; }
		if ((pad_to_go = pad_length - input.length) > 0) {
			if (pad_type == 'STR_PAD_LEFT') { input = str_pad_repeater(pad_string, pad_to_go) + input; }
			else if (pad_type == 'STR_PAD_RIGHT') { input = input + str_pad_repeater(pad_string, pad_to_go); }
			else if (pad_type == 'STR_PAD_BOTH') {
				half = str_pad_repeater(pad_string, Math.ceil(pad_to_go/2));
				input = half + input + half;
				input = input.substr(0, pad_length);
			}
		}
	 
		return input;
	},

	isEmptyObject: function( obj ) {
			for ( var name in obj ) {
				return false;
			}
			return true;
	}
	
});

// Add a function to get the week number of this month for this day
Date.prototype.getWeekOfMonth = function () {
	tmpDate = new Date(this.getFullYear(), this.getMonth(), 1);
	
	// Get first day of month
	firstDay = tmpDate.get('day');
	
	// First week has
	firstWeek = 7 - firstDay;
	week = 1;
	while (this.getDate() > firstWeek && firstWeek <= this.getLastDayOfMonth()) {
		week++;
		firstWeek += 7;
	}

	return week;	
}

// Add a function to get the dates for this week of month
Date.prototype.getWeekDatesOfMonth = function (week) {
	tmpDate = new Date(this.getFullYear(), this.getMonth(), 1);
	
	// Get first day of month
	firstDay = tmpDate.get('day');
	
	// Get number of days in month
	numDays = tmpDate.getLastDayOfMonth();
	
	// Get last day of month
	tmpDate.set('date', numDays);
	lastDay = tmpDate.get('day');
	
	// First week has
	firstWeek = 7 - firstDay;
	
	// Last week has 
	lastWeek = lastDay + 1;
	
	// first week
	if (week == 1) {
		return [1, 1 + firstWeek - 1];
	}
	
	// last week
	if (week == tmpDate.getWeeksInMonth()) {
		return [tmpDate.getLastDayOfMonth()-lastWeek+1, tmpDate.getLastDayOfMonth()];	
	}
	
	sun = 1 + firstWeek + (7 * (week-2));
	sat = sun + 6;
	
	return [sun, sat];
}

// Add a function to get the number of weeks in the current month
Date.prototype.getWeeksInMonth = function () {
	tmpDate = new Date(this.getFullYear(), this.getMonth(), 1);
	
	// Get first day of month
	firstDay = tmpDate.get('day');
	
	// Get number of days in month
	numDays = tmpDate.getLastDayOfMonth();
	
	// Get last day of month
	tmpDate.set('date', numDays);
	lastDay = tmpDate.get('day');
	
	// First week has
	firstWeek = 7 - firstDay;
	
	// Last week has 
	lastWeek = lastDay + 1;
	
	// Number of weeks (excluding the part weeks)
	numWeeks = (numDays - (firstWeek + lastWeek))/7;
	
	// If there were days in the first part week, add a week
	if (firstWeek != 0) {
		numWeeks++;	
	}
	
	// If there were days in the last part week, add a week	
	if (lastWeek != 0) {
		numWeeks++;	
	}
	
	return numWeeks;
	
}



