5660acd0-bade-4839-a2c8-6f3d66d39fc0.png

原文链接

虽说不喜欢做这种做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