Extjs4 日期+时分秒组件datetimefield

截止目前最新的Ext-4.2.1.883版本,分别提供日期组件(xtype:'datefield')和时间组件(xtype:'timefield'),却没有提供日期+时分秒组件。

搜索到的牛人扩展组件代码贴下:


1、新建时间选择器上的时分秒输入框类TimePickerField.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
/**
  * 时间输入框, 三个整数框分别输入时,分,秒.
  * @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:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
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组件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
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,首先引入扩展类:


1
requires: 'MyApp.ux.DateTimeField' ,

具体使用:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{
                                 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、使用体验:

可实现日期时分秒的选择输入,但操作体验略差强人意。如:选择器上只有'现在'按钮,若增加‘确定’按钮,点击后选择器消失,日期时分秒值填入框体就好了。现在选非'现在'的精确时间,最后需以点击日期结束,框体中的年月日时分秒才与选择器中完全一致。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值