/* Created by Kevin Dibble 
 * Uses Mootools
 * Add a class of "calender" to input feilds - thats all!!
 * <input name="date" type="text" class="required calender" size="12" rel="{message : 'Please enter the date', calOptions : {format: 'D, jS of F-Y',doDays: false}}"/>
 */
var Calender = new Class({
	Implements : [Options],
	options : {
		format		: 'j-n-Y',
		offsetLeft	: 'auto',
		offsetTop	: 'auto',
		opacity		: 1,
		startMonth	: false,		// Must be an integer number (Jan = 0)
		startYear	: false,		// Must be 4 digits (2004) Not as 04
		doDays		: true,			// Set to False to only show month and year
		startDate	: false,		// Sets the lowest acceptable date  (must be in d-m-y format)
		stopDate	: false,		// Sets the highest acceptable date (must be in d-m-y format
		weekend		: true
	},
 	initialize : function(obj,options){
		this.setOptions(options);	
		this.object		= $(obj);
		this.timer		= null;	
		var hideCalender = this.hideCalender.bind(this);
		this.hideBG		= new Element("div",{
							'class' : 'calHideBack',
							'height' : $(document.body).getSize().y,
							'events' : {'click' : hideCalender}
						});	
		this.allMonths	= Array('january','february','march','april','may','june','july','august','september','october','november','december');
		this.allDays	= Array("sunday","monday","tuesday","wednesday","thursday","friday","saturday"); 
		this.theDate 	= new Date();							// Create Date Object
		if(this.options.startMonth != false){
			this.theDate.setMonth(this.options.startMonth + 1);
		}
		if(this.options.startYear != false){
			this.theDate.setYear(this.options.startYear);
		}
		if(this.options.startDate != false){
			var d = this.options.startDate.split('-');
			this.options.startDate = new Date();
			this.options.startDate.setDate(d[0]);
			this.options.startDate.setMonth(d[1]-1);
			this.options.startDate.setYear(d[2]);
		}
		if(this.options.stopDate != false){
			var d = this.options.stopDate.split('-');
			this.options.stopDate = new Date();
			this.options.stopDate.setDate(d[0]);
			this.options.stopDate.setMonth(d[1]-1);
			this.options.stopDate.setYear(d[2]);
		}
		this.calender 	= new Element("div",{
			'class' : 'calenderFrame',
			'html'	: '<span></span><div class="calbottom">close</div>'
		});
		$(this.calender).getElement('.calbottom').addEvent("click",hideCalender);
		$(this.calender).setStyle("opacity",0);					// Hide the calender to begin with
		var showCalender = this.showCalender.bind(this);
		$(this.calender).inject($(document.body),'top');
		var keypress= this.keypress.bind(this);
		this.keyFn 	= function(event){keypress(event);};
		$(obj).addEvent("focus",showCalender);
		$(obj).addEvent("click",showCalender);
		this.rd  	= this.returnDate.bind(this);
		this.hc		= this.hideCalender.bind(this);
		this.buildCalender();
	},
	returnDate: function(obj){
		if (!isNaN($(obj).get("html")) || !isNaN($(obj).get("rel"))) {
			if(this.options.doDays==false){
				this.theDate.setDate(1);
			}else{
				this.theDate.setDate($(obj).get("html").toInt());
			}
			var suffix  = 'th';
			switch (this.theDate.getDate()){
				case 1: case 21: case 31:
					suffix = "st";
				break;
				case 2: case 22: case 32:
					suffix = "nd";
				break;
				case 3: case 23:
					suffix = "rd";
				break;
			}
			var tmpDate = ""+this.theDate.getFullYear();
			var cleanedDate = this.options.format.replace(/d/g,(this.theDate.getDate() < 10)? "0" + this.theDate.getDate() : this.theDate.getDate());		// Input the Date Number
			cleanedDate = cleanedDate.replace(/j/g,this.theDate.getDate());		// Input the Date Number
			cleanedDate = cleanedDate.replace(/y/g,tmpDate.substring(2,4));		// Get the Short Year
			cleanedDate = cleanedDate.replace(/Y/g,this.theDate.getFullYear());	// Get the Long Year
			cleanedDate = cleanedDate.replace(/m/g,((this.theDate.getMonth()+1) < 10)? "0" + (this.theDate.getMonth()+1): this.theDate.getMonth()+1);	// Input the Month
			cleanedDate = cleanedDate.replace(/n/g,(this.theDate.getMonth()+1));// Input the Month
			cleanedDate = cleanedDate.replace(/t/g,32-new Date(this.theDate.getYear(),this.theDate.getMonth(),32).getDate());				// Return the amount of days in a month
			cleanedDate = cleanedDate.replace(/l/g,this.allDays[this.theDate.getDay()]);					// Input the Full Day of week
			cleanedDate = cleanedDate.replace(/D/g,this.allDays[this.theDate.getDay()].substring(0,3)); 	// Input a short Day of week
			cleanedDate = cleanedDate.replace(/F/g,this.allMonths[this.theDate.getMonth()]);				// Input the Full Month
			cleanedDate = cleanedDate.replace(/M/g,this.allMonths[this.theDate.getMonth()].substring(0,3));	// Input the Short Month
			cleanedDate = cleanedDate.replace(/S/g,suffix);						// Input the suffix
			$(this.object).value = cleanedDate.capitalize().replace(/Of/g,"of");// Return the text with words placed into correct case
		}	
		this.hideCalender(); 													//hide the calender
	},
	showCalender: function(){
		$(this.hideBG).inject($(document.body),'bottom');
		var i = (Browser.Engine.gecko)?  window  : $(document.body);
		i.addEvent(Browser.Engine.gecko ? "keypress" : "keydown",this.keyFn);
		if(Browser.Engine.trident && Browser.Engine.version < 5) {				// If IE 6 or less
			$(document.body).getElements('select').each(function(item,index){
				item.style.visibility = "hidden"; 				 				// Hide the Select object
			});
		}
		$(this.calender).getElements("select").each(function(item,index){
			$(item).style.visibility = "visible";													 
		});
		if(this.options.offsetTop == 'auto'){
			this.options.offsetTop = $(this.object).getSize().y - 80;	
		}
		if(this.options.offsetLeft == 'auto'){
			this.options.offsetLeft = ($(this.object).getSize().x /2);	
		}
		$(this.calender).setStyle("top",($(this.object).getPosition().y + this.options.offsetTop));
		$(this.calender).setStyle("left",($(this.object).getPosition().x + this.options.offsetLeft));
		$(this.calender).setStyle("display","block");
		$(this.calender).set("opacity",this.options.opacity);
		$(this.object).blur();
		return false;															// Stop Propagation of event of focus and click
	},
	hideCalender: function(){
		this.hideBG = $(this.hideBG).dispose();
		var i = (Browser.Engine.gecko)?  window  : $(document.body);
		i.removeEvent(Browser.Engine.gecko ? "keypress" : "keydown",this.keyFn);
		$(this.calender).set("opacity",0);
		$(this.calender).setStyle("display","none");
		if(Browser.Engine.trident && Browser.Engine.version < 5) {				// If IE 6 or less
			$(document.body).getElements('select').each(function(item,index){
				item.style.visibility = "visible"; 								// Hide the Select object
			});
		}
	},
	buildCalender: function(){
		$clear(this.timer);
		var i =0;
		this.theDate.setDate(1);												//Set the day to the first for the month
		var DaysInMonth=32-new Date(this.theDate.getYear(),this.theDate.getMonth(),32).getDate();
		var DaysInLastMonth = 32-new Date(this.theDate.getYear(),this.theDate.getMonth()-1,32).getDate();
		var startfrom=this.theDate.getDay();
		var goTo=DaysInMonth+startfrom+1;
		DaysInMonth =((DaysInMonth + startfrom)>34)? 41: 34;
		var NextMonth = 1;
		var DisplayMonth="<table cellpadding='0' cellspacing='0'><tr class='calYear'><td colspan='2' class='calenderPreviousYear'>&lt;&lt;&lt;</td><td colspan='3'><div class='selectContainer'><select>";
		var begin = this.theDate.getFullYear()-5;
		var end   = this.theDate.getFullYear()+5;
		if(this.options.startDate != false){
			begin = this.options.startDate.getFullYear();	
		}
		if(this.options.startDate != false){
			end = this.options.stopDate.getFullYear();	
		}
		for(i=begin;i<end;i++){
			DisplayMonth+= (i==this.theDate.getFullYear())? "<option selected='selected' value='"+i+"'>"+i+"</option>" : "<option value='"+i+"'>"+i+"</option>";
		}
		DisplayMonth+="</select></div><td colspan='2' class='calenderYearAdvance'>&gt;&gt;&gt;</td></tr><tr class='calMonth'><td colspan='2' class='monthPrevious'>&lt;&lt;&lt;</td>";
		DisplayMonth+="<td colspan='3' class='month' rel='1'>"+this.allMonths[this.theDate.getMonth()].capitalize()+"</td>";
		DisplayMonth+="<td colspan='2' class='monthAdvance'>&gt;&gt;&gt;</td></tr>";
		if(this.options.doDays){
			DisplayMonth+="<tr class='calDay'><td>S</td><td>S</td><td>M</td><td>T</td><td>W</td><td>T</td><td>F</td></tr><tr>";
			for(i=0;i<=DaysInMonth;i++){
				DisplayMonth+= (i%7==0)? "</tr><tr>" : '';
				DisplayMonth+= (i>startfrom&&i<goTo)? "<td align='center' class='day'>"+(i-startfrom)+"</td>" : (i<=startfrom)? "<td class='pday'>"+(DaysInLastMonth-(startfrom-i))+"</td>" : "<td class='nday'>"+(++NextMonth)+"</td>" ;
			}
		}
		DisplayMonth+="</tr></table>";
		$(this.calender).getElement("span").set("html",DisplayMonth);
		var setupFunctions = this.setupFunctions.bind(this);
		this.timer = setupFunctions.delay(200);
	},
	setupFunctions: function(){
		var returnDate  = this.returnDate.bind(this);
		if(this.options.doDays==false){
			$(this.calender).getElement('.month').removeEvents();
			$(this.calender).getElement('.month').addEvent('click',function(){returnDate(this);});
		}
		$(this.calender).getElements('.day').each(function(item,index){
			item.removeEvents();
			item.addEvent('click',function(){returnDate(this)});
			item.addEvent('mouseenter',function(){this.addClass("dayOvr")});
			item.addEvent('mouseleave',function(){this.removeClass("dayOvr");});
		});
		var sety 		= this.setDateYear.bind(this);
		var setYearN 	= this.setDateYearN.bind(this);
		var setMonthN 	= this.setDateMonth.bind(this);
		$(this.calender).getElement('select').removeEvents();
		$(this.calender).getElement('select').addEvent('change',function(event){sety(this.value);});
		$(this.calender).getElements('.monthAdvance').each(function(item){
			item.removeEvents();
			item.addEvent('click',function(){setMonthN(1);});
		});
		$(this.calender).getElements('.monthPrevious').each(function(item){
			item.removeEvents();													 
			item.addEvent('click',function(){setMonthN(-1);});
		});
		$(this.calender).getElements('.calenderYearAdvance').each(function(item){
			item.removeEvents();
			item.addEvent('click',function(){setYearN(1);});
		});
		$(this.calender).getElements('.calenderPreviousYear').each(function(item){
			item.removeEvents();
			item.addEvent('click',function(){setYearN(-1);});
		});
		$(this.calender).getElements('.pday').each(function(item,index){
			item.removeEvents();
			item.addEvent('click',function(){setMonthN(-1)});
		});
		$(this.calender).getElements('.nday').each(function(item,index){
			item.removeEvents();
			item.addEvent('click',function(){setMonthN(1)});
		});
	},
	keypress: function(event){
		var ev = new Event(event);
		switch(ev.code){
			case 37:
				ev.stop();
				this.setDateMonth(-1);
				break;
			case 39: 
				ev.stop();
				this.setDateMonth(1);
				break;
			case 38:
				ev.stop();
				this.setDateYearN(1);
				break;
			case 40:
				ev.stop();
				this.setDateYearN(-1);
				break;
			case 13: 
				ev.stop();
				var obj = new Element("div",{html : '1'});
				this.returnDate(obj);
				break;
			case 9:
				this.hideCalender();
				ev.stop();
				break;
			case 17: case 116 :		// CTRL Key or F5 Key
				break;
			default:
				ev.stop();
				break;
		}
	},
	setDateYear: function(theYear){
		var oldYear = this.theDate.getFullYear();
		this.theDate.setYear(theYear);
		if(this.options.startDate != false){
			if(this.theDate.getTime()<this.options.startDate.getTime()){
				this.theDate.setYear(oldYear);
				return false;	
			}
		}
		if(this.options.stopDate != false){
			if(this.theDate.getTime()> this.options.stopDate.getTime()){
				this.theDate.setYear(oldYear);
				return false;	
			}
		}
		this.buildCalender();
	},
	setDateYearN: function(theYear){
		this.theDate.setYear(this.theDate.getFullYear()+theYear);
		if(this.options.startDate != false){
			if(this.theDate.getTime() < this.options.startDate.getTime()){
				this.theDate.setTime(this.options.stopDate.getTime());
			}
		}
		if(this.options.stopDate != false){
			if(this.theDate.getTime() > this.options.stopDate.getTime()){
				this.theDate.setTime(this.options.startDate.getTime()); 
			}
		}
		this.buildCalender();
	},
	setDateMonth: function(theMonth){
		this.theDate.setMonth(this.theDate.getMonth()+theMonth);
		if(this.options.startDate != false){
			if(this.theDate.getTime() < this.options.startDate.getTime()){
				this.theDate.setTime(this.options.stopDate.getTime());
			}
		}
		if(this.options.stopDate != false){
			if(this.theDate.getTime() > this.options.stopDate.getTime()){
				this.theDate.setTime(this.options.startDate.getTime()); 
			}
		}
		this.buildCalender();
	}
});
