Extjs4 日期+時分秒組件datetimefield

截止目前最新的Ext-4.2.1.883版本,分別提供日期組件(xtype:'datefield')和時間組件(xtype:'timefield'),卻沒有提供日期+時分秒組件。

搜索到的牛人擴展組件代碼貼下:


1、新建時間選擇器上的時分秒輸入框類TimePickerField.js

/**
 * 時間輸入框, 三個整數框分別輸入時,分,秒.
 * @author wangzilong
 * update Ext - 4.1 2012/04/27
 */
Ext.define('MyApp.ux.TimePickerField', {
      extend: 'Ext.form.field.Base',
      alias: 'widget.timepicker',
      alternateClassName: 'Ext.form.field.TimePickerField',
      requires: ['Ext.form.field.Number'],
      // 隱藏BaseField的輸入框 , hidden basefield's input
      inputType: 'hidden',
      style: 'padding:4px 0 0 0;margin-bottom:0px',
      /**
       * @cfg {String} value
       * initValue, format: 'H:i:s'
       */
      value: null,
      /**
      * @cfg {Object} spinnerCfg
      * 數字輸入框參數, number input config
      */
      spinnerCfg: {
          width: 40
      },
      /** Override. */
      initComponent: function() {
          var me = this;
          me.value = me.value || Ext.Date.format(new Date(), 'H:i:s');
          me.callParent();// called setValue
          me.spinners = [];
          var cfg = Ext.apply({}, me.spinnerCfg, {
                readOnly: me.readOnly,
                disabled: me.disabled,
                style: 'float: left',
                listeners: {
                    change: {
                        fn: me.onSpinnerChange,
                        scope: me
                    }
                }
            });
          me.hoursSpinner = Ext.create('Ext.form.field.Number', Ext.apply({}, cfg, {
                  minValue: 0,
                  maxValue: 23
              }));
          me.minutesSpinner = Ext.create('Ext.form.field.Number', Ext.apply({}, cfg, {
                  minValue: 0,
                  maxValue: 59
              }));
          // TODO 使用timeformat 判斷是否創建秒輸入框, maybe second field is not always need.
          me.secondsSpinner = Ext.create('Ext.form.field.Number', Ext.apply({}, cfg, {
                  minValue: 0,
                  maxValue: 59
              }));
          me.spinners.push(me.hoursSpinner, me.minutesSpinner, me.secondsSpinner);
      },
      /**
          * @private
          * Override.
          */
      onRender: function() {
          var me = this, spinnerWrapDom, spinnerWrap;
          me.callParent(arguments);
          // render to original BaseField input td
          // spinnerWrap = Ext.get(Ext.DomQuery.selectNode('div', this.el.dom)); // 4.0.2
          spinnerWrapDom = Ext.dom.Query.select('td', this.getEl().dom)[1]; // 4.0 ->4.1 div->td
          spinnerWrap = Ext.get(spinnerWrapDom);
          me.callSpinnersFunction('render', spinnerWrap);
          Ext.core.DomHelper.append(spinnerWrap, {
                tag: 'div',
                cls: 'x-form-clear-left'
            });
          this.setRawValue(this.value);
      },
      _valueSplit: function(v) {
          if(Ext.isDate(v)) {
              v = Ext.Date.format(v, 'H:i:s');
          }
          var split = v.split(':');
          return {
              h: split.length > 0 ? split[0] : 0,
              m: split.length > 1 ? split[1] : 0,
              s: split.length > 2 ? split[2] : 0
          };
      },
      onSpinnerChange: function() {
          if(!this.rendered) {
              return;
          }
          this.fireEvent('change', this, this.getValue(), this.getRawValue());
      },
      // 依次調用各輸入框函數, call each spinner's function
      callSpinnersFunction: function(funName, args) {
          for(var i = 0; i < this.spinners.length; i++) {
              this.spinners[i][funName](args);
          }
      },
      // @private get time as object,
      getRawValue: function() {
          if(!this.rendered) {
              var date = this.value || new Date();
              return this._valueSplit(date);
          } else {
              return {
                  h: this.hoursSpinner.getValue(),
                  m: this.minutesSpinner.getValue(),
                  s: this.secondsSpinner.getValue()
              };
          }
      },
      // private
      setRawValue: function(value) {
          value = this._valueSplit(value);
          if(this.hoursSpinner) {
              this.hoursSpinner.setValue(value.h);
              this.minutesSpinner.setValue(value.m);
              this.secondsSpinner.setValue(value.s);
          }
      },
      // overwrite
      getValue: function() {
          var v = this.getRawValue();
          return Ext.String.leftPad(v.h, 2, '0') + ':' + Ext.String.leftPad(v.m, 2, '0') + ':'
            + Ext.String.leftPad(v.s, 2, '0');
      },
      // overwrite
      setValue: function(value) {
          this.value = Ext.isDate(value) ? Ext.Date.format(value, 'H:i:s') : value;
          if(!this.rendered) {
              return;
          }
          this.setRawValue(this.value);
          this.validate();
      },
      // overwrite
      disable: function() {
          this.callParent(arguments);
          this.callSpinnersFunction('disable', arguments);
      },
      // overwrite
      enable: function() {
          this.callParent(arguments);
          this.callSpinnersFunction('enable', arguments);
      },
      // overwrite
      setReadOnly: function() {
          this.callParent(arguments);
          this.callSpinnersFunction('setReadOnly', arguments);
      },
      // overwrite
      clearInvalid: function() {
          this.callParent(arguments);
          this.callSpinnersFunction('clearInvalid', arguments);
      },
      // overwrite
      isValid: function(preventMark) {
          return this.hoursSpinner.isValid(preventMark) && this.minutesSpinner.isValid(preventMark)
            && this.secondsSpinner.isValid(preventMark);
      },
      // overwrite
      validate: function() {
          return this.hoursSpinner.validate() && this.minutesSpinner.validate() && this.secondsSpinner.validate();
      }
  });


2、將日期選擇器datepicker組件擴展成日期時分秒選擇器datetimepicker:

Ext.define('MyApp.ux.DateTimePicker', {
      extend: 'Ext.picker.Date',
      alias: 'widget.datetimepicker',
      todayText: '現在',
      timeLabel: '時間',
      requires: ['MyApp.ux.TimePickerField'],
      initComponent: function() {
          // keep time part for value
          var value = this.value || new Date();
          this.callParent();
          this.value = value;
      },
      onRender: function(container, position) {
          if(!this.timefield) {
              this.timefield = Ext.create('MyApp.ux.TimePickerField', {
                    fieldLabel: this.timeLabel,
                    labelWidth: 40,
                    value: Ext.Date.format(this.value, 'H:i:s')
                });
          }
          this.timefield.ownerCt = this;
          this.timefield.on('change', this.timeChange, this);
          this.callParent(arguments);
          var table = Ext.get(Ext.DomQuery.selectNode('table', this.el.dom));
          var tfEl = Ext.core.DomHelper.insertAfter(table, {
                tag: 'div',
                style: 'border:0px;',
                children: [{
                      tag: 'div',
                      cls: 'x-datepicker-footer ux-timefield'
                  }]
            }, true);
          this.timefield.render(this.el.child('div div.ux-timefield'));
          var p = this.getEl().parent('div.x-layer');
          if(p) {
              p.setStyle("height", p.getHeight() + 31);
          }
      },
      // listener 時間域修改, timefield change
      timeChange: function(tf, time, rawtime) {
          // if(!this.todayKeyListener) { // before render
          this.value = this.fillDateTime(this.value);
          // } else {
          // this.setValue(this.value);
          // }
      },
      // @private
      fillDateTime: function(value) {
          if(this.timefield) {
              var rawtime = this.timefield.getRawValue();
              value.setHours(rawtime.h);
              value.setMinutes(rawtime.m);
              value.setSeconds(rawtime.s);
          }
          return value;
      },
      // @private
      changeTimeFiledValue: function(value) {
          this.timefield.un('change', this.timeChange, this);
          this.timefield.setValue(this.value);
          this.timefield.on('change', this.timeChange, this);
      },
      /* TODO 時間值與輸入框綁定, 考慮: 創建this.timeValue 將日期和時間分開保存. */
      // overwrite
      setValue: function(value) {
          this.value = value;
          this.changeTimeFiledValue(value);
          return this.update(this.value);
      },
      // overwrite
      getValue: function() {
          return this.fillDateTime(this.value);
      },
      // overwrite : fill time before setValue
      handleDateClick: function(e, t) {
          var me = this,
              handler = me.handler;
          e.stopEvent();
          if(!me.disabled && t.dateValue && !Ext.fly(t.parentNode).hasCls(me.disabledCellCls)) {
              me.doCancelFocus = me.focusOnSelect === false;
              me.setValue(this.fillDateTime(new Date(t.dateValue))); // overwrite: fill time before setValue
              delete me.doCancelFocus;
              me.fireEvent('select', me, me.value);
              if(handler) {
                  handler.call(me.scope || me, me, me.value);
              }
              me.onSelect();
          }
      },
      // overwrite : fill time before setValue
      selectToday: function() {
          var me = this,
              btn = me.todayBtn,
              handler = me.handler;
          if(btn && !btn.disabled) {
              // me.setValue(Ext.Date.clearTime(new Date())); //src
              me.setValue(new Date());// overwrite: fill time before setValue
              me.fireEvent('select', me, me.value);
              if(handler) {
                  handler.call(me.scope || me, me, me.value);
              }
              me.onSelect();
          }
          return me;
      }
  });


2、引用日期時分秒選擇器datetimepicker,將日期datefield組件擴展成日期時分秒datetimefield組件:

Ext.Loader.setConfig({enabled:true});
Ext.Loader.setPath('MyApp', '../houtai/js');
Ext.define('MyApp.ux.DateTimeField', {
      extend: 'Ext.form.field.Date',
      alias: 'widget.datetimefield',
      requires: ['MyApp.ux.DateTimePicker'],
      initComponent: function() {
          this.format = this.format;
          this.callParent();
      },
      // overwrite
      createPicker: function() {
          var me = this,
              format = Ext.String.format;
          return Ext.create('MyApp.ux.DateTimePicker', {
                ownerCt: me.ownerCt,
                renderTo: document.body,
                floating: true,
                hidden: true,
                focusOnShow: true,
                minDate: me.minValue,
                maxDate: me.maxValue,
                disabledDatesRE: me.disabledDatesRE,
                disabledDatesText: me.disabledDatesText,
                disabledDays: me.disabledDays,
                disabledDaysText: me.disabledDaysText,
                format: me.format,
                showToday: me.showToday,
                startDay: me.startDay,
                minText: format(me.minText, me.formatDate(me.minValue)),
                maxText: format(me.maxText, me.formatDate(me.maxValue)),
                listeners: {
                    scope: me,
                    select: me.onSelect
                },
                keyNavConfig: {
                    esc: function() {
                        me.collapse();
                    }
                }
            });
      }
  });

3、在form中使用xtype:datetimefield,首先引入擴展類:


requires:'MyApp.ux.DateTimeField',

具體使用:

{
                                xtype:'datetimefield',
                                width : 300,
                                labelWidth : 80,
                                endDateField:'etime',
                                vtype:'daterange',
                                fieldLabel: '記錄時間下限',
                                format: 'Y-m-d H:i:s ',
                                name:'stime'
                            },
                            {
                                xtype:'datetimefield',
                                width : 300,
                                labelWidth : 80,
                                startDateField:'stime',
                                vtype:'daterange',
                                fieldLabel: '記錄時間上限',
                                format: 'Y-m-d H:i:s ',
                                name:'etime'
                            },


4、頁面效果:

152016382.jpg

152018806.jpg

5、使用體驗:

可實現日期時分秒的選擇輸入,但操作體驗略差強人意。如:選擇器上只有'現在'按鈕,若增加‘確定’按鈕,點擊後選擇器消失,日期時分秒值填入框體就好了。現在選非'現在'的精確時間,最後需以點擊日期結束,框體中的年月日時分秒才與選擇器中完全一致。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章