text: ﻿/**
   * jQuery EasyUI 1.5
   * 
   * Copyright (c) 2009-2016 www.jeasyui.com. All rights reserved.
   *
   * Licensed under the freeware license: http://www.jeasyui.com/license_freeware.php
   * To use it on other terms please contact us: info@jeasyui.com
   *
   */
  /**
   * calendar - jQuery EasyUI
   * 
   */
  (function($){
  	
  	function setSize(target, param){
  		var opts = $.data(target, 'calendar').options;
  		var t = $(target);
  		if (param){
  			$.extend(opts, {
  				width: param.width,
  				height: param.height
  			});
  		}
  		t._size(opts, t.parent());
  		t.find('.calendar-body')._outerHeight(t.height() - t.find('.calendar-header')._outerHeight());
  		if (t.find('.calendar-menu').is(':visible')){
  			showSelectMenus(target);
  		}
  	}
  	
  	function init(target){
  		$(target).addClass('calendar').html(
  				'<div class="calendar-header">' +
  					'<div class="calendar-nav calendar-prevmonth"></div>' +
  					'<div class="calendar-nav calendar-nextmonth"></div>' +
  					'<div class="calendar-nav calendar-prevyear"></div>' +
  					'<div class="calendar-nav calendar-nextyear"></div>' +
  					'<div class="calendar-title">' +
  						'<span class="calendar-text"></span>' +
  					'</div>' +
  				'</div>' +
  				'<div class="calendar-body">' +
  					'<div class="calendar-menu">' +
  						'<div class="calendar-menu-year-inner">' +
  							'<span class="calendar-nav calendar-menu-prev"></span>' +
  							'<span><input class="calendar-menu-year" type="text"></input></span>' +
  							'<span class="calendar-nav calendar-menu-next"></span>' +
  						'</div>' +
  						'<div class="calendar-menu-month-inner">' +
  						'</div>' +
  					'</div>' +
  				'</div>'
  		);
  		
  		
  		$(target).bind('_resize', function(e,force){
  			if ($(this).hasClass('easyui-fluid') || force){
  				setSize(target);
  			}
  			return false;
  		});
  	}
  	
  	function bindEvents(target){
  		var opts = $.data(target, 'calendar').options;
  		var menu = $(target).find('.calendar-menu');
  		menu.find('.calendar-menu-year').unbind('.calendar').bind('keypress.calendar', function(e){
  			if (e.keyCode == 13){
  				setDate(true);
  			}
  		});
  		$(target).unbind('.calendar').bind('mouseover.calendar', function(e){
  			var t = toTarget(e.target);
  			if (t.hasClass('calendar-nav') || t.hasClass('calendar-text') || (t.hasClass('calendar-day') && !t.hasClass('calendar-disabled'))){
  				t.addClass('calendar-nav-hover');
  			}
  		}).bind('mouseout.calendar', function(e){
  			var t = toTarget(e.target);
  			if (t.hasClass('calendar-nav') || t.hasClass('calendar-text') || (t.hasClass('calendar-day') && !t.hasClass('calendar-disabled'))){
  				t.removeClass('calendar-nav-hover');
  			}
  		}).bind('click.calendar', function(e){
  			var t = toTarget(e.target);
  			if (t.hasClass('calendar-menu-next') || t.hasClass('calendar-nextyear')){
  				showYear(1);
  			} else if (t.hasClass('calendar-menu-prev') || t.hasClass('calendar-prevyear')){
  				showYear(-1);
  			} else if (t.hasClass('calendar-menu-month')){
  				menu.find('.calendar-selected').removeClass('calendar-selected');
  				t.addClass('calendar-selected');
  				setDate(true);
  			} else if (t.hasClass('calendar-prevmonth')){
  				showMonth(-1);
  			} else if (t.hasClass('calendar-nextmonth')){
  				showMonth(1);
  			} else if (t.hasClass('calendar-text')){
  				if (menu.is(':visible')){
  					menu.hide();
  				} else {
  					showSelectMenus(target);
  				}
  			} else if (t.hasClass('calendar-day')){
  				if (t.hasClass('calendar-disabled')){return}
  				var oldValue = opts.current;
  				t.closest('div.calendar-body').find('.calendar-selected').removeClass('calendar-selected');
  				t.addClass('calendar-selected');
  				var parts = t.attr('abbr').split(',');
  				var y = parseInt(parts[0]);
  				var m = parseInt(parts[1]);
  				var d = parseInt(parts[2]);
  				opts.current = new Date(y, m-1, d);
  				opts.onSelect.call(target, opts.current);
  				if (!oldValue || oldValue.getTime() != opts.current.getTime()){
  					opts.onChange.call(target, opts.current, oldValue);
  				}
  				if (opts.year != y || opts.month != m){
  					opts.year = y;
  					opts.month = m;
  					show(target);
  				}
  			}
  		});
  		function toTarget(t){
  			var day = $(t).closest('.calendar-day');
  			if (day.length){
  				return day;
  			} else {
  				return $(t);
  			}
  		}
  		function setDate(hideMenu){
  			var menu = $(target).find('.calendar-menu');
  			var year = menu.find('.calendar-menu-year').val();
  			var month = menu.find('.calendar-selected').attr('abbr');
  			if (!isNaN(year)){
  				opts.year = parseInt(year);
  				opts.month = parseInt(month);
  				show(target);
  			}
  			if (hideMenu){menu.hide()}
  		}
  		function showYear(delta){
  			opts.year += delta;
  			show(target);
  			menu.find('.calendar-menu-year').val(opts.year);
  		}
  		function showMonth(delta){
  			opts.month += delta;
  			if (opts.month > 12){
  				opts.year++;
  				opts.month = 1;
  			} else if (opts.month < 1){
  				opts.year--;
  				opts.month = 12;
  			}
  			show(target);
  			
  			menu.find('td.calendar-selected').removeClass('calendar-selected');
  			menu.find('td:eq(' + (opts.month-1) + ')').addClass('calendar-selected');
  		}
  	}
  	
  	/**
  	 * show the select menu that can change year or month, if the menu is not be created then create it.
  	 */
  	function showSelectMenus(target){
  		var opts = $.data(target, 'calendar').options;
  		$(target).find('.calendar-menu').show();
  		
  		if ($(target).find('.calendar-menu-month-inner').is(':empty')){
  			$(target).find('.calendar-menu-month-inner').empty();
  			var t = $('<table class="calendar-mtable"></table>').appendTo($(target).find('.calendar-menu-month-inner'));
  			var idx = 0;
  			for(var i=0; i<3; i++){
  				var tr = $('<tr></tr>').appendTo(t);
  				for(var j=0; j<4; j++){
  					$('<td class="calendar-nav calendar-menu-month"></td>').html(opts.months[idx++]).attr('abbr',idx).appendTo(tr);
  				}
  			}
  		}
  		
  		var body = $(target).find('.calendar-body');
  		var sele = $(target).find('.calendar-menu');
  		var seleYear = sele.find('.calendar-menu-year-inner');
  		var seleMonth = sele.find('.calendar-menu-month-inner');
  		
  		seleYear.find('input').val(opts.year).focus();
  		seleMonth.find('td.calendar-selected').removeClass('calendar-selected');
  		seleMonth.find('td:eq('+(opts.month-1)+')').addClass('calendar-selected');
  		
  		sele._outerWidth(body._outerWidth());
  		sele._outerHeight(body._outerHeight());
  		seleMonth._outerHeight(sele.height() - seleYear._outerHeight());
  	}
  	
  	/**
  	 * get weeks data.
  	 */
  	function getWeeks(target, year, month){
  		var opts = $.data(target, 'calendar').options;
  		var dates = [];
  		var lastDay = new Date(year, month, 0).getDate();
  		for(var i=1; i<=lastDay; i++) dates.push([year,month,i]);
  		
  		// group date by week
  		var weeks = [], week = [];
  		var memoDay = -1;
  		while(dates.length > 0){
  			var date = dates.shift();
  			week.push(date);
  			var day = new Date(date[0],date[1]-1,date[2]).getDay();
  			if (memoDay == day){
  				day = 0;
  			} else if (day == (opts.firstDay==0 ? 7 : opts.firstDay) - 1){
  				weeks.push(week);
  				week = [];
  			}
  			memoDay = day;
  		}
  		if (week.length){
  			weeks.push(week);
  		}
  		
  		var firstWeek = weeks[0];
  		if (firstWeek.length < 7){
  			while(firstWeek.length < 7){
  				var firstDate = firstWeek[0];
  				var date = new Date(firstDate[0],firstDate[1]-1,firstDate[2]-1)
  				firstWeek.unshift([date.getFullYear(), date.getMonth()+1, date.getDate()]);
  			}
  		} else {
  			var firstDate = firstWeek[0];
  			var week = [];
  			for(var i=1; i<=7; i++){
  				var date = new Date(firstDate[0], firstDate[1]-1, firstDate[2]-i);
  				week.unshift([date.getFullYear(), date.getMonth()+1, date.getDate()]);
  			}
  			weeks.unshift(week);
  		}
  		
  		var lastWeek = weeks[weeks.length-1];
  		while(lastWeek.length < 7){
  			var lastDate = lastWeek[lastWeek.length-1];
  			var date = new Date(lastDate[0], lastDate[1]-1, lastDate[2]+1);
  			lastWeek.push([date.getFullYear(), date.getMonth()+1, date.getDate()]);
  		}
  		if (weeks.length < 6){
  			var lastDate = lastWeek[lastWeek.length-1];
  			var week = [];
  			for(var i=1; i<=7; i++){
  				var date = new Date(lastDate[0], lastDate[1]-1, lastDate[2]+i);
  				week.push([date.getFullYear(), date.getMonth()+1, date.getDate()]);
  			}
  			weeks.push(week);
  		}
  		
  		return weeks;
  	}
  	
  	/**
  	 * show the calendar day.
  	 */
  	function show(target){
  		var opts = $.data(target, 'calendar').options;
  		if (opts.current && !opts.validator.call(target, opts.current)){
  			opts.current = null;
  		}
  		
  		var now = new Date();
  		var todayInfo = now.getFullYear()+','+(now.getMonth()+1)+','+now.getDate();
  		var currentInfo = opts.current ? (opts.current.getFullYear()+','+(opts.current.getMonth()+1)+','+opts.current.getDate()) : '';
  		// calulate the saturday and sunday index
  		var saIndex = 6 - opts.firstDay;
  		var suIndex = saIndex + 1;
  		if (saIndex >= 7) saIndex -= 7;
  		if (suIndex >= 7) suIndex -= 7;
  		
  		$(target).find('.calendar-title span').html(opts.months[opts.month-1] + ' ' + opts.year);
  		
  		var body = $(target).find('div.calendar-body');
  		body.children('table').remove();
  		
  		var data = ['<table class="calendar-dtable" cellspacing="0" cellpadding="0" border="0">'];
  		data.push('<thead><tr>');
  		if (opts.showWeek){
  			data.push('<th class="calendar-week">'+opts.weekNumberHeader+'</th>');
  		}
  		for(var i=opts.firstDay; i<opts.weeks.length; i++){
  			data.push('<th>'+opts.weeks[i]+'</th>');
  		}
  		for(var i=0; i<opts.firstDay; i++){
  			data.push('<th>'+opts.weeks[i]+'</th>');
  		}
  		data.push('</tr></thead>');
  		
  		data.push('<tbody>');
  		var weeks = getWeeks(target, opts.year, opts.month);
  		for(var i=0; i<weeks.length; i++){
  			var week = weeks[i];
  			var cls = '';
  			if (i == 0){cls = 'calendar-first';}
  			else if (i == weeks.length - 1){cls = 'calendar-last';}
  			data.push('<tr class="' + cls + '">');
  			if (opts.showWeek){
  				var weekNumber = opts.getWeekNumber(new Date(week[0][0], parseInt(week[0][1])-1, week[0][2]));
  				data.push('<td class="calendar-week">'+weekNumber+'</td>');
  			}
  			for(var j=0; j<week.length; j++){
  				var day = week[j];
  				var s = day[0]+','+day[1]+','+day[2];
  				var dvalue = new Date(day[0], parseInt(day[1])-1, day[2]);
  				var d = opts.formatter.call(target, dvalue);
  				var css = opts.styler.call(target, dvalue);
  				var classValue = '';
  				var styleValue = '';
  				if (typeof css == 'string'){
  					styleValue = css;
  				} else if (css){
  					classValue = css['class'] || '';
  					styleValue = css['style'] || '';
  				}
  				
  				var cls = 'calendar-day';
  				if (!(opts.year == day[0] && opts.month == day[1])){
  					cls += ' calendar-other-month';
  				}
  				if (s == todayInfo){cls += ' calendar-today';}
  				if (s == currentInfo){cls += ' calendar-selected';}
  				if (j == saIndex){cls += ' calendar-saturday';}
  				else if (j == suIndex){cls += ' calendar-sunday';}
  				if (j == 0){cls += ' calendar-first';}
  				else if (j == week.length-1){cls += ' calendar-last';}
  				
  				cls += ' ' + classValue;
  				if (!opts.validator.call(target, dvalue)){
  					cls += ' calendar-disabled';
  				}
  				
  				data.push('<td class="' + cls + '" abbr="' + s + '" style="' + styleValue + '">' + d + '</td>');
  			}
  			data.push('</tr>');
  		}
  		data.push('</tbody>');
  		data.push('</table>');
  		
  		body.append(data.join(''));
  		body.children('table.calendar-dtable').prependTo(body);
  
  		opts.onNavigate.call(target, opts.year, opts.month);
  	}
  	
  	$.fn.calendar = function(options, param){
  		if (typeof options == 'string'){
  			return $.fn.calendar.methods[options](this, param);
  		}
  		
  		options = options || {};
  		return this.each(function(){
  			var state = $.data(this, 'calendar');
  			if (state){
  				$.extend(state.options, options);
  			} else {
  				state = $.data(this, 'calendar', {
  					options:$.extend({}, $.fn.calendar.defaults, $.fn.calendar.parseOptions(this), options)
  				});
  				init(this);
  			}
  			if (state.options.border == false){
  				$(this).addClass('calendar-noborder');
  			}
  			setSize(this);
  			bindEvents(this);
  			show(this);
  			$(this).find('div.calendar-menu').hide();	// hide the calendar menu
  		});
  	};
  	
  	$.fn.calendar.methods = {
  		options: function(jq){
  			return $.data(jq[0], 'calendar').options;
  		},
  		resize: function(jq, param){
  			return jq.each(function(){
  				setSize(this, param);
  			});
  		},
  		moveTo: function(jq, date){
  			return jq.each(function(){
  				if (!date){
  					var now = new Date();
  					$(this).calendar({
  						year: now.getFullYear(),
  						month: now.getMonth()+1,
  						current: date
  					});
  					return;
  				}
  				var opts = $(this).calendar('options');
  				if (opts.validator.call(this, date)){
  					var oldValue = opts.current;
  					$(this).calendar({
  						year: date.getFullYear(),
  						month: date.getMonth()+1,
  						current: date
  					});
  					if (!oldValue || oldValue.getTime() != date.getTime()){
  						opts.onChange.call(this, opts.current, oldValue);
  					}
  				}
  			});
  		}
  	};
  	
  	$.fn.calendar.parseOptions = function(target){
  		var t = $(target);
  		return $.extend({}, $.parser.parseOptions(target, [
  			'weekNumberHeader',{firstDay:'number',fit:'boolean',border:'boolean',showWeek:'boolean'}
  		]));
  	};
  	
  	$.fn.calendar.defaults = {
  		width:180,
  		height:180,
  		fit:false,
  		border:true,
  		showWeek:false,
  		firstDay:0,
  		weeks:['S','M','T','W','T','F','S'],
  		months:['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
  		year:new Date().getFullYear(),
  		month:new Date().getMonth()+1,
  		current:(function(){
  			var d = new Date();
  			return new Date(d.getFullYear(), d.getMonth(), d.getDate());
  		})(),
  		weekNumberHeader:'',
  		getWeekNumber: function(date){
  			var checkDate = new Date(date.getTime());
  			checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));
  			var time = checkDate.getTime();
  			checkDate.setMonth(0);
  			checkDate.setDate(1);
  			return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
  		},
  
  		formatter:function(date){return date.getDate()},
  		styler:function(date){return ''},
  		validator:function(date){return true},
  		
  		onSelect: function(date){},
  		onChange: function(newDate, oldDate){},
  		onNavigate: function(year, month){}
  	};
  })(jQuery);
  