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

适用于2.4.1版本

uxPickerTime

使用方法参考:datepicker控件

 Ext.define('ux.picker.Time', {
extend: 'Ext.picker.Picker',
xtype: 'uxPickerTime',
alternateClassName: 'uxPickerTime',
requires: ['Ext.DateExtras', 'Ext.util.InputBlocker'], /**
* @event change
* Fired when the value of this picker has changed and the done button is pressed.
* @param {Ext.picker.Date} this This Picker
* @param {Date} value The date value
*/ config: {
/**
* @cfg {Number} yearFrom
* 开始年份,如果他比yearTo大,则选择顺序颠倒
* @accessor
*/
yearFrom: 2014, /**
* @cfg {Number} [yearTo=new Date().getFullYear()]
* 结束年份
* @accessor
*/
yearTo: 2000, /**
* @cfg {String} monthText
* 月显示值
* @accessor
*/
monthText: '月', /**
* @cfg {String} dayText
* 日显示值
* @accessor
*/
dayText: '日', /**
* @cfg {String} yearText
* 年显示值
* @accessor
*/
yearText: '年', /**
* @cfg {String} hourText
* 小时显示值
*/
hourText: '时', /**
* @cfg {String} minuteText
* 分显示值
*/
minuteText: '分', /**
* @cfg {String} ampmText
* 上午/下午显示值
*/
ampmText: '上午/下午',
/**
* @cfg {Array} slotOrder
* 默认的选项列表
* @accessor
*/
slotOrder: ['year', 'month', 'day', 'hour', 'minute'], // /**
* @cfg {Int}
*分钟间隔
* @accessor
*/
minuteInterval: 1, /**
* @cfg {Boolean} ampm
*是否使用12小时制
* @accessor
*/
ampm: false,
useTitles: true
}, platformConfig: [{
theme: ['Windows'],
doneButton: {
iconCls: 'check2',
ui: 'round',
text: ''
}
}], initialize: function () {
this.callParent(); this.on({
scope: this,
delegate: '> slot',
slotpick: this.onSlotPick
}); this.on({
scope: this,
show: this.onSlotPick
});
}, setValue: function (value, animated) {
if (Ext.isDate(value)) {
var ampm = 'AM',
currentHours = hour = value.getHours();
if (this.getAmpm()) {
if (currentHours > 12) {
ampm = "PM";
hour -= 12;
} else if (currentHours == 12) {
ampm = "PM";
} else if (currentHours == 0) {
hour = 12;
}
}
value = {
day: value.getDate(),
month: value.getMonth() + 1,
year: value.getFullYear(),
hour: hour,
minute: value.getMinutes(),
ampm: ampm
};
} this.callParent([value, animated]);
this.onSlotPick();
},
//获取值
getValue: function (useDom) {
var values = {},
items = this.getItems().items,
ln = items.length,
daysInMonth, day, month, year, hour, minute, item, i; for (i = 0; i < ln; i++) {
item = items[i];
if (item instanceof Ext.picker.Slot) {
values[item.getName()] = item.getValue(useDom);
}
} //if all the slots return null, we should not return a date
if (values.year === null && values.month === null && values.day === null && values.hour === null && values.minute === null) {
return null;
} year = Ext.isNumber(values.year) ? values.year : 1;
month = Ext.isNumber(values.month) ? values.month : 1;
day = Ext.isNumber(values.day) ? values.day : 1;
hour = Ext.isNumber(values.hour) ? values.hour : 1;
minute = Ext.isNumber(values.minute) ? values.minute : 1; if (month && year && month && day) {
daysInMonth = this.getDaysInMonth(month, year);
}
day = (daysInMonth) ? Math.min(day, daysInMonth) : day;
if (values.ampm && values.ampm == "PM" && hour < 12) {
hour = hour + 12;
}
if (values.ampm && values.ampm == "AM" && hour == 12) {
hour = 0;
}
return new Date(year, month - 1, day, hour, minute);
}, /**
* Updates the yearFrom configuration
*/
updateYearFrom: function () {
if (this.initialized) {
this.createSlots();
}
}, /**
* Updates the yearTo configuration
*/
updateYearTo: function () {
if (this.initialized) {
this.createSlots();
}
}, /**
* Updates the monthText configuration
*/
updateMonthText: function (newMonthText, oldMonthText) {
var innerItems = this.getInnerItems,
ln = innerItems.length,
item, i; //loop through each of the current items and set the title on the correct slice
if (this.initialized) {
for (i = 0; i < ln; i++) {
item = innerItems[i]; if ((typeof item.title == "string" && item.title == oldMonthText) || (item.title.html == oldMonthText)) {
item.setTitle(newMonthText);
}
}
}
}, /**
* Updates the {@link #dayText} configuration.
*/
updateDayText: function (newDayText, oldDayText) {
var innerItems = this.getInnerItems,
ln = innerItems.length,
item, i; //loop through each of the current items and set the title on the correct slice
if (this.initialized) {
for (i = 0; i < ln; i++) {
item = innerItems[i]; if ((typeof item.title == "string" && item.title == oldDayText) || (item.title.html == oldDayText)) {
item.setTitle(newDayText);
}
}
}
}, /**
* Updates the yearText configuration
*/
updateYearText: function (yearText) {
var innerItems = this.getInnerItems,
ln = innerItems.length,
item, i; //loop through each of the current items and set the title on the correct slice
if (this.initialized) {
for (i = 0; i < ln; i++) {
item = innerItems[i]; if (item.title == this.yearText) {
item.setTitle(yearText);
}
}
}
}, // @private
constructor: function () {
this.callParent(arguments);
this.createSlots();
}, /**
* Generates all slots for all years specified by this component, and then sets them on the component
* @private
*/
createSlots: function () {
var me = this,
slotOrder = me.getSlotOrder(),
yearsFrom = me.getYearFrom(),
yearsTo = me.getYearTo(),
years = [],
days = [],
months = [],
hours = [],
minutes = [],
ampm = [],
reverse = yearsFrom > yearsTo,
ln, i, daysInMonth; if (!this.getAmpm()) {
var index = slotOrder.indexOf('ampm')
if (index >= 0) {
slotOrder.splice(index);
}
}
//填充年列表
while (yearsFrom) {
years.push({
text: yearsFrom,
value: yearsFrom
}); if (yearsFrom === yearsTo) {
break;
} if (reverse) {
yearsFrom--;
} else {
yearsFrom++;
}
}
//填充天列表
daysInMonth = me.getDaysInMonth(1, new Date().getFullYear()); for (i = 0; i < daysInMonth; i++) {
days.push({
text: i + 1,
value: i + 1
});
}
//填充月列表
for (i = 0, ln = Ext.Date.monthNames.length; i < ln; i++) {
months.push({
text: Ext.Date.monthNames[i],
value: i + 1
});
}
//填充小时列表
var hourLimit = (this.getAmpm()) ? 12 : 23
var hourStart = (this.getAmpm()) ? 1 : 0
for (i = hourStart; i <= hourLimit; i++) {
hours.push({
text: this.pad2(i),
value: i
});
}
//填充分钟列表
for (i = 0; i < 60; i += this.getMinuteInterval()) {
minutes.push({
text: this.pad2(i),
value: i
});
}
//填充上午/下午
ampm.push({
text: '上午',
value: 'AM'
}, {
text: '下午',
value: 'PM'
}); var slots = []; slotOrder.forEach(function (item) {
slots.push(me.createSlot(item, days, months, years, hours, minutes, ampm));
}); me.setSlots(slots);
}, /**
* Returns a slot config for a specified date.
* @private
*/
createSlot: function (name, days, months, years, hours, minutes, ampm) {
switch (name) {
case 'year':
return {
name: 'year',
align: 'center',
data: years,
title: this.getYearText(),
flex: 3
};
case 'month':
return {
name: name,
align: 'center',
data: months,
title: this.getMonthText(),
flex: 3
};
case 'day':
return {
name: 'day',
align: 'center',
data: days,
width: '1px',
title: this.getDayText(),
flex: 2
};
case 'hour':
return {
name: 'hour',
align: 'center',
data: hours,
title: this.getHourText(),
flex: 2
};
case 'minute':
return {
name: 'minute',
align: 'center',
data: minutes,
title: this.getMinuteText(),
flex: 2
};
case 'ampm':
return {
name: 'ampm',
align: 'center',
data: ampm,
title: this.getAmpmText(),
flex: 2
};
}
}, onSlotPick: function () {
var value = this.getValue(true),
slot = this.getDaySlot(),
year = value.getFullYear(),
month = value.getMonth(),
days = [],
daysInMonth, i;
if (!value || !Ext.isDate(value) || !slot) {
return;
} this.callParent(arguments); //get the new days of the month for this new date
daysInMonth = this.getDaysInMonth(month + 1, year);
for (i = 0; i < daysInMonth; i++) {
days.push({
text: i + 1,
value: i + 1
});
}
// We don't need to update the slot days unless it has changed
if (slot.getStore().getCount() == days.length) {
return;
} slot.getStore().setData(days); // Now we have the correct amount of days for the day slot, lets update it
var store = slot.getStore(),
viewItems = slot.getViewItems(),
valueField = slot.getValueField(),
index, item; index = store.find(valueField, value.getDate());
if (index == -1) {
return;
} item = Ext.get(viewItems[index]); slot.selectedIndex = index;
slot.scrollToItem(item);
slot.setValue(slot.getValue(true)); }, getDaySlot: function () {
var innerItems = this.getInnerItems(),
ln = innerItems.length,
i, slot; if (this.daySlot) {
return this.daySlot;
} for (i = 0; i < ln; i++) {
slot = innerItems[i];
if (slot.isSlot && slot.getName() == "day") {
this.daySlot = slot;
return slot;
}
} return null;
}, // @private
getDaysInMonth: function (month, year) {
var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
return month == 2 && this.isLeapYear(year) ? 29 : daysInMonth[month - 1];
}, // @private
isLeapYear: function (year) {
return !!((year & 3) === 0 && (year % 100 || (year % 400 === 0 && year)));
}, onDoneButtonTap: function () {
var oldValue = this._value,
newValue = this.getValue(true),
testValue = newValue; if (Ext.isDate(newValue)) {
testValue = newValue.toDateString();
}
if (Ext.isDate(oldValue)) {
oldValue = oldValue.toDateString();
}
if (testValue != oldValue) {
this.fireEvent('change', this, newValue);
}
this.hide();
Ext.util.InputBlocker.unblockInputs();
},
pad2: function (number) {
return (number < 10 ? '0' : '') + number;
}
});

uxFieldTime

使用方法参考:datepickerfield控件

 Ext.define('ux.field.Time', {
extend: 'Ext.field.Text',
alternateClassName: 'uxFieldTime',
xtype: 'uxFieldTime',
requires: [
'ux.picker.Time',
'Ext.DateExtras'
], /**
* @event change
* Fires when a date is selected
* @param {Ext.field.DatePicker} this
* @param {Date} newDate The new date
* @param {Date} oldDate The old date
*/ config: {
ui: 'select', /**
* @cfg {Object/ux.picker.Time} picker
* An object that is used when creating the internal {@link ux.picker.Time} component or a direct instance of {@link ux.picker.Time}.
* @accessor
*/
picker: true, /**
* @cfg {Boolean}
* @hide
* @accessor
*/
clearIcon: false, /**
* @cfg {Object/Date} value
* Default value for the field and the internal {@link ux.picker.Time} component. Accepts an object of 'year',
* 'month' and 'day' values, all of which should be numbers, or a {@link Date}.
*
* Example: {year: 1989, day: 1, month: 5} = 1st May 1989 or new Date()
* @accessor
*/ /**
* @cfg {Boolean} destroyPickerOnHide
* 完成选择时隐藏或者销毁该控件,默认销毁
* @accessor
*/
destroyPickerOnHide: false, /**
* @cfg {String} dateFormat 默认时间格式
* 接受任何有效的时间格式. 请参考 {@link Ext.Date}.
*/
dateFormat: 'Y-m-d H:i', /**
* @cfg {Object}
* @hide
*/
component: {
useMask: true
}
}, initialize: function () {
var me = this,
component = me.getComponent(); me.callParent(); component.on({
scope: me,
masktap: 'onMaskTap'
}); component.doMaskTap = Ext.emptyFn; if (Ext.browser.is.AndroidStock2) {
component.input.dom.disabled = true;
}
}, syncEmptyCls: Ext.emptyFn, applyValue: function (value) {
if (!Ext.isDate(value) && !Ext.isObject(value)) {
return null;
} if (Ext.isObject(value)) {
return new Date(value.year, value.month - 1, value.day, value.hour, value.minute);
} return value;
}, updateValue: function (newValue, oldValue) {
var me = this,
picker = me._picker; if (picker && picker.isPicker) {
picker.setValue(newValue);
} // Ext.Date.format expects a Date
if (newValue !== null) {
me.getComponent().setValue(Ext.Date.format(newValue, me.getDateFormat() || Ext.util.Format.defaultDateFormat));
} else {
me.getComponent().setValue('');
} if (newValue !== oldValue) {
me.fireEvent('change', me, newValue, oldValue);
}
}, /**
* Updates the date format in the field.
* @private
*/
updateDateFormat: function (newDateFormat, oldDateFormat) {
var value = this.getValue();
if (newDateFormat != oldDateFormat && Ext.isDate(value)) {
this.getComponent().setValue(Ext.Date.format(value, newDateFormat || Ext.util.Format.defaultDateFormat));
}
}, /**
* Returns the {@link Date} value of this field.
* If you wanted a formated date
* @return {Date} The date selected
*/
getValue: function () {
if (this._picker && this._picker instanceof ux.picker.Time) {
return this._picker.getValue();
}
return this._value;
}, /**
* Returns the value of the field formatted using the specified format. If it is not specified, it will default to
* {@link #dateFormat} and then {@link Ext.util.Format#defaultDateFormat}.
* @param {String} format The format to be returned.
* @return {String} The formatted date.
*/
getFormattedValue: function (format) {
var value = this.getValue();
return (Ext.isDate(value)) ? Ext.Date.format(value, format || this.getDateFormat() || Ext.util.Format.defaultDateFormat) : value;
}, applyPicker: function (picker, pickerInstance) {
if (pickerInstance && pickerInstance.isPicker) {
picker = pickerInstance.setConfig(picker);
} return picker;
}, getPicker: function () {
var picker = this._picker,
value = this.getValue(); if (picker && !picker.isPicker) {
picker = Ext.factory(picker, ux.picker.Time);
if (value != null) {
picker.setValue(value);
}
} picker.on({
scope: this,
change: 'onPickerChange',
hide: 'onPickerHide'
}); this._picker = picker; return picker;
}, /**
* @private
* Listener to the tap event of the mask element. Shows the internal DatePicker component when the button has been tapped.
*/
onMaskTap: function () {
if (this.getDisabled()) {
return false;
} this.onFocus(); return false;
}, /**
* Called when the picker changes its value.
* @param {ux.picker.Time} picker The date picker.
* @param {Object} value The new value from the date picker.
* @private
*/
onPickerChange: function (picker, value) {
var me = this,
oldValue = me.getValue(); me.setValue(value);
me.fireEvent('select', me, value);
me.onChange(me, value, oldValue);
}, /**
* Override this or change event will be fired twice. change event is fired in updateValue
* for this field. TOUCH-2861
*/
onChange: Ext.emptyFn, /**
* Destroys the picker when it is hidden, if
* {@link Ext.field.DatePicker#destroyPickerOnHide destroyPickerOnHide} is set to `true`.
* @private
*/
onPickerHide: function () {
var me = this,
picker = me.getPicker(); if (me.getDestroyPickerOnHide() && picker) {
picker.destroy();
me._picker = me.getInitialConfig().picker || true;
}
}, reset: function () {
this.setValue(this.originalValue);
}, onFocus: function (e) {
var component = this.getComponent();
this.fireEvent('focus', this, e); if (Ext.os.is.Android4) {
component.input.dom.focus();
}
component.input.dom.blur(); if (this.getReadOnly()) {
return false;
} this.isFocused = true; this.getPicker().show();
}, // @private
destroy: function () {
var picker = this._picker; if (picker && picker.isPicker) {
picker.destroy();
} this.callParent(arguments);
}
//<deprecated product=touch since=2.0>
}, function () {
this.override({
getValue: function (format) {
if (format) {
//<debug warn>
Ext.Logger.deprecate("format argument of the getValue method is deprecated, please use getFormattedValue instead", this);
//</debug>
return this.getFormattedValue(format);
}
return this.callOverridden();
}
}); /**
* @method getDatePicker
* @inheritdoc Ext.field.DatePicker#getPicker
* @deprecated 2.0.0 Please use #getPicker instead
*/
Ext.deprecateMethod(this, 'getDatePicker', 'getPicker');
//</deprecated>
});

效果图:

只需要时、分选项如下:

             xtype: 'uxFieldTime',
picker: {
slotOrder: ['hour', 'minute']
},
dateFormat: 'H:i',
value: new Date(),
label: '时间:',
placeHolder: '请输入时间'

一些额外的css:

 /*#region pick */

 .x-picker-slot-title {
height:auto;
text-align:center;
padding:0.2em 0;
}
.x-picker-slot .x-dataview-item {
padding:0 8px !important;
}
.x-webkit .x-layout-box.x-horizontal > .x-layout-box-item.x-picker-slot {
width:auto !important;
}
/*#endregion*/

sencha touch datepicker/datepickerfield(时间选择控件)扩展的更多相关文章

  1. sencha touch datepicker/datepickerfield(时间选择控件)扩展(废弃 仅参考)

    参考资料:https://market.sencha.com/extensions/datetimepicker 上面的扩展在2.2有些问题,参考源码重新写了一个 TimePicker: Ext.de ...

  2. 基于zepto的移动端日期和时间选择控件

    前段时间给大家分享过一个基于jQuery Mobile的移动端日期时间拾取器,大家反应其由于加载过大的插件导致影响调用速度.那么今天我把从网络上搜集到的两个适合移动端应用的日期和时间选择插件分享给大家 ...

  3. wpf timePicker 时间选择控件

    wpf里有日期选择控件,但没有时间选择控件.其他地方也有类似的,但效果并不太好,而且复杂.所以就自己写了个.参考codeproject上的. 分两部分. 第一部分是.cs文件.也就是control控件 ...

  4. 共享MFC每周时间选择控件代码

    自己写的周时间选择控件,原理就是在Static上用GDI画图. 支持选择每周内每一天内的任意时间段,可以任意拖动修改时间段,任意合并时间段 效果如下图: VS2012代码下载:https://gith ...

  5. WinForm时间选择控件(DateTimePicker)如何选择(显示)时分秒

    C# Windows窗体应用中,用到时间选择控件DateTimePicker,发现不能选择时分秒,难道要自己写一个控件?! 答案是否定的,通过属性修改是可以选择时间的,DateTimePicker完全 ...

  6. 给easyui datebox时间框控件扩展一个清空的实例

    给easyui datebox扩展一个清空的实例 步骤一:拓展插件 /** * 给时间框控件扩展一个清除的按钮 */ $.fn.datebox.defaults.cleanText = '清空'; ( ...

  7. Extjs DateTime 日期时间选择控件 (非点击日期强制选择) 支持4.0以上

    Extjs的日期控件,仅仅能支持到日期选择,对时间的选择并不完好.而网上下载的控件,都是基于Ext.form.dateField 开发.在选中日期后自己主动选择,并隐藏此选择窗体. 在经过一番改造后, ...

  8. bootstrap-datetimepicker:基于twitter bootstrap的日期/时间选择控件

    bootstrap-datetimepicker是一个基于twitter bootstrap的简单日期/时间选择控件. <!DOCTYPE HTML> <html> <h ...

  9. 2019-8-30-win10-uwp-好看的时间选择控件

    title author date CreateTime categories win10 uwp 好看的时间选择控件 lindexi 2019-08-30 08:57:20 +0800 2018-0 ...

随机推荐

  1. 利用Delphi编写IE扩展

    就是如何使IE扩展组件可以响应事件.    在自己的程序中使用过WebBrowser控件的朋友都知道,WebBrowser控件定义了诸如BeforeNavigate.DownloadComplete ...

  2. YUV 4:2:0 格式和YUV411格式区别

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/coloriy/article/details/6668447 MPEG 储存的 YU(Cb)V(Cr ...

  3. [leetcode]Unique Paths II @ Python

    原题地址:https://oj.leetcode.com/problems/unique-paths-ii/ 题意: Follow up for "Unique Paths": N ...

  4. OpenGL核心技术之HDR

    笔者介绍:姜雪伟.IT公司技术合伙人,IT高级讲师,CSDN社区专家.特邀编辑,畅销书作者.国家专利发明人;已出版书籍:<手把手教你架构3D游戏引擎>电子工业出版社和<Unity3D ...

  5. 微软BI 之SSIS 系列 - 在 SSIS 输出平面文件时根据运行日期生成不同的文件名称

    开篇介绍 在 SSIS 中操作文件的输入和输出是非常方便的,这个例子讲解一个最简单的需求:比如每天从数据库中查询一批数据要输出到文件,每天产生一个文件,那么文件的名称按照"文件名+日期&qu ...

  6. Eclipse 插件开发 -- 深入理解菜单(Menu)功能及其扩展点( FROM IBM)

    Eclipse 插件开发 -- 深入理解菜单(Menu)功能及其扩展点 菜单是各种软件及开发平台会提供的必备功能,Eclipse 也不例外,提供了丰富的菜单,包括主菜单(Main Menu),视图 / ...

  7. Notes中几个处理多值域的通用函数

    1.查找出查找内容在多值域中的索引值 getItemIndex(域名,域值,文档) Public Function getItemIndex(ByVal fieldName As String, By ...

  8. mysql和redis的区别

    一..redis和mysql的区别总结 (1)类型上         从类型上来说,mysql是关系型数据库,redis是缓存数据库 (2)作用上        mysql用于持久化的存储数据到硬盘, ...

  9. Failed to execute goal org.mybatis.generator:mybatis-generator-maven-plugin:1.3.2:generate

    (1)将Maven项目先clean,接着install下 (2)运行mvn mybatis-generator:generate命令 注意修改generatorConfig.xml的location: ...

  10. R8500 MPv2 版本 刷 Kong编译的 ddwrt 后,使用Entware-ng 安装opkg安装第三方软件

    先说R8500吧. 由于Netgear网件的问题导致R8500在去年双11前夕出现了全球范围的Boot Loop的问题,现象为新设备开机一段时间后,路由器进入不停重启的状态,电源灯桔黄色.在和网件工程 ...