支持年月日、年月、年月日时分秒、年月日时分、时分秒、时分六种下拉选择
注意,需要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"> </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"> </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);