首页 > 代码库 > sencha touch datepicker/datepickerfield(时间选择控件)扩展

sencha touch datepicker/datepickerfield(时间选择控件)扩展

参考资料: https://market.sencha.com/extensions/datetimepicker

适用于2.4.1版本

uxPickerTime

使用方法参考:datepicker控件

  1 Ext.define(‘ux.picker.Time‘, {  2     extend: ‘Ext.picker.Picker‘,  3     xtype: ‘uxPickerTime‘,  4     alternateClassName: ‘uxPickerTime‘,  5     requires: [‘Ext.DateExtras‘, ‘Ext.util.InputBlocker‘],  6   7     /**  8     * @event change  9     * Fired when the value of this picker has changed and the done button is pressed. 10     * @param {Ext.picker.Date} this This Picker 11     * @param {Date} value The date value 12     */ 13  14     config: { 15         /** 16         * @cfg {Number} yearFrom 17         * 开始年份,如果他比yearTo大,则选择顺序颠倒 18         * @accessor 19         */ 20         yearFrom: 2014, 21  22         /** 23         * @cfg {Number} [yearTo=new Date().getFullYear()] 24         * 结束年份 25         * @accessor 26         */ 27         yearTo: 2000, 28  29         /** 30         * @cfg {String} monthText 31         * 月显示值 32         * @accessor 33         */ 34         monthText: ‘月‘, 35  36         /** 37         * @cfg {String} dayText 38         * 日显示值 39         * @accessor 40         */ 41         dayText: ‘日‘, 42  43         /** 44         * @cfg {String} yearText 45         * 年显示值 46         * @accessor 47         */ 48         yearText: ‘年‘, 49  50         /** 51         * @cfg {String} hourText 52         * 小时显示值 53         */ 54         hourText: ‘时‘, 55  56         /** 57         * @cfg {String} minuteText 58         * 分显示值 59         */ 60         minuteText: ‘分‘, 61  62         /** 63         * @cfg {String} ampmText 64         * 上午/下午显示值 65         */ 66         ampmText: ‘上午/下午‘, 67         /** 68         * @cfg {Array} slotOrder 69         * 默认的选项列表 70         * @accessor 71         */ 72         slotOrder: [‘year‘, ‘month‘, ‘day‘, ‘hour‘, ‘minute‘], // 73  74         /** 75         * @cfg {Int}  76         *分钟间隔 77         * @accessor 78         */ 79         minuteInterval: 1, 80  81         /** 82         * @cfg {Boolean} ampm 83         *是否使用12小时制 84         * @accessor 85         */ 86         ampm: false, 87         useTitles: true 88     }, 89  90     platformConfig: [{ 91         theme: [‘Windows‘], 92         doneButton: { 93             iconCls: ‘check2‘, 94             ui: ‘round‘, 95             text: ‘‘ 96         } 97     }], 98  99     initialize: function () {100         this.callParent();101 102         this.on({103             scope: this,104             delegate: ‘> slot‘,105             slotpick: this.onSlotPick106         });107 108         this.on({109             scope: this,110             show: this.onSlotPick111         });112     },113 114     setValue: function (value, animated) {115         if (Ext.isDate(value)) {116             var ampm = ‘AM‘,117             currentHours = hour = value.getHours();118             if (this.getAmpm()) {119                 if (currentHours > 12) {120                     ampm = "PM";121                     hour -= 12;122                 } else if (currentHours == 12) {123                     ampm = "PM";124                 } else if (currentHours == 0) {125                     hour = 12;126                 }127             }128             value =http://www.mamicode.com/ {129                 day: value.getDate(),130                 month: value.getMonth() + 1,131                 year: value.getFullYear(),132                 hour: hour,133                 minute: value.getMinutes(),134                 ampm: ampm135             };136         }137 138         this.callParent([value, animated]);139         this.onSlotPick();140     },141     //获取值142     getValue: function (useDom) {143         var values = {},144             items = this.getItems().items,145             ln = items.length,146             daysInMonth, day, month, year, hour, minute, item, i;147 148         for (i = 0; i < ln; i++) {149             item = items[i];150             if (item instanceof Ext.picker.Slot) {151                 values[item.getName()] = item.getValue(useDom);152             }153         }154 155         //if all the slots return null, we should not return a date156         if (values.year === null && values.month === null && values.day === null && values.hour === null && values.minute === null) {157             return null;158         }159 160         year = Ext.isNumber(values.year) ? values.year : 1;161         month = Ext.isNumber(values.month) ? values.month : 1;162         day = Ext.isNumber(values.day) ? values.day : 1;163         hour = Ext.isNumber(values.hour) ? values.hour : 1;164         minute = Ext.isNumber(values.minute) ? values.minute : 1;165 166         if (month && year && month && day) {167             daysInMonth = this.getDaysInMonth(month, year);168         }169         day = (daysInMonth) ? Math.min(day, daysInMonth) : day;170         if (values.ampm && values.ampm == "PM" && hour < 12) {171             hour = hour + 12;172         }173         if (values.ampm && values.ampm == "AM" && hour == 12) {174             hour = 0;175         }176         return new Date(year, month - 1, day, hour, minute);177     },178 179     /**180     * Updates the yearFrom configuration181     */182     updateYearFrom: function () {183         if (this.initialized) {184             this.createSlots();185         }186     },187 188     /**189     * Updates the yearTo configuration190     */191     updateYearTo: function () {192         if (this.initialized) {193             this.createSlots();194         }195     },196 197     /**198     * Updates the monthText configuration199     */200     updateMonthText: function (newMonthText, oldMonthText) {201         var innerItems = this.getInnerItems,202             ln = innerItems.length,203             item, i;204 205         //loop through each of the current items and set the title on the correct slice206         if (this.initialized) {207             for (i = 0; i < ln; i++) {208                 item = innerItems[i];209 210                 if ((typeof item.title == "string" && item.title == oldMonthText) || (item.title.html == oldMonthText)) {211                     item.setTitle(newMonthText);212                 }213             }214         }215     },216 217     /**218     * Updates the {@link #dayText} configuration.219     */220     updateDayText: function (newDayText, oldDayText) {221         var innerItems = this.getInnerItems,222             ln = innerItems.length,223             item, i;224 225         //loop through each of the current items and set the title on the correct slice226         if (this.initialized) {227             for (i = 0; i < ln; i++) {228                 item = innerItems[i];229 230                 if ((typeof item.title == "string" && item.title == oldDayText) || (item.title.html == oldDayText)) {231                     item.setTitle(newDayText);232                 }233             }234         }235     },236 237     /**238     * Updates the yearText configuration239     */240     updateYearText: function (yearText) {241         var innerItems = this.getInnerItems,242             ln = innerItems.length,243             item, i;244 245         //loop through each of the current items and set the title on the correct slice246         if (this.initialized) {247             for (i = 0; i < ln; i++) {248                 item = innerItems[i];249 250                 if (item.title == this.yearText) {251                     item.setTitle(yearText);252                 }253             }254         }255     },256 257     // @private258     constructor: function () {259         this.callParent(arguments);260         this.createSlots();261     },262 263     /**264     * Generates all slots for all years specified by this component, and then sets them on the component265     * @private266     */267     createSlots: function () {268         var me = this,269             slotOrder = me.getSlotOrder(),270             yearsFrom = me.getYearFrom(),271             yearsTo = me.getYearTo(),272             years = [],273             days = [],274             months = [],275                hours = [],276             minutes = [],277             ampm = [],278             reverse = yearsFrom > yearsTo,279             ln, i, daysInMonth;280 281         if (!this.getAmpm()) {282             var index = slotOrder.indexOf(‘ampm‘)283             if (index >= 0) {284                 slotOrder.splice(index);285             }286         }287         //填充年列表288         while (yearsFrom) {289             years.push({290                 text: yearsFrom,291                 value: yearsFrom292             });293 294             if (yearsFrom === yearsTo) {295                 break;296             }297 298             if (reverse) {299                 yearsFrom--;300             } else {301                 yearsFrom++;302             }303         }304         //填充天列表305         daysInMonth = me.getDaysInMonth(1, new Date().getFullYear());306 307         for (i = 0; i < daysInMonth; i++) {308             days.push({309                 text: i + 1,310                 value: i + 1311             });312         }313         //填充月列表314         for (i = 0, ln = Ext.Date.monthNames.length; i < ln; i++) {315             months.push({316                 text: Ext.Date.monthNames[i],317                 value: i + 1318             });319         }320         //填充小时列表321         var hourLimit = (this.getAmpm()) ? 12 : 23322         var hourStart = (this.getAmpm()) ? 1 : 0323         for (i = hourStart; i <= hourLimit; i++) {324             hours.push({325                 text: this.pad2(i),326                 value: i327             });328         }329         //填充分钟列表330         for (i = 0; i < 60; i += this.getMinuteInterval()) {331             minutes.push({332                 text: this.pad2(i),333                 value: i334             });335         }336         //填充上午/下午337         ampm.push({338             text: ‘上午‘,339             value: ‘AM‘340         }, {341             text: ‘下午‘,342             value: ‘PM‘343         });344 345         var slots = [];346 347         slotOrder.forEach(function (item) {348             slots.push(me.createSlot(item, days, months, years, hours, minutes, ampm));349         });350 351         me.setSlots(slots);352     },353 354     /**355     * Returns a slot config for a specified date.356     * @private357     */358     createSlot: function (name, days, months, years, hours, minutes, ampm) {359         switch (name) {360             case ‘year‘:361                 return {362                     name: ‘year‘,363                     align: ‘center‘,364                     data: years,365                     title: this.getYearText(),366                     flex: 3367                 };368             case ‘month‘:369                 return {370                     name: name,371                     align: ‘center‘,372                     data: months,373                     title: this.getMonthText(),374                     flex: 3375                 };376             case ‘day‘:377                 return {378                     name: ‘day‘,379                     align: ‘center‘,380                     data: days,381                     width: ‘1px‘,382                     title: this.getDayText(),383                     flex: 2384                 };385             case ‘hour‘:386                 return {387                     name: ‘hour‘,388                     align: ‘center‘,389                     data: hours,390                     title: this.getHourText(),391                     flex: 2392                 };393             case ‘minute‘:394                 return {395                     name: ‘minute‘,396                     align: ‘center‘,397                     data: minutes,398                     title: this.getMinuteText(),399                     flex: 2400                 };401             case ‘ampm‘:402                 return {403                     name: ‘ampm‘,404                     align: ‘center‘,405                     data: ampm,406                     title: this.getAmpmText(),407                     flex: 2408                 };409         }410     },411 412     onSlotPick: function () {413         var value = http://www.mamicode.com/this.getValue(true),414             slot = this.getDaySlot(),415             year = value.getFullYear(),416             month = value.getMonth(),417             days = [],418             daysInMonth, i;419         if (!value || !Ext.isDate(value) || !slot) {420             return;421         }422 423         this.callParent(arguments);424 425         //get the new days of the month for this new date426         daysInMonth = this.getDaysInMonth(month + 1, year);427         for (i = 0; i < daysInMonth; i++) {428             days.push({429                 text: i + 1,430                 value: i + 1431             });432         }433         // We don‘t need to update the slot days unless it has changed434         if (slot.getStore().getCount() == days.length) {435             return;436         }437 438         slot.getStore().setData(days);439 440         // Now we have the correct amount of days for the day slot, lets update it441         var store = slot.getStore(),442             viewItems = slot.getViewItems(),443             valueField = slot.getValueField(),444             index, item;445 446         index = store.find(valueField, value.getDate());447         if (index == -1) {448             return;449         }450 451         item = Ext.get(viewItems[index]);452 453         slot.selectedIndex = index;454         slot.scrollToItem(item);455         slot.setValue(slot.getValue(true));456 457 458     },459 460     getDaySlot: function () {461         var innerItems = this.getInnerItems(),462             ln = innerItems.length,463             i, slot;464 465         if (this.daySlot) {466             return this.daySlot;467         }468 469         for (i = 0; i < ln; i++) {470             slot = innerItems[i];471             if (slot.isSlot && slot.getName() == "day") {472                 this.daySlot = slot;473                 return slot;474             }475         }476 477         return null;478     },479 480     // @private481     getDaysInMonth: function (month, year) {482         var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];483         return month == 2 && this.isLeapYear(year) ? 29 : daysInMonth[month - 1];484     },485 486     // @private487     isLeapYear: function (year) {488         return !!((year & 3) === 0 && (year % 100 || (year % 400 === 0 && year)));489     },490 491     onDoneButtonTap: function () {492         var oldValue = http://www.mamicode.com/this._value,493             newValue = http://www.mamicode.com/this.getValue(true),494             testValue =http://www.mamicode.com/ newValue;495 496         if (Ext.isDate(newValue)) {497             testValue =http://www.mamicode.com/ newValue.toDateString();498         }499         if (Ext.isDate(oldValue)) {500             oldValue =http://www.mamicode.com/ oldValue.toDateString();501         }502         if (testValue != oldValue) {503             this.fireEvent(‘change‘, this, newValue);504         }505         this.hide();506         Ext.util.InputBlocker.unblockInputs();507     },508     pad2: function (number) {509         return (number < 10 ? ‘0‘ : ‘‘) + number;510     }511 });

uxFieldTime

使用方法参考:datepickerfield控件

  1 Ext.define(‘ux.field.Time‘, {  2     extend: ‘Ext.field.Text‘,  3     alternateClassName: ‘uxFieldTime‘,  4     xtype: ‘uxFieldTime‘,  5     requires: [  6         ‘ux.picker.Time‘,  7         ‘Ext.DateExtras‘  8     ],  9  10     /** 11     * @event change 12     * Fires when a date is selected 13     * @param {Ext.field.DatePicker} this 14     * @param {Date} newDate The new date 15     * @param {Date} oldDate The old date 16     */ 17  18     config: { 19         ui: ‘select‘, 20  21         /** 22         * @cfg {Object/ux.picker.Time} picker 23         * An object that is used when creating the internal {@link ux.picker.Time} component or a direct instance of {@link ux.picker.Time}. 24         * @accessor 25         */ 26         picker: true, 27  28         /** 29         * @cfg {Boolean} 30         * @hide 31         * @accessor 32         */ 33         clearIcon: false, 34  35         /** 36         * @cfg {Object/Date} value 37         * Default value for the field and the internal {@link ux.picker.Time} component. Accepts an object of ‘year‘, 38         * ‘month‘ and ‘day‘ values, all of which should be numbers, or a {@link Date}. 39         * 40         * Example: {year: 1989, day: 1, month: 5} = 1st May 1989 or new Date() 41         * @accessor 42         */ 43  44  45         /** 46         * @cfg {Boolean} destroyPickerOnHide 47         * 完成选择时隐藏或者销毁该控件,默认销毁 48         * @accessor 49         */ 50         destroyPickerOnHide: false, 51  52         /** 53         * @cfg {String} dateFormat 默认时间格式 54         * 接受任何有效的时间格式. 请参考 {@link Ext.Date}. 55         */ 56         dateFormat: ‘Y-m-d H:i‘, 57  58         /** 59         * @cfg {Object} 60         * @hide 61         */ 62         component: { 63             useMask: true 64         } 65     }, 66  67     initialize: function () { 68         var me = this, 69             component = me.getComponent(); 70  71         me.callParent(); 72  73         component.on({ 74             scope: me, 75             masktap: ‘onMaskTap‘ 76         }); 77  78  79         component.doMaskTap = Ext.emptyFn; 80  81         if (Ext.browser.is.AndroidStock2) { 82             component.input.dom.disabled = true; 83         } 84     }, 85  86     syncEmptyCls: Ext.emptyFn, 87  88     applyValue: function (value) { 89         if (!Ext.isDate(value) && !Ext.isObject(value)) { 90             return null; 91         } 92  93         if (Ext.isObject(value)) { 94             return new Date(value.year, value.month - 1, value.day, value.hour, value.minute); 95         } 96  97         return value; 98     }, 99 100     updateValue: function (newValue, oldValue) {101         var me = this,102             picker = me._picker;103 104         if (picker && picker.isPicker) {105             picker.setValue(newValue);106         }107 108         // Ext.Date.format expects a Date109         if (newValue !== null) {110             me.getComponent().setValue(Ext.Date.format(newValue, me.getDateFormat() || Ext.util.Format.defaultDateFormat));111         } else {112             me.getComponent().setValue(‘‘);113         }114 115         if (newValue !== oldValue) {116             me.fireEvent(‘change‘, me, newValue, oldValue);117         }118     },119 120     /**121     * Updates the date format in the field.122     * @private123     */124     updateDateFormat: function (newDateFormat, oldDateFormat) {125         var value = http://www.mamicode.com/this.getValue();126         if (newDateFormat != oldDateFormat && Ext.isDate(value)) {127             this.getComponent().setValue(Ext.Date.format(value, newDateFormat || Ext.util.Format.defaultDateFormat));128         }129     },130 131     /**132     * Returns the {@link Date} value of this field.133     * If you wanted a formated date134     * @return {Date} The date selected135     */136     getValue: function () {137         if (this._picker && this._picker instanceof ux.picker.Time) {138             return this._picker.getValue();139         }140         return this._value;141     },142 143     /**144     * Returns the value of the field formatted using the specified format. If it is not specified, it will default to145     * {@link #dateFormat} and then {@link Ext.util.Format#defaultDateFormat}.146     * @param {String} format The format to be returned.147     * @return {String} The formatted date.148     */149     getFormattedValue: function (format) {150         var value = http://www.mamicode.com/this.getValue();151         return (Ext.isDate(value)) ? Ext.Date.format(value, format || this.getDateFormat() || Ext.util.Format.defaultDateFormat) : value;152     },153 154     applyPicker: function (picker, pickerInstance) {155         if (pickerInstance && pickerInstance.isPicker) {156             picker = pickerInstance.setConfig(picker);157         }158 159         return picker;160     },161 162     getPicker: function () {163         var picker = this._picker,164             value = http://www.mamicode.com/this.getValue();165 166         if (picker && !picker.isPicker) {167             picker = Ext.factory(picker, ux.picker.Time);168             if (value != null) {169                 picker.setValue(value);170             }171         }172 173         picker.on({174             scope: this,175             change: ‘onPickerChange‘,176             hide: ‘onPickerHide‘177         });178 179         this._picker = picker;180 181         return picker;182     },183 184     /**185     * @private186     * Listener to the tap event of the mask element. Shows the internal DatePicker component when the button has been tapped.187     */188     onMaskTap: function () {189         if (this.getDisabled()) {190             return false;191         }192 193         this.onFocus();194 195         return false;196     },197 198     /**199     * Called when the picker changes its value.200     * @param {ux.picker.Time} picker The date picker.201     * @param {Object} value The new value from the date picker.202     * @private203     */204     onPickerChange: function (picker, value) {205         var me = this,206             oldValue =http://www.mamicode.com/ me.getValue();207 208         me.setValue(value);209         me.fireEvent(‘select‘, me, value);210         me.onChange(me, value, oldValue);211     },212 213     /**214     * Override this or change event will be fired twice. change event is fired in updateValue215     * for this field. TOUCH-2861216     */217     onChange: Ext.emptyFn,218 219     /**220     * Destroys the picker when it is hidden, if221     * {@link Ext.field.DatePicker#destroyPickerOnHide destroyPickerOnHide} is set to `true`.222     * @private223     */224     onPickerHide: function () {225         var me = this,226             picker = me.getPicker();227 228         if (me.getDestroyPickerOnHide() && picker) {229             picker.destroy();230             me._picker = me.getInitialConfig().picker || true;231         }232     },233 234     reset: function () {235         this.setValue(this.originalValue);236     },237 238     onFocus: function (e) {239         var component = this.getComponent();240         this.fireEvent(‘focus‘, this, e);241 242         if (Ext.os.is.Android4) {243             component.input.dom.focus();244         }245         component.input.dom.blur();246 247         if (this.getReadOnly()) {248             return false;249         }250 251         this.isFocused = true;252 253         this.getPicker().show();254     },255 256     // @private257     destroy: function () {258         var picker = this._picker;259 260         if (picker && picker.isPicker) {261             picker.destroy();262         }263 264         this.callParent(arguments);265     }266     //<deprecated product=touch since=2.0>267 }, function () {268     this.override({269         getValue: function (format) {270             if (format) {271                 //<debug warn>272                 Ext.Logger.deprecate("format argument of the getValue method is deprecated, please use getFormattedValue instead", this);273                 //</debug>274                 return this.getFormattedValue(format);275             }276             return this.callOverridden();277         }278     });279 280     /**281     * @method getDatePicker282     * @inheritdoc Ext.field.DatePicker#getPicker283     * @deprecated 2.0.0 Please use #getPicker instead284     */285     Ext.deprecateMethod(this, ‘getDatePicker‘, ‘getPicker‘);286     //</deprecated>287 });

效果图:

只需要时、分选项如下:

1             xtype: ‘uxFieldTime‘,2             picker: {3                 slotOrder: [‘hour‘, ‘minute‘]4             },5             dateFormat: ‘H:i‘,6             value: new Date(),7             label: ‘时间:‘,8             placeHolder: ‘请输入时间‘

一些额外的css:

 1 /*#region pick */ 2  3 .x-picker-slot-title { 4     height:auto; 5     text-align:center; 6     padding:0.2em 0; 7 } 8 .x-picker-slot .x-dataview-item { 9     padding:0 8px !important;10 }11 .x-webkit .x-layout-box.x-horizontal > .x-layout-box-item.x-picker-slot {12     width:auto !important;13 }14 /*#endregion*/

 

sencha touch datepicker/datepickerfield(时间选择控件)扩展