基于Extjs6 的带时分秒的日期选择框
首先实现一个带时分秒的picker
Ext.define('W.picker.DateTime', {
extend: 'Ext.picker.Date',
alias: 'widget.w.datetimepicker',
alternateClassName : 'Ext.DateTimePicker',
okText: 'ok',
renderTpl: [
'<div id="{id}-innerEl" data-ref="innerEl" role="presentation">',
'<div class="{baseCls}-header">',
'<div id="{id}-prevEl" data-ref="prevEl" class="{baseCls}-prev {baseCls}-arrow" role="presentation" title="{prevText}"></div>',
'<div id="{id}-middleBtnEl" data-ref="middleBtnEl" class="{baseCls}-month" role="heading">{%this.renderMonthBtn(values, out)%}</div>',
'<div id="{id}-nextEl" data-ref="nextEl" class="{baseCls}-next {baseCls}-arrow" role="presentation" title="{nextText}"></div>',
'</div>',
'<table role="grid" id="{id}-eventEl" data-ref="eventEl" class="{baseCls}-inner" cellspacing="0" tabindex="0" aria-readonly="true">',
'<thead>',
'<tr role="row">',
'<tpl for="dayNames">',
'<th role="columnheader" class="{parent.baseCls}-column-header" aria-label="{.}">',
'<div role="presentation" class="{parent.baseCls}-column-header-inner">{.:this.firstInitial}</div>',
'</th>',
'</tpl>',
'</tr>',
'</thead>',
'<tbody>',
'<tr role="row">',
'<tpl for="days">',
'{#:this.isEndOfWeek}',
'<td role="gridcell">',
'<div hidefocus="on" class="{parent.baseCls}-date"></div>',
'</td>',
'</tpl>',
'</tr>',
'</tbody>',
'</table>',
'<table id="{id}-timeEl" style="table-layout:auto;margin:0 auto;width:90%;text-align:center;" class="x-datepicker-inner" cellspacing="0">',
'<tbody><tr>',
'<td width="30%">{%this.renderHourField(values,out)%}</td>',
'<td width="35%">{%this.renderMinuteField(values,out)%}</td>',
'<td width="35%">{%this.renderSecondField(values,out)%}</td>',
'</tr></tbody>',
'</table>',
'<tpl if="showToday">',
'<div id="{id}-footerEl" data-ref="footerEl" role="presentation" class="{baseCls}-footer">',
'{%this.renderTodayBtn(values, out)%}',
'{%this.renderOkBtn(values, out)%}',
'</div>',
'</tpl>',
'<div id="{id}-todayText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{todayText}.</div>',
'<div id="{id}-ariaMinText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaMinText}.</div>',
'<div id="{id}-ariaMaxText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaMaxText}.</div>',
'<div id="{id}-ariaDisabledDaysText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaDisabledDaysText}.</div>',
'<div id="{id}-ariaDisabledDatesText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaDisabledDatesText}.</div>',
'</div>',
{
firstInitial: function(value) {
return Ext.picker.Date.prototype.getDayInitial(value);
},
isEndOfWeek: function(value) {
value--;
var end = value % 7 === 0 && value !== 0;
return end ? '</tr><tr role="row">' : '';
},
renderTodayBtn: function(values, out) {
Ext.DomHelper.generateMarkup(values.$comp.todayBtn.getRenderTree(), out);
},
renderMonthBtn: function(values, out) {
Ext.DomHelper.generateMarkup(values.$comp.monthBtn.getRenderTree(), out);
},
renderHourField : function(values, out) {
Ext.DomHelper.generateMarkup(values.$comp.hourField
.getRenderTree(), out);
},
renderMinuteField : function(values, out) {
Ext.DomHelper.generateMarkup(values.$comp.minuteField
.getRenderTree(), out);
},
renderSecondField : function(values, out) {
Ext.DomHelper.generateMarkup(values.$comp.secondField
.getRenderTree(), out);
},
renderOkBtn : function(values, out) {
Ext.DomHelper.generateMarkup(values.$comp.okBtn
.getRenderTree(), out);
}
}
],
beforeRender : function() {
var me = this,
encode = Ext.String.htmlEncode,
days = new Array(me.numDays),
today = Ext.Date.format(new Date(), me.format);
if (me.padding && !me.width) {
me.cacheWidth();
}
me.hourField = new Ext.form.field.Number({
ownerCt : me,
ownerLayout : me.getComponentLayout(),
editable: true,
allowDecimals: false,
minValue : 0,
maxValue : 23,
step : 1,
width : '100%',
fieldCls : Ext.baseCSSPrefix + 'form-field w-datetime',
enableKeyEvents : true,
listeners : {
specialkey : function(field, e) {
if (e.getKey() == e.ENTER) {
e.stopEvent();
me.minuteField.focus(true);
}
},
afterrender: function (field, e) {
field.getEl().on('click', function (a, b) {
if (!field.hasFocus) {
}
});
}
}
});
me.minuteField = new Ext.form.field.Number({
ownerCt : me,
ownerLayout : me.getComponentLayout(),
editable: true,
minValue : 0,
maxValue : 59,
allowDecimals: false,
fieldCls : Ext.baseCSSPrefix + 'form-field w-datetime',
step : 1,
width : '100%',
labelWidth : 5,
fieldLabel : ' ',
enableKeyEvents : true,
listeners : {
specialkey : function(field, e) {
if (e.getKey() == e.ENTER) {
e.stopEvent();
me.secondField.focus(true);
}
},
afterrender: function (field, e) {
field.getEl().on('click', function (a, b) {
a.stopPropagation()
if (!field.hasFocus) {
}
});
}
}
});
me.secondField = new Ext.form.field.Number({
ownerCt : me,
ownerLayout : me.getComponentLayout(),
editable: true,
minValue : 0,
maxValue : 59,
allowDecimals: false,
step : 1,
width : '100%',
labelWidth : 5,
fieldLabel : ' ',
fieldCls : Ext.baseCSSPrefix + 'form-field w-datetime',
enableKeyEvents : true,
listeners : {
specialkey : function(field, e) {
if (e.getKey() == e.ENTER) {
e.stopEvent();
me.okBtn.focus(true);
}
},
afterrender: function (field, e) {
field.getEl().on('click', function (a, b) {
if (!field.hasFocus) {
}
});
}
}
});
me.monthBtn = new Ext.button.Split({
ownerCt : me,
ownerLayout : me.getComponentLayout(),
text : '',
tooltip : me.monthYearText,
tabIndex : -1,
ariaRole : 'presentation',
listeners : {
click : me.doShowMonthPicker,
arrowclick : me.doShowMonthPicker,
scope : me
}
});
if (me.showToday) {
me.okBtn = new Ext.button.Button({
ui : me.footerButtonUI,
ownerCt : me,
ownerLayout : me.getComponentLayout(),
text : me.okText,
handler : me.okHandler,
scope : me
});
me.todayBtn = new Ext.button.Button({
ui : me.footerButtonUI,
ownerCt : me,
ownerLayout : me.getComponentLayout(),
tooltipType : 'title',
tabIndex : -1,
ariaRole : 'presentation',
handler : me.selectToday,
scope : me
});
}
me.callParent();
Ext.applyIf(me, {
renderData : {}
});
Ext.apply(me.renderData, {
dayNames : me.dayNames,
showToday : me.showToday,
prevText : encode(me.prevText),
nextText : encode(me.nextText),
todayText : encode(me.todayText),
ariaMinText : encode(me.ariaMinText),
ariaMaxText : encode(me.ariaMaxText),
ariaDisabledDaysText : encode(me.ariaDisabledDaysText),
ariaDisabledDatesText : encode(me.ariaDisabledDatesText),
days : days
});
me.protoEl.unselectable();
},
handleDateClick: function(e, t) {
var me = this;
e.stopEvent();
if (!me.disabled && t.dateValue && !Ext.fly(t.parentNode).hasCls(me.disabledCellCls)) {
var hours = me.value.getHours(),
minutes = me.value.getMinutes(),
seconds = me.value.getSeconds(),
selectedDate = new Date(t.dateValue);
selectedDate.setHours(hours);
selectedDate.setMinutes(minutes);
selectedDate.setSeconds(seconds);
me.setValue(selectedDate);
me.update(selectedDate, true);
}
},
onSelect: function() {
if (this.hideOnSelect) {
this.hide();
}
},
okHandler : function() {
var me = this,
btn = me.okBtn,
handler = me.handler;
if (btn && !btn.disabled) {
me.setValue(this.getValue());
me.fireEvent('select', me, me.value);
me.onSelect();
if (handler) {
Ext.callback(handler, me.scope, [me, me.value], null, me, me);
}
}
},
fullUpdate: function(date) {
this.callParent(arguments);
this.hourField.setValue(date.getHours());
this.minuteField.setValue(date.getMinutes());
this.secondField.setValue(date.getSeconds());
},
selectToday: function() {
var me = this,
btn = me.todayBtn,
handler = me.handler;
if (btn && !btn.disabled) {
var date = new Date();
me.hourField.setValue(date.getHours());
me.minuteField.setValue(date.getMinutes());
me.secondField.setValue(date.getSeconds());
me.setValue(date);
me.fireEvent('select', me, me.value);
if (handler) {
Ext.callback(handler, me.scope, [me, me.value], null, me, me);
}
me.onSelect();
}
return me;
},
update: function(date, forceRefresh) {
this.hourField.setValue(date.getHours());
this.minuteField.setValue(date.getMinutes());
this.secondField.setValue(date.getSeconds());
this.callParent(arguments);
},
setValue : function(value, isfixed) {
var me = this;
this.value = Ext.Date.clone(value || new Date());
if (isfixed !== true) {
this.value.setHours(me.hourField.getValue());
this.value.setMinutes(me.minuteField.getValue());
this.value.setSeconds(me.secondField.getValue());
}
return this.update(this.value, true);
},
onMouseDown: function(e) {
console.log(e);
if (e.target.tagName === 'INPUT' && e.target.id.startsWith('numberfield')) {
} else {
e.preventDefault();
}
},
privates: {
finishRenderChildren : function() {
var me = this;
me.callParent();
me.hourField.finishRender();
me.minuteField.finishRender();
me.secondField.finishRender();
if (me.showToday) {
me.okBtn.finishRender();
}
},
}
});
然后实现field
Ext.define('W.form.field.DateTime', {
extend : 'Ext.form.field.Date',
alias : 'widget.datetimefield',
requires : [ 'W.picker.DateTime' ],
createPicker : function() {
var me = this, format = Ext.String.format;
return new W.picker.DateTime({
pickerField : me,
floating : true,
preventRefocus : true,
hidden : true,
minDate : me.minValue,
maxDate : me.maxValue,
disabledDatesRE : me.disabledDatesRE,
disabledDatesText : me.disabledDatesText,
ariaDisabledDatesText : me.ariaDisabledDatesText,
disabledDays : me.disabledDays,
disabledDaysText : me.disabledDaysText,
ariaDisabledDaysText : me.ariaDisabledDaysText,
format : me.format,
showToday : me.showToday,
startDay : me.startDay,
minText : format(me.minText, me.formatDate(me.minValue)),
ariaMinText : format(me.ariaMinText, me.formatDate(me.minValue,
me.ariaFormat)),
maxText : format(me.maxText, me.formatDate(me.maxValue)),
ariaMaxText : format(me.ariaMaxText, me.formatDate(me.maxValue,
me.ariaFormat)),
listeners : {
scope : me,
select : me.onSelect,
tabout : me.onTabOut
},
keyNavConfig : {
esc : function() {
me.inputEl.focus();
me.collapse();
}
}
});
},
onExpand : function() {
var value = this.rawDate;
this.picker.setValue(Ext.isDate(value) ? value : new Date(), true);
}
})