			
		var DateWidget = new Class({

			ARROW_PATH: "/gifimages/MenuArrow",
			ONE_DAY_IN_MILLIS: 1000 * 60 * 60 * 24,
			myDrag: null,

			/**
			 * Height of the popup if we're only showing Saturdays
			 */
			SATS_HEIGHT: '275px',
			ALL_DAYS_HEIGHT: '480px',
			
			showing: false,

			Implements: Options,
			initialize: function(seasons, shortMonths, shortDays, targetDateFieldId, widgetTop, widgetLeft){
				this.seasons = seasons;
				this.shortMonths = shortMonths;
				this.shortDays = shortDays;

				this.targetDateFieldId = targetDateFieldId;
				this.widgetTop = widgetTop;
				this.widgetLeft = widgetLeft;
				//for web site users we don't want to show the first month of the next season, 
				//because they just have to choose the FROM date and the length of their stay
				this.showFirstSatOfNextYear = false;
				/*
				if($defined(options)){
					this.options = options;
				}
				*/
				this.myDrag = null;
				if($defined($('quickDatesDiv'))){
					this.myDrag = new Drag.Move($('quickDatesDiv'));
				}

			},
			/*
			options: {
				showAllDaysOfTheWeek: 'false'
			},
			*/
			
			
			
			
			isShowing: function(){
				return this.showing;
			},
			
			show: function(fieldId){
				this.targetDateFieldId = fieldId;
				var currentOne = $(fieldId);
				this.widgetTop = $(fieldId).getPosition().y + 50;
				this.widgetLeft = $(fieldId).getPosition().x;
				this.showThyself();
			},
			
			showThyself: function(){

				
				$('quickDatesDiv').setStyle('height', this.getDatesDivHeight());
				
				this.showing = true;
				
				var openingDuration = 500;
				$('quickDatesOpener').setStyle('visibility','visible');	
				$('quickDatesOpener').setStyle('borderStyle','solid');			
				$('quickDatesOpener').setStyle('borderColor','#cccccc');			
				$('quickDatesOpener').setStyle('borderWidth','1px');	
				$('quickDatesOpener').setStyle('zIndex','2');	
				
				var myEffect = new Fx.Morph($('quickDatesOpener'),{
					duration: openingDuration
				});
				var widget = this;

				myEffect.start({
					height: $('quickDatesDiv').clientHeight,
					width: $('quickDatesDiv').clientWidth,
					top: widget.widgetTop,
					left: widget.widgetLeft,
					position: 'absolute'
				}).chain(function(){
					$('quickDatesDiv').setStyle('top',widget.widgetTop);
					$('quickDatesDiv').setStyle('left',widget.widgetLeft);
					//widget.showShadow();
					$('quickDatesOpener').setStyle('visibility','hidden');

					var distanceFromBottom = widget.getDistanceFromBottom($('quickDatesDiv'));
					if(distanceFromBottom < 0){
						scrollToBottomOfObject(distanceFromBottom);
					}
				});
				

			},
			
			/**
			 * Regulates the height of the popup depending on whether we're showing just Saturdays
			 * or all days of the week
			 */
			
			getDatesDivHeight: function(){

				//if(this.showAllDaysOfTheWeek()){
					//return this.ALL_DAYS_HEIGHT;
				//}
				return this.SATS_HEIGHT;

			},
			

			/**
			* Gets the distance from the bottom of the objectId to the bottom of the visible
			* screen. If the result is negative, then the bottom of the object is off the screen,
			* and we need to scroll down.
			*/
			getDistanceFromBottom: function(objectId){
				
				//the screen height (the height of what we're actually looking at)
				var windowHeight = window.getHeight();
				//the position of the top of the window in relation to the whole page
				var windowTopOffset = window.getScrollTop();
				//now we've got the y pos of the bottom of the window in relation to the whole page
				var windowBottomPos = windowHeight + windowTopOffset;
				
				//get all the coordinates of the object
				var objCoords = $(objectId).getCoordinates();
				return windowBottomPos - (objCoords.bottom);
			},

			
			hide: function(){
				$(this.targetDateFieldId).focus();
				this.hideThyself();
			},
			
			hideThyself: function(){
				this.showing = false;
				this.turnOffAllArrows('yearArrow');
				this.turnOffAllArrows('monthYear');
				this.removeMonthMenus();
				this.removeSatsMenus();
				//this.hideShadow();
				$('quickDatesDiv').setStyle('top','-1000px');

				$('quickDatesOpener').setStyle('visibility', 'hidden');			
				$('quickDatesOpener').setStyle('width', '0px');			
				$('quickDatesOpener').setStyle('height', '0px');			

			},
			
			/**
			 * not used anymore
			 */
			showShadow: function(){
				var shadowObj = new Element('img',{
					id: 'datesShadowImg',
					src: '/gifimages/maps/shadow.png',
					styles: {
						position: 'absolute',
						top: this.widgetTop + 10,
						left: this.widgetLeft + 10,
						width: $('quickDatesDiv').clientWidth,
						height: $('quickDatesDiv').clientHeight,
						zIndex: '2',
						visibility: 'hidden'
					}
				});
				shadowObj.inject($('quickDatesDiv'), 'before');
				shadowObj.setStyle('visibility','visible');
			},
			
			/**
			 * not used any more
			 */
			hideShadow: function (){
				$('datesShadowImg').destroy();
			},
			
			
			/**
			 * Shows the month menu block for the year the mouse is hovering over
			 */
			showMonths: function(season){
				this.turnOffAllArrows('yearArrow');
				this.changeYearArrowColour(season, 'White');
				this.removeSatsMenus();
				this.removeMonthMenus();
				
				var yearLinkCoords = $('link' + season).getCoordinates($('quickDatesDiv'));

				
				
				var monthsDiv = new Element('div',{
					id: 'monthMenu' + season,
					'class': 'dateMenu',
					styles: {
						width: 80,
						position: 'absolute',
						top: yearLinkCoords.top - 2,
						left: (yearLinkCoords.right + 1)
					}
				});

				//save the name of the top monthYear link so that later we can call it up
				//so that we know where to place the sats links next to it 
				//In the long version with all days of the week we place it at the top next to the
				//first monthYearLink
				this.topMonthDivId = 'monthYearLink' + season + '0';
				var monthsYearArray = this.getMonthsYearArray(season);				
				this.prepareMenuLinks(monthsYearArray, monthsDiv, season, 'monthYear', this.ARROW_PATH);
				monthsDiv.inject($('quickDatesDiv'));
			},
			
			/**
			 * Reads the showAllDaysOfTheWeek hidden field
			 */
			showAllDaysOfTheWeek: function(){
				if($defined($('showAllDaysOfTheWeek')) && $('showAllDaysOfTheWeek').value === 'true'){
					return true;
				}
				return false;
			},
			
			/**
			 * Reads the hasPrezziMensili hidden field
			 */
			hasPrezziMensili: function(){
				if($defined($('hasPrezziMensili')) && $('hasPrezziMensili').value === 'true'){
					return true;
				}
				return false;
			},
			
			/**
			 * Shows the sats menu block for the month the mouse is hovering over
			 */
			showSats: function(monthYear, season, monthYearId){
				
				this.removeSatsMenus();
				this.changeYearArrowColour(season, 'White');
				
				var monthYearCoords = $(monthYearId).getCoordinates($('quickDatesDiv'));
				var satsArray = this.getSatsArray(monthYear);
				
				//if there are just Saturdays, then we position the Sats div next to the current month
				//we're over in the list
				var topPosition = monthYearCoords.top;
				var overflower = 'none';
				var heighter = '';
				var widther = '120px';
				//otherwise we position next to the first month
				if(this.showAllDaysOfTheWeek() & !this.hasPrezziMensili()){
					var positioner  = $(this.topMonthDivId).getPosition($('quickDatesDiv'));
					topPosition = $(this.topMonthDivId).getPosition($('quickDatesDiv')).y;
					if(satsArray.length > 16){
						//we have to have scroll instead of auto otherwise
						//the last choice in the visible bit doesn't respond properly in 
						//Firefox
						overflower = 'scroll';
						heighter = '260px';
					}
					widther = '140px';
				}
				
				var satsDiv = new Element('div',{
					id: 'sats' + monthYear,
					'class': 'dateMenu',
					styles: {
						width: widther,
						position: 'absolute',
						top: topPosition - 2,
						left: (monthYearCoords.right + 1),
						height: heighter
					}
				});
				
				if(Browser.Engine.trident){
					satsDiv.setStyles({
						overflow: 'visible', 
						overflowX: 'hidden', 
						overflowY: 'auto'
					});
				}else{
					satsDiv.setStyle('overflow', overflower);
				}

				
				this.prepareMenuLinks(satsArray, satsDiv, season, 'sats' + monthYear, this.ARROW_PATH);
				satsDiv.inject($('quickDatesDiv'));
				//alert(satsDiv.getPosition().y + satsDiv.get('height') + ':' + screen.height);
				
				//stop the drag for the sats menu appears with its
				//scroller, we can use the scroller without moving the whole date widget
				if($defined(satsDiv)){
					satsDiv.addEvent('mouseover', function(){
						this.myDrag.detach();
					}.bind(this));
					satsDiv.addEvent('mouseout', function(){
						this.myDrag.attach();
					}.bind(this));
				}
				
			},

			/**
			 * Removes any months menu blocks that might be open
			 */
			removeMonthMenus: function(){
				this.seasons.each(function(value,index){
					var currMenu = $('monthMenu' + value);	
					if($defined(currMenu)){
						currMenu.destroy();
					}					
				});
			},
			
			/**
			 * Removes any sats menu blocks that might be open
			 */
			removeSatsMenus: function(){
				var satsMenuObjs = $$('div[id^=sats]');
				satsMenuObjs.each(function(value, index){
					value.destroy();
				});
			},
			
			/**
			 * Within a month or sats menu block, prepares the links on each line
			 */
			prepareMenuLinks: function(textArray, holdingDiv, season, idRoot, arrowPath){
				
				textArray.each(function(value, index){
					
					//can't pass 'this' yet again, so we copy the binded this to a variable
					var widget = this;

					var currentLink = new Element('a',{
						id: idRoot + 'Link' + season + index,
						html: '&nbsp;' + value + '&nbsp;',
						href: '',
						styles: {
							textAlign: 'right',
							'float': 'right'
						},
						'class': 'dateChooserLink',
						events: {
							mouseover: function(){
								widget.turnOffAllArrows(idRoot, season);
								if(widget.isMonthMenu(holdingDiv.id)){
									$(idRoot + 'Arrow' + season + index).src = arrowPath + 'White.gif';
									//widget.showSats(value, season, idRoot + 'Link' + season + index);
								}
							},
							click: function(){
								if(!widget.isSatsMenu(holdingDiv.id)){
									//new code 17.05.2010
									if(widget.isMonthMenu(holdingDiv.id)){
										widget.showSats(value, season, idRoot + 'Link' + season + index);
									}
									this.blur();
									return false;
								}else{
									if($(widget.targetDateFieldId).get('type') === 'text'){
										$(widget.targetDateFieldId).value = widget.formatDate(value, '.');
										$(widget.targetDateFieldId).blur();
										//if we've placed an overlay, now destroy it
										if($defined($('myOverlay'))){
											$('myOverlay').destroy();
										}
									}else{
										widget.selectTargetFieldValue(widget.targetDateFieldId, widget.formatDate(value, '.'));
									}//end if
									//change doesn't get fired, so we have to do it
									$(widget.targetDateFieldId).fireEvent('change');
									//reset drag because with mouseover the satsDiv we detached it
									widget.myDrag.attach();
									widget.hideThyself();
									return false;
								}//end if
							}
						}
					});
					
					
					currentLink.inject(holdingDiv);

					//there's no right-arrow on the sats menu list
					if(!widget.isSatsMenu(holdingDiv.id)){
						var arrowImg = new Element('img',{
							src: arrowPath + 'Black.gif',
							id: idRoot + 'Arrow' + season + index,
							styles: {
								border: '0px',
								marginRight: '2px'
							}
						});
						arrowImg.inject(currentLink);
					}
					
					currentLink.set('class','dateChooserLink');
					
				},this);
			},

			isMonthMenu: function(holdingDivId){
				return holdingDivId.indexOf('monthMenu') > -1;
			},
			
			isSatsMenu: function(holdingDivId){
				return holdingDivId.indexOf('sats') > -1;
			},

			/**
			 * Selects the chosen date in the target date <select> field
			 */
			selectTargetFieldValue: function(targetDateFieldId, dateString){
				var optionsArray = $(targetDateFieldId).options;
				for(var i = 0; i < optionsArray.length; i = i + 1){
					var theValue = optionsArray[i].value;
					if(optionsArray[i].value === dateString){
						$(targetDateFieldId).selectedIndex = i;
					}
				}
			},


			/**
			 * Takes a date in the form 'dd MMM yyyy' and converts it to 'dd.mm.yyyy'
			 */
			formatDate: function(stringDate, separator){
				stringDate = stringDate.stripTags();
				var dateSplitArray = stringDate.split(' ');
				var monther = this.shortMonths.indexOf(dateSplitArray[2]);
				return this.makeTwoDigitNumber(dateSplitArray[1]) + separator + this.makeTwoDigitNumber(this.shortMonths.indexOf(dateSplitArray[2]) + 1) + separator + dateSplitArray[3];
			},

			makeTwoDigitNumber: function(theNumber){
				if((theNumber + '').length == 1){
					return '0' + theNumber;
				}
				return theNumber;
			},
			
			/**
			 * makes sure all arrows are black, using part of an id as identifier
			 */
			turnOffAllArrows: function(idToFind){
				var arrowArray = $$('img[id^=' + idToFind + ']');
				var widget = this;
				arrowArray.each(function(value,index){
					if(arrowArray[index].src.indexOf('White.gif') > -1){
						arrowArray[index].src = widget.ARROW_PATH + 'Black.gif';
					}
				}),widget;
			},

			/**
			 * Changes arrow colour in the top year menu
			 */
			changeYearArrowColour: function(season, colour){
				$('yearArrow' + season).src = this.ARROW_PATH + colour + ".gif";
			},
			
			//do we need this?
			doMousedown: function(season){
				//menusAreOpen=true;
				$('link' + season).blur();
			},
			
			/**
			 * Gives an array of month 'MMM yyyy' texts for the year chosen eg 'Jan 2008' etc
			 */
			getMonthsYearArray: function(season){
				var monthsYearArray = new Array();
				
				var counter = 0;
				for(var i = this.getStartMonth(season); i < this.shortMonths.length; i = i + 1){
					monthsYearArray[counter] = this.shortMonths[i] + " " + season;
					counter = counter + 1;
				}
				return monthsYearArray;
			},

			/**
			 * Gives an array of Saturdays 'dd MMM yyyy' texts for the month and year chosen eg '10 Jan 2008' etc
			 */
			getSatsArray: function(monthYear){
				var satsArray = new Array();
				//split up the monthYear
				var monthYearArray = monthYear.split(' ');
				var monther = monthYearArray[0];
				var yearer = monthYearArray[1];
				var yearerInt = yearer.toInt();
				//find the month int by looking up its index in the shortMonths array
				var montherInt = this.shortMonths.indexOf(monther);
				var theDate = new Date(yearer.toInt(),montherInt,1);
				var index = 0;
				var currentMonth = montherInt;
				while(currentMonth == montherInt){

					if(this.hasPrezziMensili()){
						satsArray[index] = this.formatLongDate(theDate);
						break;
					}
					
					if(this.isValidSaturday(theDate)){
						if(this.isSaturday(theDate)){
							var beginBold = '';
							var endBold = '';
							
							//show Saturdays in bold if we're showing all days of the month
							if(this.showAllDaysOfTheWeek()){
								beginBold = '<span style=\"font-weight: bold; font-size: 10px;\">';
								endBold = '</span>';								
							}//end if
							var currentDate = beginBold + this.formatLongDate(theDate) + endBold;
							if(!this.sameDateAsLastOne(currentDate, satsArray, index)){
								satsArray[index] = currentDate;
								index = index + 1;
							}//end if
						} else {
							if(this.showAllDaysOfTheWeek()){
								var currentDate = this.formatLongDate(theDate);
								if(!this.sameDateAsLastOne(currentDate, satsArray, index)){
									satsArray[index] = currentDate;
									index = index + 1;
								}//end if
							} //end if
						}//end if
					}//end if
					
					
					//add on a day
					theDate.setTime(theDate.getTime() + this.ONE_DAY_IN_MILLIS);
					currentMonth = theDate.getMonth();
				}//end while
				
				//if it's december we add on the first Saturday of the next year
				//for 2011 we add TWO Saturdays, (this will eventually have to be taken off again)
				//so we add the counter variable, which previously wasn't necessary. To remove the extra
				//date just remove the three references to counter
				var counter = 0;
				if(montherInt == 11 && this.showFirstSatOfNextYear){
					while(counter < 2){
						while(!this.isSaturday(theDate)){
							//we already added one day in the loop
							theDate.setTime(theDate.getTime() + (this.ONE_DAY_IN_MILLIS));
						}
						satsArray[index] = theDate.getDate() + " " + this.shortMonths[theDate.getMonth()] + " " + theDate.getFullYear();
						theDate.setTime(theDate.getTime() + (this.ONE_DAY_IN_MILLIS));
						counter = counter + 1;
						index = index + 1;
					}//end while
				}
				return satsArray;
			},
			
			formatLongDate: function(theDate){
				var formattedLongDate = '';
				formattedLongDate += this.shortDays[theDate.getDay()] + " ";
				formattedLongDate += this.makeTwoDigitNumber(theDate.getDate()) + " ";
				formattedLongDate += this.shortMonths[theDate.getMonth()] + " ";
				formattedLongDate += theDate.getFullYear();
				return formattedLongDate;
			},
			
			/**
			 * It is possible once in a blue moon for dates to get repeated, because we add on a day each time in the loop
			 * but the Date object takes changing between Summer Time and Winter time into account, so adding a day onto 
			 * the last Date at the end of October only adds on 23 hours instead of 24. So if the date is the same as the one
			 * before we just ignore it and continue
			 */
			sameDateAsLastOne: function(currentDate, satsArray, currentIndex){
				if(satsArray != null && satsArray.length > 1){
					var lastDate = satsArray[currentIndex - 1];
					if($defined(currentDate) && $defined(lastDate)){
						if(currentDate == lastDate){
							return true;
						}
					}
				}
				return false;
			},
			
			/**
			 * Any Saturday is valid if it's greater than or equal to last Saturday
			 */
			isValidSaturday: function(theDate){
				var lastSaturday = this.getLastSaturdaysDate();
				if(theDate > lastSaturday){
					return true;
				}
				return theDate >= this.getLastSaturdaysDate();
			}, 

			/**
			 * Gets the start month for the year
			 */
			getStartMonth: function(season){
				var todaysDate = new Date();
				var thisYear = todaysDate.getFullYear();
				if(season < thisYear){
					//we only want the last month for this season - we've gone back one week from the beginning of Jan
					return 11;
				}
				if(season > thisYear){
					//we want every month of next year
					return 0;
				}
				if(season == thisYear){
					//in the first week of the year we don't want to go back a week when working
					//out the first month
//					if(todaysDate.getMonth() > 0 && todaysDate.getDate() > 7){
//						return this.getLastSaturdaysDate().getMonth();
//					}else{
//						return 0;
//					}
					if(todaysDate.getMonth() == 0 && todaysDate.getDate() < 8){
						return 0;
					}else{
						return this.getLastSaturdaysDate().getMonth();
					}
				}
			},
			

			/**
			 * If it isn't Saturday today, goes back until it finds last Saturday
			 * and returns the month for the day found.
			 * NB remember that Dates come different if you use getFullYear() or getYear() to create them
			 * you get GMT + 1 CET with getYear() and GMT + 2 CEST with getFullYear()
			 */
			getLastSaturdaysDate: function(){
				
				var nowDate = new Date();
				//put time back to midnight
				nowDate = new Date(nowDate.getFullYear(), nowDate.getMonth(), nowDate.getDate());

				while(!this.isSaturday(nowDate)){
					nowDate = new Date(nowDate.getTime() - this.ONE_DAY_IN_MILLIS);
					//make sure you get the right kind of Date by using getFullYear()
					nowDate = new Date(nowDate.getFullYear(), nowDate.getMonth(), nowDate.getDate());
				}
				return nowDate;
			},
			
			isSaturday: function(theDate){
				return theDate.getDay() == 6;
			}
		}); //end DateWidget class
		


