jquery datefield

支持年月日、年月、年月日时分秒、年月日时分、时分秒、时分六种下拉选择

注意,需要moment.js插件作为前提

;
(function($) {
	/** 国际化 **/
	$.i18n = $.i18n || {};
	$.i18n.week = '周';
	$.i18n.days = [ '日', '一', '二', '三', '四', '五', '六' ];
	$.i18n.shortDays = [ '日', '一', '二', '三', '四', '五', '六' ];
	$.i18n.months = [ "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月",
			"十月", "十一", "十二" ];
	$.i18n.shortMonths = [ "一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月",
			"九月", "十月", "十一", "十二" ];

	$.i18n.datepicker={
		OK:'确定',
		CLEAR:'清空',
		TODAY:'今天'
	}
	
	if (!$.browser) {
		var userAgent = navigator.userAgent.toLowerCase();
		// Figure out what browser is being used
		$.browser = {
			version : (userAgent.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/) || [])[1],
			safari : /webkit/.test(userAgent),
			opera : /opera/.test(userAgent),
			chrome: /chrome/.test(userAgent),
			msie : /msie/.test(userAgent) && !/opera/.test(userAgent),
			mozilla : /mozilla/.test(userAgent)
					&& !/(compatible|webkit)/.test(userAgent)
		};
	}

	/** 高版本浏览器支持 **/
	var ele = document.createElement("input");
	var _support_placeholder = 'placeholder' in ele;
		
	//TNND IE9在WIN7卸载会退到IE8后,内核版本仍然是IE9BUG:'opacity' in ele.style
	var ltIE9 = $.browser.msie && (!('opacity' in ele.style) || $.browser.version < 9);
	
	ele = null;
/** 国际化文本 **/
    moment.lang('cn', {
	    weekdays : ["星期日", "星期一","星期二", "星期三", "星期四", "星期五", "星期六"]
	});

	// 日期解析
	Date.parseDate = function(str, format) {
		
		if (!str) {return null;}

		if (Date.isDate(str)) {return str;}

		if(format){var d=moment(str, format);return d.isValid() ? d.toDate() : null;}

		var date =  moment(str,"YYYYMMDDThhmmss");
		
		!date.isValid() ? date=moment(str,"YYYYMMDDhhmmss") : false;

		!date.isValid() ? date=moment(str) : false;

		return date.isValid() ? date.toDate() : null;

	};

    // 是否日期
	Date.isDate = function(date) { return Object.prototype.toString.call(date) == '[Object Date]' || date instanceof Date;};

	// 日期格式化
	Date.prototype.formatDate = function(format) {return moment(this).format(format || 'YYYY-MM-DD hh:mm:ss');};

	// 周数 ISO 8601
	Date.prototype.getWeek = function() {return moment(this).week();};
	/**
	 * datepicker
	 * @constructor
	 */
	$.datepicker = function($element, options) {
		
		var self = this,timestamp=+new Date();

		// datetime、dateminute、date、month、time、minute
		this.type=options.type || 'date';

		// 默认值
		this.value = Date.parseDate(options.value,this.getFormat(this.type)) || new Date();

		this.$element = $element.addClass("date-picker");
	
		options.cls && $element.addClass(options.cls);

		options.width ? $element.width(options.width) : false;
		
		options.height ? $element.height(options.height) : false;

		$element.html('<div class="view-top">'
						+'<table style="width:100%;" cellspacing=0 cellpadding=0><tbody>'
							+'<tr>'
								+'<td><span class="cell-icon icon-prev-year"></span></td>'
								+'<td><span class="cell-icon icon-prev-month"></span></td>'
								+'<td class="cell-selected-month">'+this.textMonth(this.value.getMonth() + 1)+'</td>'
								+'<td class="cell-selected-year">'+this.textYear(this.value.getFullYear())+'</td>'
								+'<td><span class="cell-icon  icon-next-month"></span></td>'
								+'<td><span class="cell-icon icon-next-year"></span></td>'
							+'</tr>'
						+'</tbody></table>'
					  +'</div>' 
					  +'<div class="view-date" style="display:block;">'
					 	+'<table style="width:100%;" cellspacing=0 cellpadding=0><tbody></tbody></table>'
					  +'</div>' 
					  +'<div class="view-month" style="display:none;">'
					 	+'<table style="width:100%;" cellspacing=0 cellpadding=0><tbody></tbody></table>'
					  +'</div>' 
					  +'<div class="view-time" style="display:none;">'
					 	+'<table style="width:100%;" cellspacing=0 cellpadding=0><tbody></tbody></table>'
					  +'</div>');

		// 工具栏
		var html=[];
		
		(this.type==='datetime' || this.type==='dateminute') && html.push('<span id="dp_'+timestamp+'_clock" class="icon-clock"></span>');
		
		options.showClear && html.push('<input type="button" id="dp_'+timestamp+'_clear" class="btn-clear" value="'+$.i18n.datepicker.CLEAR+'" />');
		
		options.showToday && html.push('<input type="button" id="dp_'+timestamp+'_today" class="btn-today" value="'+$.i18n.datepicker.TODAY+'" />');
		
		options.showOK && html.push('<input type="button" id="dp_'+timestamp+'_ok" class="btn-ok" value="'+$.i18n.datepicker.OK+'" />');
	
		html.length && $element.append('<div class="view-bottom">'+html.join("")+'</div>');
		
		this.$top=$element.find("> .view-top");

		this.$dateView=this.$top.next();
		
		this.$monthView=this.$dateView.next();
		
		this.$timeView=this.$monthView.next();
				
		this.$bottom=$element.find("> .view-bottom");
		
		if(this.type === 'date'){
			
			this.$timeView.remove();
			this.$timeView=null;

		}
		
		if(this.type === 'month'){
			
			this.$timeView.remove();
			this.$timeView=null;
			
			this.$dateView.remove();
			this.$dateView=null;
			
			this.$monthView.css("display","");

		}
		
		// 时间选择器
		if(this.type==='time' || this.type==='minute'){
			
			this.$top.remove();
			this.$top=null;
			
			this.$dateView.remove();
			this.$dateView=null;
			
			this.$monthView.html("");
			this.$monthView=null;
			
			this.$timeView.css("display","");
		}

		this.showWeek = !!options.showWeek;
		
		// 显示上月/下月日期
		this.showOtherMonth = !!options.showOtherMonth;

		// 每周第一天
		this.firstDayOfWeek = options.firstDayOfWeek;
	
		// 最大值
		this.setMaxDate(options.maxDate,true);
		
		// 最小值
		this.setMinDate(options.minDate,true);
		
		// 禁用星期
		this.setDisableDays(options.disableDays,true);
		
		// 正则禁用
		this.setDisableDates(options.disableDates,false);

		var selector = "td.cell-date,td.cell-month,td.cell-year";
		
		$element
				.on("mouseover.datepicker", selector, function() {

					!/cell-disabled/.test(this.className) && $(this).addClass("cell-hover");
					
				})
				.on("mouseout.datepicker", selector, function() {

					!/cell-disabled/.test(this.className) && $(this).removeClass("cell-hover");
					
				}).on(
		"click.datepicker",
		"td.cell,.cell-icon,td.cell-selected-year,td.cell-selected-month,.icon-clock,.icon-prev-hour,.icon-next-hour,.icon-prev-minute,.icon-next-minute,.icon-prev-second,.icon-next-second,.btn-clear,.btn-ok,.btn-today",
		function(e) {
		
			// 事件分发处理
			var sf=self;
			
			// TIME VIEW: 小时点选
			if(/cell-hour/.test(this.className)){
				
				var date=sf.value;
		
				date.setHours(+$(this).text());
			
				sf.draw(date,"time");

				sf.trigger("timepick",!/cell-disabled/.test(this.className) && /row-time/.test(this.parentNode.className) ? false : true);
				
				return;
			}
			
			// TIME VIEW: 分点选
			if(/cell-minute/.test(this.className)){
				
				var date=sf.value;
		
				date.setMinutes(+$(this).text());
			
				sf.draw(date,"time");
				
				sf.trigger("timepick",!/cell-disabled/.test(this.className) && /row-time/.test(this.parentNode.className) ? false : true);
				
				return;
			}
			
			// TIME VIEW: 秒点选
			if(/cell-second/.test(this.className)){
				
				var date=sf.value;
		
				date.setSeconds(+$(this).text());
			
				sf.draw(date,"time");
				
				sf.trigger("timepick",!/cell-disabled/.test(this.className) && /row-time/.test(this.parentNode.className) ? false : true);
				
				return;
			}
			
			// TIME VIEW: 小时递减
			if(/icon-prev-hour/.test(this.className)){
				
				var date=sf.value;
		
				date.setHours((date.getHours()-5+24)%24);
			
				sf.draw(date,"time");
				
				sf.trigger("timepick",true);
				
				return;
			}
			
			// TIME VIEW: 分递减
			if(/icon-prev-minute/.test(this.className)){
				
				var date=sf.value;
					
				date.setMinutes((date.getMinutes()-5+60)%60);
				
				sf.draw(date,"time");
				
				sf.trigger("timepick",true);
				
				return;
			}
			
			// TIME VIEW: 秒递减
			if(/icon-prev-second/.test(this.className)){
				
				var date=sf.value;
				
				date.setSeconds((date.getSeconds()-5+60)%60);
				
				sf.draw(date,"time");
				
				sf.trigger("timepick",true);
				
				return;
			}
			
			// TIME VIEW: 小时递增
			if(/icon-next-hour/.test(this.className)){

				var date=sf.value;
				
				date.setHours((date.getHours()+5+24)%24);
				
				sf.draw(date,"time");
				
				sf.trigger("timepick",true);
				
				return;
			}
			
			// TIME VIEW: 分递增
			if(/icon-next-minute/.test(this.className)){
			
				var date=sf.value;
				
				date.setMinutes((date.getMinutes()+5+60)%60);
				
				sf.draw(date,"time");
				
				sf.trigger("timepick",true);
				
				return;
			}
			
			// TIME VIEW: 秒递增
			if(/icon-next-second/.test(this.className)){
			
				var date=sf.value;
				
				date.setSeconds((date.getSeconds()+5+60)%60);
				
				sf.draw(date,"time");
				
				sf.trigger("timepick",true);
				
				return;
			}

			// 禁用
			if (/cell-disabled/.test(this.className)) {return;}

			// DATE VIEW: 点选下一月日期
			if (/cell-next-month/.test(this.className)) {
				
				var $top = sf.$top,day = +this.className.match(/\d{1,2}/);

				var date = sf.value,year = date.getFullYear(),month = date.getMonth();

				// 当前月没有这天怎么办,必须先置为1
				date.setDate(1);
				
				date.setMonth(month + 1);
				date.setDate(day);

				sf.$dateView && sf.draw(date,"date");
				
				sf.$monthView && sf.draw(date,"month");

				sf.trigger('datepick');

				return;
			}

			// DATE VIEW:点选上一月日期
			if (/cell-prev-month/.test(this.className)) {
				
				var $top = sf.$top,day = +this.className.match(/\d{1,2}/);

				var date = sf.value,year = date.getFullYear(),month = date.getMonth();

				// 当前月没有这天怎么办,必须先置为1
				date.setDate(1);
				
				date.setMonth(month - 1);
				date.setDate(day);

				sf.$dateView && sf.draw(date,"date");
				
				sf.$monthView && sf.draw(date,"month");

				sf.trigger('datepick');

				return;
			}

			// DATE VIEW:点选当月日期
			if (/cell-date/.test(this.className)) {
				
				var date=sf.value,day = +this.className.match(/\d{1,2}/);

				if (day !== date.getDate()) {
					
					var $cell = $(this);
					
					date.setDate(day);

					// 移除选中样式
					$cell.parent().parent().find(".cell-date.cell-selected").removeClass("cell-selected");

					$cell.addClass("cell-selected");
				
				}

				sf.trigger('datepick');

				return;
			}

			// MONTH View:点选月份
			if (/cell-month/.test(this.className)) {
				
				var date = sf.value,month = +this.className.match(/\d{1,2}/);

				if (month !== date.getMonth()+1) {

					var $cell = $(this) , $top=sf.$top;
					
					date.setMonth(month - 1);

					$top.find("td.cell-selected-month").html(sf.textMonth(month));

					// 移除选中样式
					$cell.parent().parent().find(".cell-month.cell-selected").removeClass("cell-selected");
					
					$cell.addClass("cell-selected");

					sf.$dateView && sf.draw(date, "date");

				}

				sf.trigger('monthpick');
				
				return;
			}

			// MONTH VIEW: 点选年份
			if (/cell-year/.test(this.className)) {
				
				var date = self.value,year = +this.className.match(/\d{4}/);

				if (year !== date.getFullYear()) {

					var $top=sf.$top , $cell=$(this);
					
					date.setFullYear(year);

					$top.find("td.cell-selected-year").html(sf.textYear(year));
					
					// 移除选中样式
					$cell.parent().parent().find(".cell-year.cell-selected").removeClass("cell-selected");
					
					$cell.addClass("cell-selected");

					sf.$dateView && sf.draw(date, "date");

				}
				
				sf.trigger('yearpick');
				
				return;
			}

			// MONTH VIEW: 点选下10年箭头
			if (/cell-next-10/.test(this.className)) {
				
				var year = +sf.$monthView.find("> table > tbody > tr:eq(0) > td:eq(3)")[0].className.match(/\d{4}/);
				
				var date = new Date(+self.value);
				
				date.setFullYear(year + 10);
				
				sf.draw(date, "month");

				return;
			}

			// MONTH VIEW: 点选上10年箭头
			if (/cell-prev-10/.test(this.className)) {
				
				var year = +sf.$monthView.find("> table > tbody > tr:eq(0) > td:eq(3)")[0].className.match(/\d{4}/);
				
				var date = new Date(+self.value);
				
				date.setFullYear(year - 10);
				
				sf.draw(date, "month");

				return;
			}

			// TOP VIEW: 点选下一月箭头
			if (/icon-next-month/.test(this.className)) {
				
				var date = sf.value;
				
				date.setMonth(date.getMonth() + 1);

				sf.draw(date,"date");

				sf.draw(date,"month");

				sf.$timeView && sf.$timeView.css("display")!=="none" && sf.draw(date,"time");
				
				sf.trigger('monthpick');

				return;
			}

			// TOP VIEW: 点选上一月箭头 
			if (/icon-prev-month/.test(this.className)) {

				var date = sf.value;
				
				date.setMonth(date.getMonth() - 1);

				sf.draw(date,"date");

				sf.draw(date,"month");
				
				sf.$timeView && sf.$timeView.css("display")!=="none" && sf.draw(date,"time");

				sf.trigger('monthpick');

				return;
			}

			// TOP VIEW: 点选下一年箭头 
			if (/icon-next-year/.test(this.className)) {

				var date = sf.value;
				
				date.setYear(date.getFullYear() + 1);

				sf.draw(date,"date");

				sf.draw(date,"month");

				sf.$timeView && sf.$timeView.css("display")!=="none" && sf.draw(date,"time");
				
				sf.trigger('yearpick');

				return;
			}

			// TOP VIEW: 点选上一年箭头
			if (/icon-prev-year/.test(this.className)) {

				var date = sf.value;
				
				date.setYear(date.getFullYear() - 1);

				sf.draw(date,"date");

				sf.draw(date,"month");
				
				sf.$timeView && sf.$timeView.css("display")!=="none" && sf.draw(date,"time");
				
				sf.trigger('yearpick');
				
				return;
			}

			// TOP VIEW: 切换 日期 视图、年月视图
			if (/cell-selected-year/.test(this.className) || /cell-selected-month/.test(this.className)) {

				if(sf.$timeView && sf.$timeView.css("display")!=='none'){
					
					sf.$timeView.hide();
					
					sf.$dateView && sf.$dateView.show();
					
					sf.$monthView && sf.$monthView.hide();
				
				}else{

					if(sf.$dateView){
						sf.$dateView.css("display")==="none" ? sf.$dateView.show() && sf.$monthView && sf.$monthView.hide() : sf.$dateView.hide() && sf.$monthView && sf.$monthView.show();
					} 

				}
				
				return;
			}
			
			// BOTTON VIEW: 工具栏闹钟图标
			if(/icon-clock/.test(this.className)){
				
				var show=sf.$timeView.css("display")==="none";
	
				sf.$monthView && sf.$monthView.hide();
				
				sf.$dateView && sf.$dateView[show ? "hide" : "show"]();

				show && sf.draw(sf.value,"time");
				
				sf.$timeView.toggle();
				
				return;
			}
			
			// BOTTOM VIEW:工具栏今天按钮
			if(/btn-today/.test(this.className)){
				
				sf.value=new Date();
				
				sf.redraw();
				
				sf.trigger("datepick");
				
				return;
				
			}
			
			// BOTTOM VIEW:工具栏今天按钮
			if(/btn-clear/.test(this.className)){
				
				sf.trigger("clear");
				
				return;				
			}
			
			// BOTTOM VIEW:工具栏今天按钮
			if(/btn-ok/.test(this.className)){
				
				sf.trigger("datepick");
				
				return;
			}
			
		}).on("mousewheel.datepicker",function(e){// 鼠标滚轮

			var sf=self,date=sf.value,cls=e.target.className;
			
			if(/cell-hour/.test(cls)){
				
				date.setHours((date.getHours()-e.deltaY+24)%24);
				
				sf.draw(date,"time");
				
				sf.trigger("timepick",true);
				
			}
			
			if(/cell-minute/.test(cls)){
				
				date.setMinutes((date.getMinutes()-e.deltaY+60)%60);
				
				sf.draw(date,"time");
				
				sf.trigger("timepick",true);
				
			}
			
			if(/cell-second/.test(cls)){
				
				date.setSeconds((date.getSeconds()-e.deltaY+60)%60);
				
				sf.draw(date,"time");
				
				sf.trigger("timepick",true);
				
			}

			return false;
		});
	};
	
	$.datepicker.prototype.textMonth=function(month){return $.i18n.months[+month - 1];};
	
	$.datepicker.prototype.textYear=function(year){return year;};

	// 重新绘制日期
	$.datepicker.prototype.redraw = function(date) {
		
		this.value = date || this.value;

		this.$dateView && this.draw(this.value, 'date');
		
		this.$monthView && this.draw(this.value, 'month');
		
		this.$timeView && this.draw(this.value, 'time');
		
		return this;
	};

	// 绘制日期
	$.datepicker.prototype.draw = function(date, type) {

		var $view = this["$"+type+"View"];
		
		if (!$view) {return this;}

		$view = $view.find(" > table > tbody");
		
		// 当前日期
		var current_date=new Date(),cyear=current_date.getFullYear(),cmonth=current_date.getMonth(),cday=current_date.getDate(),chour=current_date.getHours(),cminute=current_date.getMinutes(),csecond=current_date.getSeconds(),cmill=current_date.getMilliseconds();
		
		// 选中日期
		var syear = this.value.getFullYear(), smonth = this.value.getMonth() + 1, sday = this.value.getDate(),shour=this.value.getHours(),sminute=this.value.getMinutes(),ssecond=this.value.getSeconds(),smill=this.value.getMilliseconds();
		
		this.$top && this.$top.find("td.cell-selected-year").html(this.textYear(syear));
			
		this.$top && this.$top.find("td.cell-selected-month").html(this.textMonth(smonth));
		
		// 绘制日期
		var year = date.getFullYear(), month = date.getMonth() + 1, day = date.getDate(),hour=date.getHours(),minute=date.getMinutes(),second=date.getSeconds(),mill=date.getMilliseconds();
		
		// 临时计算参数
		var real_date = new Date(year, month - 1, day,hour,minute,mill), real_year = year, real_month = month, real_day = day,real_hour=hour,real_minute=minute,real_second=second,real_mill=mill;

		var y = m = d = 0,fmt;

		var count = 0, html = [];

		// 补0函数
		var rpad = function(value) {return value > 9 ? value : "0" + value;};

		/** ---------------------------Draw Date View--------------------------- **/
		if (type == 'date') {
				
			fmt=this.getFormat("date");
			
			var selected_str=this.value.formatDate(fmt);
			
			var current_str=current_date.formatDate(fmt);

			var

			// 指定月多少天
			days_in_month = new Date(year, month, 0).getDate(),

			// get the selected month's starting day (from 0 to 6)
			first_day = new Date(year, month - 1, 1).getDay(),

			// 上月显示多少天
			days_in_previous_month = new Date(year, month - 1, 0).getDate(),

			// 下月显示多少天
			days_from_previous_month = first_day - this.firstDayOfWeek;

			// the final value of how many days are there to be shown from the previous month
			days_from_previous_month = days_from_previous_month < 0 ? 7 + days_from_previous_month
					: days_from_previous_month;

			// 显示周
			if (this.showWeek) {
				
				html[count++] = '<tr  class="row-week"><th>'+$.i18n.week+'</th>';
				
				for ( var i = 0; i < 7; i++) 
					html[count++] = '<th>'+$.i18n.days[(this.firstDayOfWeek + i) % 7]+'</th>';
				
				html[count++] = '</tr>';
				
			}
			
			html[count++] = '<tr>';

			// 42单元格
			for (i = 0; i < 42; i++) {

				// 一周7天
				if (i > 0 && i % 7 === 0) {html[count++] = '</tr><tr>';}

				//ISO 8601 周序号
				if (this.showWeek && i % 7 === 0)
					html[count++] = '<td class="cell-week">'+rpad(new Date(year, month - 1, (i- days_from_previous_month + 1)).getWeek(), 2)+'</td>';

				// the number of the day in month
				var day = (i - days_from_previous_month + 1);
				
				real_date = new Date(year, month - 1, day,real_hour,real_minute,real_second,real_mill);

				if (i < days_from_previous_month) {

					// 不显示上一月日期
					if (!this.showOtherMonth) {html[count++] = '<td class="cell cell-date cell-disabled">&nbsp;</td>';continue;}

					//'<td class="cell cell-{value} cell-date{prev}{next}{selected}{disabled}">{value}</td>'
					html[count++]='<td class="cell cell-';
					html[count++]=rpad(days_in_previous_month- days_from_previous_month + i + 1, 2);
					html[count++]=' cell-date cell-prev-month';
					html[count++]=!this.isLegal(real_date,'date') ? ' cell-disabled" >' : '" >';
					html[count++]=rpad(days_in_previous_month- days_from_previous_month + i + 1, 2);
					html[count++]='</td>';

					continue;
				} 
				
				if (day > days_in_month) {

					// 不显示下一月日期
					if (!this.showOtherMonth) {html[count++] = '<td class="cell cell-date cell-disabled">&nbsp;</td>';continue;}

					//'<td class="cell cell-{value} cell-date{prev}{next}{selected}{disabled}">{value}</td>'
					html[count++]='<td class="cell cell-';
					html[count++]=rpad(day - days_in_month, 2);
					html[count++]=' cell-date cell-next-month';
					html[count++]=!this.isLegal(real_date,'date') ? ' cell-disabled" >' : '" >';
					html[count++]=rpad(day - days_in_month, 2);
					html[count++]='</td>';

					continue;
					
				} 

				var real_str=real_date.formatDate(fmt);
				
				//'<td class="cell cell-{value} cell-date{prev}{next}{selected}{disabled}">{value}</td>'
				html[count++]='<td class="cell cell-';
				html[count++]=rpad(day, 2);
				html[count++]=' cell-date';
				html[count++]= current_str==real_str ? ' cell-current' : '';
				html[count++]= real_str==selected_str ? ' cell-selected' : '';
				html[count++]=!this.isLegal(real_date,'date') ? ' cell-disabled" >' : '" >';
				html[count++]=rpad(day, 2);
				html[count++]='</td>';
					
			}

			html[count++] = '</tr>';
			
			$view.html(html.join(""));
			
			return this;
		}

		/** ---------------------------Draw Month View--------------------------- **/
		if (type == 'month') {

			var mod=0;
			
			for ( var i = 0; i < 22; i++) {
				
				mod = i % 4;
				
				mod === 0 ? html[count++] = "<tr>" : false;

				tpl = '<td class="cell cell-{type} cell-{value}{selected}{disabled}" >{text}</td>';

				/** month **/
				if (mod == 0 || mod == 1) {
								
					fmt=this.getFormat("month");
			
					real_date.setFullYear(year);

					m = mod === 0 ? i / 4 + 1 : (i - 1) / 4 + 7;
					
					real_date.setMonth(m - 1);
					
					//'<td class="cell cell-{type} cell-{value}{current}{selected}{disabled}" >{text}</td>';
					html[count++]='<td class="cell cell-month cell-'+rpad(m, 2);
	
					real_date.formatDate(fmt) == current_date.formatDate(fmt) ? html[count++]=' cell-current' : false;
					real_date.formatDate(fmt) == this.value.formatDate(fmt) ? html[count++]=' cell-selected' : false;
	
					html[count++]=!this.isLegal(real_date,"month") ? ' cell-disabled" >' : '" >';
					
					html[count++]=this.textMonth(m);
					html[count++]='</td>';


				} else {
					
					/** year **/
					
					fmt=this.getFormat("year");

					y = i % 2 == 0 ? year - (5 - Math.floor(i / 4)) : year
							+ Math.floor(i / 4);
					
					real_date.setFullYear(y);
					
					//'<td class="cell cell-{type} cell-{value}{current}{selected}{disabled}" >{text}</td>';
					html[count++]='<td class="cell cell-year cell-'+y;
	
					real_date.formatDate(fmt) == current_date.formatDate(fmt) ? html[count++]=' cell-current' : false;
					real_date.formatDate(fmt) == this.value.formatDate(fmt) ? html[count++]=' cell-selected' : false;
	
					html[count++]=!this.isLegal(real_date,"year") ? ' cell-disabled" >' : '" >';
					
					html[count++]=this.textYear(y);
					html[count++]='</td>';
					
				}

				mod === 3 ? html[count++] = "</tr>" : false;

			}

			html[count++] = '<td class="cell cell-prev-10">←</td>';
			html[count++] = '<td class="cell cell-next-10">→</td>';
			html[count++] = "</tr>";

			$view.html(html.join(""));
	
			return this;
		}

		if(type === 'time'){
	
			var allowSecond = this.type==='datetime' || this.type==='time';
			
			var fHour=(real_hour-2+24)%24,fMinute=(real_minute-2+60)%60,fSecond=(real_second-2+60)%60;
			
			html[count++]='<tr><td><span class="icon-time icon-prev-hour"></span></td><td><span class="icon-time icon-prev-minute"></span></td>';
			
			allowSecond ? html[count++]='<td><span class="icon-time icon-prev-second"></span></td>' : false;
			
			html[count++]='</tr>';
			
			for(var i=0;i<5;i++){
				
				html[count++]='<tr class="'+( i==2 ? "row-time" : "")+'">';
				
				// HOUR
				html[count++]='<td class="cell cell-hour cell-';
				
				html[count++]=(fHour+i)%24;
				
				real_date.setHours((fHour+i)%24);
				html[count++]=!this.isLegal(real_date,"datehour") ? ' cell-disabled" >' : '" >';
				
				html[count++]=rpad((fHour+i)%24,2);
				
				i==2 ? html[count++]='<i class="icon-hour"></i>' : false;
				
				html[count++]='</td>';
				
				// MINUTE
				html[count++]='<td class="cell cell-minute cell-';
				
				html[count++]=(fMinute+i)%60;
				
				real_date.setHours(real_hour);
				real_date.setMinutes((fMinute+i)%60);
				html[count++]=!this.isLegal(real_date,"dateminute") ? ' cell-disabled" >' : '" >';
				
				html[count++]=rpad((fMinute+i)%60,2);
				
				i==2 ? html[count++]='<i class="icon-minute"></i>' : false;
				
				html[count++]='</td>';
				
				// SECOND
				if(allowSecond){
					
					html[count++]='<td class="cell cell-second cell-';
					
					html[count++]=(fSecond+i)%60;
					
					real_date.setHours(real_hour);
					real_date.setMinutes(real_minute);
					real_date.setSeconds((fSecond+i)%60);
					html[count++]=!this.isLegal(real_date,"datetime") ? ' cell-disabled" >' : '" >';
					
					html[count++]=rpad((fSecond+i)%60,2);
				
					i==2 ? html[count++]='<i class="icon-second"></i>' : false;
				
					html[count++]='</td>';
				
				}
			
				html[count++]='</tr>';
				
			}
			
			html[count++]='<tr><td><span class="icon-time icon-next-hour"></span></td><td><span class="icon-time icon-next-minute"></span></td>';
			
			allowSecond ? html[count++]='<td><span class="icon-time icon-next-second"></span></td>' : false;
			
			html[count++]='</tr>';
			
			$view.html(html.join(""));
			
			return this;
		}
		
		return this;

	};

	// 日期最大值
	$.datepicker.prototype.setMaxDate=function(maxDate,ignoreRedraw){

		var format=this.getFormat();
		
		this.maxDate = maxDate ? (Date.isDate(maxDate) ? moment(maxDate.formatDate(format),format).toDate() : moment(maxDate,format).toDate()) : false ;
		
		!!ignoreRedraw && this.redraw();
		
		return this;
	};
	
	// 日期最小值
	$.datepicker.prototype.setMinDate=function(minDate,ignoreRedraw){

		var format=this.getFormat();
	
		this.minDate = minDate ? (Date.isDate(minDate) ? moment(minDate.formatDate(format),format).toDate() : moment(minDate,format).toDate()) : false ;

		!!ignoreRedraw && this.redraw();

		return this;
	};
	
	// 正则星期
	$.datepicker.prototype.setDisableDays=function(disableDays,ignoreRedraw){
		
		this.disableDays=disableDays;
	
		!!ignoreRedraw && this.redraw();

		return this;
	};
	
	// 正则禁用
	$.datepicker.prototype.setDisableDates=function(disableDates,ignoreRedraw){
		
		this.disableDates=disableDates;
	
		!!ignoreRedraw && this.redraw();

		return this;
	};	
	
	$.datepicker.prototype.getFormat=function(type){
		
		type= type || this.type;
		
		var formaters={
			datetime:'YYYY-MM-DD HH:mm:ss',
			dateminute:'YYYY-MM-DD HH:mm',
			datehour:'YYYY-MM-DD HH',
		  	date:'YYYY-MM-DD',
		  	month:'YYYY-MM',
		  	year:'YYYY',
		  	time:'HH:mm:ss',
		  	minute:'HH:mm',
		  	hour:'HH'
		};
		
		return formaters[type];

	};
	
	// YYYY-MM-DD hh:mm:ss
	$.datepicker.prototype.isLegal = function(date, type) {
		
		var l = 0,format=this.getFormat(),fmt=this.getFormat(type);
		
		//最大日期
		if (this.maxDate){
			var f=Date.parseDate(this.maxDate.formatDate(fmt),fmt),t=Date.parseDate(date.formatDate(fmt),fmt);
			if(f.getTime() < t.getTime()) {return false;}
		} 

		//最小日期
		if (this.minDate){
			var f=Date.parseDate(this.minDate.formatDate(fmt),fmt),t=Date.parseDate(date.formatDate(fmt),fmt);
			if(f.getTime() > t.getTime()) {return false;}
		}

		// 禁用星期
		if (type === 'date' && (l=this.disableDays && this.disableDays.length || 0)) {
			var day=date.getDay();
			while (l--) 
				if(day == this.disableDays[l]) 
					return false;

		}
		
		// 正则禁用
		if(l = this.disableDates && this.disableDates.length || 0){

			for(var i=0,l=format.length - fmt.length;i<l;i++)
			fmt+=".";

			var date_str=date.formatDate(fmt);
		
			while (l--) 
				if (new RegExp(this.disableDates[l]).test(date_str))
					return false;
		}

		return true;
	};

	$.datepicker.prototype.destroy=function(){
		
		this.off();
		
		this.$element.off(".datepicker").removeData().remove();

		return this;		
	};
	
	$.datepicker.prototype.trigger = function(event) {
		
		var date = this.isLegal(this.value) ? this.value : null;
		
		var params = [ this, date ];
		for ( var i = 1, l = arguments.length; i < l; i++) {
			params[i+1] = arguments[i];
		}

		var type=event.toUpperCase();
		event=new jQuery.Event(type, type+"."+this.widget );
		this.$element.triggerHandler(event, params);
	
		return event;
	};

	$.datepicker.prototype.on = function(event, handler) {
		this.$element.on(event.toUpperCase() + "." + this.widget, handler);
		return this;
	};
	
	$.datepicker.prototype.one = function(event, handler) {
		this.$element.one(event.toUpperCase() + "." + this.widget, handler);
		return this;
	};

	$.datepicker.prototype.off = function(event, handler) {
		this.$element.off(event.toUpperCase() + "." + this.widget, handler);
		return this;
	};

	$.datepicker.prototype.widget = 'datepicker';

	/**
	 * datepicker plugin
	 */
	$.fn.datepicker = function(options) {
	
		var f=null,fields=[];

		for(var i=0,l=this.length;i<l;i++){
				f=$.data(this[i], "widget");
				!f ? (f=new $.datepicker(this.eq(i), $.extend( {}, $.fn.datepicker.defaults, options)),$.data(this[i], "widget", f)) : false;
				fields[i]=f;
		}

		return l===1 ? fields[0] : fields;
	
	};

	/**
	 * Default options for autocomplete plugin
	 */
	$.fn.datepicker.defaults = {
		/** class on input **/
		cls : '',

		width : 200,

		height : false,

		// datetime、dateminute、date、month、time、minute
		type : 'date',

		disableDays : [],

		disableDates : [],

		minDate : false,

		minDate : false,

		showWeek : true,

		showOtherMonth : true,
		
		// 今天按钮
		showToday:false,
		
		// OK按钮
		showOK:false,
		
		// 清空
		showClear:false,

		firstDayOfWeek : 0,

		value : false
	};

	////////////////////////////////////////////////////////
	///////////////////////////////////////////////////////
	///////////////////////////////////////////////////////
	///////////////////////////////////////////////////////
	
	$.datefield = function($element, options) {
		
		var self = this,input = $element[0],value=options.value || input.value,name=options.name || input.name;
		this.$element = (options.cls ? $element : $element.addClass(options.cls)).removeAttr("name");
		input.autocomplete = 'off';;
		input.value='';
		
		// 只读状态
		this._read_only=false;
		!!options.readOnly || $element.prop("readOnly") ? this.readOnly(true) : false;
		
		// 隐藏域
		this.$hidden = $("<input type='hidden' ignoreElement='true' name='"+ name + "' value='' />").appendTo(input.parentNode);
		
		// 日期显示格式
		this.format = options.format || $.datepicker.prototype.getFormat(options.type);
		
		// 日期前后台交互格式
		this.valueFormat = options.valueFormat || this.format;

		this.$list = $("<div class='c-list date-picker' style='display:none;'></div>").appendTo(document.body);				
		
		// 浏览器支持placeholder
		var ph = options.placeholder;
		if (ph) {
			_support_placeholder ? $element.attr("placeholder", ph)
					: this.placeholder = ph;
		} else {
			if (!_support_placeholder) {
				ph = $element.attr("placeholder");
				if (ph) {
					this.placeholder = ph;
					$element.removeAttr("placeholder");
				}
			}
		}
	
		// 初始日期处理
		value= Date.parseDate(value,this.valueFormat) || Date.parseDate(value, this.format) || Date.parseDate(value);
		
		// 参数处理
		var opts = {
			width : 200,
			value : value,
			type : options.type,
			maxDate:options.maxDate,
			minDate:options.minDate,
			showOK:options.showOK,
			showToday:options.showToday,
			showClear:options.showClear,
			disableDays : options.disableDays,
			disableDate : options.disableDates
		};

		var _pick_date = function(event, picker, date,keepVisible) {

			var sf=self;
			
			var text = date && date.formatDate(sf.format) || "";
			
			var value = date && date.formatDate(sf.valueFormat) || "";
			
			sf.$element[0].value = text;
			
			sf.$hidden[0].value = value;
			
			// 保存引用,在失去焦点时有用
			sf._selected_=value;
			
			sf.selectRange(0, text.length);
		
			!keepVisible && (event.type == 'DATEPICK' || event.type == 'TIMEPICK') ? sf.hide() : false;
		
			sf.trigger("select",value);
			
		};

		this.datepicker = this.$list.datepicker(opts).on('datepick', _pick_date).on('monthpick', _pick_date).on('yearpick',_pick_date).on("timepick",_pick_date).on("clear",function(e,p){
			
			//模拟调用
			_pick_date({type:'DATEPICK'},p,null,false);
			
		});

		this.reset(value,true);

		$element.focus(function() {
			
			var sf=self,$this=$(this);
			
			// 只读
			if(sf.isReadOnly()){return true;}

			// 已聚焦
			if($this.hasClass("focus")){return true;}

			$this.removeClass("placeholder").addClass("focus");

			// 有可能需要消除placeholder影响 
			var ph=sf.placeholder;
			ph && this.value === ph ? this.value = '' : sf.selectRange(0, this.value.length);

			// 触发事件
			sf.trigger('focus');
			
			// 下拉DOM已显示
			if(sf.isActive()){return true;}
			
			// 展示下拉DOOM
			sf.show();

		}).blur(function() {

			var sf=self;
			
			// IE7&&8 BUG处理
			if (sf._ignore_blur_) {this.focus();sf.selectRange(0, this.value.length);sf._ignore_blur_ = false;return false;}
			
			if(sf.isReadOnly()){return true;}

			$(this).removeClass("focus");

			var value=this.value,ph=sf.placeholder;
	
			// 如果用户录入非空但不合法字符,那么使用最近一次正确值
			value = ph && value == ph ?  '' : value.replace(/(^\s+)|(\s+$)/g,"");
			value = value == '' ? null : Date.parseDate(value,sf.valueFormat) || Date.parseDate(value) || Date.parseDate(sf._selected_,sf.valueFormat);
	
			sf.value(value);
			
			// 隐藏下拉
			sf.hide();

			// 触发blur事件
			sf.trigger("blur");

			// 校验
			sf.validate();

		}).click(function() {
					
			!self.isReadOnly() && !self.isActive() && self.show();
					
		}).keyup(function(e){
			
			var sf=self;
			
			if(sf.isReadOnly()){return true;}
			
			switch (e.keyCode) {
			
				case 40: // down
					
					!sf.isActive() && sf.show();

					return false;
					
				case 13: // enter
				
					sf.isActive() && sf.datepicker.trigger("datepick");

					return false;

				case 27: // escape
					
					sf.isActive() && sf.hide();
					
					return false;

				default:

					return true;
				}
		});

		// 为表格编辑器做铺垫,必须做判断
		var celleditor=options.celleditor;
		
		this.$list.mousedown(function(e) {
			
			e.preventDefault();

			// @IE6/7/8 even prevent default behavior , blur event triggered also
			self._ignore_blur_ = $.browser.msie && (+$.browser.version) < 9;
			
			// 为表格编辑器做铺垫,必须做判断
			return celleditor ? false : true;
		});
	}

	// 日期下拉是否已经打开
	$.datefield.prototype.isActive = function() {return this.$list[0].style.display === 'block';};

	// 隐藏日期选择框 
	$.datefield.prototype.hide = function() {
		
		if(this.isReadOnly()){return this;}
		
		if(!this.isActive()){return this;}
		
		this.$list[0].style.display = 'none';
		
		// 触发事件
		this.trigger("deactive");
		
		return this;
	}

	// 显示日期选择框
	$.datefield.prototype.show = function() {
	
		if(this.isReadOnly()){return this;}
		
		var isActive=this.isActive();
		
		this.$list[0].style.display='block';
		
		// jquery ui position plugin
		if ($.ui && $.position && $.fn.position) {

			this.$list.position( {
				my : "left top",
				at : "left bottom",
				collision : "flip",
				of : this.$element
			});
			
		} else {

			var bottom = 0, offset = this.$element.offset();
			
			this.$list.css( {
				top : (offset.top + this.$element[0].offsetHeight) + 'px',
				left : offset.left + 'px'
			});

		}
		
		// 触发事件
		!isActive && this.trigger("active");

		return this;

	}

	// MY GOD DOM
	$.datefield.prototype.selectRange = function(start, end) {
		
		var input = this.$element[0];
		
		if (input.setSelectionRange) {
		
			input.focus();
			
			input.setSelectionRange(start, end);
		
		} else if (input.createTextRange) {
			
			var range = input.createTextRange();
			
			range.collapse(true);
			
			range.moveEnd('character', end);
			
			range.moveStart('character', start);
		
			range.select();
		
		}
		
		return this;
	};
	
	// 数据校验
	$.datefield.prototype.validate=function(){
		
		var state=$.validate ? $.validate(this.$element) : true;
		
		return state;
	};
	
	// 日期最大值,如果是字符串,必须和隐藏值域格式一致
	$.datefield.prototype.maxDate=function(maxDate,ignoreRedraw){

		this.datepicker.setMaxDate(maxDate,ignoreRedraw);
		
		return this;
	};
	
	// 日期最小值,如果是字符串,必须和隐藏值域格式一致
	$.datefield.prototype.minDate=function(minDate,ignoreRedraw){

		this.datepicker.setMinDate(minDate,ignoreRedraw);

		return this;
	};
	
	// 正则禁用,如:disableDates:['5$'] 表示禁用以 5 结尾 日期
	$.datefield.prototype.disableDays=function(disableDays,ignoreRedraw){
		
		this.datepicker.setDisableDays(disableDays,ignoreRedraw);

		return this;
	};
	
	// 禁用星期,如:disableDates:[0,4] 表示禁用周四、周日
	$.datefield.prototype.disableDates=function(disableDates,ignoreRedraw){
		
		this.datepicker.setDisableDates(disableDates,ignoreRedraw);

		return this;
	};
	
	// 只读
	$.datefield.prototype.isReadOnly=function(){return this._read_only===true;};

	// 设置只读
	$.datefield.prototype.readOnly = function(readOnly) {
		
		readOnly=!!readOnly;
		
		this._read_only=readOnly;
	
		this.$element[readOnly ? "addClass" : "removeClass"]("readOnly").prop("readOnly",readOnly);
		
		return this;
	};

	// 值处理
	$.datefield.prototype.value = function(value, ignoreRedraw) {
		
		//获值方法
		if (value === undefined) {return this.$hidden[0].value;}

		var oldValue=this.value();
		
		// 解析日期
		var date = Date.parseDate(value,this.valueFormat) ||  Date.parseDate(value);

		// 合法性判定
		date = date && this.datepicker.isLegal(date) ? date : null;

		var newValue=date && date.formatDate(this.valueFormat) || '';
		
		// 保存最新值
		this._selected_=newValue;
		
		// 格式化隐藏值
		this.$hidden[0].value = newValue;

		// 格式化显示文本
		var text = date && date.formatDate(this.format) || '';
		
		this.$element[0].value=text;

		// placeholder样式处理
		var ph=this.placeholder;
		ph && this.$element[(text ? "remove" : "add") + "Class"]("placeholder");
		ph && text==="" ? this.$element[0].value=ph : false; 

		// 触发事件
		oldValue!=newValue && this.trigger("change",newValue,oldValue);
	
		// 触发事件
		oldValue!=newValue && this.trigger("select",newValue);
		
		// 重绘日期下拉
		date && !ignoreRedraw && oldValue!=newValue && this.datepicker.redraw(date);

		return this;
	};

	$.datefield.prototype.reset = function(value,ignoreRedraw) {

		this.value(value,ignoreRedraw);

		this._default_value = this.value();
		
		return this;
	}

	$.datefield.prototype.destroy=function(keep){
		
		this.picker.destroy && this.picker.destroy();
		
		this.$list.off().remove();
		
		this.$element.off(".datefield").removeData();

		if(!!keep){
			
			this.$element.attr("name",this.$hidden[0].name);
			this.$hidden.remove();
			
		}else{
			this.$hidden.remove();
			this.$element.remove();
		}

	};
		
	$.datefield.prototype.trigger = function(event) {
		var params = [ this];
		for ( var i = 1, l = arguments.length; i < l; i++) {
			params[i] = arguments[i];
		}
		
		var type=event.toUpperCase();
		event=new jQuery.Event(type, type+"."+this.widget );
		this.$element.triggerHandler(event, params);
	
		return event;
	};

	$.datefield.prototype.destroy=function(keep){
		
		this.datepicker && this.datepicker.destroy && this.datepicker.destroy();
		
		this.$list.off(".datefield").remove();
		
		this.$element.off(".datefield").removeData();

		this.off();
		
		var name=this.$hidden[0].name;
		
		this.$hidden.remove();
		
		!!keep ? this.$element[0].name=name : this.$element.remove();
		
	};
		
	$.datefield.prototype.on = function(event, handler) {
		this.$element.on(event.toUpperCase() + "." + this.widget, handler);
		return this;
	};
	
	$.datefield.prototype.one = function(event, handler) {
		this.$element.one(event.toUpperCase() + "." + this.widget, handler);
		return this;
	};

	$.datefield.prototype.off = function(event, handler) {
		this.$element.off(((event && event.toUpperCase()) || '') + "." + this.widget, handler);
		return this;
	};

	$.datefield.prototype.widget = 'datefield';

	$.fn.datefield = function(options) {
		
		var f=null,fields=[];

		for(var i=0,l=this.length;i<l;i++){
				f=$.data(this[i], "widget");
				!f ? (f=new $.datefield(this.eq(i), $.extend( {}, $.fn.datefield.defaults, options)),$.data(this[i], "widget", f)) : false;
				fields[i]=f;
		}

		return l===1 ? fields[0] : fields;
	
	};

	$.fn.datefield.defaults = {
		
		// 额外class
		cls : '',

		// 前后台交互属性 
		name : '',

		// 默认值
		value : false,

		// 日期下拉类型:datetime、dateminute、datehour、date、month、time、minute
		type:'date',
		
		// 日期显示格式
		format : false,//'YYYY-MM-DD',

		// 前后台交互格式
		valueFormat : false,// 'YYYY-MM-DD',

		// 日期最大值
		maxDate : false,

		// 日期最小值
		minDate : false,

		// 今天按钮
		showToday:false,
		
		// OK按钮
		showOK:false,
		
		// 清空按钮
		showClear:false,
		
		// 禁用星期
		disableDays : false,

		// 正则禁用日期 
		disableDates : false,

		// 占位文本
		placeholder : '',
		
		// 为表格单元格编辑保留,不要修改
		celleditor:false

	};

})(jQuery);

 

你可能感兴趣的:(jquery)