您的位置:首页 > Web前端 > JavaScript

EXTJS日期时间选择控件(精确到秒)

2016-01-25 23:13 1031 查看


EXTJS日期时间选择控件(精确到秒)

博客分类:

工作日志

ExtJsJSjavajsphtml

一。一些废话

近日来,有几个项目用到了EXTJS作为Web前端。也看到了一些童鞋苦苦在网上寻觅可以选择时间的控件,由于EXTJS版本差异较大,利用官方3.2的Demo制作了一个可以选择到秒的时间控件,该控件只能够用于ExtJs2.2以上的版本。经过测试ExtJs2.02版本不适用该控件,如果你还在使用2.02这个版本或者更老,请绕道。废话不说了,看代码:

二。文件明细:

Spinner.js

SpinnerField.js

DateTimeField.js

三。各文件详解

1.Spinner.js

EXTJS个版本略有不同,最后的文件解压后请覆盖源文件。这里不做详细介绍。

2.SpinnerField.js

EXTJS个版本略有不同,最后的文件解压后请覆盖源文件。这里不做详细介绍。

3.DateTimeField.js

Js代码


// 命名空间归属

Ext.ns('Ext.ux.form');

// 在该命名空间内,开辟一个名为TimePickerField的区域,我们可以当他是一个时间选择器

Ext.ux.form.TimePickerField = function(config){

// 调用构造方法,也就是说定义了他的所属--this

// this指的是什么呢?这里需要注意,首先这个东东属于这个类(对象),其次这个类(对象)在没有被调用之前或者实例之前是不会被构造的

// 那么这个this实际上是指我们实例化后的datetimefield

Ext.ux.form.TimePickerField.superclass.constructor.call(this, config);

}

// 给刚刚定义的TimePickerField加点菜吧。

// 首先它继承与Ext.form.Field,是一个扩展

Ext.extend(Ext.ux.form.TimePickerField, Ext.form.Field, {

defaultAutoCreate: {

tag: 'div'// 定义了一个DIV标签

},

cls: 'x-form-timepickerfield',// 它的样式

hoursSpinner: null,// 属性:小时选择器

minutesSpinner: null,// 属性:分钟选择器

secondsSpinner: null,// 属性:秒选择器

spinnerCfg: {

width: 40// 选择器的宽度定位40px

},

// 约束:选择数值约束,如果小于最小值该如何,如果大于最大值该如何,这里的处理方式我详细说明一下(这个约束是触发的,我们输入的值或者我们点击上下箭头选择的值后都会进入该约束检查。)

spinnerFixBoundries: function(value){

// 这里有可能会造成不解,我解释一下。

// 如果我们选择秒的时候,有一个向上的箭头和向下的箭头,如果我点击向上的箭头则秒数加1,点击向下的箭头则秒数减1。

// 如果我选择了59秒后,点击向上的箭头,由于时间秒数约束,不可能出现60,那我们要怎么办?会如何?当然是,58,59,0,1这样的序列

// 所以最大值定义为59,如果超过59那么秒数归零,就是这个逻辑。

if (value < this.field.minValue) {

value = this.field.maxValue;

}

if (value > this.field.maxValue) {

value = this.field.minValue;

}

// 这里返回了一个带有精度的值

return this.fixPrecision(value);

},

// 渲染,这个没什么可说的了所有的渲染都差不多是位置和范围之类的

onRender: function(ct, position){

Ext.ux.form.TimePickerField.superclass.onRender.call(this, ct, position);

this.rendered = false;

this.date = new Date();

// 定义一个对象,他即将有三个属性,时分秒数值,往下看。

var values = {};

// 如果实例时已经被设定了初始值,那么将这些值赋予values这个对象中。

// 再将这些值表示在时分秒选择器中

if (this.value) {

values = this._valueSplit(this.value);

this.date.setHours(values.h);

this.date.setMinutes(values.m);

this.date.setSeconds(values.s);

delete this.value;

}

// 如果实例时没被设定了初始值,简单了,时分秒选择器的初始值就不用改变了,只要values得到这些值备用即可

else {

values = {

h: this.date.getHours(),

m: this.date.getMinutes(),

s: this.date.getSeconds()

};

}

// 定义一个外围包裹,就是想把时分秒这三个选择器给包起来成为一组,下面会实例这三个选择器的,往下看。

var spinnerWrap = Ext.DomHelper.append(this.el, {

tag: 'div'

});

var cfg = Ext.apply({}, this.spinnerCfg, {

renderTo: spinnerWrap,

readOnly: this.readOnly,

disabled: this.disabled,

listeners: {

spin: {

fn: this.onSpinnerChange,

scope: this

},

valid: {

fn: this.onSpinnerChange,

scope: this

},

afterrender: {

fn: function(spinner){

spinner.wrap.applyStyles('float: left');

},

single: true

}

}

});

// 接下来实例(Ext.ux.form.SpinnerField)了几个选择器,时分秒。

this.hoursSpinner = new Ext.ux.form.SpinnerField(Ext.apply({}, cfg, {

minValue: 0,

maxValue: 23,

cls: 'first',

value: values.h

}));

this.minutesSpinner = new Ext.ux.form.SpinnerField(Ext.apply({}, cfg, {

minValue: 0,

maxValue: 59,

value: values.m

}));

this.secondsSpinner = new Ext.ux.form.SpinnerField(Ext.apply({}, cfg, {

minValue: 0,

maxValue: 59,

value: values.s

}));

Ext.DomHelper.append(spinnerWrap, {

tag: 'div',

cls: 'x-form-clear-left'

});

// 渲染完毕释放出去

this.rendered = true;

},

// 如果实例时已经被设定了初始值,那么调用这个方法,将这些值赋予values这个对象中。

_valueSplit: function(v){

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;

}

// 这里注册了这个监听类别,指明了监听的对象

this.fireEvent('change', this, this.getRawValue());

},

// 禁用

disable: function(){

Ext.ux.form.TimePickerField.superclass.disable.call(this);

this.hoursSpinner.disable();

this.minutesSpinner.disable();

this.secondsSpinner.disable();

},

// 解用

enable: function(){

Ext.ux.form.TimePickerField.superclass.enable.call(this);

this.hoursSpinner.enable();

this.minutesSpinner.enable();

this.secondsSpinner.enable();

},

// 只读

setReadOnly: function(r){

Ext.ux.form.TimePickerField.superclass.setReadOnly.call(this, r);

this.hoursSpinner.setReadOnly(r);

this.minutesSpinner.setReadOnly(r);

this.secondsSpinner.setReadOnly(r);

},

// 清除所有的无效验证

clearInvalid: function(){

Ext.ux.form.TimePickerField.superclass.clearInvalid.call(this);

this.hoursSpinner.clearInvalid();

this.minutesSpinner.clearInvalid();

this.secondsSpinner.clearInvalid();

},

// 拿到那个值,可以认为是vlaues对象

getRawValue: function(){

if (!this.hoursSpinner) {

this.date = new Date();

return {

h: this.date.getHours(),

m: this.date.getMinutes(),

s: this.date.getSeconds()

};

}

else {

return {

h: this.hoursSpinner.getValue(),

m: this.minutesSpinner.getValue(),

s: this.secondsSpinner.getValue()

};

}

},

// 赋值

setRawValue: function(v){

this.hoursSpinner.setValue(v.h);

this.minutesSpinner.setValue(v.m);

this.secondsSpinner.setValue(v.s);

},

// 有效验证

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();

},

// 这里可以自己修改想要的格式,这个值将作为返回值到调用该类的元控件中也就是DateTimeField的实例

getValue: function(){

var v = this.getRawValue();

return String.leftPad(v.h, 2, '0') + ':' +

String.leftPad(v.m, 2, '0') +

':' +

String.leftPad(v.s, 2, '0');

},

setValue: function(value){

if (!this.rendered) {

this.value = value;

return;

}

value = this._valueSplit(value);

this.setRawValue(value);

this.validate();

}

});

// 下面就没什么好说的了,就是将上面自定义的类(对象),成为一个总选择器一部分。

Ext.form.TimePickerField = Ext.ux.form.TimePickerField;

Ext.reg('timepickerfield', Ext.form.TimePickerField);

Ext.ns('Ext.ux.form');

Ext.DateTimePicker = Ext.extend(Ext.DatePicker, {

timeFormat: 'g:i:s A',

timeLabel: '时间',

timeWidth: 100,

initComponent: function(){

Ext.DateTimePicker.superclass.initComponent.call(this);

this.id = Ext.id();

},

onRender: function(container, position){

Ext.DateTimePicker.superclass.onRender.apply(this, arguments);

var table = Ext.get(Ext.DomQuery.selectNode('table tbody', container.dom));

var tfEl = Ext.DomHelper.insertBefore(table.last(), {

tag: 'tr',

children: [{

tag: 'td',

cls: 'x-date-bottom',

html: this.timeLabel,

style: 'width:30;'

}, {

tag: 'td',

cls: 'x-date-bottom ux-timefield',

colspan: '2'

}]

}, true);

this.tf.render(table.child('td.ux-timefield'));

var p = this.getEl().parent('div.x-layer');

if (p) {

p.setStyle("height", p.getHeight() + 31);

}

},

setValue: function(value){

var old = this.value;

if (!this.tf) {

this.tf = new Ext.ux.form.TimePickerField();

this.tf.ownerCt = this;

}

this.value = this.getDateTime(value);

},

getDateTime: function(value){

if (this.tf) {

var dt = new Date();

var timeval = this.tf.getValue();

value = Date.parseDate(value.format(this.dateFormat) + ' ' + this.tf.getValue(), this.format);

}

return value;

},

selectToday: function(){

if (this.todayBtn && !this.todayBtn.disabled) {

this.value = this.getDateTime(new Date());

this.fireEvent("select", this, this.value);

}

}

});

Ext.reg('datetimepickerfield', Ext.DateTimePicker);

if (parseInt(Ext.version.substr(0, 1), 10) > 2) {

Ext.menu.DateTimeItem = Ext.DateTimePicker;

Ext.override(Ext.menu.DateMenu, {

initComponent: function(){

this.on('beforeshow', this.onBeforeShow, this);

if (this.strict = (Ext.isIE7 && Ext.isStrict)) {

this.on('show', this.onShow, this, {

single: true,

delay: 20

});

}

Ext.apply(this, {

plain: true,

showSeparator: false,

items: this.picker = new Ext.DatePicker(Ext.apply({

internalRender: this.strict || !Ext.isIE,

ctCls: 'x-menu-date-item'

}, this.initialConfig))

});

Ext.menu.DateMenu.superclass.initComponent.call(this);

this.relayEvents(this.picker, ["select"]);

this.on('select', this.menuHide, this);

if (this.handler) {

this.on('select', this.handler, this.scope || this);

}

}

});

}

else {

Ext.menu.DateTimeItem = function(config){

Ext.menu.DateTimeItem.superclass.constructor.call(this, new Ext.DateTimePicker(config), config);

this.picker = this.component;

this.addEvents('select');

this.picker.on("render", function(picker){

picker.getEl().swallowEvent("click");

picker.container.addClass("x-menu-date-item");

});

this.picker.on("select", this.onSelect, this);

};

Ext.extend(Ext.menu.DateTimeItem, Ext.menu.DateMenu, {

onSelect: function(picker, date){

this.fireEvent("select", this, date, picker);

Ext.menu.DateTimeItem.superclass.handleClick.call(this);

}

});

}

Ext.menu.DateTimeMenu = function(config){

Ext.menu.DateTimeMenu.superclass.constructor.call(this, config);

this.plain = true;

var di = new Ext.menu.DateTimeItem(config);

this.add(di);

this.picker = di;

this.relayEvents(di, ["select"]);

this.on('beforeshow', function(){

if (this.picker) {

this.picker.hideMonthPicker(true);

}

}, this);

};

Ext.extend(Ext.menu.DateTimeMenu, Ext.menu.Menu, {

cls: 'x-date-menu',

beforeDestroy: function(){

this.picker.destroy();

},

hide: function(deep){

if (this.picker.tf.innerList) {

if ((Ext.EventObject.within(this.picker.tf.innerList)) || (Ext.get(Ext.EventObject.getTarget()) == this.picker.tf.innerList))

return false;

}

if (this.el && this.isVisible()) {

this.fireEvent("beforehide", this);

if (this.activeItem) {

this.activeItem.deactivate();

this.activeItem = null;

}

this.el.hide();

this.hidden = true;

this.fireEvent("hide", this);

}

if (deep === true && this.parentMenu) {

this.parentMenu.hide(true);

}

}

});

Ext.ux.form.DateTimeField = Ext.extend(Ext.form.DateField, {

dateFormat: 'Y-m-d',

timeFormat: 'H:i:s',

defaultAutoCreate: {

tag: "input",

type: "text",

size: "20",

autocomplete: "off"

},

initComponent: function(){

Ext.ux.form.DateTimeField.superclass.initComponent.call(this);

this.format = this.dateFormat + ' ' + this.timeFormat;

this.afterMethod('afterRender', function(){

this.getEl().applyStyles('top:0');

});

},

getValue: function(){

return this.parseDate(Ext.form.DateField.superclass.getValue.call(this)) || '';

},

onTriggerClick: function(){

if (this.disabled) {

return;

}

if (this.menu == null) {

this.menu = new Ext.menu.DateTimeMenu();

}

Ext.apply(this.menu.picker, {

minDate: this.minValue,

maxDate: this.maxValue,

disabledDatesRE: this.ddMatch,

disabledDatesText: this.disabledDatesText,

disabledDays: this.disabledDays,

disabledDaysText: this.disabledDaysText,

format: this.format,

timeFormat: this.timeFormat,

dateFormat: this.dateFormat,

showToday: this.showToday,

minText: String.format(this.minText, this.formatDate(this.minValue)),

maxText: String.format(this.maxText, this.formatDate(this.maxValue))

});

if (this.menuEvents) {

this.menuEvents('on');

}

else {

this.menu.on(Ext.apply({}, this.menuListeners, {

scope: this

}));

}

this.menu.picker.setValue(this.getValue() || new Date());

this.menu.show(this.el, "tl-bl?");

}

});

Ext.reg('datetimefield', Ext.ux.form.DateTimeField);

四。示例截图:



五。文件下载

优化后的时间选择控件精确到秒.zip (6.8 KB)
下载次数: 3522

分享到:




EXTJS实现的TREEGRID(后台java,框架Spri
... | java反射详解

2012-10-11 17:34

浏览 34210

评论(34)

分类:Web前端

相关推荐


评论


34 楼 zss912317 2015-12-01

请叫我东哥 写道

'this.picker'为空或不是对象

怎么解决

33 楼 qinxuekun199 2015-08-28




经修改 p.setStyle("height",
p.getHeight());后只是下面有一道线,类似分割线一样,不是很完美其他很好,感谢这里所有人,楼主太赞了

32 楼 Tiara恋空 2015-01-09
this.hoursSpinner = new Ext.ux.form.SpinnerField(Ext.apply({}, cfg, {

minValue: 0,

maxValue: 23,

cls: 'first',

value: values.h

}));

报对象不支持此操作怎么回事啊,求请教

31 楼 梦醒无尘 2014-10-24













30 楼 qq912358750 2014-07-30

请叫我东哥 写道

'this.picker'为空或不是对象

怎么解决

29 楼 hwak 2014-07-30

xusanmao 写道

都按要求声明css和js文件了,当xtype为datefield时显示正常,当xtype为datetimefield时,年,月,日,时分秒位置全部是空的压缩到一块了,是怎么回事?多谢楼主解答。

版本多少,应该是样式冲突的问题,调整一下样式也很简单的。

28 楼 hwak 2014-07-30

zhoufeng12liu 写道

时间那两个字太大怎么办????

咳咳,这个是样式问题,打开浏览器的debug模式,查看dom元素,找到class关键字,之后全局搜索有这个class的css文件,找到那一行改一下。

27 楼 xusanmao 2014-07-05
都按要求声明css和js文件了,当xtype为datefield时显示正常,当xtype为datetimefield时,年,月,日,时分秒位置全部是空的压缩到一块了,是怎么回事?多谢楼主解答。

26 楼 zhoufeng12liu 2014-04-08
时间那两个字太大怎么办????

25 楼 请叫我东哥 2014-04-02
'this.picker'为空或不是对象

怎么解决

24 楼 appleong 2014-03-05
那段代码放在哪儿???

23 楼 TonyLian 2013-12-25

TonyLian 写道

Dayday_lx 写道

不知楼主有没有发现你这个控件,选值之后,传到后台,后台request获取到格式化为

yyyy-MM-dd HH:mm:ss的日期字符串后格式发生了改变?日和时 之间多了一个T

请百度 Rfc9993 ,君不见北京飞控大厅的大屏幕上,“嫦娥三号月面工作时间”也带一个T

笔误了,是 RFC3339

22 楼 TonyLian 2013-12-25

Dayday_lx 写道

不知楼主有没有发现你这个控件,选值之后,传到后台,后台request获取到格式化为

yyyy-MM-dd HH:mm:ss的日期字符串后格式发生了改变?日和时 之间多了一个T

请百度 Rfc9993 ,君不见北京飞控大厅的大屏幕上,“嫦娥三号月面工作时间”也带一个T

21 楼 Dayday_lx 2013-12-12
不知楼主有没有发现你这个控件,选值之后,传到后台,后台request获取到格式化为

yyyy-MM-dd HH:mm:ss的日期字符串后格式发生了改变?日和时 之间多了一个T

20 楼 382259185 2013-10-28
请问在chrome下全屏问题 如何解决??

19 楼 eric442251314 2013-10-16


还是有点bug

18 楼 cermchen 2013-10-10
我加入到自己的项目中,为什么选择时分秒的时候都只有一个向下的箭头,而没有向上的箭头呢?

需要覆盖一个CSS的图标

能否把这个CSS图标也发一下?谢谢!

17 楼 cquliaoli 2013-09-04

cquliaoli 写道

cquliaoli 写道

8wy154775 写道

缺一个css文件的代码啊,老大,急求阿8wy154775@163.com

Spinner.css在ext/ux/css下有的,还有下面空白的可以修改if (p) {

p.setStyle("height", p.getHeight());

}

版本不同 可以 修改p.getHeight()后面加的值,还有如果TimeLabel---时间 宽度不够可以修改: children: [{

tag: 'td',

cls: 'x-date-bottom',

html: this.timeLabel,

style: 'width:40;'

}

中的width值,另外注意文件编码可能引起 中文"时间"显示不正确.

具体应用很简单,就像普通组件一样,只是xtype=datetimefield,如:

{

fieldLabel:'开始时间',

hiddenName:'begin_time',

name:'begin_time',

xtype:'datetimefield',

}

16 楼 cquliaoli 2013-09-04

cquliaoli 写道

8wy154775 写道

缺一个css文件的代码啊,老大,急求阿8wy154775@163.com

Spinner.css在ext/ux/css下有的,还有下面空白的可以修改if (p) {

p.setStyle("height", p.getHeight());

}

版本不同 可以 修改p.getHeight()后面加的值,还有如果TimeLabel---时间 宽度不够可以修改: children: [{

tag: 'td',

cls: 'x-date-bottom',

html: this.timeLabel,

style: 'width:40;'

}

中的width值,另外注意文件编码可能引起 中文"时间"显示不正确.

15 楼 cquliaoli 2013-09-04

8wy154775 写道

缺一个css文件的代码啊,老大,急求阿8wy154775@163.com

Spinner.css在ext/ux/css下有的,还有下面空白的可以修改if (p) {

p.setStyle("height", p.getHeight());

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: