sencha touch datepicker/datepickerfield(时间选择控件)扩展(废弃 仅参考)
参考资料:
https://market.sencha.com/extensions/datetimepicker
上面的扩展在2.2有些问题,参考源码重新写了一个
TimePicker:
Ext.define('ux.TimePicker', {
extend: 'Ext.picker.Picker',
xtype: 'timePicker',
alternateClassName: 'timePicker',
requires: ['Ext.DateExtras'],
/**
* @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: 1980,
/**
* @cfg {Number} [yearTo=new Date().getFullYear()]
* 结束年份
* @accessor
*/
yearTo: new Date().getFullYear(),
/**
* @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: 4
};
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();
this.inputBlocker.unblockInputs();
},
pad2: function (number) {
return (number < 10 ? '0' : '') + number;
}
});
使用方法参考:datepicker控件
timefield:
Ext.define('ux.Timefield', {
extend: 'Ext.field.Text',
alternateClassName: 'timefield',
xtype: 'timefield',
requires: [
'ux.TimePicker',
'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.TimePicker} picker
* An object that is used when creating the internal {@link ux.TimePicker} component or a direct instance of {@link ux.TimePicker}.
* @accessor
*/
picker: true,
/**
* @cfg {Boolean}
* @hide
* @accessor
*/
clearIcon: false,
/**
* @cfg {Object/Date} value
* Default value for the field and the internal {@link ux.TimePicker} 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.TimePicker) {
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.TimePicker);
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.TimePicker} 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>
});
使用方法参考datepickerfield控件
效果图:

只需要时、分选项如下:
xtype: 'timefield',
picker: {
slotOrder: ['hour', 'minute']
},
dateFormat: 'H:i',
value: new Date()

一些额外的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(时间选择控件)扩展(废弃 仅参考)的更多相关文章
- sencha touch datepicker/datepickerfield(时间选择控件)扩展
参考资料: https://market.sencha.com/extensions/datetimepicker 适用于2.4.1版本 uxPickerTime 使用方法参考:datepicker控 ...
- sencha touch 我的公用类myUtil(废弃 仅参考)
/*公共类*/ Ext.define('myUtil', { statics: { //store公用加载方法 storeLoadById: function (id) { var store = E ...
- 基于zepto的移动端日期和时间选择控件
前段时间给大家分享过一个基于jQuery Mobile的移动端日期时间拾取器,大家反应其由于加载过大的插件导致影响调用速度.那么今天我把从网络上搜集到的两个适合移动端应用的日期和时间选择插件分享给大家 ...
- wpf timePicker 时间选择控件
wpf里有日期选择控件,但没有时间选择控件.其他地方也有类似的,但效果并不太好,而且复杂.所以就自己写了个.参考codeproject上的. 分两部分. 第一部分是.cs文件.也就是control控件 ...
- 共享MFC每周时间选择控件代码
自己写的周时间选择控件,原理就是在Static上用GDI画图. 支持选择每周内每一天内的任意时间段,可以任意拖动修改时间段,任意合并时间段 效果如下图: VS2012代码下载:https://gith ...
- WinForm时间选择控件(DateTimePicker)如何选择(显示)时分秒
C# Windows窗体应用中,用到时间选择控件DateTimePicker,发现不能选择时分秒,难道要自己写一个控件?! 答案是否定的,通过属性修改是可以选择时间的,DateTimePicker完全 ...
- 给easyui datebox时间框控件扩展一个清空的实例
给easyui datebox扩展一个清空的实例 步骤一:拓展插件 /** * 给时间框控件扩展一个清除的按钮 */ $.fn.datebox.defaults.cleanText = '清空'; ( ...
- Extjs DateTime 日期时间选择控件 (非点击日期强制选择) 支持4.0以上
Extjs的日期控件,仅仅能支持到日期选择,对时间的选择并不完好.而网上下载的控件,都是基于Ext.form.dateField 开发.在选中日期后自己主动选择,并隐藏此选择窗体. 在经过一番改造后, ...
- bootstrap-datetimepicker:基于twitter bootstrap的日期/时间选择控件
bootstrap-datetimepicker是一个基于twitter bootstrap的简单日期/时间选择控件. <!DOCTYPE HTML> <html> <h ...
随机推荐
- linux 上安裝lnmp
1.確保有一台服務器可以正常運行 2.熟練知道一些基本的命令 3.這裡我以lnmp集成環境為例 https://lnmp.org/install.html 4.安裝大約30分鐘左右 5.安裝完畢,訪問 ...
- Fedora更改密码
开机进入单用户模式 按e --->进入编辑界面之后,在“rhgb quiet”字符前面,输入“single”加空格,回车-->返回上一步中启动命令行菜单. 按 b ---> pas ...
- 百度编辑器插入视频、iframe 失败
插入失败是因为编辑器的xssFilter过滤,导致插入出现异常 文件位置:ueditor.config.js ,大概在428行加上 video: ['autoplay', 'controls', 'l ...
- UNIX环境编程学习笔记(12)——文件I/O之目录操作
lienhua342014-09-18 1 引言 在 UNIX 系统中,目录是一种特殊的文件类型.我们可以使用 open 函数来打开目录,获取文件描述符,然后调用 stat 函数来获取目录的属性信息, ...
- Java编程思想学习笔记——访问权限修饰词
几种访问权限修饰词 public,protected,private,friendly(Java中并无该修饰词,即包访问权限,不提供任何访问修饰词) 使用时,放置在类中成员(域或方法)的定义之前的,仅 ...
- Unity UGUI 的RectTransform参数的设置
1.改变RectTransform的top GetComponent<RectTransform>().offsetMax = new Vector2(GetComponent<Re ...
- linux中如何对一个文件的内容进行处理,文件中每行有多个字段的值,中间用空格分隔开?
需求描述: 今天在帮同事看个需求,将操作系统上的文件进行修改名字,改为特定的名字,所以呢,就先把这些原名字及对应的新名字关系放到了一个文本中,对于这个文本执行循环. 文件格式如下: .00000005 ...
- oracle自定义类型 示例
) ); ---自定义类型传参给存储过程,示例如下: create or replace procedure dropWf is cursor c_tenant is and t.id not in ...
- tomcat启动时出现了Failed to start component [StandardEngine[Catalina].StandardHost[localhost]]
https://blog.csdn.net/imjcoder/article/details/78725267 <dependency> <groupId>org.spring ...
- c++运算符重载---20
原创博文,转载请标明出处--周学伟 http://www.cnblogs.com/zxouxuewei/ c++的一大特性就是重载(overload),通过重载可以把功能相似的几个函数合为一个,使得程 ...