zoukankan      html  css  js  c++  java
  • sencha touch datepicker/datepickerfield(时间选择控件)扩展(废弃 仅参考)

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

    上面的扩展在2.2有些问题,参考源码重新写了一个

    TimePicker:

      1 Ext.define('ux.TimePicker', {
      2     extend: 'Ext.picker.Picker',
      3     xtype: 'timePicker',
      4     alternateClassName: 'timePicker',
      5     requires: ['Ext.DateExtras'],
      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: 1980,
     21 
     22         /**
     23         * @cfg {Number} [yearTo=new Date().getFullYear()]
     24         * 结束年份
     25         * @accessor
     26         */
     27         yearTo: new Date().getFullYear(),
     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.onSlotPick
    106         });
    107 
    108         this.on({
    109             scope: this,
    110             show: this.onSlotPick
    111         });
    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 = {
    129                 day: value.getDate(),
    130                 month: value.getMonth() + 1,
    131                 year: value.getFullYear(),
    132                 hour: hour,
    133                 minute: value.getMinutes(),
    134                 ampm: ampm
    135             };
    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 date
    156         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 configuration
    181     */
    182     updateYearFrom: function () {
    183         if (this.initialized) {
    184             this.createSlots();
    185         }
    186     },
    187 
    188     /**
    189     * Updates the yearTo configuration
    190     */
    191     updateYearTo: function () {
    192         if (this.initialized) {
    193             this.createSlots();
    194         }
    195     },
    196 
    197     /**
    198     * Updates the monthText configuration
    199     */
    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 slice
    206         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 slice
    226         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 configuration
    239     */
    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 slice
    246         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     // @private
    258     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 component
    265     * @private
    266     */
    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: yearsFrom
    292             });
    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 + 1
    311             });
    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 + 1
    318             });
    319         }
    320         //填充小时列表
    321         var hourLimit = (this.getAmpm()) ? 12 : 23
    322         var hourStart = (this.getAmpm()) ? 1 : 0
    323         for (i = hourStart; i <= hourLimit; i++) {
    324             hours.push({
    325                 text: this.pad2(i),
    326                 value: i
    327             });
    328         }
    329         //填充分钟列表
    330         for (i = 0; i < 60; i += this.getMinuteInterval()) {
    331             minutes.push({
    332                 text: this.pad2(i),
    333                 value: i
    334             });
    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     * @private
    357     */
    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: 3
    367                 };
    368             case 'month':
    369                 return {
    370                     name: name,
    371                     align: 'center',
    372                     data: months,
    373                     title: this.getMonthText(),
    374                     flex: 4
    375                 };
    376             case 'day':
    377                 return {
    378                     name: 'day',
    379                     align: 'center',
    380                     data: days,
    381                      '1px',
    382                     title: this.getDayText(),
    383                     flex: 2
    384                 };
    385             case 'hour':
    386                 return {
    387                     name: 'hour',
    388                     align: 'center',
    389                     data: hours,
    390                     title: this.getHourText(),
    391                     flex: 2
    392                 };
    393             case 'minute':
    394                 return {
    395                     name: 'minute',
    396                     align: 'center',
    397                     data: minutes,
    398                     title: this.getMinuteText(),
    399                     flex: 2
    400                 };
    401             case 'ampm':
    402                 return {
    403                     name: 'ampm',
    404                     align: 'center',
    405                     data: ampm,
    406                     title: this.getAmpmText(),
    407                     flex: 2
    408                 };
    409         }
    410     },
    411 
    412     onSlotPick: function () {
    413         var value = 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 date
    426         daysInMonth = this.getDaysInMonth(month + 1, year);
    427         for (i = 0; i < daysInMonth; i++) {
    428             days.push({
    429                 text: i + 1,
    430                 value: i + 1
    431             });
    432         }
    433         // We don't need to update the slot days unless it has changed
    434         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 it
    441         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     // @private
    481     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     // @private
    487     isLeapYear: function (year) {
    488         return !!((year & 3) === 0 && (year % 100 || (year % 400 === 0 && year)));
    489     },
    490 
    491     onDoneButtonTap: function () {
    492         var oldValue = this._value,
    493             newValue = this.getValue(true),
    494             testValue = newValue;
    495 
    496         if (Ext.isDate(newValue)) {
    497             testValue = newValue.toDateString();
    498         }
    499         if (Ext.isDate(oldValue)) {
    500             oldValue = oldValue.toDateString();
    501         }
    502         if (testValue != oldValue) {
    503             this.fireEvent('change', this, newValue);
    504         }
    505         this.hide();
    506         this.inputBlocker.unblockInputs();
    507     },
    508     pad2: function (number) {
    509         return (number < 10 ? '0' : '') + number;
    510     }
    511 });

    使用方法参考:datepicker控件

    timefield:

      1 Ext.define('ux.Timefield', {
      2     extend: 'Ext.field.Text',
      3     alternateClassName: 'timefield',
      4     xtype: 'timefield',
      5     requires: [
      6         'ux.TimePicker',
      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.TimePicker} picker
     23         * An object that is used when creating the internal {@link ux.TimePicker} component or a direct instance of {@link ux.TimePicker}.
     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.TimePicker} 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 Date
    109         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     * @private
    123     */
    124     updateDateFormat: function (newDateFormat, oldDateFormat) {
    125         var value = 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 date
    134     * @return {Date} The date selected
    135     */
    136     getValue: function () {
    137         if (this._picker && this._picker instanceof ux.TimePicker) {
    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 to
    145     * {@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 = 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 = this.getValue();
    165 
    166         if (picker && !picker.isPicker) {
    167             picker = Ext.factory(picker, ux.TimePicker);
    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     * @private
    186     * 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.TimePicker} picker The date picker.
    201     * @param {Object} value The new value from the date picker.
    202     * @private
    203     */
    204     onPickerChange: function (picker, value) {
    205         var me = this,
    206             oldValue = 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 updateValue
    215     * for this field. TOUCH-2861
    216     */
    217     onChange: Ext.emptyFn,
    218 
    219     /**
    220     * Destroys the picker when it is hidden, if
    221     * {@link Ext.field.DatePicker#destroyPickerOnHide destroyPickerOnHide} is set to `true`.
    222     * @private
    223     */
    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     // @private
    257     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 getDatePicker
    282     * @inheritdoc Ext.field.DatePicker#getPicker
    283     * @deprecated 2.0.0 Please use #getPicker instead
    284     */
    285     Ext.deprecateMethod(this, 'getDatePicker', 'getPicker');
    286     //</deprecated>
    287 });

    使用方法参考datepickerfield控件

    效果图:

    只需要时、分选项如下:

    1             xtype: 'timefield',
    2             picker: {
    3                 slotOrder: ['hour', 'minute']
    4             },
    5             dateFormat: 'H:i',
    6             value: new Date()

    一些额外的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*/
  • 相关阅读:
    超级小白使用pip安装第三方库的正确姿势
    selenium+python自动化测试--解决无法启动IE浏览器及报错问题
    microsoft edge浏览器安装驱动
    超详细MySQL安装及基本使用教程
    Navicat15最新版本破解 亲测可用!!!
    Ubuntu 16.04安装JMeter测试工具
    JMeter_Ubuntu上安装jmeter
    韩国vps推荐-kdatacenter
    全栈之js入门篇
    Web前端之CSS_day5
  • 原文地址:https://www.cnblogs.com/mlzs/p/3324677.html
Copyright © 2011-2022 走看看