﻿//var calendar;
//calendar=Class.create();

Number.prototype.fillChar=function(){ //返回2位数日期; eg: '2'->'02'
	return (this < 10) ? "0"+this : this+"";
}
String.prototype.strGetAb=function(){ //返回星期或月份英文缩写; eg: 'January'->'Jan'
	return this.substring(0,3);
}
var calendar=Class.create({
	initialize: function(){
		this.version="2.0";

		with(new Date()){ //设置当前日期
			this.curYear	=	getFullYear();
			this.curMonth	=	getMonth()+1;
			this.curDate	=	getDate();
			this.curDay		=	getDay();
			this.curHour	=	getHours();
			this.curMinute	=	getMinutes();
			this.curSecond	=	getSeconds();
		};

		this.setMonth={ //设置月份名称
			0:	{eng:"January",		chi: "一月"},
			1:	{eng:"February",	chi: "二月"},
			2:	{eng:"March",		chi: "三月"},
			3:	{eng:"April",		chi: "四月"},
			4:	{eng:"May",			chi: "五月"},
			5:	{eng:"June",		chi: "六月"},
			6:	{eng:"July",		chi: "七月"},
			7:	{eng:"August",		chi: "八月"},
			8:	{eng:"September",	chi: "九月"},
			9:	{eng:"October",		chi: "十月"},
			10:	{eng:"November",	chi: "十一月"},
			11:	{eng:"December",	chi: "十二月"}
		};

		this.setDay	={ //设置星期名称
			0: {eng:"SUNDAY",	chi:"日"},
			1: {eng:"MONDAY",	chi:"一"},
			2: {eng:"TUESDAY",	chi:"二"},
			3: {eng:"WEDNESDAY",chi:"三"},
			4: {eng:"THURSDAY",	chi:"四"},
			5: {eng:"FRIDAY",	chi:"五"},
			6: {eng:"SATURDAY",	chi:"六"}
		};

		this.chgDateTips={
			0: {eng:"Previous Year", chi:"上一年"},
			1: {eng:"Current Year", chi:"当前"},
			2: {eng:"Next Year", chi:"下一年"},
			3: {eng:"Click to Change Year", chi:"点击这里输入年份"},
			4: {eng:"Previous Month", chi:"上一月"},
			5: {eng:"Next Month", chi:"下一月"}
		}
		this.chgYearTips={
			eng:"Tips: You can quickly change the year number with 'Up Arrow' or 'Down Arrow'.",
			chi:"提示：用键盘上、下箭头可以快速更改年份。"
		};

		this.weekDays	=	7;//设定一周天数
		this.basicID	=	"jimCal";//Calendar控件的ID种子
		this.basicNum	=	"0123456789九八七六五四三二一零";
	},

	transYear: function(yearStr){ //将数字年份和中文年份相互转换; eg: '2007'->'二〇〇七'， '二零四六'->'2046'
		var source=this.basicNum.toArray();
		var reverse=this.basicNum.toArray().reverse();
		//var outputYear=yearStr.toArray().map(function(item){return reverse[source.indexOf(item)]}).join('');
		//return outputYear;
		return yearStr.toArray().map(function(item){return reverse[source.indexOf(item)]}).join('');

	},

	addOptions: function(element,text){//增加Option
		var o=$(element);
		var oT=text;
		var oV=arguments[2] || text;

		//o.options.length=0;
		var newOption=document.createElement("option"); //增加一个 OPTION 
		newOption.value=oV; 
		newOption.text =oT; 
		try{o.add(newOption,null)}
		catch(e){o.add(newOption)}
	},

	//-----------------------------------//

	setCalID: function(){ //如页面有多个Calendar控件则生成不同的ID号; eg: 'jimCal_0','jimCal_1','jimCal_2'...
		var count=0;
		var calID=this.basicID+"_"+count;
		while($(calID)){
			calID=this.basicID+"_"+count;
			count++;
		}
		return calID;
	},

	isLeapYear: function(inputYear){ //判断是否为闰年
		if(inputYear % 400 == 0 || (inputYear % 100 !=0 && inputYear % 4 == 0)) return true;
		else return false;
	},

	getMonthDays: function(inputYear, inputMonth){ //返回每月天数
		var leapYearDays=	(this.isLeapYear(inputYear)) ? 29 : 28;
		var daysLength	=	[31,leapYearDays,31,30,31,30,31,31,30,31,30,31];
		return daysLength[inputMonth];
	},

	getCurDateString: function(){ //返回当前日期字符串; eg:20050611
		with(this) return curYear+curMonth.fillChar()+curDate.fillChar();
	},

	drawCalendar: function(inputYear, inputMonth){
		inputMonth-=1;
		var html, i, dayNo=1;
		var dayLength	=	this.getMonthDays(inputYear, inputMonth);//获取每月天数
		var firstDay	=	new Date(inputYear, inputMonth, 1).getDay();//获取每月第一天
		var weekCount	=	Math.ceil((firstDay+dayLength)/this.weekDays);//获取每月周数
		var blankCell	=	'<td>&nbsp;</td>';


		with(this){
			html ='<table id="'+setCalID()+'" class="jimCal" cellspacing="1">';
			html+=''+
				'<caption>'+
				'	<a href="javascript:void(0)" title="'+chgDateTips[4].eng+'">&#171;</a>'+
				'	<span>'+setMonth[inputMonth].eng+'</span>'+
				'	<a href="javascript:void(0)" title="'+chgDateTips[5].eng+'">&#187;</a>'+
				'	<a href="javascript:void(0)" title="'+chgDateTips[2].eng+'">&#187;</a>'+
				'	<span title="'+chgDateTips[3].eng+'">'+inputYear+'</span>'+
				'	<a href="javascript:void(0)" title="'+chgDateTips[0].eng+'">&#171;</a>'+
				//'	<a href="javascript:void(0)" title="'+chgDateTips[1].eng+'">&lang;</a>'+
				'</caption>';

			html+='<thead><tr>';
			$R(0,weekDays,true).each(function(r){html+='<th>'+this.setDay[r].eng.strGetAb()+'</th>'}, this);
			html+='</tr></thead>';

			html+='<tbody><tr>';
			
			$R(0, dayLength+firstDay, true).each(function(i){
				if(i>0 && i%weekDays==0) html+='</tr><tr>';
				if(i<firstDay) html+=blankCell;
				else{
					var dayValue=[inputYear,inputMonth+1,dayNo].invoke("fillChar").join("");
					var hidValue='<input type="hidden" name="dayValue" value="'+dayValue+'" />';
					html+='<td>'+dayNo+hidValue+'</td>';
					dayNo++;
				}
			});

			$R(0, weekCount*weekDays-(dayLength+firstDay), true).each(function(){html+=blankCell})
			html+='</tr></tbody>';

			html+='<tfoot><tr>';
			html+='<td colspan="'+this.weekDays+'">';
			with(this){
				html+=[curHour,curMinute,curSecond].invoke("fillChar").join(":")
			}
			html+='</td></tr></tfoot>';
			html+='</table>';
		}

		return html;
	},

	setCal: function(objID){
		//this.setBaseSkin(objID);
		var option=Object.extend({ //默认option
			year:this.curYear, month:this.curMonth, longWeek:false, showTime:false, show12H:false, chiLang:false,
			calInit: Prototype.emptyFunction
		},arguments[1]||{});

		this.chgCal(objID, option);
	},

	chgCal: function(objID, option){
		with(this){
			$(objID).update(drawCalendar(option.year, option.month));//生成Calendar代码
			var DOM=calDOM(objID);

			setSpecStyle(objID,DOM);//set special style
			personlize(option,DOM);//personlize option select
			calEvent(option,DOM);//Calendar event add
			chgDate(option, DOM);
		}
	},
	
	personlize: function(option,calDOM){//个性化选项
		var DOM=calDOM;

		//中文显示：年、月、周名
		if(option.chiLang){
			DOM.oCaption.down("span",0).update(this.setMonth[option.month-1].chi);
			DOM.oCaption.down("span",1).update(this.transYear(option.year.toJSON()));
			DOM.oThead.each(function(week,index){
				$(week).update(this.setDay[index].chi);
				$(week).setStyle({fontSize:"12px",fontWeight:"normal", padding:"2px 7px"});
			}, this);
		}

		//英文长周名
		if(!option.chiLang && option.longWeek){
			DOM.oThead.each(function(week,index){
				$(week).update(this.setDay[index].eng.capitalize())
			}, this);
		}

		//显示时间
		if(option.showTime){
			var curTime=[], suf="";
			new PeriodicalExecuter(function(){
				with(new Date()){
					var curHour=getHours();
					if(option.show12H){
						if(curHour > 12) {curTime[0]=curHour-12;suf=" <sub style='font:bold 9px/normal Verdana,sans-serif;color:#999;'>PM</sub>"};
						if(curHour <=12) {curTime[0]=curHour; suf=" <sup style='font:bold 9px/normal Verdana,sans-serif;color:#999;'>AM</sup>"};
					}
					else curTime[0]=curHour;
					curTime=[curTime[0], getMinutes(), getSeconds()]
					DOM.oTfoot.update(curTime.invoke("fillChar").join(":") + suf);
				}
			}, 1);
		}
		else DOM.oTfoot.up().remove();
	},
	
	calEvent: function(option,calDOM){//Calendar事件加载器
		var selfEvent=["click","dblclick","mouseover","mouseout","mousemove","mousedown","mouseup","keypress","keydown","keyup"]
		calDOM.oTbody.each(function(item){
			if(item.down()) {
				option.calInit(item);//初始化事件

				selfEvent.each(function(event){//加载各种常用事件
					if(eval("option.on"+event.capitalize())){
						Event.observe(item, event, function(){
							eval("option.on"+event.capitalize()+"(item)")
						}, false);
					}
				});
			}
		});
	},

	modifyDate: function(option, calDOM){
		
	},

	chgDate: function(option,calDOM){
		var oCap		=	calDOM.oCaption;
		var monthZone	=	oCap.down('span', 0);
		var yearZone	=	oCap.down('span', 1);
		var monthMinus	=	oCap.down('a',0);
		var monthPlus	=	oCap.down('a',1);
		var yearPlus	=	oCap.down('a',2);
		var yearMinus	=	oCap.down('a',3);

		monthListID=this.setCalID()+"_m";
		yearTextID=this.setCalID()+"_Y";
		//alert(monthListID);

		monthZone.observe( //Change Month
			"click", function(event){
				if(event.element().tagName == yearZone.tagName){
					var curMonth=monthZone.innerHTML.strip();
					monthZone.update('<select id="'+monthListID+'" name="'+monthListID+'" /></select>');
					$(monthListID).options.length=0;
					$(monthListID).setStyle({fontSize:"11px"});
					var oValue, oText, subHash;
					var cur=100;
					$H(this.setMonth).each( function(pair){
						oValue=pair.key;
						oText= (option.chiLang) ? pair.value.chi : pair.value.eng;
						this.addOptions(monthListID, oText, oValue);
						if(curMonth==oText) cur=oValue;
					}, this);
					$(monthListID).activate();
					$(monthListID).value=cur;

					var monAction=function(){
						option=Object.extend(option, {month:parseInt($F(monthListID))+1})
						this.chgCal(calDOM.oTable.up(), option);
					}.bind(this)

					$(monthListID).observe("blur", monAction);
					$(monthListID).observe("change", monAction);
					/*$(monthListID).observe(
						"change", function(){
							option=Object.extend(option, {month:parseInt($F(monthListID))+1})
							this.chgCal(calDOM.oTable.up(), option);
						}.bind(this)
					);*/
				}
			}.bind(this)
		);

		yearZone.observe( //Change Year
			"click", function(event){
				var value=yearZone.innerHTML.strip();
				var h=yearZone.getHeight();
				var w=yearZone.getWidth();
				var element=event.element();
				var ptn=/^\d+$/;
				var inputValue=(ptn.test(value)) ? value : this.transYear(value);

				if(yearZone.tagName==element.tagName) {
					yearZone.update('<input type="text" id="'+yearTextID+'" value="'+inputValue+'" />');
					$(yearTextID).setStyle({
						width:(w-2)+"px", borderWidth:0, fontSize:"11px", 
						fontWeight:"bold", border:"1px solid gray", margin:0
					});
					$(yearTextID).title=(option.chiLang)? this.chgYearTips.chi : this.chgYearTips.eng;
					$(yearTextID).activate();

					$(yearTextID).observe(
						"keydown", function(event){
							var curYear=$F(yearTextID)
							if(event.keyCode==Event.KEY_RETURN) $(yearTextID).blur();
							if(event.keyCode==Event.KEY_UP && ptn.test(curYear)){
								$(yearTextID).value=parseInt(curYear)+1;
								$(yearTextID).activate();
							}
							if(event.keyCode==Event.KEY_DOWN && ptn.test(curYear)){
								$(yearTextID).value=parseInt(curYear)-1;
								$(yearTextID).activate();
							}
							if(event.keyCode==Event.KEY_ESC){
								$(yearTextID).value=option.year;
								$(yearTextID).blur();
							}
						}
					);

					$(yearTextID).observe(
						"blur", function(){
							if(!ptn.test($F(yearTextID))){
								alert("Please input valid year number.");
								$(yearTextID).activate();
								return false;
							}
							else{
								option=Object.extend(option, {year:parseInt($F(yearTextID))})
								this.chgCal(calDOM.oTable.up(), option);
							}
						}.bind(this)	
					);
				}
			}.bind(this)	
		);

		yearPlus.observe(
			'click', function(){
				option=Object.extend(option, {year:parseInt(option.year)+1});
				this.chgCal(calDOM.oTable.up(), option);
			}.bind(this)
		);

		yearMinus.observe(
			'click', function(){
				option=Object.extend(option, {year:parseInt(option.year)-1});
				this.chgCal(calDOM.oTable.up(), option);
			}.bind(this)
		);

		monthPlus.observe(
			'click', function(){
				var newMonth = parseInt(option.month)+1;
				//console.log(newMonth);
				if(newMonth>12){
					option=Object.extend(option, {year:parseInt(option.year)+1,month:1});
				}else{
					option=Object.extend(option, {month:newMonth});
				}
				this.chgCal(calDOM.oTable.up(), option);
			}.bind(this)
		);

		monthMinus.observe(
			'click', function(){
				var newMonth = parseInt(option.month)-1;
				if(newMonth<1){
					option=Object.extend(option, {year:parseInt(option.year)-1,month:12});
				}else{
					option=Object.extend(option, {month:newMonth});
				}
				this.chgCal(calDOM.oTable.up(), option);
			}.bind(this)
		);
	},

	setSpecStyle: function(objID,DOM){

		with(DOM){
			/*oCaption.down("span",0).setStyle({
				display:"block", cssFloat:"left", textAlign:"center", cursor:"pointer"
			});
			oCaption.down("span",1).setStyle({
				display:"block", cssFloat:"right", textAlign:"center", cursor:"pointer"
			})
			oCaption.down("a",0).setStyle({
				display:"block", cssFloat:"right", textAlign:"center", cursor:"pointer"
			});
			oCaption.down("a",1).setStyle({
				display:"block", cssFloat:"right", textAlign:"center", cursor:"pointer"
			})*/
			oCaption.childElements().invoke('setStyle', 'float:right');
			oCaption.down("span",0).setStyle('float:left');
			oCaption.down("a",0).setStyle('float:left');
			oCaption.down("a",1).setStyle('float:left');

			//thead style
			oThead.each(
				function(item,index){
					if(index % this.weekDays == 0 || index % this.weekDays == this.weekDays-1){
						item.addClassName('rest')
					}
				}.bind(this)
			);

			//tbody style
			oTbody.each(function(item,index){
				if(index % this.weekDays == 0 || index % this.weekDays == this.weekDays-1) {
					item.addClassName('rest');
				}
				if(item.down() && $F(item.down()) == this.getCurDateString()){//当前日期
					item.addClassName('curDay')
				}
			}, this);
		}
	},

	calDOM: function(objID){//return calender DOM structure
		var os=$(objID).down().immediateDescendants();//获取Calendar表格的一级子节点，eg:caption,thead,tbody,tfoot
		var DOM={
			oTable	:	$(objID).down(),
			oCaption:	os.first(),
			oThead	:	os[1].getElementsBySelector("th"),
			oTbody	:	os[2].getElementsBySelector("td"),
			oTfoot	:	os.last().getElementsBySelector("td").first()
		};
		return DOM;
	}
});