Extjs4 日期+时分秒组件datetimefield

论坛 期权论坛 编程之家     
选择匿名的用户   2021-6-2 17:34   2065   0

截止目前最新的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 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:3875789
帖子:775174
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP