首页 > 代码库 > sencha touch datepicker/datepickerfield(时间选择控件)扩展
sencha touch datepicker/datepickerfield(时间选择控件)扩展
参考资料: https://market.sencha.com/extensions/datetimepicker
适用于2.4.1版本
uxPickerTime
使用方法参考:datepicker控件
1 Ext.define(‘ux.picker.Time‘, { 2 extend: ‘Ext.picker.Picker‘, 3 xtype: ‘uxPickerTime‘, 4 alternateClassName: ‘uxPickerTime‘, 5 requires: [‘Ext.DateExtras‘, ‘Ext.util.InputBlocker‘], 6 7 /** 8 * @event change 9 * Fired when the value of this picker has changed and the done button is pressed. 10 * @param {Ext.picker.Date} this This Picker 11 * @param {Date} value The date value 12 */ 13 14 config: { 15 /** 16 * @cfg {Number} yearFrom 17 * 开始年份,如果他比yearTo大,则选择顺序颠倒 18 * @accessor 19 */ 20 yearFrom: 2014, 21 22 /** 23 * @cfg {Number} [yearTo=new Date().getFullYear()] 24 * 结束年份 25 * @accessor 26 */ 27 yearTo: 2000, 28 29 /** 30 * @cfg {String} monthText 31 * 月显示值 32 * @accessor 33 */ 34 monthText: ‘月‘, 35 36 /** 37 * @cfg {String} dayText 38 * 日显示值 39 * @accessor 40 */ 41 dayText: ‘日‘, 42 43 /** 44 * @cfg {String} yearText 45 * 年显示值 46 * @accessor 47 */ 48 yearText: ‘年‘, 49 50 /** 51 * @cfg {String} hourText 52 * 小时显示值 53 */ 54 hourText: ‘时‘, 55 56 /** 57 * @cfg {String} minuteText 58 * 分显示值 59 */ 60 minuteText: ‘分‘, 61 62 /** 63 * @cfg {String} ampmText 64 * 上午/下午显示值 65 */ 66 ampmText: ‘上午/下午‘, 67 /** 68 * @cfg {Array} slotOrder 69 * 默认的选项列表 70 * @accessor 71 */ 72 slotOrder: [‘year‘, ‘month‘, ‘day‘, ‘hour‘, ‘minute‘], // 73 74 /** 75 * @cfg {Int} 76 *分钟间隔 77 * @accessor 78 */ 79 minuteInterval: 1, 80 81 /** 82 * @cfg {Boolean} ampm 83 *是否使用12小时制 84 * @accessor 85 */ 86 ampm: false, 87 useTitles: true 88 }, 89 90 platformConfig: [{ 91 theme: [‘Windows‘], 92 doneButton: { 93 iconCls: ‘check2‘, 94 ui: ‘round‘, 95 text: ‘‘ 96 } 97 }], 98 99 initialize: function () {100 this.callParent();101 102 this.on({103 scope: this,104 delegate: ‘> slot‘,105 slotpick: this.onSlotPick106 });107 108 this.on({109 scope: this,110 show: this.onSlotPick111 });112 },113 114 setValue: function (value, animated) {115 if (Ext.isDate(value)) {116 var ampm = ‘AM‘,117 currentHours = hour = value.getHours();118 if (this.getAmpm()) {119 if (currentHours > 12) {120 ampm = "PM";121 hour -= 12;122 } else if (currentHours == 12) {123 ampm = "PM";124 } else if (currentHours == 0) {125 hour = 12;126 }127 }128 value =http://www.mamicode.com/ {129 day: value.getDate(),130 month: value.getMonth() + 1,131 year: value.getFullYear(),132 hour: hour,133 minute: value.getMinutes(),134 ampm: ampm135 };136 }137 138 this.callParent([value, animated]);139 this.onSlotPick();140 },141 //获取值142 getValue: function (useDom) {143 var values = {},144 items = this.getItems().items,145 ln = items.length,146 daysInMonth, day, month, year, hour, minute, item, i;147 148 for (i = 0; i < ln; i++) {149 item = items[i];150 if (item instanceof Ext.picker.Slot) {151 values[item.getName()] = item.getValue(useDom);152 }153 }154 155 //if all the slots return null, we should not return a date156 if (values.year === null && values.month === null && values.day === null && values.hour === null && values.minute === null) {157 return null;158 }159 160 year = Ext.isNumber(values.year) ? values.year : 1;161 month = Ext.isNumber(values.month) ? values.month : 1;162 day = Ext.isNumber(values.day) ? values.day : 1;163 hour = Ext.isNumber(values.hour) ? values.hour : 1;164 minute = Ext.isNumber(values.minute) ? values.minute : 1;165 166 if (month && year && month && day) {167 daysInMonth = this.getDaysInMonth(month, year);168 }169 day = (daysInMonth) ? Math.min(day, daysInMonth) : day;170 if (values.ampm && values.ampm == "PM" && hour < 12) {171 hour = hour + 12;172 }173 if (values.ampm && values.ampm == "AM" && hour == 12) {174 hour = 0;175 }176 return new Date(year, month - 1, day, hour, minute);177 },178 179 /**180 * Updates the yearFrom configuration181 */182 updateYearFrom: function () {183 if (this.initialized) {184 this.createSlots();185 }186 },187 188 /**189 * Updates the yearTo configuration190 */191 updateYearTo: function () {192 if (this.initialized) {193 this.createSlots();194 }195 },196 197 /**198 * Updates the monthText configuration199 */200 updateMonthText: function (newMonthText, oldMonthText) {201 var innerItems = this.getInnerItems,202 ln = innerItems.length,203 item, i;204 205 //loop through each of the current items and set the title on the correct slice206 if (this.initialized) {207 for (i = 0; i < ln; i++) {208 item = innerItems[i];209 210 if ((typeof item.title == "string" && item.title == oldMonthText) || (item.title.html == oldMonthText)) {211 item.setTitle(newMonthText);212 }213 }214 }215 },216 217 /**218 * Updates the {@link #dayText} configuration.219 */220 updateDayText: function (newDayText, oldDayText) {221 var innerItems = this.getInnerItems,222 ln = innerItems.length,223 item, i;224 225 //loop through each of the current items and set the title on the correct slice226 if (this.initialized) {227 for (i = 0; i < ln; i++) {228 item = innerItems[i];229 230 if ((typeof item.title == "string" && item.title == oldDayText) || (item.title.html == oldDayText)) {231 item.setTitle(newDayText);232 }233 }234 }235 },236 237 /**238 * Updates the yearText configuration239 */240 updateYearText: function (yearText) {241 var innerItems = this.getInnerItems,242 ln = innerItems.length,243 item, i;244 245 //loop through each of the current items and set the title on the correct slice246 if (this.initialized) {247 for (i = 0; i < ln; i++) {248 item = innerItems[i];249 250 if (item.title == this.yearText) {251 item.setTitle(yearText);252 }253 }254 }255 },256 257 // @private258 constructor: function () {259 this.callParent(arguments);260 this.createSlots();261 },262 263 /**264 * Generates all slots for all years specified by this component, and then sets them on the component265 * @private266 */267 createSlots: function () {268 var me = this,269 slotOrder = me.getSlotOrder(),270 yearsFrom = me.getYearFrom(),271 yearsTo = me.getYearTo(),272 years = [],273 days = [],274 months = [],275 hours = [],276 minutes = [],277 ampm = [],278 reverse = yearsFrom > yearsTo,279 ln, i, daysInMonth;280 281 if (!this.getAmpm()) {282 var index = slotOrder.indexOf(‘ampm‘)283 if (index >= 0) {284 slotOrder.splice(index);285 }286 }287 //填充年列表288 while (yearsFrom) {289 years.push({290 text: yearsFrom,291 value: yearsFrom292 });293 294 if (yearsFrom === yearsTo) {295 break;296 }297 298 if (reverse) {299 yearsFrom--;300 } else {301 yearsFrom++;302 }303 }304 //填充天列表305 daysInMonth = me.getDaysInMonth(1, new Date().getFullYear());306 307 for (i = 0; i < daysInMonth; i++) {308 days.push({309 text: i + 1,310 value: i + 1311 });312 }313 //填充月列表314 for (i = 0, ln = Ext.Date.monthNames.length; i < ln; i++) {315 months.push({316 text: Ext.Date.monthNames[i],317 value: i + 1318 });319 }320 //填充小时列表321 var hourLimit = (this.getAmpm()) ? 12 : 23322 var hourStart = (this.getAmpm()) ? 1 : 0323 for (i = hourStart; i <= hourLimit; i++) {324 hours.push({325 text: this.pad2(i),326 value: i327 });328 }329 //填充分钟列表330 for (i = 0; i < 60; i += this.getMinuteInterval()) {331 minutes.push({332 text: this.pad2(i),333 value: i334 });335 }336 //填充上午/下午337 ampm.push({338 text: ‘上午‘,339 value: ‘AM‘340 }, {341 text: ‘下午‘,342 value: ‘PM‘343 });344 345 var slots = [];346 347 slotOrder.forEach(function (item) {348 slots.push(me.createSlot(item, days, months, years, hours, minutes, ampm));349 });350 351 me.setSlots(slots);352 },353 354 /**355 * Returns a slot config for a specified date.356 * @private357 */358 createSlot: function (name, days, months, years, hours, minutes, ampm) {359 switch (name) {360 case ‘year‘:361 return {362 name: ‘year‘,363 align: ‘center‘,364 data: years,365 title: this.getYearText(),366 flex: 3367 };368 case ‘month‘:369 return {370 name: name,371 align: ‘center‘,372 data: months,373 title: this.getMonthText(),374 flex: 3375 };376 case ‘day‘:377 return {378 name: ‘day‘,379 align: ‘center‘,380 data: days,381 width: ‘1px‘,382 title: this.getDayText(),383 flex: 2384 };385 case ‘hour‘:386 return {387 name: ‘hour‘,388 align: ‘center‘,389 data: hours,390 title: this.getHourText(),391 flex: 2392 };393 case ‘minute‘:394 return {395 name: ‘minute‘,396 align: ‘center‘,397 data: minutes,398 title: this.getMinuteText(),399 flex: 2400 };401 case ‘ampm‘:402 return {403 name: ‘ampm‘,404 align: ‘center‘,405 data: ampm,406 title: this.getAmpmText(),407 flex: 2408 };409 }410 },411 412 onSlotPick: function () {413 var value = http://www.mamicode.com/this.getValue(true),414 slot = this.getDaySlot(),415 year = value.getFullYear(),416 month = value.getMonth(),417 days = [],418 daysInMonth, i;419 if (!value || !Ext.isDate(value) || !slot) {420 return;421 }422 423 this.callParent(arguments);424 425 //get the new days of the month for this new date426 daysInMonth = this.getDaysInMonth(month + 1, year);427 for (i = 0; i < daysInMonth; i++) {428 days.push({429 text: i + 1,430 value: i + 1431 });432 }433 // We don‘t need to update the slot days unless it has changed434 if (slot.getStore().getCount() == days.length) {435 return;436 }437 438 slot.getStore().setData(days);439 440 // Now we have the correct amount of days for the day slot, lets update it441 var store = slot.getStore(),442 viewItems = slot.getViewItems(),443 valueField = slot.getValueField(),444 index, item;445 446 index = store.find(valueField, value.getDate());447 if (index == -1) {448 return;449 }450 451 item = Ext.get(viewItems[index]);452 453 slot.selectedIndex = index;454 slot.scrollToItem(item);455 slot.setValue(slot.getValue(true));456 457 458 },459 460 getDaySlot: function () {461 var innerItems = this.getInnerItems(),462 ln = innerItems.length,463 i, slot;464 465 if (this.daySlot) {466 return this.daySlot;467 }468 469 for (i = 0; i < ln; i++) {470 slot = innerItems[i];471 if (slot.isSlot && slot.getName() == "day") {472 this.daySlot = slot;473 return slot;474 }475 }476 477 return null;478 },479 480 // @private481 getDaysInMonth: function (month, year) {482 var daysInMonth = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];483 return month == 2 && this.isLeapYear(year) ? 29 : daysInMonth[month - 1];484 },485 486 // @private487 isLeapYear: function (year) {488 return !!((year & 3) === 0 && (year % 100 || (year % 400 === 0 && year)));489 },490 491 onDoneButtonTap: function () {492 var oldValue = http://www.mamicode.com/this._value,493 newValue = http://www.mamicode.com/this.getValue(true),494 testValue =http://www.mamicode.com/ newValue;495 496 if (Ext.isDate(newValue)) {497 testValue =http://www.mamicode.com/ newValue.toDateString();498 }499 if (Ext.isDate(oldValue)) {500 oldValue =http://www.mamicode.com/ oldValue.toDateString();501 }502 if (testValue != oldValue) {503 this.fireEvent(‘change‘, this, newValue);504 }505 this.hide();506 Ext.util.InputBlocker.unblockInputs();507 },508 pad2: function (number) {509 return (number < 10 ? ‘0‘ : ‘‘) + number;510 }511 });
uxFieldTime
使用方法参考:datepickerfield控件
1 Ext.define(‘ux.field.Time‘, { 2 extend: ‘Ext.field.Text‘, 3 alternateClassName: ‘uxFieldTime‘, 4 xtype: ‘uxFieldTime‘, 5 requires: [ 6 ‘ux.picker.Time‘, 7 ‘Ext.DateExtras‘ 8 ], 9 10 /** 11 * @event change 12 * Fires when a date is selected 13 * @param {Ext.field.DatePicker} this 14 * @param {Date} newDate The new date 15 * @param {Date} oldDate The old date 16 */ 17 18 config: { 19 ui: ‘select‘, 20 21 /** 22 * @cfg {Object/ux.picker.Time} picker 23 * An object that is used when creating the internal {@link ux.picker.Time} component or a direct instance of {@link ux.picker.Time}. 24 * @accessor 25 */ 26 picker: true, 27 28 /** 29 * @cfg {Boolean} 30 * @hide 31 * @accessor 32 */ 33 clearIcon: false, 34 35 /** 36 * @cfg {Object/Date} value 37 * Default value for the field and the internal {@link ux.picker.Time} component. Accepts an object of ‘year‘, 38 * ‘month‘ and ‘day‘ values, all of which should be numbers, or a {@link Date}. 39 * 40 * Example: {year: 1989, day: 1, month: 5} = 1st May 1989 or new Date() 41 * @accessor 42 */ 43 44 45 /** 46 * @cfg {Boolean} destroyPickerOnHide 47 * 完成选择时隐藏或者销毁该控件,默认销毁 48 * @accessor 49 */ 50 destroyPickerOnHide: false, 51 52 /** 53 * @cfg {String} dateFormat 默认时间格式 54 * 接受任何有效的时间格式. 请参考 {@link Ext.Date}. 55 */ 56 dateFormat: ‘Y-m-d H:i‘, 57 58 /** 59 * @cfg {Object} 60 * @hide 61 */ 62 component: { 63 useMask: true 64 } 65 }, 66 67 initialize: function () { 68 var me = this, 69 component = me.getComponent(); 70 71 me.callParent(); 72 73 component.on({ 74 scope: me, 75 masktap: ‘onMaskTap‘ 76 }); 77 78 79 component.doMaskTap = Ext.emptyFn; 80 81 if (Ext.browser.is.AndroidStock2) { 82 component.input.dom.disabled = true; 83 } 84 }, 85 86 syncEmptyCls: Ext.emptyFn, 87 88 applyValue: function (value) { 89 if (!Ext.isDate(value) && !Ext.isObject(value)) { 90 return null; 91 } 92 93 if (Ext.isObject(value)) { 94 return new Date(value.year, value.month - 1, value.day, value.hour, value.minute); 95 } 96 97 return value; 98 }, 99 100 updateValue: function (newValue, oldValue) {101 var me = this,102 picker = me._picker;103 104 if (picker && picker.isPicker) {105 picker.setValue(newValue);106 }107 108 // Ext.Date.format expects a Date109 if (newValue !== null) {110 me.getComponent().setValue(Ext.Date.format(newValue, me.getDateFormat() || Ext.util.Format.defaultDateFormat));111 } else {112 me.getComponent().setValue(‘‘);113 }114 115 if (newValue !== oldValue) {116 me.fireEvent(‘change‘, me, newValue, oldValue);117 }118 },119 120 /**121 * Updates the date format in the field.122 * @private123 */124 updateDateFormat: function (newDateFormat, oldDateFormat) {125 var value = http://www.mamicode.com/this.getValue();126 if (newDateFormat != oldDateFormat && Ext.isDate(value)) {127 this.getComponent().setValue(Ext.Date.format(value, newDateFormat || Ext.util.Format.defaultDateFormat));128 }129 },130 131 /**132 * Returns the {@link Date} value of this field.133 * If you wanted a formated date134 * @return {Date} The date selected135 */136 getValue: function () {137 if (this._picker && this._picker instanceof ux.picker.Time) {138 return this._picker.getValue();139 }140 return this._value;141 },142 143 /**144 * Returns the value of the field formatted using the specified format. If it is not specified, it will default to145 * {@link #dateFormat} and then {@link Ext.util.Format#defaultDateFormat}.146 * @param {String} format The format to be returned.147 * @return {String} The formatted date.148 */149 getFormattedValue: function (format) {150 var value = http://www.mamicode.com/this.getValue();151 return (Ext.isDate(value)) ? Ext.Date.format(value, format || this.getDateFormat() || Ext.util.Format.defaultDateFormat) : value;152 },153 154 applyPicker: function (picker, pickerInstance) {155 if (pickerInstance && pickerInstance.isPicker) {156 picker = pickerInstance.setConfig(picker);157 }158 159 return picker;160 },161 162 getPicker: function () {163 var picker = this._picker,164 value = http://www.mamicode.com/this.getValue();165 166 if (picker && !picker.isPicker) {167 picker = Ext.factory(picker, ux.picker.Time);168 if (value != null) {169 picker.setValue(value);170 }171 }172 173 picker.on({174 scope: this,175 change: ‘onPickerChange‘,176 hide: ‘onPickerHide‘177 });178 179 this._picker = picker;180 181 return picker;182 },183 184 /**185 * @private186 * Listener to the tap event of the mask element. Shows the internal DatePicker component when the button has been tapped.187 */188 onMaskTap: function () {189 if (this.getDisabled()) {190 return false;191 }192 193 this.onFocus();194 195 return false;196 },197 198 /**199 * Called when the picker changes its value.200 * @param {ux.picker.Time} picker The date picker.201 * @param {Object} value The new value from the date picker.202 * @private203 */204 onPickerChange: function (picker, value) {205 var me = this,206 oldValue =http://www.mamicode.com/ me.getValue();207 208 me.setValue(value);209 me.fireEvent(‘select‘, me, value);210 me.onChange(me, value, oldValue);211 },212 213 /**214 * Override this or change event will be fired twice. change event is fired in updateValue215 * for this field. TOUCH-2861216 */217 onChange: Ext.emptyFn,218 219 /**220 * Destroys the picker when it is hidden, if221 * {@link Ext.field.DatePicker#destroyPickerOnHide destroyPickerOnHide} is set to `true`.222 * @private223 */224 onPickerHide: function () {225 var me = this,226 picker = me.getPicker();227 228 if (me.getDestroyPickerOnHide() && picker) {229 picker.destroy();230 me._picker = me.getInitialConfig().picker || true;231 }232 },233 234 reset: function () {235 this.setValue(this.originalValue);236 },237 238 onFocus: function (e) {239 var component = this.getComponent();240 this.fireEvent(‘focus‘, this, e);241 242 if (Ext.os.is.Android4) {243 component.input.dom.focus();244 }245 component.input.dom.blur();246 247 if (this.getReadOnly()) {248 return false;249 }250 251 this.isFocused = true;252 253 this.getPicker().show();254 },255 256 // @private257 destroy: function () {258 var picker = this._picker;259 260 if (picker && picker.isPicker) {261 picker.destroy();262 }263 264 this.callParent(arguments);265 }266 //<deprecated product=touch since=2.0>267 }, function () {268 this.override({269 getValue: function (format) {270 if (format) {271 //<debug warn>272 Ext.Logger.deprecate("format argument of the getValue method is deprecated, please use getFormattedValue instead", this);273 //</debug>274 return this.getFormattedValue(format);275 }276 return this.callOverridden();277 }278 });279 280 /**281 * @method getDatePicker282 * @inheritdoc Ext.field.DatePicker#getPicker283 * @deprecated 2.0.0 Please use #getPicker instead284 */285 Ext.deprecateMethod(this, ‘getDatePicker‘, ‘getPicker‘);286 //</deprecated>287 });
效果图:
只需要时、分选项如下:
1 xtype: ‘uxFieldTime‘,2 picker: {3 slotOrder: [‘hour‘, ‘minute‘]4 },5 dateFormat: ‘H:i‘,6 value: new Date(),7 label: ‘时间:‘,8 placeHolder: ‘请输入时间‘
一些额外的css:
1 /*#region pick */ 2 3 .x-picker-slot-title { 4 height:auto; 5 text-align:center; 6 padding:0.2em 0; 7 } 8 .x-picker-slot .x-dataview-item { 9 padding:0 8px !important;10 }11 .x-webkit .x-layout-box.x-horizontal > .x-layout-box-item.x-picker-slot {12 width:auto !important;13 }14 /*#endregion*/
sencha touch datepicker/datepickerfield(时间选择控件)扩展
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。