zoukankan      html  css  js  c++  java
  • ExtJS6.0扩展日期选择控件为也可以选择时间

    PS:ExtJS自带的日期选择控件只能够选择日期,但是现在的需求需要精确到秒,所以在网上搜索了一些例子(大部分是4.0的)作为参考,然后改出了6.0可用的一个日期时间选择控件。

    1、找到extjs6.0源代码中Picker文件路径下的Date.js脚本(路径:ext-6.0.0-gplext-6.0.0classicclassicsrcpicker),拷贝一份出来命名为DateTimePicker.js

    2、修改命名空间(把白色底的改成黑色底的命名空间以及别名,你也可以修改为自己存放该文件的路径,名称也可以自己命名)

      

    3、定位到showToday模块

       把原来的:'<div id="{id}-footerEl" data-ref="footerEl" role="presentation" class="{baseCls}-footer">{%this.renderTodayBtn(values, out)%}</div>',

       替换成:'<div id="{id}-footerEl" role="presentation" style="background-color:#D9E5F3;border-top:0px solid #99BCE8;">{%this.renderHour(values, out)%}{%this.renderMinute(values, out)%}{%this.renderSecond(values, out)%}<center>{%this.renderOkQueDingBtn(values, out)%}&nbsp;&nbsp;{%this.renderTodayBtn(values, out)%}</center></div>',

       也就是增加 时、分、秒、OK控件

       

    1  '<tpl if="showToday">',
    2                 //'<div id="{id}-footerEl" data-ref="footerEl" role="presentation" class="{baseCls}-footer">{%this.renderTodayBtn(values, out)%}</div>',
    3               '<div id="{id}-footerEl" role="presentation" style="background-color:#D9E5F3;border-top:0px solid #99BCE8;">{%this.renderHour(values, out)%}{%this.renderMinute(values, out)%}{%this.renderSecond(values, out)%}<center>{%this.renderOkQueDingBtn(values, out)%}&nbsp;&nbsp;{%this.renderTodayBtn(values, out)%}</center></div>',
    4             '</tpl>',

    4、添加时、分、秒、OK控件的渲染事件

     1 longDay: function(value){
     2                 return Ext.Date.format(value, this.longDayFormat);
     3             },
     4             renderHour: function(values, out) {
     5                 out.push('<font  style="float : left;">&nbsp&nbsp</font>');
     6                 Ext.DomHelper.generateMarkup(values.$comp.hour.getRenderTree(), out);
     7             },
     8             renderMinute: function(values, out) {
     9                 out.push('<font  style="float : left;font-weight:bold;">&nbsp:&nbsp&nbsp</font>');
    10                 Ext.DomHelper.generateMarkup(values.$comp.minute.getRenderTree(), out);
    11             },
    12             renderSecond: function(values, out) {
    13                 out.push('<font style="float : left;font-weight:bold;">&nbsp:&nbsp&nbsp</font>');
    14                 Ext.DomHelper.generateMarkup(values.$comp.second.getRenderTree(), out);
    15             },
    16             renderOkQueDingBtn: function(values, out) {  
    17                 Ext.DomHelper.generateMarkup(values.$comp.okQueDingBtn.getRenderTree(), out);  
    18             },

    5、在beforeRender事件中,添加时、分、秒、OK控件的事件

    me.monthBtn = new Ext.button.Split({
                ownerCt: me,
                ownerLayout: me.getComponentLayout(),
                text: '',
                tooltip: me.monthYearText,
                tabIndex: -1,
                ariaRole: 'presentation',
                listeners: {
                    click: me.doShowMonthPicker,
                    arrowclick: me.doShowMonthPicker,
                    scope: me
                }
            });
    
            me.hour = Ext.create('Ext.form.field.Number', {
                scope: me,
                ownerCt: me,
                editable : true,
                ownerLayout: me.getComponentLayout(),
                minValue: 0,
                maxValue: 23,
                 70,
                style : {float:"left"},
                enableKeyEvents: true,
                listeners: {
                     keyup: function(field, e){
                         if (field.getValue() > 23){
                             e.stopEvent();
                             field.setValue(23);
                         }
                     }
                 }
            });
            
            me.minute = Ext.create('Ext.form.field.Number', {
                scope: me,
                ownerCt: me,
                style : {float:"left"},
                ownerLayout: me.getComponentLayout(),
                minValue: 0,
                maxValue: 59,
                editable : true,
                 70,
                enableKeyEvents: true,
                listeners: {
                    keyup: function(field, e){
                        if (field.getValue() > 59){
                            e.stopEvent();
                            field.setValue(59);
                        }
                    }
                }
            });
            
          me.second = Ext.create('Ext.form.field.Number', {
                scope: me,
                ownerCt: me,
                editable : true,
                style : {float:"left"},
                ownerLayout: me.getComponentLayout(),
                minValue: 0,
                maxValue: 59,
                 70,
                enableKeyEvents: true,
                listeners: {
                    keyup: function(field, e){
                        if (field.getValue() > 59){
                            e.stopEvent();
                            field.setValue(59);
                        }
                    }
                }
            });
           me.okQueDingBtn = new Ext.button.Button({  
                ownerCt: me,  
                ownerLayout: me.getComponentLayout(),  
                text: me.okText,  
                tooltip: me.okTip,  
                tooltipType:'title',  
                handler:me.okQueDingHandler,//确认按钮的事件委托  
                scope: me  
            });  

    6、添加OK按钮处理事件

     1 /** 
     2      * 确认 按钮触发的调用 
     3      */  
     4     okQueDingHandler : function(){  
     5         var me = this,  
     6             btn = me.okQueDingBtn;  
     7   
     8         if(btn && !btn.disabled){  
     9             me.setValue(this.getValue());  
    10             me.fireEvent('select', me, me.value);  
    11             me.onSelect();  
    12         }  
    13         return me;  
    14     },  

    7、在update事件中添加更新时间的事件

    1         date.setHours(me.hour.getValue());
    2         date.setMinutes(me.minute.getValue());
    3         date.setSeconds(me.second.getValue());

    8、在beforeDestroy释放事件中添加释放OK按钮的事件

     1 beforeDestroy: function() {
     2         var me = this;
     3 
     4         if (me.rendered) {
     5             Ext.destroy(
     6                 me.keyNav,
     7                 me.monthPicker,
     8                 me.monthBtn,
     9                 me.nextRepeater,
    10                 me.prevRepeater,
    11                 me.todayBtn,
    12                 me.okQueDingBtn,
    13                 me.todayElSpan
    14             );
    15             delete me.textNodes;
    16             delete me.cells.elements;
    17         }
    18         me.callParent();
    19     },

    9、添加其他释放事件

     1  finishRenderChildren: function () {
     2             var me = this;
     3 
     4             me.callParent();
     5             me.monthBtn.finishRender();
     6             me.okQueDingBtn.finishRender();  
     7             if (me.showToday) {
     8                 me.todayBtn.finishRender();
     9             }
    10             //添加时间相关
    11             this.hour.finishRender();
    12             this.minute.finishRender();
    13             this.second.finishRender();
    14         },
    15         

    10、到此Date.js脚本就改造完毕了下面是完整的DateTimePicker.js脚本

       1 /**
       2  * A date picker. This class is used by the Ext.form.field.Date field to allow browsing and selection of valid
       3  * dates in a popup next to the field, but may also be used with other components.
       4  *
       5  * Typically you will need to implement a handler function to be notified when the user chooses a date from the picker;
       6  * you can register the handler using the {@link #select} event, or by implementing the {@link #handler} method.
       7  *
       8  * By default the user will be allowed to pick any date; this can be changed by using the {@link #minDate},
       9  * {@link #maxDate}, {@link #disabledDays}, {@link #disabledDatesRE}, and/or {@link #disabledDates} configs.
      10  *
      11  * All the string values documented below may be overridden by including an Ext locale file in your page.
      12  *
      13  *     @example
      14  *     Ext.create('Ext.panel.Panel', {
      15  *         title: 'Choose a future date:',
      16  *          200,
      17  *         bodyPadding: 10,
      18  *         renderTo: Ext.getBody(),
      19  *         items: [{
      20  *             xtype: 'datepicker',
      21  *             minDate: new Date(),
      22  *             handler: function(picker, date) {
      23  *                 // do something with the selected date
      24  *             }
      25  *         }]
      26  *     });
      27  */
      28 Ext.define('Ext.ux.DateTimePicker', {
      29     extend: 'Ext.Component',
      30     alias: 'widget.datetimepicker',
      31     alternateClassName: 'Ext.DateTimePicker',
      32     requires: [
      33         'Ext.XTemplate',
      34         'Ext.button.Button',
      35         'Ext.button.Split',
      36         'Ext.util.ClickRepeater',
      37         'Ext.util.KeyNav',
      38         'Ext.fx.Manager',
      39         'Ext.picker.Month'
      40     ],
      41     
      42     //<locale>
      43     /**
      44      * @cfg {String} todayText
      45      * The text to display on the button that selects the current date
      46      */
      47     todayText: 'Today',
      48     //添加确定按钮
      49     okText:'Ok',
      50     okTip:'Ok',
      51     //</locale>
      52     
      53     //<locale>
      54     /**
      55      * @cfg {String} ariaTitle
      56      * The text to display for the aria title
      57      */
      58     ariaTitle: 'Date Picker: {0}',
      59     //</locale>
      60     
      61     //<locale>
      62     /**
      63      * @cfg {String} ariaTitleDateFormat
      64      * The date format to display for the current value in the {@link #ariaTitle}
      65      */
      66     ariaTitleDateFormat: 'F d',
      67     //</locale>
      68 
      69     /**
      70      * @cfg {Function} handler
      71      * Optional. A function that will handle the select event of this picker. The handler is passed the following
      72      * parameters:
      73      *
      74      *   - `picker` : Ext.picker.Date
      75      *
      76      * This Date picker.
      77      *
      78      *   - `date` : Date
      79      *
      80      * The selected date.
      81      */
      82 
      83     /**
      84      * @cfg {Object} scope
      85      * The scope (`this` reference) in which the `{@link #handler}` function will be called.
      86      *
      87      * Defaults to this DatePicker instance.
      88      */
      89 
      90     //<locale>
      91     /**
      92      * @cfg {String} todayTip
      93      * A string used to format the message for displaying in a tooltip over the button that selects the current date.
      94      * The `{0}` token in string is replaced by today's date.
      95      */
      96     todayTip: '{0} (Spacebar)',
      97     //</locale>
      98 
      99     //<locale>
     100     /**
     101      * @cfg {String} minText
     102      * The error text to display if the minDate validation fails.
     103      */
     104     minText: 'This date is before the minimum date',
     105     //</locale>
     106     
     107     //<locale>
     108     /**
     109      * @cfg {String} ariaMinText The text that will be announced by Assistive Technologies
     110      * such as screen readers when user is navigating to the cell which date is less than
     111      * {@link #minDate}.
     112      */
     113     ariaMinText: "This date is before the minimum date",
     114     //</locale>
     115 
     116     //<locale>
     117     /**
     118      * @cfg {String} maxText
     119      * The error text to display if the maxDate validation fails.
     120      */
     121     maxText: 'This date is after the maximum date',
     122     //</locale>
     123     
     124     //<locale>
     125     /**
     126      * @cfg {String} ariaMaxText The text that will be announced by Assistive Technologies
     127      * such as screen readers when user is navigating to the cell which date is later than
     128      * {@link #maxDate}.
     129      */
     130     ariaMaxText: "This date is after the maximum date",
     131     //</locale>
     132 
     133     /**
     134      * @cfg {String} format
     135      * The default date format string which can be overriden for localization support. The format must be valid
     136      * according to {@link Ext.Date#parse} (defaults to {@link Ext.Date#defaultFormat}).
     137      */
     138 
     139     //<locale>
     140     /**
     141      * @cfg {String} disabledDaysText
     142      * The tooltip to display when the date falls on a disabled day.
     143      */
     144     disabledDaysText: 'Disabled',
     145     //</locale>
     146     
     147     //<locale>
     148     /**
     149      * @cfg {String} ariaDisabledDaysText The text that Assistive Technologies such as screen readers
     150      * will announce when the date falls on a disabled day of week.
     151      */
     152     ariaDisabledDaysText: "This day of week is disabled",
     153     //</locale>
     154     
     155     //<locale>
     156     /**
     157      * @cfg {String} disabledDatesText
     158      * The tooltip text to display when the date falls on a disabled date.
     159      */
     160     disabledDatesText: 'Disabled',
     161     //</locale>
     162 
     163     //<locale>
     164     /**
     165      * @cfg {String} ariaDisabledDatesText The text that Assistive Technologies such as screen readers
     166      * will announce when the date falls on a disabled date.
     167      */
     168     ariaDisabledDatesText: "This date is disabled",
     169     
     170     //</locale>
     171     /**
     172      * @cfg {String[]} monthNames
     173      * An array of textual month names which can be overriden for localization support (defaults to Ext.Date.monthNames)
     174      * @deprecated This config is deprecated. In future the month names will be retrieved from {@link Ext.Date}
     175      */
     176 
     177     /**
     178      * @cfg {String[]} dayNames
     179      * An array of textual day names which can be overriden for localization support (defaults to Ext.Date.dayNames)
     180      * @deprecated This config is deprecated. In future the day names will be retrieved from {@link Ext.Date}
     181      */
     182 
     183     //<locale>
     184     /**
     185      * @cfg {String} nextText
     186      * The next month navigation button tooltip
     187      */
     188     nextText: 'Next Month (Control+Right)',
     189     //</locale>
     190 
     191     //<locale>
     192     /**
     193      * @cfg {String} prevText
     194      * The previous month navigation button tooltip
     195      */
     196     prevText: 'Previous Month (Control+Left)',
     197     //</locale>
     198 
     199     //<locale>
     200     /**
     201      * @cfg {String} monthYearText
     202      * The header month selector tooltip
     203      */
     204     monthYearText: 'Choose a month (Control+Up/Down to move years)',
     205     //</locale>
     206     
     207     //<locale>
     208     /**
     209      * @cfg {String} monthYearFormat
     210      * The date format for the header month
     211      */
     212     monthYearFormat: 'F Y',
     213     //</locale>
     214 
     215     //<locale>
     216     /**
     217      * @cfg {Number} [startDay=undefined]
     218      * Day index at which the week should begin, 0-based.
     219      *
     220      * Defaults to `0` (Sunday).
     221      */
     222     startDay: 0,
     223     //</locale>
     224 
     225     //<locale>
     226     /**
     227      * @cfg {Boolean} showToday
     228      * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar that
     229      * selects the current date.
     230      */
     231     showToday: true,
     232     //</locale>
     233 
     234     /**
     235      * @cfg {Date} [minDate=null]
     236      * Minimum allowable date (JavaScript date object)
     237      */
     238 
     239     /**
     240      * @cfg {Date} [maxDate=null]
     241      * Maximum allowable date (JavaScript date object)
     242      */
     243 
     244     /**
     245      * @cfg {Number[]} [disabledDays=null]
     246      * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday.
     247      */
     248 
     249     /**
     250      * @cfg {RegExp} [disabledDatesRE=null]
     251      * JavaScript regular expression used to disable a pattern of dates. The {@link #disabledDates}
     252      * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the
     253      * disabledDates value.
     254      */
     255 
     256     /**
     257      * @cfg {String[]} disabledDates
     258      * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular expression so
     259      * they are very powerful. Some examples:
     260      *
     261      *   - ['03/08/2003', '09/16/2003'] would disable those exact dates
     262      *   - ['03/08', '09/16'] would disable those days for every year
     263      *   - ['^03/08'] would only match the beginning (useful if you are using short years)
     264      *   - ['03/../2006'] would disable every day in March 2006
     265      *   - ['^03'] would disable every day in every March
     266      *
     267      * Note that the format of the dates included in the array should exactly match the {@link #format} config. In order
     268      * to support regular expressions, if you are using a date format that has '.' in it, you will have to escape the
     269      * dot when restricting dates. For example: ['03\.08\.03'].
     270      */
     271 
     272     /**
     273      * @cfg {Boolean} disableAnim
     274      * True to disable animations when showing the month picker.
     275      */
     276     disableAnim: false,
     277 
     278     /**
     279      * @cfg {String} [baseCls='x-datepicker']
     280      * The base CSS class to apply to this components element.
     281      */
     282     baseCls: Ext.baseCSSPrefix + 'datepicker',
     283 
     284     /**
     285      * @cfg {String} [selectedCls='x-datepicker-selected']
     286      * The class to apply to the selected cell.
     287      */
     288 
     289     /**
     290      * @cfg {String} [disabledCellCls='x-datepicker-disabled']
     291      * The class to apply to disabled cells.
     292      */
     293 
     294     //<locale>
     295     /**
     296      * @cfg {String} longDayFormat
     297      * The format for displaying a date in a longer format.
     298      */
     299     longDayFormat: 'F d, Y',
     300     //</locale>
     301 
     302     /**
     303      * @cfg {Object} keyNavConfig
     304      * Specifies optional custom key event handlers for the {@link Ext.util.KeyNav} attached to this date picker. Must
     305      * conform to the config format recognized by the {@link Ext.util.KeyNav} constructor. Handlers specified in this
     306      * object will replace default handlers of the same name.
     307      */
     308 
     309     /**
     310      * @cfg {String}
     311      * The {@link Ext.button.Button#ui} to use for the date picker's footer buttons.
     312      */
     313     footerButtonUI: 'default',
     314 
     315     isDatePicker: true,
     316     
     317     ariaRole: 'region',
     318     focusable: true,
     319 
     320     childEls: [
     321         'innerEl', 'eventEl', 'prevEl', 'nextEl', 'middleBtnEl', 'footerEl'
     322     ],
     323     
     324     border: true,
     325     
     326     /**
     327      * @cfg
     328      * @inheritdoc
     329      */
     330     renderTpl: [
     331         '<div id="{id}-innerEl" data-ref="innerEl" role="presentation">',
     332             '<div class="{baseCls}-header">',
     333                 '<div id="{id}-prevEl" data-ref="prevEl" class="{baseCls}-prev {baseCls}-arrow" role="presentation" title="{prevText}"></div>',
     334                 '<div id="{id}-middleBtnEl" data-ref="middleBtnEl" class="{baseCls}-month" role="heading">{%this.renderMonthBtn(values, out)%}</div>',
     335                 '<div id="{id}-nextEl" data-ref="nextEl" class="{baseCls}-next {baseCls}-arrow" role="presentation" title="{nextText}"></div>',
     336             '</div>',
     337             '<table role="grid" id="{id}-eventEl" data-ref="eventEl" class="{baseCls}-inner" cellspacing="0" tabindex="0">',
     338                 '<thead>',
     339                     '<tr role="row">',
     340                         '<tpl for="dayNames">',
     341                             '<th role="columnheader" class="{parent.baseCls}-column-header" aria-label="{.}">',
     342                                 '<div role="presentation" class="{parent.baseCls}-column-header-inner">{.:this.firstInitial}</div>',
     343                             '</th>',
     344                         '</tpl>',
     345                     '</tr>',
     346                 '</thead>',
     347                 '<tbody>',
     348                     '<tr role="row">',
     349                         '<tpl for="days">',
     350                             '{#:this.isEndOfWeek}',
     351                             '<td role="gridcell">',
     352                                 '<div hidefocus="on" class="{parent.baseCls}-date"></div>',
     353                             '</td>',
     354                         '</tpl>',
     355                     '</tr>',
     356                 '</tbody>',
     357             '</table>',
     358             '<tpl if="showToday">',
     359                 //'<div id="{id}-footerEl" data-ref="footerEl" role="presentation" class="{baseCls}-footer">{%this.renderTodayBtn(values, out)%}</div>',
     360               '<div id="{id}-footerEl" role="presentation" style="background-color:#D9E5F3;border-top:0px solid #99BCE8;">{%this.renderHour(values, out)%}{%this.renderMinute(values, out)%}{%this.renderSecond(values, out)%}<center>{%this.renderOkQueDingBtn(values, out)%}&nbsp;&nbsp;{%this.renderTodayBtn(values, out)%}</center></div>',
     361             '</tpl>',
     362             // These elements are used with Assistive Technologies such as screen readers
     363             '<div id="{id}-todayText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{todayText}.</div>',
     364             '<div id="{id}-todayText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{okText}.</div>',
     365             '<div id="{id}-ariaMinText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaMinText}.</div>',
     366             '<div id="{id}-ariaMaxText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaMaxText}.</div>',
     367             '<div id="{id}-ariaDisabledDaysText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaDisabledDaysText}.</div>',
     368             '<div id="{id}-ariaDisabledDatesText" class="' + Ext.baseCSSPrefix + 'hidden-clip">{ariaDisabledDatesText}.</div>',
     369         '</div>',
     370         {
     371             firstInitial: function(value) {
     372                 return Ext.picker.Date.prototype.getDayInitial(value);
     373             },
     374             isEndOfWeek: function(value) {
     375                 // convert from 1 based index to 0 based
     376                 // by decrementing value once.
     377                 value--;
     378                 var end = value % 7 === 0 && value !== 0;
     379                 return end ? '</tr><tr role="row">' : '';
     380             },
     381             longDay: function(value){
     382                 return Ext.Date.format(value, this.longDayFormat);
     383             },
     384             renderHour: function(values, out) {
     385                 out.push('<font  style="float : left;">&nbsp&nbsp</font>');
     386                 Ext.DomHelper.generateMarkup(values.$comp.hour.getRenderTree(), out);
     387             },
     388             renderMinute: function(values, out) {
     389                 out.push('<font  style="float : left;font-weight:bold;">&nbsp:&nbsp&nbsp</font>');
     390                 Ext.DomHelper.generateMarkup(values.$comp.minute.getRenderTree(), out);
     391             },
     392             renderSecond: function(values, out) {
     393                 out.push('<font style="float : left;font-weight:bold;">&nbsp:&nbsp&nbsp</font>');
     394                 Ext.DomHelper.generateMarkup(values.$comp.second.getRenderTree(), out);
     395             },
     396             renderOkQueDingBtn: function(values, out) {  
     397                 Ext.DomHelper.generateMarkup(values.$comp.okQueDingBtn.getRenderTree(), out);  
     398             },
     399             renderTodayBtn: function(values, out) {
     400                 Ext.DomHelper.generateMarkup(values.$comp.todayBtn.getRenderTree(), out);
     401             },
     402             renderMonthBtn: function(values, out) {
     403                 Ext.DomHelper.generateMarkup(values.$comp.monthBtn.getRenderTree(), out);
     404             }
     405         }
     406     ],
     407 
     408     // Default value used to initialise each date in the DatePicker.
     409     // __Note:__ 12 noon was chosen because it steers well clear of all DST timezone changes.
     410     initHour: 12, // 24-hour format
     411 
     412     numDays: 42,
     413 
     414     /**
     415      * @event select
     416      * Fires when a date is selected
     417      * @param {Ext.picker.Date} this DatePicker
     418      * @param {Date} date The selected date
     419      */
     420 
     421     /**
     422      * @private
     423      * @inheritdoc
     424      */
     425     initComponent: function() {
     426         var me = this,
     427             clearTime = Ext.Date.clearTime;
     428 
     429         me.selectedCls = me.baseCls + '-selected';
     430         me.disabledCellCls = me.baseCls + '-disabled';
     431         me.prevCls = me.baseCls + '-prevday';
     432         me.activeCls = me.baseCls + '-active';
     433         me.cellCls = me.baseCls + '-cell';
     434         me.nextCls = me.baseCls + '-prevday';
     435         me.todayCls = me.baseCls + '-today';
     436         
     437         
     438         if (!me.format) {
     439             me.format = Ext.Date.defaultFormat;
     440         }
     441         if (!me.dayNames) {
     442             me.dayNames = Ext.Date.dayNames;
     443         }
     444         me.dayNames = me.dayNames.slice(me.startDay).concat(me.dayNames.slice(0, me.startDay));
     445 
     446         me.callParent();
     447 
     448         me.value = me.value ? clearTime(me.value, true) : clearTime(new Date());
     449 
     450         me.initDisabledDays();
     451     },
     452 
     453     // Keep the tree structure correct for Ext.form.field.Picker input fields which poke a 'pickerField' reference down into their pop-up pickers.
     454     getRefOwner: function() {
     455         return this.pickerField || this.callParent();
     456     },
     457 
     458     getRefItems: function() {
     459         var results = [],
     460             monthBtn = this.monthBtn,
     461             todayBtn = this.todayBtn;
     462 
     463         if (monthBtn) {
     464             results.push(monthBtn);
     465         }
     466 
     467         if (todayBtn) {
     468             results.push(todayBtn);
     469         }
     470 
     471         return results;
     472     },
     473 
     474     beforeRender: function() {
     475         /*
     476          * days array for looping through 6 full weeks (6 weeks * 7 days)
     477          * Note that we explicitly force the size here so the template creates
     478          * all the appropriate cells.
     479          */
     480         var me = this,
     481             encode = Ext.String.htmlEncode,
     482             days = new Array(me.numDays),
     483             today = Ext.Date.format(new Date(), me.format);
     484 
     485         if (me.padding && !me.width) {
     486             me.cacheWidth();
     487         }
     488 
     489         me.monthBtn = new Ext.button.Split({
     490             ownerCt: me,
     491             ownerLayout: me.getComponentLayout(),
     492             text: '',
     493             tooltip: me.monthYearText,
     494             tabIndex: -1,
     495             ariaRole: 'presentation',
     496             listeners: {
     497                 click: me.doShowMonthPicker,
     498                 arrowclick: me.doShowMonthPicker,
     499                 scope: me
     500             }
     501         });
     502 
     503         me.hour = Ext.create('Ext.form.field.Number', {
     504             scope: me,
     505             ownerCt: me,
     506             editable : true,
     507             ownerLayout: me.getComponentLayout(),
     508             minValue: 0,
     509             maxValue: 23,
     510              70,
     511             style : {float:"left"},
     512             enableKeyEvents: true,
     513             listeners: {
     514                  keyup: function(field, e){
     515                      if (field.getValue() > 23){
     516                          e.stopEvent();
     517                          field.setValue(23);
     518                      }
     519                  }
     520              }
     521         });
     522         
     523         me.minute = Ext.create('Ext.form.field.Number', {
     524             scope: me,
     525             ownerCt: me,
     526             style : {float:"left"},
     527             ownerLayout: me.getComponentLayout(),
     528             minValue: 0,
     529             maxValue: 59,
     530             editable : true,
     531              70,
     532             enableKeyEvents: true,
     533             listeners: {
     534                 keyup: function(field, e){
     535                     if (field.getValue() > 59){
     536                         e.stopEvent();
     537                         field.setValue(59);
     538                     }
     539                 }
     540             }
     541         });
     542         
     543       me.second = Ext.create('Ext.form.field.Number', {
     544             scope: me,
     545             ownerCt: me,
     546             editable : true,
     547             style : {float:"left"},
     548             ownerLayout: me.getComponentLayout(),
     549             minValue: 0,
     550             maxValue: 59,
     551              70,
     552             enableKeyEvents: true,
     553             listeners: {
     554                 keyup: function(field, e){
     555                     if (field.getValue() > 59){
     556                         e.stopEvent();
     557                         field.setValue(59);
     558                     }
     559                 }
     560             }
     561         });
     562        me.okQueDingBtn = new Ext.button.Button({  
     563             ownerCt: me,  
     564             ownerLayout: me.getComponentLayout(),  
     565             text: me.okText,  
     566             tooltip: me.okTip,  
     567             tooltipType:'title',  
     568             handler:me.okQueDingHandler,//确认按钮的事件委托  
     569             scope: me  
     570         });  
     571         if (me.showToday) {
     572             me.todayBtn = new Ext.button.Button({
     573                 ui: me.footerButtonUI,
     574                 ownerCt: me,
     575                 ownerLayout: me.getComponentLayout(),
     576                 text: Ext.String.format(me.todayText, today),
     577                 tooltip: Ext.String.format(me.todayTip, today),
     578                 tooltipType: 'title',
     579                 tabIndex: -1,
     580                 ariaRole: 'presentation',
     581                 handler: me.selectToday,
     582                 scope: me
     583             });
     584         }
     585 
     586         me.callParent();
     587 
     588         Ext.applyIf(me, {
     589             renderData: {}
     590         });
     591 
     592         Ext.apply(me.renderData, {
     593             dayNames: me.dayNames,
     594             showToday: me.showToday,
     595             prevText: encode(me.prevText),
     596             nextText: encode(me.nextText),
     597             todayText: encode(me.todayText),
     598             ariaMinText: encode(me.ariaMinText),
     599             ariaMaxText: encode(me.ariaMaxText),
     600             ariaDisabledDaysText: encode(me.ariaDisabledDaysText),
     601             ariaDisabledDatesText: encode(me.ariaDisabledDatesText),
     602             days: days
     603         });
     604 
     605         me.protoEl.unselectable();
     606     },
     607 
     608     cacheWidth: function() {
     609         var me = this,
     610             padding = me.parseBox(me.padding),
     611             widthEl = Ext.getBody().createChild({
     612                 cls: me.baseCls + ' ' + me.borderBoxCls,
     613                 style: 'position:absolute;top:-1000px;left:-1000px;'
     614             });
     615 
     616         me.self.prototype.width = widthEl.getWidth() + padding.left + padding.right;
     617         widthEl.destroy();
     618     },
     619 
     620     /**
     621      * @inheritdoc
     622      * @private
     623      */
     624     onRender: function(container, position) {
     625         var me = this;
     626 
     627         me.callParent(arguments);
     628 
     629         me.cells = me.eventEl.select('tbody td');
     630         me.textNodes = me.eventEl.query('tbody td div');
     631         
     632         me.eventEl.set({ 'aria-labelledby': me.monthBtn.id });
     633 
     634         me.mon(me.eventEl, {
     635             scope: me,
     636             mousewheel: me.handleMouseWheel,
     637             click: {
     638                 fn: me.handleDateClick,
     639                 delegate: 'div.' + me.baseCls + '-date'
     640             }
     641         });
     642         
     643     },
     644 
     645     /**
     646      * @inheritdoc
     647      * @private
     648      */
     649     initEvents: function(){
     650         var me = this,
     651             pickerField = me.pickerField,
     652             eDate = Ext.Date,
     653             day = eDate.DAY;
     654 
     655         me.callParent();
     656 
     657         // If we're part of a date field, don't allow us to focus, the field will
     658         // handle that. If we are standalone, then allow the default behaviour
     659         // to occur to receive focus
     660         if (pickerField) {
     661             me.el.on('mousedown', me.onMouseDown, me);
     662         }
     663 
     664         me.prevRepeater = new Ext.util.ClickRepeater(me.prevEl, {
     665             handler: me.showPrevMonth,
     666             scope: me,
     667             preventDefault: true,
     668             stopDefault: true
     669         });
     670 
     671         me.nextRepeater = new Ext.util.ClickRepeater(me.nextEl, {
     672             handler: me.showNextMonth,
     673             scope: me,
     674             preventDefault: true,
     675             stopDefault: true
     676         });
     677 
     678         me.keyNav = new Ext.util.KeyNav(me.eventEl, Ext.apply({
     679             scope: me,
     680 
     681             left: function(e) {
     682                 if (e.ctrlKey) {
     683                     me.showPrevMonth();
     684                 } else {
     685                     me.update(eDate.add(me.activeDate, day, -1));
     686                 }
     687             },
     688 
     689             right: function(e){
     690                 if (e.ctrlKey) {
     691                     me.showNextMonth();
     692                 } else {
     693                     me.update(eDate.add(me.activeDate, day, 1));
     694                 }
     695             },
     696 
     697             up: function(e) {
     698                 if (e.ctrlKey) {
     699                     me.showNextYear();
     700                 } else {
     701                     me.update(eDate.add(me.activeDate, day, -7));
     702                 }
     703             },
     704 
     705             down: function(e) {
     706                 if (e.ctrlKey) {
     707                     me.showPrevYear();
     708                 } else {
     709                     me.update(eDate.add(me.activeDate, day, 7));
     710                 }
     711             },
     712 
     713             pageUp: function(e) {
     714                 if (e.ctrlKey) {
     715                     me.showPrevYear();
     716                 } else {
     717                     me.showPrevMonth();
     718                 }
     719             },
     720 
     721             pageDown: function(e) {
     722                 if (e.ctrlKey) {
     723                     me.showNextYear();
     724                 } else {
     725                     me.showNextMonth();
     726                 }
     727             },
     728 
     729             tab: function(e) {
     730                 // When the picker is floating and attached to an input field, its
     731                 // 'select' handler will focus the inputEl so when navigation happens
     732                 // it does so as if the input field was focused all the time.
     733                 // This is the desired behavior and we try not to interfere with it
     734                 // in the picker itself, see below.
     735                 me.handleTabClick(e);
     736                 
     737                 // Allow default behaviour of TAB - it MUST be allowed to navigate.
     738                 return true;
     739             },
     740 
     741             enter: function(e) {
     742                 me.handleDateClick(e, me.activeCell.firstChild);
     743             },
     744 
     745             space: function() {
     746                 me.setValue(new Date(me.activeCell.firstChild.dateValue));
     747                 var startValue = me.startValue,
     748                     value = me.value,
     749                     pickerValue;
     750 
     751                 if (pickerField) {
     752                     pickerValue = pickerField.getValue();
     753                     if (pickerValue && startValue && pickerValue.getTime() === value.getTime()) {
     754                         pickerField.setValue(startValue);
     755                     } else {
     756                         pickerField.setValue(value);
     757                     }
     758                 }
     759             },
     760 
     761             home: function(e) {
     762                 me.update(eDate.getFirstDateOfMonth(me.activeDate));
     763             },
     764 
     765             end: function(e) {
     766                 me.update(eDate.getLastDateOfMonth(me.activeDate));
     767             }
     768         }, me.keyNavConfig));
     769 
     770         if (me.disabled) {
     771             me.syncDisabled(true);
     772         }
     773         me.update(me.value);
     774     },
     775 
     776     onMouseDown: function(e) {
     777         e.preventDefault();
     778     },
     779 
     780     handleTabClick: function (e) {
     781         var me = this,
     782             t = me.getSelectedDate(me.activeDate),
     783             handler = me.handler;
     784 
     785         // The following code is like handleDateClick without the e.stopEvent()
     786         if (!me.disabled && t.dateValue && !Ext.fly(t.parentNode).hasCls(me.disabledCellCls)) {
     787             me.setValue(new Date(t.dateValue));
     788             me.fireEvent('select', me, me.value);
     789             if (handler) {
     790                 handler.call(me.scope || me, me, me.value);
     791             }
     792             me.onSelect();
     793         }
     794     },
     795 
     796     getSelectedDate: function (date) {
     797         var me = this,
     798             t = date.getTime(),
     799             cells = me.cells,
     800             cls = me.selectedCls,
     801             cellItems = cells.elements,
     802             cLen = cellItems.length,
     803             cell, c;
     804 
     805         cells.removeCls(cls);
     806 
     807         for (c = 0; c < cLen; c++) {
     808             cell = cellItems[c].firstChild;
     809             if (cell.dateValue === t) {
     810                 return cell;
     811             }
     812         }
     813         return null;
     814     },
     815 
     816     /**
     817      * Setup the disabled dates regex based on config options
     818      * @private
     819      */
     820     initDisabledDays: function() {
     821         var me = this,
     822             dd = me.disabledDates,
     823             re = '(?:',
     824             len,
     825             d, dLen, dI;
     826 
     827         if(!me.disabledDatesRE && dd){
     828                 len = dd.length - 1;
     829 
     830             dLen = dd.length;
     831 
     832             for (d = 0; d < dLen; d++) {
     833                 dI = dd[d];
     834 
     835                 re += Ext.isDate(dI) ? '^' + Ext.String.escapeRegex(Ext.Date.dateFormat(dI, me.format)) + '$' : dI;
     836                 if (d !== len) {
     837                     re += '|';
     838                 }
     839             }
     840 
     841             me.disabledDatesRE = new RegExp(re + ')');
     842         }
     843     },
     844 
     845     /**
     846      * Replaces any existing disabled dates with new values and refreshes the DatePicker.
     847      * @param {String[]/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config for
     848      * details on supported values), or a JavaScript regular expression used to disable a pattern of dates.
     849      * @return {Ext.picker.Date} this
     850      */
     851     setDisabledDates: function(dd) {
     852         var me = this;
     853 
     854         if (Ext.isArray(dd)) {
     855             me.disabledDates = dd;
     856             me.disabledDatesRE = null;
     857         } else {
     858             me.disabledDatesRE = dd;
     859         }
     860         me.initDisabledDays();
     861         me.update(me.value, true);
     862         return me;
     863     },
     864 
     865     /**
     866      * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.
     867      * @param {Number[]} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config for details
     868      * on supported values.
     869      * @return {Ext.picker.Date} this
     870      */
     871     setDisabledDays: function(dd) {
     872         this.disabledDays = dd;
     873         return this.update(this.value, true);
     874     },
     875 
     876     /**
     877      * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.
     878      * @param {Date} value The minimum date that can be selected
     879      * @return {Ext.picker.Date} this
     880      */
     881     setMinDate: function(dt) {
     882         this.minDate = dt;
     883         return this.update(this.value, true);
     884     },
     885 
     886     /**
     887      * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.
     888      * @param {Date} value The maximum date that can be selected
     889      * @return {Ext.picker.Date} this
     890      */
     891     setMaxDate: function(dt) {
     892         this.maxDate = dt;
     893         return this.update(this.value, true);
     894     },
     895 
     896     /**
     897      * Sets the value of the date field
     898      * @param {Date} value The date to set
     899      * @return {Ext.picker.Date} this
     900      */
     901     setValue: function(value) {
     902         // If passed a null value just pass in a new date object.
     903         this.value = Ext.Date.clearTime(value || new Date(), true);
     904         return this.update(this.value);
     905     },
     906 
     907     /**
     908      * Gets the current selected value of the date field
     909      * @return {Date} The selected date
     910      */
     911     getValue: function() {
     912         return this.value;
     913     },
     914 
     915     //<locale type="function">
     916     /**
     917      * Gets a single character to represent the day of the week
     918      * @return {String} The character
     919      */
     920     getDayInitial: function(value) {
     921         return value.substr(0,1);
     922     },
     923     //</locale>
     924 
     925     /**
     926      * @inheritdoc
     927      * @private
     928      */
     929     onEnable: function() {
     930         var me = this;
     931 
     932         me.callParent();
     933         me.syncDisabled(false);
     934         me.update(me.activeDate);
     935 
     936     },
     937 
     938     /**
     939      * @inheritdoc
     940      * @private
     941      */
     942     onShow: function() {
     943         var me = this;
     944 
     945         me.callParent();
     946         me.syncDisabled(false);
     947         if (me.pickerField) {
     948             me.startValue = me.pickerField.getValue();
     949         }
     950     },
     951     
     952     /**
     953      * @inheritdoc
     954      * @private
     955      */
     956     onHide: function() {
     957         this.callParent();
     958         this.syncDisabled(true);
     959     },
     960 
     961     /**
     962      * @inheritdoc
     963      * @private
     964      */
     965     onDisable: function() {
     966         this.callParent();
     967         this.syncDisabled(true);
     968     },
     969 
     970     /**
     971      * Get the current active date.
     972      * @private
     973      * @return {Date} The active date
     974      */
     975     getActive: function(){
     976         return this.activeDate || this.value;
     977     },
     978 
     979     /**
     980      * Run any animation required to hide/show the month picker.
     981      * @private
     982      * @param {Boolean} isHide True if it's a hide operation
     983      */
     984     runAnimation: function(isHide){
     985         var picker = this.monthPicker,
     986             options = {
     987                 duration: 200,
     988                 callback: function() {
     989                     picker.setVisible(!isHide);
     990                 }
     991             };
     992 
     993         if (isHide) {
     994             picker.el.slideOut('t', options);
     995         } else {
     996             picker.el.slideIn('t', options);
     997         }
     998     },
     999 
    1000     /**
    1001      * Hides the month picker, if it's visible.
    1002      * @param {Boolean} [animate] Indicates whether to animate this action. If the animate
    1003      * parameter is not specified, the behavior will use {@link #disableAnim} to determine
    1004      * whether to animate or not.
    1005      * @return {Ext.picker.Date} this
    1006      */
    1007     hideMonthPicker: function(animate){
    1008         var me = this,
    1009             picker = me.monthPicker;
    1010 
    1011         if (picker && picker.isVisible()) {
    1012             if (me.shouldAnimate(animate)) {
    1013                 me.runAnimation(true);
    1014             } else {
    1015                 picker.hide();
    1016             }
    1017         }
    1018         return me;
    1019     },
    1020     
    1021     doShowMonthPicker: function(){
    1022         // Wrap in an extra call so we can prevent the button
    1023         // being passed as an animation parameter.
    1024         this.showMonthPicker();
    1025     },
    1026     
    1027     doHideMonthPicker: function() {
    1028         // Wrap in an extra call so we can prevent this
    1029         // being passed as an animation parameter
    1030         this.hideMonthPicker();
    1031     },
    1032 
    1033     /**
    1034      * Show the month picker
    1035      * @param {Boolean} [animate] Indicates whether to animate this action. If the animate
    1036      * parameter is not specified, the behavior will use {@link #disableAnim} to determine
    1037      * whether to animate or not.
    1038      * @return {Ext.picker.Date} this
    1039      */
    1040     showMonthPicker: function(animate) {
    1041         var me = this,
    1042             el = me.el,
    1043             picker;
    1044         
    1045         if (me.rendered && !me.disabled) {
    1046             picker = me.createMonthPicker();            
    1047             if (!picker.isVisible()) {
    1048                 picker.setValue(me.getActive());
    1049                 picker.setSize(el.getSize());
    1050 
    1051                 // Null out floatParent so that the [-1, -1] position is not made relative to this
    1052                 picker.floatParent = null;
    1053                 picker.setPosition(-el.getBorderWidth('l'), -el.getBorderWidth('t'));
    1054                 if (me.shouldAnimate(animate)) {
    1055                     me.runAnimation(false);
    1056                 } else {
    1057                     picker.show();
    1058                 }
    1059             }
    1060         }
    1061         return me;
    1062     },
    1063     
    1064     /**
    1065      * Checks whether a hide/show action should animate
    1066      * @private
    1067      * @param {Boolean} [animate] A possible animation value
    1068      * @return {Boolean} Whether to animate the action
    1069      */
    1070     shouldAnimate: function(animate) {
    1071         return Ext.isDefined(animate) ? animate : !this.disableAnim;
    1072     },
    1073 
    1074     /**
    1075      * Create the month picker instance
    1076      * @private
    1077      * @return {Ext.picker.Month} picker
    1078      */
    1079     createMonthPicker: function() {
    1080         var me = this,
    1081             picker = me.monthPicker;
    1082 
    1083         if (!picker) {
    1084             me.monthPicker = picker = new Ext.picker.Month({
    1085                 renderTo: me.el,
    1086                 // We need to set the ownerCmp so that owns() can correctly
    1087                 // match up the component hierarchy so that focus does not leave
    1088                 // an owning picker field if/when this gets focus.
    1089                 ownerCmp: me,
    1090                 floating: true,
    1091                 padding: me.padding,
    1092                 shadow: false,
    1093                 small: me.showToday === false,
    1094                 footerButtonUI: me.footerButtonUI,
    1095                 listeners: {
    1096                     scope: me,
    1097                     cancelclick: me.onCancelClick,
    1098                     okclick: me.onOkClick,
    1099                     yeardblclick: me.onOkClick,
    1100                     monthdblclick: me.onOkClick
    1101                 }
    1102             });
    1103             if (!me.disableAnim) {
    1104                 // hide the element if we're animating to prevent an initial flicker
    1105                 picker.el.setStyle('display', 'none');
    1106             }
    1107             picker.hide();
    1108             me.on('beforehide', me.doHideMonthPicker, me);
    1109         }
    1110         return picker;
    1111     },
    1112 
    1113     /**
    1114      * Respond to an ok click on the month picker
    1115      * @private
    1116      */
    1117     onOkClick: function(picker, value) {
    1118         var me = this,
    1119             month = value[0],
    1120             year = value[1],
    1121             date = new Date(year, month, me.getActive().getDate());
    1122 
    1123         if (date.getMonth() !== month) {
    1124             // 'fix' the JS rolling date conversion if needed
    1125             date = Ext.Date.getLastDateOfMonth(new Date(year, month, 1));
    1126         }
    1127         me.setValue(date);
    1128         me.hideMonthPicker();
    1129     },
    1130 
    1131     /**
    1132      * Respond to a cancel click on the month picker
    1133      * @private
    1134      */
    1135     onCancelClick: function() {
    1136         this.selectedUpdate(this.activeDate);
    1137         this.hideMonthPicker();
    1138     },
    1139 
    1140     /**
    1141      * Show the previous month.
    1142      * @param {Object} e
    1143      * @return {Ext.picker.Date} this
    1144      */
    1145     showPrevMonth: function(e) {
    1146         return this.setValue(Ext.Date.add(this.activeDate, Ext.Date.MONTH, -1));
    1147     },
    1148 
    1149     /**
    1150      * Show the next month.
    1151      * @param {Object} e
    1152      * @return {Ext.picker.Date} this
    1153      */
    1154     showNextMonth: function(e) {
    1155         return this.setValue(Ext.Date.add(this.activeDate, Ext.Date.MONTH, 1));
    1156     },
    1157 
    1158     /**
    1159      * Show the previous year.
    1160      * @return {Ext.picker.Date} this
    1161      */
    1162     showPrevYear: function() {
    1163         return this.setValue(Ext.Date.add(this.activeDate, Ext.Date.YEAR, -1));
    1164     },
    1165 
    1166     /**
    1167      * Show the next year.
    1168      * @return {Ext.picker.Date} this
    1169      */
    1170     showNextYear: function() {
    1171         return this.setValue(Ext.Date.add(this.activeDate, Ext.Date.YEAR, 1));
    1172     },
    1173 
    1174     /**
    1175      * Respond to the mouse wheel event
    1176      * @private
    1177      * @param {Ext.event.Event} e
    1178      */
    1179     handleMouseWheel: function(e) {
    1180         e.stopEvent();
    1181         if(!this.disabled){
    1182             var delta = e.getWheelDelta();
    1183             if(delta > 0){
    1184                 this.showPrevMonth();
    1185             } else if(delta < 0){
    1186                 this.showNextMonth();
    1187             }
    1188         }
    1189     },
    1190 
    1191     /**
    1192      * Respond to a date being clicked in the picker
    1193      * @private
    1194      * @param {Ext.event.Event} e
    1195      * @param {HTMLElement} t
    1196      */
    1197     handleDateClick: function(e, t) {
    1198         var me = this,
    1199             handler = me.handler;
    1200 
    1201         e.stopEvent();
    1202         if(!me.disabled && t.dateValue && !Ext.fly(t.parentNode).hasCls(me.disabledCellCls)){
    1203             me.setValue(new Date(t.dateValue));
    1204             me.fireEvent('select', me, me.value);
    1205             if (handler) {
    1206                 handler.call(me.scope || me, me, me.value);
    1207             }
    1208             // event handling is turned off on hide
    1209             // when we are using the picker in a field
    1210             // therefore onSelect comes AFTER the select
    1211             // event.
    1212             me.onSelect();
    1213         }
    1214     },
    1215 
    1216     /**
    1217      * Perform any post-select actions
    1218      * @private
    1219      */
    1220     onSelect: function() {
    1221         if (this.hideOnSelect) {
    1222              this.hide();
    1223          }
    1224     },
    1225 
    1226     /**
    1227      * Sets the current value to today.
    1228      * @return {Ext.picker.Date} this
    1229      */
    1230     selectToday: function() {
    1231         var me = this,
    1232             btn = me.todayBtn,
    1233             handler = me.handler;
    1234 
    1235         if (btn && !btn.disabled) {
    1236             me.setValue(Ext.Date.clearTime(new Date()));
    1237             me.fireEvent('select', me, me.value);
    1238             if (handler) {
    1239                 handler.call(me.scope || me, me, me.value);
    1240             }
    1241             me.onSelect();
    1242         }
    1243         return me;
    1244     },
    1245 
    1246     /**
    1247      * Update the selected cell
    1248      * @private
    1249      * @param {Date} date The new date
    1250      */
    1251     selectedUpdate: function(date) {
    1252         var me        = this,
    1253             t         = date.getTime(),
    1254             cells     = me.cells,
    1255             cls       = me.selectedCls,
    1256             c,
    1257             cLen      = cells.getCount(),
    1258             cell;
    1259         
    1260         me.eventEl.dom.setAttribute('aria-busy', 'true');
    1261         
    1262         cell = me.activeCell;
    1263         
    1264         if (cell) {
    1265             Ext.fly(cell).removeCls(cls);
    1266             cell.setAttribute('aria-selected', false);
    1267         }
    1268 
    1269         for (c = 0; c < cLen; c++) {
    1270             cell = cells.item(c);
    1271 
    1272             if (me.textNodes[c].dateValue === t) {
    1273                 me.activeCell = cell.dom;
    1274                 me.eventEl.dom.setAttribute('aria-activedescendant', cell.dom.id);
    1275                 cell.dom.setAttribute('aria-selected', true);
    1276                 cell.addCls(cls);
    1277                 me.fireEvent('highlightitem', me, cell);
    1278                 break;
    1279             }
    1280         }
    1281         
    1282         me.eventEl.dom.removeAttribute('aria-busy');
    1283     },
    1284 
    1285     /**
    1286      * Update the contents of the picker for a new month
    1287      * @private
    1288      * @param {Date} date The new date
    1289      */
    1290     fullUpdate: function(date) {
    1291         var me = this,
    1292             cells = me.cells.elements,
    1293             textNodes = me.textNodes,
    1294             disabledCls = me.disabledCellCls,
    1295             eDate = Ext.Date,
    1296             i = 0,
    1297             extraDays = 0,
    1298             newDate = +eDate.clearTime(date, true),
    1299             today = +eDate.clearTime(new Date()),
    1300             min = me.minDate ? eDate.clearTime(me.minDate, true) : Number.NEGATIVE_INFINITY,
    1301             max = me.maxDate ? eDate.clearTime(me.maxDate, true) : Number.POSITIVE_INFINITY,
    1302             ddMatch = me.disabledDatesRE,
    1303             ddText = me.disabledDatesText,
    1304             ddays = me.disabledDays ? me.disabledDays.join('') : false,
    1305             ddaysText = me.disabledDaysText,
    1306             format = me.format,
    1307             days = eDate.getDaysInMonth(date),
    1308             firstOfMonth = eDate.getFirstDateOfMonth(date),
    1309             startingPos = firstOfMonth.getDay() - me.startDay,
    1310             previousMonth = eDate.add(date, eDate.MONTH, -1),
    1311             ariaTitleDateFormat = me.ariaTitleDateFormat,
    1312             prevStart, current, disableToday, tempDate, setCellClass, html, cls,
    1313             formatValue, value;
    1314 
    1315         if (startingPos < 0) {
    1316             startingPos += 7;
    1317         }
    1318 
    1319         days += startingPos;
    1320         prevStart = eDate.getDaysInMonth(previousMonth) - startingPos;
    1321         current = new Date(previousMonth.getFullYear(), previousMonth.getMonth(), prevStart, me.initHour);
    1322 
    1323         if (me.showToday) {
    1324             tempDate = eDate.clearTime(new Date());
    1325             disableToday = (tempDate < min || tempDate > max ||
    1326                 (ddMatch && format && ddMatch.test(eDate.dateFormat(tempDate, format))) ||
    1327                 (ddays && ddays.indexOf(tempDate.getDay()) !== -1));
    1328 
    1329             if (!me.disabled) {
    1330                 me.todayBtn.setDisabled(disableToday);
    1331             }
    1332         }
    1333 
    1334         setCellClass = function(cellIndex, cls){
    1335             var cell = cells[cellIndex],
    1336                 describedBy = [];
    1337             
    1338             // Cells are not rendered with ids
    1339             if (!cell.hasAttribute('id')) {
    1340                 cell.setAttribute('id', me.id + '-cell-' + cellIndex);
    1341             }
    1342             
    1343             // store dateValue number as an expando
    1344             value = +eDate.clearTime(current, true);
    1345             cell.firstChild.dateValue = value;
    1346             
    1347             cell.setAttribute('aria-label', eDate.format(current, ariaTitleDateFormat));
    1348             
    1349             // Here and below we can't use title attribute instead of data-qtip
    1350             // because JAWS will announce title value before cell content
    1351             // which is not what we need. Also we are using aria-describedby attribute
    1352             // and not placing the text in aria-label because some cells may have
    1353             // compound descriptions (like Today and Disabled day).
    1354             cell.removeAttribute('aria-describedby');
    1355             cell.removeAttribute('data-qtip');
    1356             
    1357             if (value === today) {
    1358                 cls += ' ' + me.todayCls;
    1359                 describedBy.push(me.id + '-todayText');
    1360             }
    1361             
    1362             if (value === newDate) {
    1363                 me.activeCell = cell;
    1364                 me.eventEl.dom.setAttribute('aria-activedescendant', cell.id);
    1365                 cell.setAttribute('aria-selected', true);
    1366                 cls += ' ' + me.selectedCls;
    1367                 me.fireEvent('highlightitem', me, cell);
    1368             }
    1369             else {
    1370                 cell.setAttribute('aria-selected', false);
    1371             }
    1372 
    1373             if (value < min) {
    1374                 cls += ' ' + disabledCls;
    1375                 describedBy.push(me.id + '-ariaMinText');
    1376                 cell.setAttribute('data-qtip', me.minText);
    1377             }
    1378             else if (value > max) {
    1379                 cls += ' ' + disabledCls;
    1380                 describedBy.push(me.id + '-ariaMaxText');
    1381                 cell.setAttribute('data-qtip', me.maxText);
    1382             }
    1383             else if (ddays && ddays.indexOf(current.getDay()) !== -1){
    1384                 cell.setAttribute('data-qtip', ddaysText);
    1385                 describedBy.push(me.id + '-ariaDisabledDaysText');
    1386                 cls += ' ' + disabledCls;
    1387             }
    1388             else if (ddMatch && format){
    1389                 formatValue = eDate.dateFormat(current, format);
    1390                 if(ddMatch.test(formatValue)){
    1391                     cell.setAttribute('data-qtip', ddText.replace('%0', formatValue));
    1392                     describedBy.push(me.id + '-ariaDisabledDatesText');
    1393                     cls += ' ' + disabledCls;
    1394                 }
    1395             }
    1396             
    1397             if (describedBy.length) {
    1398                 cell.setAttribute('aria-describedby', describedBy.join(' '));
    1399             }
    1400             
    1401             cell.className = cls + ' ' + me.cellCls;
    1402         };
    1403         
    1404         me.eventEl.dom.setAttribute('aria-busy', 'true');
    1405 
    1406         for (; i < me.numDays; ++i) {
    1407             if (i < startingPos) {
    1408                 html = (++prevStart);
    1409                 cls = me.prevCls;
    1410             } else if (i >= days) {
    1411                 html = (++extraDays);
    1412                 cls = me.nextCls;
    1413             } else {
    1414                 html = i - startingPos + 1;
    1415                 cls = me.activeCls;
    1416             }
    1417             textNodes[i].innerHTML = html;
    1418             current.setDate(current.getDate() + 1);
    1419             setCellClass(i, cls);
    1420         }
    1421         
    1422         me.eventEl.dom.removeAttribute('aria-busy');
    1423 
    1424         me.monthBtn.setText(Ext.Date.format(date, me.monthYearFormat));
    1425     },
    1426 
    1427     /**
    1428      * Update the contents of the picker
    1429      * @private
    1430      * @param {Date} date The new date
    1431      * @param {Boolean} forceRefresh True to force a full refresh
    1432      */
    1433     update: function(date, forceRefresh) {
    1434         var me = this,
    1435             active = me.activeDate;
    1436         //添加时间相关
    1437         date.setHours(me.hour.getValue());
    1438         date.setMinutes(me.minute.getValue());
    1439         date.setSeconds(me.second.getValue());
    1440         
    1441         if (me.rendered) {
    1442             me.activeDate = date;
    1443             if (!forceRefresh && active && me.el &&
    1444                     active.getMonth() === date.getMonth() &&
    1445                     active.getFullYear() === date.getFullYear()) {
    1446                 me.selectedUpdate(date, active);
    1447             } else {
    1448                 me.fullUpdate(date, active);
    1449             }
    1450         }
    1451         return me;
    1452     },
    1453    /** 
    1454      * 确认 按钮触发的调用 
    1455      */  
    1456     okQueDingHandler : function(){  
    1457         var me = this,  
    1458             btn = me.okQueDingBtn;  
    1459   
    1460         if(btn && !btn.disabled){  
    1461             me.setValue(this.getValue());  
    1462             me.fireEvent('select', me, me.value);  
    1463             me.onSelect();  
    1464         }  
    1465         return me;  
    1466     },  
    1467     /**
    1468      * @private
    1469      * @inheritdoc
    1470      */
    1471     beforeDestroy: function() {
    1472         var me = this;
    1473 
    1474         if (me.rendered) {
    1475             Ext.destroy(
    1476                 me.keyNav,
    1477                 me.monthPicker,
    1478                 me.monthBtn,
    1479                 me.nextRepeater,
    1480                 me.prevRepeater,
    1481                 me.todayBtn,
    1482                 me.okQueDingBtn,
    1483                 me.todayElSpan
    1484             );
    1485             delete me.textNodes;
    1486             delete me.cells.elements;
    1487         }
    1488         me.callParent();
    1489     },
    1490 
    1491     privates: {
    1492         // Do the job of a container layout at this point even though we are not a Container.
    1493         // TODO: Refactor as a Container.
    1494         finishRenderChildren: function () {
    1495             var me = this;
    1496 
    1497             me.callParent();
    1498             me.monthBtn.finishRender();
    1499             me.okQueDingBtn.finishRender();  
    1500             if (me.showToday) {
    1501                 me.todayBtn.finishRender();
    1502             }
    1503             //添加时间相关
    1504             this.hour.finishRender();
    1505             this.minute.finishRender();
    1506             this.second.finishRender();
    1507         },
    1508         
    1509         getFocusEl: function() {
    1510             return this.eventEl;
    1511         },
    1512 
    1513         /**
    1514          * Set the disabled state of various internal components
    1515          * @param {Boolean} disabled
    1516          * @private
    1517          */
    1518         syncDisabled: function (disabled) {
    1519             var me = this,
    1520                 keyNav = me.keyNav;
    1521 
    1522             // If we have one, we have all
    1523             if (keyNav) {
    1524                 keyNav.setDisabled(disabled);
    1525                 me.prevRepeater.setDisabled(disabled);
    1526                 me.nextRepeater.setDisabled(disabled);
    1527                 if (me.todayBtn) {
    1528                     me.todayBtn.setDisabled(disabled);
    1529                 }
    1530             }
    1531         }
    1532     }
    1533 });

     11、下面则是扩展出来的一个DeteTimeField控件

     完整的DeteTimeField.js代码

      1 /**
      2  * @docauthor Jason Johnston <jason@sencha.com>
      3  *
      4  * Provides a date input field with a {@link Ext.picker.Date date picker} dropdown and automatic date
      5  * validation.
      6  *
      7  * This field recognizes and uses the JavaScript Date object as its main {@link #value} type. In addition,
      8  * it recognizes string values which are parsed according to the {@link #format} and/or {@link #altFormats}
      9  * configs. These may be reconfigured to use date formats appropriate for the user's locale.
     10  *
     11  * The field may be limited to a certain range of dates by using the {@link #minValue}, {@link #maxValue},
     12  * {@link #disabledDays}, and {@link #disabledDates} config parameters. These configurations will be used both
     13  * in the field's validation, and in the date picker dropdown by preventing invalid dates from being selected.
     14  *
     15  * # Example usage
     16  *
     17  *     @example
     18  *     Ext.create('Ext.form.Panel', {
     19  *         renderTo: Ext.getBody(),
     20  *          300,
     21  *         bodyPadding: 10,
     22  *         title: 'Dates',
     23  *         items: [{
     24  *             xtype: 'datefield',
     25  *             anchor: '100%',
     26  *             fieldLabel: 'From',
     27  *             name: 'from_date',
     28  *             maxValue: new Date()  // limited to the current date or prior
     29  *         }, {
     30  *             xtype: 'datefield',
     31  *             anchor: '100%',
     32  *             fieldLabel: 'To',
     33  *             name: 'to_date',
     34  *             value: new Date()  // defaults to today
     35  *         }]
     36  *     });
     37  *
     38  * # Date Formats Examples
     39  *
     40  * This example shows a couple of different date format parsing scenarios. Both use custom date format
     41  * configurations; the first one matches the configured `format` while the second matches the `altFormats`.
     42  *
     43  *     @example
     44  *     Ext.create('Ext.form.Panel', {
     45  *         renderTo: Ext.getBody(),
     46  *          300,
     47  *         bodyPadding: 10,
     48  *         title: 'Dates',
     49  *         items: [{
     50  *             xtype: 'datefield',
     51  *             anchor: '100%',
     52  *             fieldLabel: 'Date',
     53  *             name: 'date',
     54  *             // The value matches the format; will be parsed and displayed using that format.
     55  *             format: 'm d Y',
     56  *             value: '2 4 1978'
     57  *         }, {
     58  *             xtype: 'datefield',
     59  *             anchor: '100%',
     60  *             fieldLabel: 'Date',
     61  *             name: 'date',
     62  *             // The value does not match the format, but does match an altFormat; will be parsed
     63  *             // using the altFormat and displayed using the format.
     64  *             format: 'm d Y',
     65  *             altFormats: 'm,d,Y|m.d.Y',
     66  *             value: '2.4.1978'
     67  *         }]
     68  *     });
     69  */
     70 Ext.define('Ext.ux.DateTimeField', {
     71     extend:'Ext.form.field.Picker',
     72     alias: 'widget.datetimefield',
     73     requires: ['Ext.ux.DateTimePicker'],
     74 
     75     //<locale>
     76     /**
     77      * @cfg {String} format
     78      * The default date format string which can be overriden for localization support. The format must be valid
     79      * according to {@link Ext.Date#parse}.
     80      */
     81     format : "m/d/Y",
     82     //</locale>
     83     //<locale>
     84     /**
     85      * @cfg {String} altFormats
     86      * Multiple date formats separated by "|" to try when parsing a user input value and it does not match the defined
     87      * format.
     88      */
     89     altFormats : "m/d/Y|n/j/Y|n/j/y|m/j/y|n/d/y|m/j/Y|n/d/Y|m-d-y|m-d-Y|m/d|m-d|md|mdy|mdY|d|Y-m-d|n-j|n/j",
     90     //</locale>
     91     //<locale>
     92     /**
     93      * @cfg {String} disabledDaysText
     94      * The tooltip to display when the date falls on a disabled day.
     95      */
     96     disabledDaysText : "Disabled",
     97     //</locale>
     98     //<locale>
     99     /**
    100      * @cfg {String} disabledDatesText
    101      * The tooltip text to display when the date falls on a disabled date.
    102      */
    103     disabledDatesText : "Disabled",
    104     //</locale>
    105     //<locale>
    106     /**
    107      * @cfg {String} minText
    108      * The error text to display when the date in the cell is before {@link #minValue}.
    109      */
    110     minText : "The date in this field must be equal to or after {0}",
    111     //</locale>
    112     //<locale>
    113     /**
    114      * @cfg {String} maxText
    115      * The error text to display when the date in the cell is after {@link #maxValue}.
    116      */
    117     maxText : "The date in this field must be equal to or before {0}",
    118     //</locale>
    119     //<locale>
    120     /**
    121      * @cfg {String} invalidText
    122      * The error text to display when the date in the field is invalid.
    123      */
    124     invalidText : "{0} is not a valid date - it must be in the format {1}",
    125     //</locale>
    126     /**
    127      * @cfg {String} [triggerCls='x-form-date-trigger']
    128      * An additional CSS class used to style the trigger button. The trigger will always get the class 'x-form-trigger'
    129      * and triggerCls will be **appended** if specified (default class displays a calendar icon).
    130      */
    131     triggerCls : Ext.baseCSSPrefix + 'form-date-trigger',
    132     /**
    133      * @cfg {Boolean} showToday
    134      * false to hide the footer area of the Date picker containing the Today button and disable the keyboard handler for
    135      * spacebar that selects the current date.
    136      */
    137     showToday : true,
    138     /**
    139      * @cfg {Date/String} minValue
    140      * The minimum allowed date. Can be either a Javascript date object or a string date in a valid format.
    141      */
    142     /**
    143      * @cfg {Date/String} maxValue
    144      * The maximum allowed date. Can be either a Javascript date object or a string date in a valid format.
    145      */
    146     /**
    147      * @cfg {Number[]} disabledDays
    148      * An array of days to disable, 0 based. Some examples:
    149      *
    150      *     // disable Sunday and Saturday:
    151      *     disabledDays:  [0, 6]
    152      *     // disable weekdays:
    153      *     disabledDays: [1,2,3,4,5]
    154      */
    155     /**
    156      * @cfg {String[]} disabledDates
    157      * An array of "dates" to disable, as strings. These strings will be used to build a dynamic regular expression so
    158      * they are very powerful. Some examples:
    159      *
    160      *     // disable these exact dates:
    161      *     disabledDates: ["03/08/2003", "09/16/2003"]
    162      *     // disable these days for every year:
    163      *     disabledDates: ["03/08", "09/16"]
    164      *     // only match the beginning (useful if you are using short years):
    165      *     disabledDates: ["^03/08"]
    166      *     // disable every day in March 2006:
    167      *     disabledDates: ["03/../2006"]
    168      *     // disable every day in every March:
    169      *     disabledDates: ["^03"]
    170      *
    171      * Note that the format of the dates included in the array should exactly match the {@link #format} config. In order
    172      * to support regular expressions, if you are using a {@link #format date format} that has "." in it, you will have
    173      * to escape the dot when restricting dates. For example: `["03\.08\.03"]`.
    174      */
    175 
    176     /**
    177      * @cfg {String} submitFormat
    178      * The date format string which will be submitted to the server. The format must be valid according to
    179      * {@link Ext.Date#parse}.
    180      *
    181      * Defaults to {@link #format}.
    182      */
    183 
    184     /**
    185      * @cfg {Boolean} useStrict
    186      * True to enforce strict date parsing to prevent the default Javascript "date rollover".
    187      * Defaults to the useStrict parameter set on Ext.Date
    188      * See {@link Ext.Date#parse}.
    189      */
    190     useStrict: undefined,
    191 
    192     // in the absence of a time value, a default value of 12 noon will be used
    193     // (note: 12 noon was chosen because it steers well clear of all DST timezone changes)
    194     initTime: '12', // 24 hour format
    195 
    196     initTimeFormat: 'H',
    197 
    198     matchFieldWidth: false,
    199     //<locale>
    200     /**
    201      * @cfg {Number} [startDay=undefined]
    202      * Day index at which the week should begin, 0-based.
    203      *
    204      * Defaults to `0` (Sunday).
    205      */
    206     startDay: 0,
    207     //</locale>
    208 
    209     /**
    210      * @inheritdoc
    211      */
    212     valuePublishEvent: ['select', 'blur'],
    213 
    214     initComponent : function(){
    215         var me = this,
    216             isString = Ext.isString,
    217             min, max;
    218 
    219         min = me.minValue;
    220         max = me.maxValue;
    221         if(isString(min)){
    222             me.minValue = me.parseDate(min);
    223         }
    224         if(isString(max)){
    225             me.maxValue = me.parseDate(max);
    226         }
    227         me.disabledDatesRE = null;
    228         me.initDisabledDays();
    229 
    230         me.callParent();
    231     },
    232 
    233     initValue: function() {
    234         var me = this,
    235             value = me.value;
    236 
    237         // If a String value was supplied, try to convert it to a proper Date
    238         if (Ext.isString(value)) {
    239             me.value = me.rawToValue(value);
    240         }
    241 
    242         me.callParent();
    243     },
    244 
    245     // private
    246     initDisabledDays : function(){
    247         if(this.disabledDates){
    248             var dd   = this.disabledDates,
    249                 len  = dd.length - 1,
    250                 re   = "(?:",
    251                 d,
    252                 dLen = dd.length,
    253                 date;
    254 
    255             for (d = 0; d < dLen; d++) {
    256                 date = dd[d];
    257 
    258                 re += Ext.isDate(date) ? '^' + Ext.String.escapeRegex(date.dateFormat(this.format)) + '$' : date;
    259                 if (d !== len) {
    260                     re += '|';
    261                 }
    262             }
    263 
    264             this.disabledDatesRE = new RegExp(re + ')');
    265         }
    266     },
    267 
    268     /**
    269      * Replaces any existing disabled dates with new values and refreshes the Date picker.
    270      * @param {String[]} disabledDates An array of date strings (see the {@link #disabledDates} config for details on
    271      * supported values) used to disable a pattern of dates.
    272      */
    273     setDisabledDates : function(disabledDates){
    274         var me = this,
    275             picker = me.picker;
    276 
    277         me.disabledDates = disabledDates;
    278         me.initDisabledDays();
    279         if (picker) {
    280             picker.setDisabledDates(me.disabledDatesRE);
    281         }
    282     },
    283 
    284     /**
    285      * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the Date picker.
    286      * @param {Number[]} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config for details on
    287      * supported values.
    288      */
    289     setDisabledDays : function(disabledDays){
    290         var picker = this.picker;
    291 
    292         this.disabledDays = disabledDays;
    293         if (picker) {
    294             picker.setDisabledDays(disabledDays);
    295         }
    296     },
    297 
    298     /**
    299      * Replaces any existing {@link #minValue} with the new value and refreshes the Date picker.
    300      * @param {Date} value The minimum date that can be selected
    301      */
    302     setMinValue : function(value){
    303         var me = this,
    304             picker = me.picker,
    305             minValue = (Ext.isString(value) ? me.parseDate(value) : value);
    306 
    307         me.minValue = minValue;
    308         if (picker) {
    309             picker.minText = Ext.String.format(me.minText, me.formatDate(me.minValue));
    310             picker.setMinDate(minValue);
    311         }
    312     },
    313 
    314     /**
    315      * Replaces any existing {@link #maxValue} with the new value and refreshes the Date picker.
    316      * @param {Date} value The maximum date that can be selected
    317      */
    318     setMaxValue : function(value){
    319         var me = this,
    320             picker = me.picker,
    321             maxValue = (Ext.isString(value) ? me.parseDate(value) : value);
    322 
    323         me.maxValue = maxValue;
    324         if (picker) {
    325             picker.maxText = Ext.String.format(me.maxText, me.formatDate(me.maxValue));
    326             picker.setMaxDate(maxValue);
    327         }
    328     },
    329 
    330     /**
    331      * Runs all of Date's validations and returns an array of any errors. Note that this first runs Text's validations,
    332      * so the returned array is an amalgamation of all field errors. The additional validation checks are testing that
    333      * the date format is valid, that the chosen date is within the min and max date constraints set, that the date
    334      * chosen is not in the disabledDates regex and that the day chosed is not one of the disabledDays.
    335      * @param {Object} [value] The value to get errors for (defaults to the current field value)
    336      * @return {String[]} All validation errors for this field
    337      */
    338     getErrors: function(value) {
    339         value = arguments.length > 0 ? value : this.formatDate(this.processRawValue(this.getRawValue()));
    340 
    341         var me = this,
    342             format = Ext.String.format,
    343             clearTime = Ext.Date.clearTime,
    344             errors = me.callParent([value]),
    345             disabledDays = me.disabledDays,
    346             disabledDatesRE = me.disabledDatesRE,
    347             minValue = me.minValue,
    348             maxValue = me.maxValue,
    349             len = disabledDays ? disabledDays.length : 0,
    350             i = 0,
    351             svalue,
    352             fvalue,
    353             day,
    354             time;
    355 
    356         
    357 
    358         if (value === null || value.length < 1) { // if it's blank and textfield didn't flag it then it's valid
    359              return errors;
    360         }
    361 
    362         svalue = value;
    363         value = me.parseDate(value);
    364         if (!value) {
    365             errors.push(format(me.invalidText, svalue, Ext.Date.unescapeFormat(me.format)));
    366             return errors;
    367         }
    368 
    369         time = value.getTime();
    370         if (minValue && time < clearTime(minValue).getTime()) {
    371             errors.push(format(me.minText, me.formatDate(minValue)));
    372         }
    373 
    374         if (maxValue && time > clearTime(maxValue).getTime()) {
    375             errors.push(format(me.maxText, me.formatDate(maxValue)));
    376         }
    377 
    378         if (disabledDays) {
    379             day = value.getDay();
    380 
    381             for(; i < len; i++) {
    382                 if (day === disabledDays[i]) {
    383                     errors.push(me.disabledDaysText);
    384                     break;
    385                 }
    386             }
    387         }
    388 
    389         fvalue = me.formatDate(value);
    390         if (disabledDatesRE && disabledDatesRE.test(fvalue)) {
    391             errors.push(format(me.disabledDatesText, fvalue));
    392         }
    393 
    394         return errors;
    395     },
    396 
    397     rawToValue: function(rawValue) {
    398         return this.parseDate(rawValue) || rawValue || null;
    399     },
    400 
    401     valueToRaw: function(value) {
    402         return this.formatDate(this.parseDate(value));
    403     },
    404 
    405     /**
    406      * @method setValue
    407      * Sets the value of the date field. You can pass a date object or any string that can be parsed into a valid date,
    408      * using {@link #format} as the date format, according to the same rules as {@link Ext.Date#parse} (the default
    409      * format used is "m/d/Y").
    410      *
    411      * Usage:
    412      *
    413      *     //All of these calls set the same date value (May 4, 2006)
    414      *
    415      *     //Pass a date object:
    416      *     var dt = new Date('5/4/2006');
    417      *     dateField.setValue(dt);
    418      *
    419      *     //Pass a date string (default format):
    420      *     dateField.setValue('05/04/2006');
    421      *
    422      *     //Pass a date string (custom format):
    423      *     dateField.format = 'Y-m-d';
    424      *     dateField.setValue('2006-05-04');
    425      *
    426      * @param {String/Date} date The date or valid date string
    427      * @return {Ext.form.field.Date} this
    428      */
    429 
    430     /**
    431      * Attempts to parse a given string value using a given {@link Ext.Date#parse date format}.
    432      * @param {String} value The value to attempt to parse
    433      * @param {String} format A valid date format (see {@link Ext.Date#parse})
    434      * @return {Date} The parsed Date object, or null if the value could not be successfully parsed.
    435      */
    436     safeParse : function(value, format) {
    437         var me = this,
    438             utilDate = Ext.Date,
    439             result = null,
    440             strict = me.useStrict,
    441             parsedDate;
    442 
    443         if (utilDate.formatContainsHourInfo(format)) {
    444             // if parse format contains hour information, no DST adjustment is necessary
    445             result = utilDate.parse(value, format, strict);
    446         } else {
    447             // set time to 12 noon, then clear the time
    448             parsedDate = utilDate.parse(value + ' ' + me.initTime, format + ' ' + me.initTimeFormat, strict);
    449             if (parsedDate) {
    450                 result = utilDate.clearTime(parsedDate);
    451             }
    452         }
    453         return result;
    454     },
    455 
    456     // @private
    457     getSubmitValue: function() {
    458         var format = this.submitFormat || this.format,
    459             value = this.getValue();
    460 
    461         return value ? Ext.Date.format(value, format) : '';
    462     },
    463 
    464     /**
    465      * @private
    466      */
    467     parseDate : function(value) {
    468         if(!value || Ext.isDate(value)){
    469             return value;
    470         }
    471 
    472         var me = this,
    473             val = me.safeParse(value, me.format),
    474             altFormats = me.altFormats,
    475             altFormatsArray = me.altFormatsArray,
    476             i = 0,
    477             len;
    478 
    479         if (!val && altFormats) {
    480             altFormatsArray = altFormatsArray || altFormats.split('|');
    481             len = altFormatsArray.length;
    482             for (; i < len && !val; ++i) {
    483                 val = me.safeParse(value, altFormatsArray[i]);
    484             }
    485         }
    486         return val;
    487     },
    488 
    489     // private
    490     formatDate: function(date){
    491         return Ext.isDate(date) ? Ext.Date.dateFormat(date, this.format) : date;
    492     },
    493 
    494     createPicker: function() {
    495         var me = this,
    496             format = Ext.String.format;
    497 
    498         // Create floating Picker BoundList. It will acquire a floatParent by looking up
    499         // its ancestor hierarchy (Pickers use their pickerField property as an upward link)
    500         // for a floating component.
    501         return new Ext.ux.DateTimePicker({
    502             pickerField: me,
    503             floating: true,
    504             focusable: false, // Key events are listened from the input field which is never blurred
    505             hidden: true,
    506             minDate: me.minValue,
    507             maxDate: me.maxValue,
    508             disabledDatesRE: me.disabledDatesRE,
    509             disabledDatesText: me.disabledDatesText,
    510             disabledDays: me.disabledDays,
    511             disabledDaysText: me.disabledDaysText,
    512             format: me.format,
    513             showToday: me.showToday,
    514             startDay: me.startDay,
    515             minText: format(me.minText, me.formatDate(me.minValue)),
    516             maxText: format(me.maxText, me.formatDate(me.maxValue)),
    517             listeners: {
    518                 scope: me,
    519                 select: me.onSelect
    520             },
    521             keyNavConfig: {
    522                 esc: function() {
    523                     me.collapse();
    524                 }
    525             }
    526         });
    527     },
    528 
    529     onSelect: function(m, d) {
    530         var me = this;
    531 
    532         me.setValue(d);
    533         me.fireEvent('select', me, d);
    534         me.collapse();
    535     },
    536 
    537     /**
    538      * @private
    539      * Sets the Date picker's value to match the current field value when expanding.
    540      */
    541     onExpand: function() {
    542         var me = this,
    543             value = me.getValue() instanceof Date ? me.getValue() : new Date();
    544         me.picker.setValue(value);     
    545         me.picker.hour.setValue(value.getHours());
    546         me.picker.minute.setValue(value.getMinutes());
    547         me.picker.second.setValue(value.getSeconds());
    548     },
    549 
    550     // private
    551     onBlur: function(e) {
    552         var me = this,
    553             v = me.rawToValue(me.getRawValue());
    554 
    555         if (Ext.isDate(v)) {
    556             me.setValue(v);
    557         }
    558         me.callParent([e]);
    559     }
    560 
    561     /**
    562      * @cfg {Boolean} grow
    563      * @private
    564      */
    565     /**
    566      * @cfg {Number} growMin
    567      * @private
    568      */
    569     /**
    570      * @cfg {Number} growMax
    571      * @private
    572      */
    573     /**
    574      * @method autoSize
    575      * @private
    576      */
    577 });

     PS:写这篇文章也是为了方便以后自己用,也方便一下使用EXTJS的同道,为了生命远离EXTJS...

    参考文章:http://www.cnblogs.com/linxiong945/p/3977445.html

                  http://toutiao.com/a4669125293/

                  http://gogo1217.iteye.com/blog/1856265

                  http://express.ruanko.com/ruanko-express_69/tech-overnight1.html

                  http://blog.csdn.net/oscar999/article/details/9984679

  • 相关阅读:
    通过rabbitmqadmin管理rabbitmq
    OpenCASCADE Incremental Mesh
    RvmTranslator6.6
    PipeCAD之管道标准库PipeStd(2)
    PipeCAD之管道标准库PipeStd
    OpenCASCADE Face Normals
    OpenCASCADE Make Face With Holes
    RvmTranslator6.5 is released
    qmake生成Visual Studio工程
    Levmar:Levenberg-Marquardt非线性最小二乘算法
  • 原文地址:https://www.cnblogs.com/ganqiyin/p/5029633.html
Copyright © 2011-2022 走看看