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 ...
随机推荐
- 纯CSS3实现的顶部社会化分享按钮
今天要分享一款纯CSS3实现的社会化分享按钮,它放置在网页的顶部,你可以选择将它固定在网页顶部,这样对用户分享内容就十分方便.这些社会化分享按钮的图标文件来自google和bootstrap的字体文件 ...
- win7下命令行提示符从C盘进入E盘的文件夹下
进入E:\papercode\3D-point-cloud-generation-master\3D-point-cloud-generation-master
- Java华氏转摄氏
package test; import java.util.Scanner; public class temperature { public static void main(String[] ...
- JAVA构造方法与方法是啥意思,方法重载方法覆盖俗谈
构造函数跟构造方法是一样的,只是称呼不同; C语言里叫函数,Java里叫方法. 成员方法必须有返回类型即使是没有返回,也要写上void 构造方法没有返回类型,而且和类名一样!一个类里面,一看就知道了譬 ...
- Thinkphp5笔记七:设置错误页面②
更加完美的去设置错误页面. 一.准备一个错误页面 error.html,位置:thinkphp\template\index\default\error.html ,准备把前段所有的错误提示都指向这里 ...
- 【WP8】自定义配置存储类
之前在WP7升级到WP8的时候遇到配置不兼容的问题 情景:之前只有一个WP7版本,现在需要发布WP8版本,让用户可以从原来的WP7版本升级到WP8版本 一般情况下从WP7升级到WP8没什么问题 但是在 ...
- 在Eclipse中查看Javadoc文档
当我们需要查看JDK中类的API介绍时,通常采用的方式是直接查看离线文档或者某些网站提供的在线文档.如下图: 而本文档最终达到的效果是,不需要切换出eclipse,直接在eclipse中查看JDK的J ...
- Spring Boot项目使用Eclipse进行断点调试Debug
1.在命令行下定位到项目根目录,启动Spring Boot项目,命令如下: java -Xdebug -Xrunjdwp:server=y,transport=dt_socket,address=80 ...
- 站长常用的200个js代码 站长常用js代码大全 站长常用js代码集合
站长常用的200个js代码 1.文本框焦点问题 onBlur:当失去输入焦点后产生该事件 onFocus:当输入获得焦点后,产生该文件 Onchange:当文字值改变时,产生该事件 Onselect: ...
- 【Oracle】两个表Join关联更新
两个表关联,用B表的字段更新A表的字段. UPDATE ( SELECT A.COL1 A_COL, B.COL2 B_COL FROM table1 A INNER JOIN table2 B ON ...