ExtJS自定义控件 之一:datetimefield控件
来源:互联网 发布:大数据 感知 编辑:程序博客网 时间:2024/06/18 05:05
这一年都在使用ExtJS 5.0开发系统,经常会遇到的一个场景就是时间日期的选择了。比如说,预定场地的时候就必须由用户选择预定的日期和时间。
可惜的是,ExtJS 5.0没有自带一个可以同时选择日期时间的控件(ExtJS 6.0已经推出了,还没用过,不知道加入这种控件没~),通常偷懒的做法就是,先放一个日期控件,然后再放一个时间控件。用户使用的时候,先选择日期,再选择时间,最后用很别扭的办法将日期和时间拼装起来。
理想的状态是,提供给用户一个可以同时选择时间和日期的控件,并且数据是“日期+时间”的Date类型。既符合使用习惯,又方便开发。
故第二种偷懒的方式是,从网上扒一个现成的解决方案来用。此法最快,但是在过程中遇到了一个问题,现成可以搜索到的方案都有点旧,大多数还停留在ExtJS 2.X、3.X和4.X版本,自从ExtJS从4升级到5之后,API改变了许多,所以并不能直接使用。
最后只能是自己写一个。准确来说,应该是拿了一份现成的代码修改,这个代码在ExtJS 5.0下不能正确运行,但是需要修改的量非常少,所以很感谢这份现成代码的作者,可惜没有署名,不知道是谁。
ExtJS 5.0上测试成功,实现方法是:
1、自定义一个时间选择器TimePickerField,继承自Ext.form.field.Base,由三个NumberField组成。
Ext.define('MyApp.ux.DateTimeField.TimePickerField', { extend: 'Ext.form.field.Base', alias: 'widget.timepicker', alternateClassName: 'Ext.form.field.TimePickerField', requires: ['Ext.form.field.Number'], inputType: 'text', fieldLabel: '时间', labelWidth: 40, style: 'padding:4px 0; margin: 0; ', value: null, spinnerCfg: { width: 50, }, initComponent: function() { var me = this; me.value = me.value || Ext.Date.format(new Date(), 'H:i:s'); me.callParent(arguments); me.spinners = []; var cfg = Ext.apply({}, me.spinnerCfg, { // readOnly: me.readOnly, disabled: me.disabled, style: 'float: left', listeners: { change: { fn: me.onSpinnerChange, scope: me } } }); me.hoursSpinner = Ext.create('Ext.form.field.Number', Ext.apply({}, cfg, { // minValue: -1, // maxValue: 24, minNum: 0, maxNum: 23, })); me.minutesSpinner = Ext.create('Ext.form.field.Number', Ext.apply({}, cfg, { // minValue: -1, // maxValue: 60, minNum: 0, maxNum: 59, })); me.secondsSpinner = Ext.create('Ext.form.field.Number', Ext.apply({}, cfg, { // minValue: -1, // MAXVALUE: 60, minNum: 0, maxNum: 59, })); me.spinners.push(me.hoursSpinner, me.minutesSpinner, me.secondsSpinner); }, onRender: function() { var me = this, spinnerWrapDom, spinnerWrap; me.callParent(arguments); spinnerWrap = Ext.get(Ext.DomQuery.selectNode('div', this.el.dom)); me.callSpinnersFunction('render', spinnerWrap); this.el.dom.getElementsByTagName('input')[0].style.display = 'none'; var newTimePicker = Ext.DomHelper.append(spinnerWrap, { tag: 'div', cls: 'x-form-clear-left' }, true); this.setRawValue(this.value); }, _valueSplit: function(v) { if(Ext.isDate(v)) { v = Ext.Date.format(v, 'H:i:s'); } var split = v.split(':'); return { h: split.length > 0 ? split[0] : 0, m: split.length > 1 ? split[1] : 0, s: split.length > 2 ? split[2] : 0 }; }, onSpinnerChange: function() { if(!this.rendered) { return; } //限制时间范围 var args = arguments; //this, newValue, oldValue, eOpts args[0].setValue( (args[1]>args[0].maxNum) ? args[0].minNum : args[0].value ); args[0].setValue( (args[1]<args[0].minNum) ? args[0].maxNum : args[0].value ); this.fireEvent('change', this, this.getValue(), this.getRawValue()); }, // 依次调用各输入框函数, call each spinner's function callSpinnersFunction: function(funName, args) { for(var i = 0; i < this.spinners.length; i++) { if( this.spinners[i][funName] != null && this.spinners[i][funName] != undefined ){ this.spinners[i][funName](args); } } }, getRawValue: function() { if(!this.rendered) { var date = this.value || new Date(); return this._valueSplit(date); } else { return { h: this.hoursSpinner.getValue(), m: this.minutesSpinner.getValue(), s: this.secondsSpinner.getValue() }; } }, setRawValue: function(value) { var v = this._valueSplit(value); if(this.hoursSpinner) { this.hoursSpinner.setValue(v.h); this.minutesSpinner.setValue(v.m); this.secondsSpinner.setValue(v.s); } }, getValue: function() { var v = this.getRawValue(); return Ext.String.leftPad(v.h, 2, '0') + ':' + Ext.String.leftPad(v.m, 2, '0') + ':' + Ext.String.leftPad(v.s, 2, '0'); }, setValue: function(value) { this.value = Ext.isDate(value) ? Ext.Date.format(value, 'H:i:s') : value; if(!this.rendered) { return; } this.setRawValue(this.value); this.validate(); }, disable: function() { this.callParent(arguments); this.callSpinnersFunction('disable', arguments); }, enable: function() { this.callParent(arguments); this.callSpinnersFunction('enable', arguments); }, setReadOnly: function() { this.callParent(arguments); this.callSpinnersFunction('setReadOnly', arguments); }, clearInvalid: function() { this.callParent(arguments); this.callSpinnersFunction('clearInvalid', arguments); }, isValid: function(preventMark) { return this.hoursSpinner.isValid(preventMark) && this.minutesSpinner.isValid(preventMark) && this.secondsSpinner.isValid(preventMark); }, validate: function() { return this.hoursSpinner.validate() && this.minutesSpinner.validate() && this.secondsSpinner.validate(); } });
2、自定义一个DateTimePicker,继承自Ext.picker.Date,实际上就是在原有的DateField的基础上增加TimePicker和一个确认按键。
Ext.define('MyApp.ux.DateTimeField.DateTimePicker', { extend: 'Ext.picker.Date', alias: 'widget.datetimepicker', requires: ['MyApp.ux.DateTimeField.TimePickerField','Ext.dom.Query'], todayText: '现在', timeLabel: '时间', buttonText: '确定', initComponent: function() { this.callParent(); this.value = this.value || new Date(); }, onRender: function(container, position) { this.callParent(arguments); var me = this; //确认按键 var btnCfg = Ext.apply({}, {}, { style: 'center', listeners: { click: { fn: function(){ this.confirmDate(); }, scope: me } } }); me.confirmBtn = Ext.create('Ext.Button', Ext.apply({}, btnCfg, { text: '确认', })); me.confirmBtn.render(this.el.child('div div.x-datepicker-footer')); if(!this.timefield) { this.timefield = Ext.create('MyApp.ux.DateTimeField.TimePickerField', { fieldLabel: this.timeLabel, labelWidth: 40, value: Ext.Date.format(this.value, 'H:i:s'), }); } this.timefield.ownerCt = this;//指定范围 this.timefield.on('change', this.timeChange, this);// var table = Ext.get(Ext.DomQuery.selectNode('table', this.el.dom)); var tfEl = Ext.DomHelper.insertAfter(table, { tag: 'div', style: 'border:0px;', children: [{ tag: 'div', cls: 'x-datepicker-footer ux-timefield' }] }, true); this.timefield.render(this.el.child('div div.ux-timefield')); var p = this.getEl().parent('div.x-layer'); if(p) { p.setStyle("height", p.getHeight() + 31); } }, // listener 时间域修改, timefield change timeChange: function(tf, time, rawtime) { this.value = this.fillDateTime(this.value); }, fillDateTime: function(value) { if(this.timefield) { var rawtime = this.timefield.getRawValue(); value.setHours(rawtime.h); value.setMinutes(rawtime.m); value.setSeconds(rawtime.s); } return value; }, changeTimeFiledValue: function(value) { this.timefield.un('change', this.timeChange, this); this.timefield.setValue(this.value); this.timefield.on('change', this.timeChange, this); }, setValue: function(value) { this.value = value; this.changeTimeFiledValue(value); return this.update(this.value); }, getValue: function() { return this.fillDateTime(this.value); }, handleDateClick: function(e, t) { var me = this, handler = me.handler; e.stopEvent(); if(!me.disabled && t.dateValue && !Ext.fly(t.parentNode).hasCls(me.disabledCellCls)) { me.doCancelFocus = me.focusOnSelect === false; me.setValue(this.fillDateTime(new Date(t.dateValue))); delete me.doCancelFocus; me.fireEvent('select', me, me.value); if(handler) { handler.call(me.scope || me, me, me.value); } me.onSelect(); } }, //确认按键 confirmDate: function(){ var that = this; that.fireEvent('select', that, that.value);//模拟用户选择 that.onSelect(); }, selectToday: function() { var me = this, btn = me.todayBtn, handler = me.handler; if(btn && !btn.disabled) { me.setValue(new Date()); me.fireEvent('select', me, me.value); if(handler) { handler.call(me.scope || me, me, me.value); } me.onSelect(); } return me; } });
3、将DateTimePicker装载到Ext.form.field.Date中,初始化日期时间的格式。
Ext.define('MyApp.ux.DateTimeField.DateTimeField', { extend: 'Ext.form.field.Date', alias: 'widget.datetimefield', requires: ['MyApp.ux.DateTimeField.DateTimePicker'], initComponent: function() { this.format = this.format; this.callParent(); }, format: 'Y-m-d H:i:s', createPicker: function() { var me = this, format = Ext.String.format; return Ext.create('MyApp.ux.DateTimeField.DateTimePicker', { ownerCt: me.ownerCt, // renderTo: document.body, floating: true, // hidden: true, focusOnShow: true, minDate: me.minValue, maxDate: me.maxValue, disabledDatesRE: me.disabledDatesRE, disabledDatesText: me.disabledDatesText, disabledDays: me.disabledDays, disabledDaysText: me.disabledDaysText, format: me.format, showToday: me.showToday, startDay: me.startDay, minText: format(me.minText, me.formatDate(me.minValue)), maxText: format(me.maxText, me.formatDate(me.maxValue)), listeners: { scope: me, select: me.onSelect }, keyNavConfig: { esc: function() { me.collapse(); } } }); } });
将以上代码拷到ux当中,调用的时候可以Ext.create之,也可以require之后直接使用alias。
效果嘛,就像下图那样:
介绍完毕。
谢谢大家。
1 0
- ExtJS自定义控件 之一:datetimefield控件
- extjs 日期时间控件 datetimefield
- ExtJs 基于ExtJs2.2以上的日期时间选择控件datetimefield
- Android自定义控件之一
- android 自定义控件之一
- 自定义控件之一:自定义属性
- 如何编写ExtJS自定义控件
- Extjs 通过继承自定义控件
- ExtJS08:时间控件Cls.form.DateTimeField
- winForm自定义控件攻略之一
- 自定义控件的方法之一
- 自定义view之一:自定义验证码控件
- 自定义控件专题之一:前言、基础
- Android 自定义控件学习之一 基础知识
- Android 自定义控件学习之一 基础知识
- 自定义控件(面试热门问题之一)
- Android 自定义控件 基础概述之一
- android 自定义控件系列之一 圆形图控件
- Windows配置NetBeans为SourceCodePro字体
- 单片机中使用C库函数记录
- Opengl ES 线的三角化
- Android API中被@hide注释的方法引用报错解决
- 《java入门第一季》之面向对象(多态向下转型)
- ExtJS自定义控件 之一:datetimefield控件
- Flask下拉列表与数据库同步
- leetcode.279. Perfect Squares
- 今天经理给我讲了好多东西(spring mvc)
- java底层知识(3)--CPU 高速缓存
- 版本管理
- 创建一个内容提供者Creating a Content Provider——翻译总结自developer.android.com
- Android5.0(L)输入法表情界面㊗和㊙显示框框
- C++程序设计必知:生存期