原文链接
虽说不喜欢做这种做XX内部管理系统的生活,虽说不喜欢extjs,但是工作就是工作,找些乐趣也好。
也感谢恶魔主管给我时间去了解,去修改一些很细节的体验方面的东西。
唉,算了他又不看,不拍马屁了···
extjs没有日期加时分秒的时间控件,然而我们用到了,所以需要自己去找。
我们用了extjs5,但是大部分的这种控件都是停留在extjs4的,4和5相差很多,都不是很兼容。只找到了一个兼容的。
https://github.com/gportela85/DateTimeField
可是他使用的这种样式:
这样体验很不好。而且也不是那么的尽善尽美。
其实这个和所有5没能兼容的日期控件都是一个问题。如果你的时分秒用input做,那么当你点击进去的时候,获取了当前input的焦点,就会失去时间空间的焦点,这样时间选择面板就会消失,就好像你点击别处他会消失是一个道理。
上面说的这个空间也有这个问题,右边的时间选择只能拖动两个滚动条。但是不能点击别处,否则消失。
我们要做的事在这个基础上做修改,让他变成封面的样子。
首先看他的代码,是新加了一个panel组件。
me.timePicker = Ext.create('Ext.panel.Panel', { layout: { type: 'hbox', align: 'stretch' }, border: false, defaults: { flex: 1 }, width: 130, floating: true, dockedItems: [{ xtype: 'toolbar', dock: 'top', ui: 'footer', items: [ '->', { xtype: 'label', text: me.timeFormat == 'h' ? '12:00 AM' : '00:00' }, '->' ] }], items: [me.hourSlider, me.minuteSlider] });
这样会有问题,因为点击了这个panel,日期面板就会消失,因为日期组件的焦点失去了。
所以作为第一步修改,我们不用panel,而是用menu组件。
menu和panel的不同是,他有一个属性ownerCmp,类似配置自己的父节点。这样我点击这个范围时候,和点击在日期面板上是一样的。类似两个div的包含,但是这点在extjs的实现上是需要配置的。
me.timePicker = Ext.create('Ext.menu.Menu', { layout: { type: 'hbox', align: 'stretch' }, ownerCmp: me,
像这样,我们解决了点击的问题。
第二部是换掉他的滚动条。
me.hourSlider = new Ext.slider.Single( { xtype: 'slider', fieldLabel: 'Hour', labelAlign: 'top', labelSeparator: ' ', padding: '0 0 10 17', value: 0, minValue: 0, maxValue: 23, vertical: true, listeners: { change: me.changeTimeValue, scope: me } });
他用的是slider,我们要改成text number。
me.hourSlider = new Ext.form.field.Number( { value: 0, minValue: 0, maxValue: 23, width:58, padding:'5 0', listeners: { change: me.changeTimeValue, scope: me } });
这样我们可以往里面输入想要的值了。而我们进入了hour的input的焦点时候,也不会失去日期组件的焦点。
顺便说一句,我们点击日期面板儿日期组件不失去焦点也是因为他设定了ownerCmp
getPicker: function() { var me = this, picker = me.picker; if (!picker) { me.picker = picker = me.createPicker(); // For upward component searches. picker.ownerCmp = me; } return me.picker; },
这是http://docs.sencha.com/extjs/5.1/5.1.0-apidocs/source/Picker.html#Ext-form-field-Picker里面的代码。
第三部我们把他的位置换到下面。
把上面所说的控件里面的showTimePicker改一下即可。
me.timePicker.setWidth(el.getWidth()); me.timePicker.showBy(me, alignTo, [ 0, yPos]);
但是这样会有一点问题,当他从日期组件的上面出来的时候:
他会盖住原有的组件,因为高度还是按照他原来的设定的。所以我们还需要算一下高度:
offsetY = el.getOffsetsTo(me.ownerCmp)[1]; if(offsetY< 0) el.setTop(top - height); if(bottom < height && offsetY > 0) el.setTop(top-height-el.getHeight()-me.ownerCmp.getHeight());
第一个if 把下面我们后加的menu的高度减去。
第二个if判断当日期面板还在下面但是我们的menu显示不全时 同样放到上面去。
第四步我们要防止他在日期面板选择日期的时候消失的效果。
因为我们需要选择好线面的时间才能让他消失,所以需要他在选择日期时保持显示状态。
我们看http://docs.sencha.com/extjs/5.1/5.1.0-apidocs/source/Date2.html#Ext-picker-Date里的代码:
onSelect: function() { if (this.hideOnSelect) { this.hide(); } },
他又一个hideOnselect的属性,当他为false的时候,onSelect事件不会触发hide();但是事实是我们加上他也不会阻止他的hide()。
找了半天原因,在 http://docs.sencha.com/extjs/5.1/5.1.0-apidocs/source/Date3.html#Ext-form-field-Date 的源码,也就是我们的日期组件的源码中:
onSelect: function(m, d) { var me = this; me.setValue(d); me.fireEvent('select', me, d); me.collapse(); },
onSelect 是会触发collapse的,而在collapse中···
collapse: function() { var me = this; if (me.isExpanded && !me.isDestroyed && !me.destroying) { var openCls = me.openCls, picker = me.picker, aboveSfx = '-above'; // hide the picker and set isExpanded flag picker.hide(); me.isExpanded = false; // remove the openCls me.bodyEl.removeCls([openCls, openCls + aboveSfx]); picker.el.removeCls(picker.baseCls + aboveSfx); // remove event listeners me.hideListeners.destroy(); Ext.un('resize', me.alignPicker, me); me.fireEvent('collapse', me); me.onCollapse(); } },
还是hide()掉了他·····(这段代码在 http://docs.sencha.com/extjs/5.1/5.1.0-apidocs/source/Picker.html#Ext-form-field-Picker 中,Ext-form-field-Date 和 Ext-form-field-Picker 是继承关系。)
太丧失了···
解决办法就是在我们自己的 field-date中,复写这个方法,并且注释掉collapse。
这样,我们整个的功能就搞定了。当然具体的赋值与取值过程都是之前的组件已经实现的了,我这里就不累赘了。
附个源码,但希望所有前端远离extjs,真爱生命······
原文链接:http://www.gbtags.com/gb/share/5655.htm
转载于:https://blog.51cto.com/361737/1671406