├── Readme.txt ├── index.html ├── css └── pikaday.css ├── pikaday.min.js └── pikaday.js /Readme.txt: -------------------------------------------------------------------------------- 1 | Pikaday 中文修改版 2 | 3 | 原始版本:http://dbushell.com/2012/10/09/pikaday-javascript-datepicker/ 4 | 5 | 在原有基础上,做出以下修改: 6 | 1. 把语言改为中文。 7 | 2. 输出日期格式改为国内最常用的YYYY-MM-DD格式。 8 | 3. 修改了一些样式,兼容了ie6、7版本。 9 | 10 | By Travis -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Pikaday 7 | 8 | 9 | 31 | 32 | 33 |

Pikaday

34 | 35 | 36 |
37 | 38 | 39 | 40 | 41 | 63 | 64 | -------------------------------------------------------------------------------- /css/pikaday.css: -------------------------------------------------------------------------------- 1 | @charset "UTF-8"; 2 | 3 | /*! 4 | * Pikaday 5 | * Copyright © 2012 David Bushell | BSD & MIT license | http://dbushell.com/ 6 | */ 7 | 8 | .pika-single { 9 | z-index: 9999; 10 | display: block; 11 | position: relative; 12 | width: 210px; 13 | padding: 8px; 14 | color: #333; 15 | background: #fff; 16 | border: 1px solid #ccc; 17 | border-right-color: #bbb; 18 | border-bottom-color: #bbb; 19 | font-family: Arial, 'Microsoft YaHei'; 20 | } 21 | 22 | .pika-single.is-hidden { 23 | display: none; 24 | } 25 | 26 | .pika-single.is-bound { 27 | position: absolute; 28 | box-shadow: 0 5px 15px -5px rgba(0,0,0,0.5); 29 | } 30 | 31 | .pika-title { 32 | height:30px; 33 | overflow:hidden; 34 | } 35 | 36 | .pika-label { 37 | float:left; 38 | position: relative; 39 | z-index: 9999; 40 | overflow: hidden; 41 | margin: 0; 42 | padding: 5px 0; 43 | font-size: 14px; 44 | line-height: 20px; 45 | font-weight: bold; 46 | background-color: #fff; 47 | _display:inline; 48 | } 49 | 50 | .pika-label-year { 51 | margin-left:40px; 52 | width:58px; 53 | } 54 | 55 | .pika-label-month { 56 | width:50px; 57 | } 58 | .pika-title select { 59 | cursor: pointer; 60 | position: absolute; 61 | z-index: 9998; 62 | margin: 0; 63 | left: 0; 64 | top: 5px; 65 | opacity: 0; 66 | } 67 | 68 | .pika-prev, 69 | .pika-next { 70 | display: block; 71 | cursor: pointer; 72 | outline: none; 73 | position: relative; 74 | padding: 0; 75 | width: 20px; 76 | height: 30px; 77 | text-indent:100%; 78 | overflow: hidden; 79 | opacity: 0.5; 80 | _text-decoration:none; 81 | _text-align:center; 82 | _color:#555; 83 | _text-indent:0; 84 | _font:bold 16px/30px 'SimSun'; 85 | } 86 | 87 | .pika-prev:hover, 88 | .pika-next:hover { 89 | opacity: 1; 90 | } 91 | 92 | .pika-prev, 93 | .is-rtl .pika-next { 94 | float: left; 95 | background: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAUklEQVR42u3VMQoAIBADQf8Pgj+OD9hG2CtONJB2ymQkKe0HbwAP0xucDiQWARITIDEBEnMgMQ8S8+AqBIl6kKgHiXqQqAeJepBo/z38J/U0uAHlaBkBl9I4GwAAAABJRU5ErkJggg=='); 96 | } 97 | 98 | .pika-next, 99 | .is-rtl .pika-prev { 100 | float: right; 101 | background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAeCAYAAAAsEj5rAAAAU0lEQVR42u3VOwoAMAgE0dwfAnNjU26bYkBCFGwfiL9VVWoO+BJ4Gf3gtsEKKoFBNTCoCAYVwaAiGNQGMUHMkjGbgjk2mIONuXo0nC8XnCf1JXgArVIZAQh5TKYAAAAASUVORK5CYII='); 102 | } 103 | 104 | .pika-prev.is-disabled, 105 | .pika-next.is-disabled { 106 | cursor: default; 107 | opacity: 0.2; 108 | } 109 | 110 | .pika-table { 111 | width: 100%; 112 | border-collapse: collapse; 113 | border-spacing: 0; 114 | border: 0; 115 | } 116 | 117 | .pika-table th, 118 | .pika-table td { 119 | width: 30px; 120 | height:25px; 121 | } 122 | 123 | .pika-table th { 124 | color: #999; 125 | font-size: 12px; 126 | line-height: 25px; 127 | font-weight: bold; 128 | text-align: center; 129 | } 130 | 131 | .pika-button { 132 | cursor: pointer; 133 | display: block; 134 | outline: none; 135 | border: 0; 136 | margin: 0; 137 | width: 20px; 138 | height:15px; 139 | padding: 5px; 140 | color: #666; 141 | font-size: 12px; 142 | line-height: 15px; 143 | text-align: right; 144 | background: #f5f5f5; 145 | text-decoration:none; 146 | } 147 | 148 | .is-today .pika-button { 149 | color: #33aaff; 150 | font-weight: bold; 151 | } 152 | 153 | .is-selected .pika-button { 154 | color: #fff; 155 | font-weight: bold; 156 | background: #33aaff; 157 | box-shadow: inset 0 1px 3px #178fe5; 158 | border-radius: 3px; 159 | } 160 | 161 | .is-disabled .pika-button { 162 | pointer-events: none; 163 | cursor: default; 164 | color: #999; 165 | opacity: 0.3; 166 | } 167 | 168 | a.pika-button:hover { 169 | color: #fff; 170 | background: #ff8000; 171 | box-shadow: none; 172 | border-radius: 3px; 173 | } -------------------------------------------------------------------------------- /pikaday.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Pikaday 3 | * Copyright © 2012 David Bushell | BSD & MIT license | http://dbushell.com/ 4 | */ 5 | (function(window,document,undefined){'use strict';var hasMoment=typeof window.moment==='function',hasEventListeners=!!window.addEventListener,sto=window.setTimeout,addEvent=function(el,e,callback,capture){if(hasEventListeners){el.addEventListener(e,callback,!!capture)}else{el.attachEvent('on'+e,callback)}},removeEvent=function(el,e,callback,capture){if(hasEventListeners){el.removeEventListener(e,callback,!!capture)}else{el.detachEvent('on'+e,callback)}},trim=function(str){return str.trim?str.trim():str.replace(/^\s+|\s+$/g,'')},hasClass=function(el,cn){return(' '+el.className+' ').indexOf(' '+cn+' ')!==-1},addClass=function(el,cn){if(!hasClass(el,cn)){el.className=(el.className==='')?cn:el.className+' '+cn}},removeClass=function(el,cn){el.className=trim((' '+el.className+' ').replace(' '+cn+' ',' '))},isArray=function(obj){return(/Array/).test(Object.prototype.toString.call(obj))},isDate=function(obj){return(/Date/).test(Object.prototype.toString.call(obj))&&!isNaN(obj.getTime())},isLeapYear=function(year){return year%4===0&&year%100!==0||year%400===0},getDaysInMonth=function(year,month){return[31,isLeapYear(year)?29:28,31,30,31,30,31,31,30,31,30,31][month]},compareDates=function(a,b){return a.getTime()===b.getTime()},extend=function(to,from,overwrite){var prop,hasProp;for(prop in from){hasProp=to[prop]!==undefined;if(hasProp&&typeof from[prop]==='object'&&from[prop].nodeName===undefined){if(isDate(from[prop])){if(overwrite){to[prop]=new Date(from[prop].getTime())}}else if(isArray(from[prop])){if(overwrite){to[prop]=from[prop].slice(0)}}else{to[prop]=extend({},from[prop],overwrite)}}else if(overwrite||!hasProp){to[prop]=from[prop]}}return to},defaults={field:null,bound:undefined,format:'YYYY-MM-DD',defaultDate:null,setDefaultDate:false,firstDay:0,minDate:null,maxDate:null,yearRange:10,minYear:1990,maxYear:2099,minMonth:undefined,maxMonth:undefined,isRTL:false,numberOfMonths:1,i18n:{months:['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'],monthsShort:['1','2','3','4','5','6','7','8','9','10','11','12'],weekdays:['星期天','星期一','星期二','星期三','星期四','星期五','星期六'],weekdaysShort:['日','一','二','三','四','五','六']},onSelect:null,onOpen:null,onClose:null},renderDayName=function(opts,day,abbr){day+=opts.firstDay;while(day>=7){day-=7}return abbr?opts.i18n.weekdaysShort[day]:opts.i18n.weekdays[day]},renderDay=function(i,isSelected,isToday,isDisabled,isEmpty){if(isEmpty){return''}var arr=[];if(isDisabled){arr.push('is-disabled')}if(isToday){arr.push('is-today')}if(isSelected){arr.push('is-selected')}return''+i+''+''},renderRow=function(days,isRTL){return''+(isRTL?days.reverse():days).join('')+''},renderBody=function(rows){return''+rows.join('')+''},renderHead=function(opts){var i,arr=[];for(i=0;i<7;i++){arr.push(''+renderDayName(opts,i,true)+'')}return''+(opts.isRTL?arr.reverse():arr).join('')+''},renderTitle=function(instance){var i,j,arr,opts=instance._o,month=instance._m,year=instance._y,isMinYear=year===opts.minYear,isMaxYear=year===opts.maxYear,html='
',prev=true,next=true,months=opts.i18n.monthsShort?opts.i18n.monthsShort:opts.i18n.months;if(isMinYear&&(month===0||opts.minMonth>=month)){prev=false}html+='<';if(isArray(opts.yearRange)){i=opts.yearRange[0];j=opts.yearRange[1]+1}else{i=year-opts.yearRange;j=1+year+opts.yearRange}for(arr=[];i=opts.minYear){arr.push('')}}html+='
'+year+'年
';for(arr=[],i=0;i<12;i++){arr.push('')}html+='
'+months[month]+'月
';if(isMaxYear&&(month===11||opts.maxMonth<=month)){next=false}html+='>';return html+='
'},renderTable=function(opts,data){return''+renderHead(opts)+renderBody(data)+'
'};window.Pikaday=function(options){var self=this,opts=self.config(options);self._onMouseDown=function(e){if(!self._v){return}e=e||window.event;var target=e.target||e.srcElement;if(!target){return}if(!hasClass(target,'is-disabled')){if(hasClass(target,'pika-button')&&!hasClass(target,'is-empty')){self.setDate(new Date(self._y,self._m,parseInt(target.innerHTML,10)));if(opts.bound){sto(function(){self.hide()},100)}return}else if(hasClass(target,'pika-prev')){self.prevMonth()}else if(hasClass(target,'pika-next')){self.nextMonth()}}if(!hasClass(target,'pika-select')){if(e.preventDefault){e.preventDefault()}else{return e.returnValue=false}}else{self._c=true}};self._onChange=function(e){e=e||window.event;var target=e.target||e.srcElement;if(!target){return}if(hasClass(target,'pika-select-month')){self.gotoMonth(target.value)}else if(hasClass(target,'pika-select-year')){self.gotoYear(target.value)}};self._onInputChange=function(e){if(hasMoment){self.setDate(window.moment(opts.field.value,opts.format).toDate())}else{var date=new Date(Date.parse(opts.field.value));self.setDate(isDate(date)?date:null)}if(!self._v){self.show()}};self._onInputFocus=function(e){self.show()};self._onInputClick=function(e){self.show()};self._onInputBlur=function(e){if(!self._c){self._b=sto(function(){self.hide()},50)}self._c=false};self._onClick=function(e){e=e||window.event;var target=e.target||e.srcElement,pEl=target;if(!target){return}if(!hasEventListeners&&hasClass(target,'pika-select')){if(!target.onchange){target.setAttribute('onchange','return;');addEvent(target,'change',self._onChange)}}do{if(hasClass(pEl,'pika-single')){return}}while((pEl=pEl.parentNode));if(self._v&&target!==opts.field){self.hide()}};self.el=document.createElement('div');self.el.className='pika-single'+(opts.isRTL?' is-rtl':'');addEvent(self.el,'mousedown',self._onMouseDown,true);addEvent(self.el,'change',self._onChange);if(opts.field){if(opts.bound){document.body.appendChild(self.el)}else{opts.field.parentNode.insertBefore(self.el,opts.field.nextSibling)}addEvent(opts.field,'change',self._onInputChange);if(!opts.defaultDate){if(hasMoment&&opts.field.value){opts.defaultDate=window.moment(opts.field.value,opts.format).toDate()}else{opts.defaultDate=new Date(Date.parse(opts.field.value))}opts.setDefaultDate=true}}var defDate=opts.defaultDate;if(isDate(defDate)){if(opts.setDefaultDate){self.setDate(defDate)}else{self.gotoDate(defDate)}}else{self.gotoDate(new Date())}if(opts.bound){this.hide();self.el.className+=' is-bound';addEvent(opts.field,'click',self._onInputClick);addEvent(opts.field,'focus',self._onInputFocus);addEvent(opts.field,'blur',self._onInputBlur)}else{this.show()}};window.Pikaday.prototype={config:function(options){if(!this._o){this._o=extend({},defaults,true)}var opts=extend(this._o,options,true);opts.isRTL=!!opts.isRTL;opts.field=(opts.field&&opts.field.nodeName)?opts.field:null;opts.bound=!!(opts.bound!==undefined?opts.field&&opts.bound:opts.field);var nom=parseInt(opts.numberOfMonths,10)||1;opts.numberOfMonths=nom>4?4:nom;if(!isDate(opts.minDate)){opts.minDate=false}if(!isDate(opts.maxDate)){opts.maxDate=false}if((opts.minDate&&opts.maxDate)&&opts.maxDate100){opts.yearRange=100}}return opts},toString:function(format){if(!isDate(this._d))return'';var y=this._d.getFullYear();var m=this._d.getMonth()+1;var d=this._d.getDate();m=m<10?'0'+m:m;d=d<10?'0'+d:d;return hasMoment?window.moment(this._d).format(format||this._o.format):(y+'-'+m+'-'+d)},getMoment:function(){return hasMoment?window.moment(this._d):null},getDate:function(){return isDate(this._d)?new Date(this._d.getTime()):null},setDate:function(date){if(!date){this._d=null;return this.draw()}if(typeof date==='string'){date=new Date(Date.parse(date))}if(!isDate(date)){return}var min=this._o.minDate,max=this._o.maxDate;if(isDate(min)&&datemax){date=max}this._d=new Date(date.getTime());this._d.setHours(0,0,0,0);this.gotoDate(this._d);if(this._o.field){this._o.field.value=this.toString()}if(typeof this._o.onSelect==='function'){this._o.onSelect.call(this,this.getDate())}},gotoDate:function(date){if(!isDate(date)){return}this._y=date.getFullYear();this._m=date.getMonth();this.draw()},gotoToday:function(){this.gotoDate(new Date())},gotoMonth:function(month){if(!isNaN((month=parseInt(month,10)))){this._m=month<0?0:month>11?11:month;this.draw()}},nextMonth:function(){if(++this._m>11){this._m=0;this._y++}this.draw()},prevMonth:function(){if(--this._m<0){this._m=11;this._y--}this.draw()},gotoYear:function(year){if(!isNaN(year)){this._y=parseInt(year,10);this.draw()}},draw:function(force){if(!this._v&&!force){return}var opts=this._o,minYear=opts.minYear,maxYear=opts.maxYear,minMonth=opts.minMonth,maxMonth=opts.maxMonth;if(this._y<=minYear){this._y=minYear;if(!isNaN(minMonth)&&this._m=maxYear){this._y=maxYear;if(!isNaN(maxMonth)&&this._m>maxMonth){this._m=maxMonth}}this.el.innerHTML=renderTitle(this)+this.render(this._y,this._m);if(opts.bound){var pEl=opts.field,left=pEl.offsetLeft,top=pEl.offsetTop+pEl.offsetHeight;while((pEl=pEl.offsetParent)){left+=pEl.offsetLeft;top+=pEl.offsetTop}this.el.style.cssText='position:absolute;left:'+left+'px;top:'+top+'px;';sto(function(){opts.field.focus()},1)}},render:function(year,month){var opts=this._o,now=new Date(),days=getDaysInMonth(year,month),before=new Date(year,month,1).getDay(),data=[],row=[];now.setHours(0,0,0,0);if(opts.firstDay>0){before-=opts.firstDay;if(before<0){before+=7}}var cells=days+before,after=cells;while(after>7){after-=7}cells+=7-after;for(var i=0,r=0;iopts.maxDate),isSelected=isDate(this._d)?compareDates(day,this._d):false,isToday=compareDates(day,now),isEmpty=i=(days+before);row.push(renderDay(1+(i-before),isSelected,isToday,isDisabled,isEmpty));if(++r===7){data.push(renderRow(row,opts.isRTL));row=[];r=0}}return renderTable(opts,data)},isVisible:function(){return this._v},show:function(){if(!this._v){if(this._o.bound){addEvent(document,'click',this._onClick)}removeClass(this.el,'is-hidden');this._v=true;this.draw();if(typeof this._o.onOpen==='function'){this._o.onOpen.call(this)}}},hide:function(){var v=this._v;if(v!==false){if(this._o.bound){removeEvent(document,'click',this._onClick)}this.el.style.cssText='';addClass(this.el,'is-hidden');this._v=false;if(v!==undefined&&typeof this._o.onClose==='function'){this._o.onClose.call(this)}}},destroy:function(){this.hide();removeEvent(this.el,'mousedown',this._onMouseDown,true);removeEvent(this.el,'change',this._onChange);if(this._o.field){removeEvent(this._o.field,'change',this._onInputChange);if(this._o.bound){removeEvent(this._o.field,'click',this._onInputClick);removeEvent(this._o.field,'focus',this._onInputFocus);removeEvent(this._o.field,'blur',this._onInputBlur)}}if(this.el.parentNode){this.el.parentNode.removeChild(this.el)}}}})(window,window.document); -------------------------------------------------------------------------------- /pikaday.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Pikaday 3 | * Copyright © 2012 David Bushell | BSD & MIT license | http://dbushell.com/ 4 | */ 5 | 6 | (function(window, document, undefined) 7 | { 8 | 'use strict'; 9 | 10 | /** 11 | * feature detection and helper functions 12 | */ 13 | var hasMoment = typeof window.moment === 'function', 14 | 15 | hasEventListeners = !!window.addEventListener, 16 | 17 | sto = window.setTimeout, 18 | 19 | addEvent = function(el, e, callback, capture) 20 | { 21 | if (hasEventListeners) { 22 | el.addEventListener(e, callback, !!capture); 23 | } else { 24 | el.attachEvent('on' + e, callback); 25 | } 26 | }, 27 | 28 | removeEvent = function(el, e, callback, capture) 29 | { 30 | if (hasEventListeners) { 31 | el.removeEventListener(e, callback, !!capture); 32 | } else { 33 | el.detachEvent('on' + e, callback); 34 | } 35 | }, 36 | 37 | trim = function(str) 38 | { 39 | return str.trim ? str.trim() : str.replace(/^\s+|\s+$/g,''); 40 | }, 41 | 42 | hasClass = function(el, cn) 43 | { 44 | return (' ' + el.className + ' ').indexOf(' ' + cn + ' ') !== -1; 45 | }, 46 | 47 | addClass = function(el, cn) 48 | { 49 | if (!hasClass(el, cn)) { 50 | el.className = (el.className === '') ? cn : el.className + ' ' + cn; 51 | } 52 | }, 53 | 54 | removeClass = function(el, cn) 55 | { 56 | el.className = trim((' ' + el.className + ' ').replace(' ' + cn + ' ', ' ')); 57 | }, 58 | 59 | isArray = function(obj) 60 | { 61 | return (/Array/).test(Object.prototype.toString.call(obj)); 62 | }, 63 | 64 | isDate = function(obj) 65 | { 66 | return (/Date/).test(Object.prototype.toString.call(obj)) && !isNaN(obj.getTime()); 67 | }, 68 | 69 | isLeapYear = function(year) 70 | { 71 | // solution by Matti Virkkunen: http://stackoverflow.com/a/4881951 72 | return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0; 73 | }, 74 | 75 | getDaysInMonth = function(year, month) 76 | { 77 | return [31, isLeapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31][month]; 78 | }, 79 | 80 | compareDates = function(a,b) 81 | { 82 | // weak date comparison (use date.setHours(0,0,0,0) to ensure correct result) 83 | return a.getTime() === b.getTime(); 84 | }, 85 | 86 | extend = function(to, from, overwrite) 87 | { 88 | var prop, hasProp; 89 | for (prop in from) { 90 | hasProp = to[prop] !== undefined; 91 | if (hasProp && typeof from[prop] === 'object' && from[prop].nodeName === undefined) { 92 | if (isDate(from[prop])) { 93 | if (overwrite) { 94 | to[prop] = new Date(from[prop].getTime()); 95 | } 96 | } 97 | else if (isArray(from[prop])) { 98 | if (overwrite) { 99 | to[prop] = from[prop].slice(0); 100 | } 101 | } else { 102 | to[prop] = extend({}, from[prop], overwrite); 103 | } 104 | } else if (overwrite || !hasProp) { 105 | to[prop] = from[prop]; 106 | } 107 | } 108 | return to; 109 | }, 110 | 111 | 112 | /** 113 | * defaults and localisation 114 | */ 115 | defaults = { 116 | 117 | // bind the picker to a form field 118 | field: null, 119 | 120 | // automatically show/hide the picker on `field` focus (default `true` if `field` is set) 121 | bound: undefined, 122 | 123 | // the default output format for `.toString()` and `field` value 124 | format: 'YYYY-MM-DD', 125 | 126 | // the initial date to view when first opened 127 | defaultDate: null, 128 | 129 | // make the `defaultDate` the initial selected value 130 | setDefaultDate: false, 131 | 132 | // first day of week (0: Sunday, 1: Monday etc) 133 | firstDay: 0, 134 | 135 | // the minimum/earliest date that can be selected 136 | minDate: null, 137 | // the maximum/latest date that can be selected 138 | maxDate: null, 139 | 140 | // number of years either side, or array of upper/lower range 141 | yearRange: 10, 142 | 143 | // used internally (don't config outside) 144 | minYear: 1990, 145 | maxYear: 2099, 146 | minMonth: undefined, 147 | maxMonth: undefined, 148 | 149 | isRTL: false, 150 | 151 | // how many months are visible (not implemented yet) 152 | numberOfMonths: 1, 153 | 154 | // internationalization 155 | /* i18n: { 156 | 157 | months : ['January','February','March','April','May','June','July','August','September','October','November','December'], 158 | //monthsShort : ['Jan_Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'], 159 | weekdays : ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'], 160 | weekdaysShort : ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'] 161 | }, */ 162 | 163 | i18n: { 164 | 165 | months : ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'], 166 | monthsShort : ['1','2','3','4','5','6','7','8','9','10','11','12'], 167 | weekdays : ['星期天', '星期一','星期二','星期三','星期四','星期五','星期六'], 168 | weekdaysShort : ['日','一','二','三','四','五','六'] 169 | }, 170 | 171 | // callback function 172 | onSelect: null, 173 | onOpen: null, 174 | onClose: null 175 | }, 176 | 177 | 178 | /** 179 | * templating functions to abstract HTML rendering 180 | */ 181 | renderDayName = function(opts, day, abbr) 182 | { 183 | day += opts.firstDay; 184 | while (day >= 7) { 185 | day -= 7; 186 | } 187 | return abbr ? opts.i18n.weekdaysShort[day] : opts.i18n.weekdays[day]; 188 | }, 189 | 190 | renderDay = function(i, isSelected, isToday, isDisabled, isEmpty) 191 | { 192 | if (isEmpty) { 193 | return ''; 194 | } 195 | var arr = []; 196 | if (isDisabled) { 197 | arr.push('is-disabled'); 198 | } 199 | if (isToday) { 200 | arr.push('is-today'); 201 | } 202 | if (isSelected) { 203 | arr.push('is-selected'); 204 | } 205 | return '' + i + '' + ''; 206 | }, 207 | 208 | renderRow = function(days, isRTL) 209 | { 210 | return '' + (isRTL ? days.reverse() : days).join('') + ''; 211 | }, 212 | 213 | renderBody = function(rows) 214 | { 215 | return '' + rows.join('') + ''; 216 | }, 217 | 218 | renderHead = function(opts) 219 | { 220 | var i, arr = []; 221 | for (i = 0; i < 7; i++) { 222 | arr.push('' + renderDayName(opts, i, true) + ''); 223 | } 224 | return '' + (opts.isRTL ? arr.reverse() : arr).join('') + ''; 225 | }, 226 | 227 | renderTitle = function(instance) 228 | { 229 | var i, j, arr, 230 | opts = instance._o, 231 | month = instance._m, 232 | year = instance._y, 233 | isMinYear = year === opts.minYear, 234 | isMaxYear = year === opts.maxYear, 235 | html = '
', 236 | prev = true, 237 | next = true, 238 | months = opts.i18n.monthsShort ? opts.i18n.monthsShort : opts.i18n.months; 239 | 240 | if (isMinYear && (month === 0 || opts.minMonth >= month)) { 241 | prev = false; 242 | } 243 | html += '<'; 244 | 245 | if (isArray(opts.yearRange)) { 246 | i = opts.yearRange[0]; 247 | j = opts.yearRange[1] + 1; 248 | } else { 249 | i = year - opts.yearRange; 250 | j = 1 + year + opts.yearRange; 251 | } 252 | 253 | for (arr = []; i < j && i <= opts.maxYear; i++) { 254 | if (i >= opts.minYear) { 255 | arr.push(''); 256 | } 257 | } 258 | html += '
' + year + '年
'; 259 | 260 | for (arr = [], i = 0; i < 12; i++) { 261 | arr.push(''); 265 | } 266 | html += '
' + months[month] + '月
'; 267 | 268 | if (isMaxYear && (month === 11 || opts.maxMonth <= month)) { 269 | next = false; 270 | } 271 | html += '>'; 272 | 273 | return html += '
'; 274 | }, 275 | 276 | renderTable = function(opts, data) 277 | { 278 | return '' + renderHead(opts) + renderBody(data) + '
'; 279 | }; 280 | 281 | 282 | /** 283 | * Pikaday constructor 284 | */ 285 | window.Pikaday = function(options) 286 | { 287 | var self = this, 288 | opts = self.config(options); 289 | 290 | self._onMouseDown = function(e) 291 | { 292 | if (!self._v) { 293 | return; 294 | } 295 | e = e || window.event; 296 | var target = e.target || e.srcElement; 297 | if (!target) { 298 | return; 299 | } 300 | 301 | if (!hasClass(target, 'is-disabled')) { 302 | if (hasClass(target, 'pika-button') && !hasClass(target, 'is-empty')) { 303 | self.setDate(new Date(self._y, self._m, parseInt(target.innerHTML, 10))); 304 | if (opts.bound) { 305 | sto(function() { 306 | self.hide(); 307 | }, 100); 308 | } 309 | return; 310 | } 311 | else if (hasClass(target, 'pika-prev')) { 312 | self.prevMonth(); 313 | } 314 | else if (hasClass(target, 'pika-next')) { 315 | self.nextMonth(); 316 | } 317 | } 318 | if (!hasClass(target, 'pika-select')) { 319 | if (e.preventDefault) { 320 | e.preventDefault(); 321 | } else { 322 | return e.returnValue = false; 323 | } 324 | } else { 325 | self._c = true; 326 | } 327 | }; 328 | 329 | self._onChange = function(e) 330 | { 331 | e = e || window.event; 332 | var target = e.target || e.srcElement; 333 | if (!target) { 334 | return; 335 | } 336 | if (hasClass(target, 'pika-select-month')) { 337 | self.gotoMonth(target.value); 338 | } 339 | else if (hasClass(target, 'pika-select-year')) { 340 | self.gotoYear(target.value); 341 | } 342 | }; 343 | 344 | self._onInputChange = function(e) 345 | { 346 | if (hasMoment) { 347 | self.setDate(window.moment(opts.field.value, opts.format).toDate()); 348 | } 349 | else { 350 | var date = new Date(Date.parse(opts.field.value)); 351 | self.setDate(isDate(date) ? date : null); 352 | } 353 | if (!self._v) { 354 | self.show(); 355 | } 356 | }; 357 | 358 | self._onInputFocus = function(e) 359 | { 360 | self.show(); 361 | }; 362 | 363 | self._onInputClick = function(e) 364 | { 365 | self.show(); 366 | }; 367 | 368 | self._onInputBlur = function(e) 369 | { 370 | if (!self._c) { 371 | self._b = sto(function() { 372 | self.hide(); 373 | }, 50); 374 | } 375 | self._c = false; 376 | }; 377 | 378 | self._onClick = function(e) 379 | { 380 | e = e || window.event; 381 | var target = e.target || e.srcElement, 382 | pEl = target; 383 | if (!target) { 384 | return; 385 | } 386 | if (!hasEventListeners && hasClass(target, 'pika-select')) { 387 | if (!target.onchange) { 388 | target.setAttribute('onchange', 'return;'); 389 | addEvent(target, 'change', self._onChange); 390 | } 391 | } 392 | do { 393 | if (hasClass(pEl, 'pika-single')) { 394 | return; 395 | } 396 | } 397 | while ((pEl = pEl.parentNode)); 398 | if (self._v && target !== opts.field) { 399 | self.hide(); 400 | } 401 | }; 402 | 403 | self.el = document.createElement('div'); 404 | self.el.className = 'pika-single' + (opts.isRTL ? ' is-rtl' : ''); 405 | 406 | addEvent(self.el, 'mousedown', self._onMouseDown, true); 407 | addEvent(self.el, 'change', self._onChange); 408 | 409 | if (opts.field) { 410 | if (opts.bound) { 411 | document.body.appendChild(self.el); 412 | } else { 413 | opts.field.parentNode.insertBefore(self.el, opts.field.nextSibling); 414 | } 415 | addEvent(opts.field, 'change', self._onInputChange); 416 | 417 | if (!opts.defaultDate) { 418 | if (hasMoment && opts.field.value) { 419 | opts.defaultDate = window.moment(opts.field.value, opts.format).toDate(); 420 | } else { 421 | opts.defaultDate = new Date(Date.parse(opts.field.value)); 422 | } 423 | opts.setDefaultDate = true; 424 | } 425 | } 426 | 427 | var defDate = opts.defaultDate; 428 | 429 | if (isDate(defDate)) { 430 | if (opts.setDefaultDate) { 431 | self.setDate(defDate); 432 | } else { 433 | self.gotoDate(defDate); 434 | } 435 | } else { 436 | self.gotoDate(new Date()); 437 | } 438 | 439 | if (opts.bound) { 440 | this.hide(); 441 | self.el.className += ' is-bound'; 442 | addEvent(opts.field, 'click', self._onInputClick); 443 | addEvent(opts.field, 'focus', self._onInputFocus); 444 | addEvent(opts.field, 'blur', self._onInputBlur); 445 | } else { 446 | this.show(); 447 | } 448 | 449 | }; 450 | 451 | 452 | /** 453 | * public Pikaday API 454 | */ 455 | window.Pikaday.prototype = { 456 | 457 | 458 | /** 459 | * configure functionality 460 | */ 461 | config: function(options) 462 | { 463 | if (!this._o) { 464 | this._o = extend({}, defaults, true); 465 | } 466 | 467 | var opts = extend(this._o, options, true); 468 | 469 | opts.isRTL = !!opts.isRTL; 470 | 471 | opts.field = (opts.field && opts.field.nodeName) ? opts.field : null; 472 | 473 | opts.bound = !!(opts.bound !== undefined ? opts.field && opts.bound : opts.field); 474 | 475 | var nom = parseInt(opts.numberOfMonths, 10) || 1; 476 | opts.numberOfMonths = nom > 4 ? 4 : nom; 477 | 478 | if (!isDate(opts.minDate)) { 479 | opts.minDate = false; 480 | } 481 | if (!isDate(opts.maxDate)) { 482 | opts.maxDate = false; 483 | } 484 | if ((opts.minDate && opts.maxDate) && opts.maxDate < opts.minDate) { 485 | opts.maxDate = opts.minDate = false; 486 | } 487 | if (opts.minDate) { 488 | opts.minYear = opts.minDate.getFullYear(); 489 | opts.minMonth = opts.minDate.getMonth(); 490 | } 491 | if (opts.maxDate) { 492 | opts.maxYear = opts.maxDate.getFullYear(); 493 | opts.maxMonth = opts.maxDate.getMonth(); 494 | } 495 | 496 | if (isArray(opts.yearRange)) { 497 | var fallback = new Date().getFullYear() - 10; 498 | opts.yearRange[0] = parseInt(opts.yearRange[0], 10) || fallback; 499 | opts.yearRange[1] = parseInt(opts.yearRange[1], 10) || fallback; 500 | } else { 501 | opts.yearRange = Math.abs(parseInt(opts.yearRange, 10)) || defaults.yearRange; 502 | if (opts.yearRange > 100) { 503 | opts.yearRange = 100; 504 | } 505 | } 506 | 507 | return opts; 508 | }, 509 | 510 | /** 511 | * return a formatted string of the current selection (using Moment.js if available) 512 | */ 513 | toString: function(format) 514 | { 515 | if(!isDate(this._d)) return ''; 516 | var y = this._d.getFullYear(); 517 | var m = this._d.getMonth() + 1; 518 | var d = this._d.getDate(); 519 | m = m < 10 ? '0' + m : m; 520 | d = d < 10 ? '0' + d : d; 521 | return hasMoment ? window.moment(this._d).format(format || this._o.format) : (y + '-' + m + '-' + d); 522 | }, 523 | 524 | /** 525 | * return a Moment.js object of the current selection (if available) 526 | */ 527 | getMoment: function() 528 | { 529 | return hasMoment ? window.moment(this._d) : null; 530 | }, 531 | 532 | /** 533 | * return a Date object of the current selection 534 | */ 535 | getDate: function() 536 | { 537 | return isDate(this._d) ? new Date(this._d.getTime()) : null; 538 | }, 539 | 540 | /** 541 | * set the current selection 542 | */ 543 | setDate: function(date) 544 | { 545 | if (!date) { 546 | this._d = null; 547 | return this.draw(); 548 | } 549 | if (typeof date === 'string') { 550 | date = new Date(Date.parse(date)); 551 | } 552 | if (!isDate(date)) { 553 | return; 554 | } 555 | 556 | var min = this._o.minDate, 557 | max = this._o.maxDate; 558 | 559 | if (isDate(min) && date < min) { 560 | date = min; 561 | } else if (isDate(max) && date > max) { 562 | date = max; 563 | } 564 | 565 | this._d = new Date(date.getTime()); 566 | this._d.setHours(0,0,0,0); 567 | this.gotoDate(this._d); 568 | 569 | if (this._o.field) { 570 | this._o.field.value = this.toString(); 571 | } 572 | if (typeof this._o.onSelect === 'function') { 573 | this._o.onSelect.call(this, this.getDate()); 574 | } 575 | }, 576 | 577 | /** 578 | * change view to a specific date 579 | */ 580 | gotoDate: function(date) 581 | { 582 | if (!isDate(date)) { 583 | return; 584 | } 585 | this._y = date.getFullYear(); 586 | this._m = date.getMonth(); 587 | this.draw(); 588 | }, 589 | 590 | gotoToday: function() 591 | { 592 | this.gotoDate(new Date()); 593 | }, 594 | 595 | /** 596 | * change view to a specific month (zero-index, e.g. 0: January) 597 | */ 598 | gotoMonth: function(month) 599 | { 600 | if (!isNaN( (month = parseInt(month, 10)) )) { 601 | this._m = month < 0 ? 0 : month > 11 ? 11 : month; 602 | this.draw(); 603 | } 604 | }, 605 | 606 | nextMonth: function() 607 | { 608 | if (++this._m > 11) { 609 | this._m = 0; 610 | this._y++; 611 | } 612 | this.draw(); 613 | }, 614 | 615 | prevMonth: function() 616 | { 617 | if (--this._m < 0) { 618 | this._m = 11; 619 | this._y--; 620 | } 621 | this.draw(); 622 | }, 623 | 624 | /** 625 | * change view to a specific full year (e.g. "2012") 626 | */ 627 | gotoYear: function(year) 628 | { 629 | if (!isNaN(year)) { 630 | this._y = parseInt(year, 10); 631 | this.draw(); 632 | } 633 | }, 634 | 635 | /** 636 | * refresh the HTML 637 | */ 638 | draw: function(force) 639 | { 640 | if (!this._v && !force) { 641 | return; 642 | } 643 | var opts = this._o, 644 | minYear = opts.minYear, 645 | maxYear = opts.maxYear, 646 | minMonth = opts.minMonth, 647 | maxMonth = opts.maxMonth; 648 | 649 | if (this._y <= minYear) { 650 | this._y = minYear; 651 | if (!isNaN(minMonth) && this._m < minMonth) { 652 | this._m = minMonth; 653 | } 654 | } 655 | if (this._y >= maxYear) { 656 | this._y = maxYear; 657 | if (!isNaN(maxMonth) && this._m > maxMonth) { 658 | this._m = maxMonth; 659 | } 660 | } 661 | 662 | this.el.innerHTML = renderTitle(this) + this.render(this._y, this._m); 663 | 664 | if (opts.bound) { 665 | var pEl = opts.field, 666 | left = pEl.offsetLeft, 667 | top = pEl.offsetTop + pEl.offsetHeight; 668 | while((pEl = pEl.offsetParent)) { 669 | left += pEl.offsetLeft; 670 | top += pEl.offsetTop; 671 | } 672 | this.el.style.cssText = 'position:absolute;left:' + left + 'px;top:' + top + 'px;'; 673 | sto(function() { 674 | opts.field.focus(); 675 | }, 1); 676 | } 677 | }, 678 | 679 | /** 680 | * render HTML for a particular month 681 | */ 682 | render: function(year, month) 683 | { 684 | var opts = this._o, 685 | now = new Date(), 686 | days = getDaysInMonth(year, month), 687 | before = new Date(year, month, 1).getDay(), 688 | data = [], 689 | row = []; 690 | now.setHours(0,0,0,0); 691 | if (opts.firstDay > 0) { 692 | before -= opts.firstDay; 693 | if (before < 0) { 694 | before += 7; 695 | } 696 | } 697 | var cells = days + before, 698 | after = cells; 699 | while(after > 7) { 700 | after -= 7; 701 | } 702 | cells += 7 - after; 703 | for (var i = 0, r = 0; i < cells; i++) 704 | { 705 | var day = new Date(year, month, 1 + (i - before)), 706 | isDisabled = (opts.minDate && day < opts.minDate) || (opts.maxDate && day > opts.maxDate), 707 | isSelected = isDate(this._d) ? compareDates(day, this._d) : false, 708 | isToday = compareDates(day, now), 709 | isEmpty = i < before || i >= (days + before); 710 | 711 | row.push(renderDay(1 + (i - before), isSelected, isToday, isDisabled, isEmpty)); 712 | 713 | if (++r === 7) { 714 | data.push(renderRow(row, opts.isRTL)); 715 | row = []; 716 | r = 0; 717 | } 718 | } 719 | return renderTable(opts, data); 720 | }, 721 | 722 | isVisible: function() 723 | { 724 | return this._v; 725 | }, 726 | 727 | show: function() 728 | { 729 | if (!this._v) { 730 | if (this._o.bound) { 731 | addEvent(document, 'click', this._onClick); 732 | } 733 | removeClass(this.el, 'is-hidden'); 734 | this._v = true; 735 | this.draw(); 736 | if (typeof this._o.onOpen === 'function') { 737 | this._o.onOpen.call(this); 738 | } 739 | } 740 | }, 741 | 742 | hide: function() 743 | { 744 | var v = this._v; 745 | if (v !== false) { 746 | if (this._o.bound) { 747 | removeEvent(document, 'click', this._onClick); 748 | } 749 | this.el.style.cssText = ''; 750 | addClass(this.el, 'is-hidden'); 751 | this._v = false; 752 | if (v !== undefined && typeof this._o.onClose === 'function') { 753 | this._o.onClose.call(this); 754 | } 755 | } 756 | }, 757 | 758 | /** 759 | * GAME OVER 760 | */ 761 | destroy: function() 762 | { 763 | this.hide(); 764 | removeEvent(this.el, 'mousedown', this._onMouseDown, true); 765 | removeEvent(this.el, 'change', this._onChange); 766 | if (this._o.field) { 767 | removeEvent(this._o.field, 'change', this._onInputChange); 768 | if (this._o.bound) { 769 | removeEvent(this._o.field, 'click', this._onInputClick); 770 | removeEvent(this._o.field, 'focus', this._onInputFocus); 771 | removeEvent(this._o.field, 'blur', this._onInputBlur); 772 | } 773 | } 774 | if (this.el.parentNode) { 775 | this.el.parentNode.removeChild(this.el); 776 | } 777 | } 778 | 779 | }; 780 | 781 | })(window, window.document); --------------------------------------------------------------------------------