Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / docs / source / Date.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5   <title>The source code</title>
6   <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../prettify/prettify.js"></script>
8   <style type="text/css">
9     .highlight { display: block; background-color: #ddd; }
10   </style>
11   <script type="text/javascript">
12     function highlight() {
13       document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
14     }
15   </script>
16 </head>
17 <body onload="prettyPrint(); highlight();">
18   <pre class="prettyprint lang-js"><span id='Ext-picker-Date'>/**
19 </span> * @class Ext.picker.Date
20  * @extends Ext.Component
21  * &lt;p&gt;A date picker. This class is used by the {@link Ext.form.field.Date} field to allow browsing and
22  * selection of valid dates in a popup next to the field, but may also be used with other components.&lt;/p&gt;
23  * &lt;p&gt;Typically you will need to implement a handler function to be notified when the user chooses a color from the
24  * picker; you can register the handler using the {@link #select} event, or by implementing the {@link #handler}
25  * method.&lt;/p&gt;
26  * &lt;p&gt;By default the user will be allowed to pick any date; this can be changed by using the {@link #minDate},
27  * {@link #maxDate}, {@link #disabledDays}, {@link #disabledDatesRE}, and/or {@link #disabledDates} configs.&lt;/p&gt;
28  * &lt;p&gt;All the string values documented below may be overridden by including an Ext locale file in your page.&lt;/p&gt;
29  * &lt;p&gt;Example usage:&lt;/p&gt;
30  * &lt;pre&gt;&lt;code&gt;new Ext.panel.Panel({
31     title: 'Choose a future date:',
32     width: 200,
33     bodyPadding: 10,
34     renderTo: Ext.getBody(),
35     items: [{
36         xtype: 'datepicker',
37         minDate: new Date(),
38         handler: function(picker, date) {
39             // do something with the selected date
40         }
41     }]
42 });&lt;/code&gt;&lt;/pre&gt;
43  * {@img Ext.picker.Date/Ext.picker.Date.png Ext.picker.Date component}
44  *
45  */
46 Ext.define('Ext.picker.Date', {
47     extend: 'Ext.Component',
48     requires: [
49         'Ext.XTemplate',
50         'Ext.button.Button',
51         'Ext.button.Split',
52         'Ext.util.ClickRepeater',
53         'Ext.util.KeyNav',
54         'Ext.EventObject',
55         'Ext.fx.Manager',
56         'Ext.picker.Month'
57     ],
58     alias: 'widget.datepicker',
59     alternateClassName: 'Ext.DatePicker',
60
61     renderTpl: [
62         '&lt;div class=&quot;{cls}&quot; id=&quot;{id}&quot; role=&quot;grid&quot; title=&quot;{ariaTitle} {value:this.longDay}&quot;&gt;',
63             '&lt;div role=&quot;presentation&quot; class=&quot;{baseCls}-header&quot;&gt;',
64                 '&lt;div class=&quot;{baseCls}-prev&quot;&gt;&lt;a href=&quot;#&quot; role=&quot;button&quot; title=&quot;{prevText}&quot;&gt;&lt;/a&gt;&lt;/div&gt;',
65                 '&lt;div class=&quot;{baseCls}-month&quot;&gt;&lt;/div&gt;',
66                 '&lt;div class=&quot;{baseCls}-next&quot;&gt;&lt;a href=&quot;#&quot; role=&quot;button&quot; title=&quot;{nextText}&quot;&gt;&lt;/a&gt;&lt;/div&gt;',
67             '&lt;/div&gt;',
68             '&lt;table class=&quot;{baseCls}-inner&quot; cellspacing=&quot;0&quot; role=&quot;presentation&quot;&gt;',
69                 '&lt;thead role=&quot;presentation&quot;&gt;&lt;tr role=&quot;presentation&quot;&gt;',
70                     '&lt;tpl for=&quot;dayNames&quot;&gt;',
71                         '&lt;th role=&quot;columnheader&quot; title=&quot;{.}&quot;&gt;&lt;span&gt;{.:this.firstInitial}&lt;/span&gt;&lt;/th&gt;',
72                     '&lt;/tpl&gt;',
73                 '&lt;/tr&gt;&lt;/thead&gt;',
74                 '&lt;tbody role=&quot;presentation&quot;&gt;&lt;tr role=&quot;presentation&quot;&gt;',
75                     '&lt;tpl for=&quot;days&quot;&gt;',
76                         '{#:this.isEndOfWeek}',
77                         '&lt;td role=&quot;gridcell&quot; id=&quot;{[Ext.id()]}&quot;&gt;',
78                             '&lt;a role=&quot;presentation&quot; href=&quot;#&quot; hidefocus=&quot;on&quot; class=&quot;{parent.baseCls}-date&quot; tabIndex=&quot;1&quot;&gt;',
79                                 '&lt;em role=&quot;presentation&quot;&gt;&lt;span role=&quot;presentation&quot;&gt;&lt;/span&gt;&lt;/em&gt;',
80                             '&lt;/a&gt;',
81                         '&lt;/td&gt;',
82                     '&lt;/tpl&gt;',
83                 '&lt;/tr&gt;&lt;/tbody&gt;',
84             '&lt;/table&gt;',
85             '&lt;tpl if=&quot;showToday&quot;&gt;',
86                 '&lt;div role=&quot;presentation&quot; class=&quot;{baseCls}-footer&quot;&gt;&lt;/div&gt;',
87             '&lt;/tpl&gt;',
88         '&lt;/div&gt;',
89         {
90             firstInitial: function(value) {
91                 return value.substr(0,1);
92             },
93             isEndOfWeek: function(value) {
94                 // convert from 1 based index to 0 based
95                 // by decrementing value once.
96                 value--;
97                 var end = value % 7 === 0 &amp;&amp; value !== 0;
98                 return end ? '&lt;/tr&gt;&lt;tr role=&quot;row&quot;&gt;' : '';
99             },
100             longDay: function(value){
101                 return Ext.Date.format(value, this.longDayFormat);
102             }
103         }
104     ],
105
106     ariaTitle: 'Date Picker',
107 <span id='Ext-picker-Date-cfg-todayText'>    /**
108 </span>     * @cfg {String} todayText
109      * The text to display on the button that selects the current date (defaults to &lt;code&gt;'Today'&lt;/code&gt;)
110      */
111     todayText : 'Today',
112 <span id='Ext-picker-Date-cfg-handler'>    /**
113 </span>     * @cfg {Function} handler
114      * Optional. A function that will handle the select event of this picker.
115      * The handler is passed the following parameters:&lt;div class=&quot;mdetail-params&quot;&gt;&lt;ul&gt;
116      * &lt;li&gt;&lt;code&gt;picker&lt;/code&gt; : Ext.picker.Date &lt;div class=&quot;sub-desc&quot;&gt;This Date picker.&lt;/div&gt;&lt;/li&gt;
117      * &lt;li&gt;&lt;code&gt;date&lt;/code&gt; : Date &lt;div class=&quot;sub-desc&quot;&gt;The selected date.&lt;/div&gt;&lt;/li&gt;
118      * &lt;/ul&gt;&lt;/div&gt;
119      */
120 <span id='Ext-picker-Date-cfg-scope'>    /**
121 </span>     * @cfg {Object} scope
122      * The scope (&lt;code&gt;&lt;b&gt;this&lt;/b&gt;&lt;/code&gt; reference) in which the &lt;code&gt;{@link #handler}&lt;/code&gt;
123      * function will be called.  Defaults to this DatePicker instance.
124      */
125 <span id='Ext-picker-Date-cfg-todayTip'>    /**
126 </span>     * @cfg {String} todayTip
127      * A string used to format the message for displaying in a tooltip over the button that
128      * selects the current date. Defaults to &lt;code&gt;'{0} (Spacebar)'&lt;/code&gt; where
129      * the &lt;code&gt;{0}&lt;/code&gt; token is replaced by today's date.
130      */
131     todayTip : '{0} (Spacebar)',
132 <span id='Ext-picker-Date-cfg-minText'>    /**
133 </span>     * @cfg {String} minText
134      * The error text to display if the minDate validation fails (defaults to &lt;code&gt;'This date is before the minimum date'&lt;/code&gt;)
135      */
136     minText : 'This date is before the minimum date',
137 <span id='Ext-picker-Date-cfg-maxText'>    /**
138 </span>     * @cfg {String} maxText
139      * The error text to display if the maxDate validation fails (defaults to &lt;code&gt;'This date is after the maximum date'&lt;/code&gt;)
140      */
141     maxText : 'This date is after the maximum date',
142 <span id='Ext-picker-Date-cfg-format'>    /**
143 </span>     * @cfg {String} format
144      * The default date format string which can be overriden for localization support.  The format must be
145      * valid according to {@link Ext.Date#parse} (defaults to {@link Ext.Date#defaultFormat}).
146      */
147 <span id='Ext-picker-Date-cfg-disabledDaysText'>    /**
148 </span>     * @cfg {String} disabledDaysText
149      * The tooltip to display when the date falls on a disabled day (defaults to &lt;code&gt;'Disabled'&lt;/code&gt;)
150      */
151     disabledDaysText : 'Disabled',
152 <span id='Ext-picker-Date-cfg-disabledDatesText'>    /**
153 </span>     * @cfg {String} disabledDatesText
154      * The tooltip text to display when the date falls on a disabled date (defaults to &lt;code&gt;'Disabled'&lt;/code&gt;)
155      */
156     disabledDatesText : 'Disabled',
157 <span id='Ext-picker-Date-cfg-monthNames'>    /**
158 </span>     * @cfg {Array} monthNames
159      * An array of textual month names which can be overriden for localization support (defaults to Ext.Date.monthNames)
160      */
161 <span id='Ext-picker-Date-cfg-dayNames'>    /**
162 </span>     * @cfg {Array} dayNames
163      * An array of textual day names which can be overriden for localization support (defaults to Ext.Date.dayNames)
164      */
165 <span id='Ext-picker-Date-cfg-nextText'>    /**
166 </span>     * @cfg {String} nextText
167      * The next month navigation button tooltip (defaults to &lt;code&gt;'Next Month (Control+Right)'&lt;/code&gt;)
168      */
169     nextText : 'Next Month (Control+Right)',
170 <span id='Ext-picker-Date-cfg-prevText'>    /**
171 </span>     * @cfg {String} prevText
172      * The previous month navigation button tooltip (defaults to &lt;code&gt;'Previous Month (Control+Left)'&lt;/code&gt;)
173      */
174     prevText : 'Previous Month (Control+Left)',
175 <span id='Ext-picker-Date-cfg-monthYearText'>    /**
176 </span>     * @cfg {String} monthYearText
177      * The header month selector tooltip (defaults to &lt;code&gt;'Choose a month (Control+Up/Down to move years)'&lt;/code&gt;)
178      */
179     monthYearText : 'Choose a month (Control+Up/Down to move years)',
180 <span id='Ext-picker-Date-cfg-startDay'>    /**
181 </span>     * @cfg {Number} startDay
182      * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
183      */
184     startDay : 0,
185 <span id='Ext-picker-Date-cfg-showToday'>    /**
186 </span>     * @cfg {Boolean} showToday
187      * False to hide the footer area containing the Today button and disable the keyboard handler for spacebar
188      * that selects the current date (defaults to &lt;code&gt;true&lt;/code&gt;).
189      */
190     showToday : true,
191 <span id='Ext-picker-Date-cfg-minDate'>    /**
192 </span>     * @cfg {Date} minDate
193      * Minimum allowable date (JavaScript date object, defaults to null)
194      */
195 <span id='Ext-picker-Date-cfg-maxDate'>    /**
196 </span>     * @cfg {Date} maxDate
197      * Maximum allowable date (JavaScript date object, defaults to null)
198      */
199 <span id='Ext-picker-Date-cfg-disabledDays'>    /**
200 </span>     * @cfg {Array} disabledDays
201      * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
202      */
203 <span id='Ext-picker-Date-cfg-disabledDatesRE'>    /**
204 </span>     * @cfg {RegExp} disabledDatesRE
205      * JavaScript regular expression used to disable a pattern of dates (defaults to null).  The {@link #disabledDates}
206      * config will generate this regex internally, but if you specify disabledDatesRE it will take precedence over the
207      * disabledDates value.
208      */
209 <span id='Ext-picker-Date-cfg-disabledDates'>    /**
210 </span>     * @cfg {Array} disabledDates
211      * An array of 'dates' to disable, as strings. These strings will be used to build a dynamic regular
212      * expression so they are very powerful. Some examples:
213      * &lt;ul&gt;
214      * &lt;li&gt;['03/08/2003', '09/16/2003'] would disable those exact dates&lt;/li&gt;
215      * &lt;li&gt;['03/08', '09/16'] would disable those days for every year&lt;/li&gt;
216      * &lt;li&gt;['^03/08'] would only match the beginning (useful if you are using short years)&lt;/li&gt;
217      * &lt;li&gt;['03/../2006'] would disable every day in March 2006&lt;/li&gt;
218      * &lt;li&gt;['^03'] would disable every day in every March&lt;/li&gt;
219      * &lt;/ul&gt;
220      * Note that the format of the dates included in the array should exactly match the {@link #format} config.
221      * In order to support regular expressions, if you are using a date format that has '.' in it, you will have to
222      * escape the dot when restricting dates. For example: ['03\\.08\\.03'].
223      */
224
225 <span id='Ext-picker-Date-cfg-disableAnim'>    /**
226 </span>     * @cfg {Boolean} disableAnim True to disable animations when showing the month picker. Defaults to &lt;tt&gt;false&lt;/tt&gt;.
227      */
228     disableAnim: true,
229
230 <span id='Ext-picker-Date-cfg-baseCls'>    /**
231 </span>     * @cfg {String} baseCls
232      * The base CSS class to apply to this components element (defaults to &lt;tt&gt;'x-datepicker'&lt;/tt&gt;).
233      */
234     baseCls: Ext.baseCSSPrefix + 'datepicker',
235
236 <span id='Ext-picker-Date-cfg-selectedCls'>    /**
237 </span>     * @cfg {String} selectedCls
238      * The class to apply to the selected cell. Defaults to &lt;tt&gt;'x-datepicker-selected'&lt;/tt&gt;
239      */
240
241 <span id='Ext-picker-Date-cfg-disabledCellCls'>    /**
242 </span>     * @cfg {String} disabledCellCls
243      * The class to apply to disabled cells. Defaults to &lt;tt&gt;'x-datepicker-disabled'&lt;/tt&gt;
244      */
245
246 <span id='Ext-picker-Date-cfg-longDayFormat'>    /**
247 </span>     * @cfg {String} longDayFormat
248      * The format for displaying a date in a longer format. Defaults to &lt;tt&gt;'F d, Y'&lt;/tt&gt;
249      */
250     longDayFormat: 'F d, Y',
251
252 <span id='Ext-picker-Date-cfg-keyNavConfig'>    /**
253 </span>     * @cfg {Object} keyNavConfig Specifies optional custom key event handlers for the {@link Ext.util.KeyNav}
254      * attached to this date picker. Must conform to the config format recognized by the {@link Ext.util.KeyNav}
255      * constructor. Handlers specified in this object will replace default handlers of the same name.
256      */
257
258 <span id='Ext-picker-Date-cfg-focusOnShow'>    /**
259 </span>     * @cfg {Boolean} focusOnShow
260      * True to automatically focus the picker on show. Defaults to &lt;tt&gt;false&lt;/tt&gt;.
261      */
262     focusOnShow: false,
263
264     // private
265     // Set by other components to stop the picker focus being updated when the value changes.
266     focusOnSelect: true,
267
268     width: 178,
269
270     // default value used to initialise each date in the DatePicker
271     // (note: 12 noon was chosen because it steers well clear of all DST timezone changes)
272     initHour: 12, // 24-hour format
273
274     numDays: 42,
275
276     // private, inherit docs
277     initComponent : function() {
278         var me = this,
279             clearTime = Ext.Date.clearTime;
280
281         me.selectedCls = me.baseCls + '-selected';
282         me.disabledCellCls = me.baseCls + '-disabled';
283         me.prevCls = me.baseCls + '-prevday';
284         me.activeCls = me.baseCls + '-active';
285         me.nextCls = me.baseCls + '-prevday';
286         me.todayCls = me.baseCls + '-today';
287         me.dayNames = me.dayNames.slice(me.startDay).concat(me.dayNames.slice(0, me.startDay));
288         this.callParent();
289
290         me.value = me.value ?
291                  clearTime(me.value, true) : clearTime(new Date());
292
293         me.addEvents(
294 <span id='Ext-picker-Date-event-select'>            /**
295 </span>             * @event select
296              * Fires when a date is selected
297              * @param {DatePicker} this DatePicker
298              * @param {Date} date The selected date
299              */
300             'select'
301         );
302
303         me.initDisabledDays();
304     },
305
306     // private, inherit docs
307     onRender : function(container, position){
308         /*
309          * days array for looping through 6 full weeks (6 weeks * 7 days)
310          * Note that we explicitly force the size here so the template creates
311          * all the appropriate cells.
312          */
313
314         var me = this,
315             days = new Array(me.numDays),
316             today = Ext.Date.format(new Date(), me.format);
317
318         Ext.applyIf(me, {
319             renderData: {},
320             renderSelectors: {}
321         });
322
323         Ext.apply(me.renderData, {
324             dayNames: me.dayNames,
325             ariaTitle: me.ariaTitle,
326             value: me.value,
327             showToday: me.showToday,
328             prevText: me.prevText,
329             nextText: me.nextText,
330             days: days
331         });
332         me.getTpl('renderTpl').longDayFormat = me.longDayFormat;
333
334         Ext.apply(me.renderSelectors, {
335             eventEl: 'table.' + me.baseCls + '-inner',
336             prevEl: '.' + me.baseCls + '-prev a',
337             nextEl: '.' + me.baseCls + '-next a',
338             middleBtnEl: '.' + me.baseCls + '-month',
339             footerEl: '.' + me.baseCls + '-footer'
340         });
341
342         this.callParent(arguments);
343         me.el.unselectable();
344
345         me.cells = me.eventEl.select('tbody td');
346         me.textNodes = me.eventEl.query('tbody td span');
347
348         me.monthBtn = Ext.create('Ext.button.Split', {
349             text: '',
350             tooltip: me.monthYearText,
351             renderTo: me.middleBtnEl
352         });
353         //~ me.middleBtnEl.down('button').addCls(Ext.baseCSSPrefix + 'btn-arrow');
354
355
356         me.todayBtn = Ext.create('Ext.button.Button', {
357             renderTo: me.footerEl,
358             text: Ext.String.format(me.todayText, today),
359             tooltip: Ext.String.format(me.todayTip, today),
360             handler: me.selectToday,
361             scope: me
362         });
363     },
364
365     // private, inherit docs
366     initEvents: function(){
367         var me = this,
368             eDate = Ext.Date,
369             day = eDate.DAY;
370
371         this.callParent();
372
373         me.prevRepeater = Ext.create('Ext.util.ClickRepeater', me.prevEl, {
374             handler: me.showPrevMonth,
375             scope: me,
376             preventDefault: true,
377             stopDefault: true
378         });
379
380         me.nextRepeater = Ext.create('Ext.util.ClickRepeater', me.nextEl, {
381             handler: me.showNextMonth,
382             scope: me,
383             preventDefault:true,
384             stopDefault:true
385         });
386
387         me.keyNav = Ext.create('Ext.util.KeyNav', me.eventEl, Ext.apply({
388             scope: me,
389             'left' : function(e){
390                 if(e.ctrlKey){
391                     me.showPrevMonth();
392                 }else{
393                     me.update(eDate.add(me.activeDate, day, -1));
394                 }
395             },
396
397             'right' : function(e){
398                 if(e.ctrlKey){
399                     me.showNextMonth();
400                 }else{
401                     me.update(eDate.add(me.activeDate, day, 1));
402                 }
403             },
404
405             'up' : function(e){
406                 if(e.ctrlKey){
407                     me.showNextYear();
408                 }else{
409                     me.update(eDate.add(me.activeDate, day, -7));
410                 }
411             },
412
413             'down' : function(e){
414                 if(e.ctrlKey){
415                     me.showPrevYear();
416                 }else{
417                     me.update(eDate.add(me.activeDate, day, 7));
418                 }
419             },
420             'pageUp' : me.showNextMonth,
421             'pageDown' : me.showPrevMonth,
422             'enter' : function(e){
423                 e.stopPropagation();
424                 return true;
425             }
426         }, me.keyNavConfig));
427
428         if(me.showToday){
429             me.todayKeyListener = me.eventEl.addKeyListener(Ext.EventObject.SPACE, me.selectToday,  me);
430         }
431         me.mon(me.eventEl, 'mousewheel', me.handleMouseWheel, me);
432         me.mon(me.eventEl, 'click', me.handleDateClick,  me, {delegate: 'a.' + me.baseCls + '-date'});
433         me.mon(me.monthBtn, 'click', me.showMonthPicker, me);
434         me.mon(me.monthBtn, 'arrowclick', me.showMonthPicker, me);
435         me.update(me.value);
436     },
437
438 <span id='Ext-picker-Date-method-initDisabledDays'>    /**
439 </span>     * Setup the disabled dates regex based on config options
440      * @private
441      */
442     initDisabledDays : function(){
443         var me = this,
444             dd = me.disabledDates,
445             re = '(?:',
446             len;
447
448         if(!me.disabledDatesRE &amp;&amp; dd){
449                 len = dd.length - 1;
450
451             Ext.each(dd, function(d, i){
452                 re += Ext.isDate(d) ? '^' + Ext.String.escapeRegex(Ext.Date.dateFormat(d, me.format)) + '$' : dd[i];
453                 if(i != len){
454                     re += '|';
455                 }
456             }, me);
457             me.disabledDatesRE = new RegExp(re + ')');
458         }
459     },
460
461 <span id='Ext-picker-Date-method-setDisabledDates'>    /**
462 </span>     * Replaces any existing disabled dates with new values and refreshes the DatePicker.
463      * @param {Array/RegExp} disabledDates An array of date strings (see the {@link #disabledDates} config
464      * for details on supported values), or a JavaScript regular expression used to disable a pattern of dates.
465      * @return {Ext.picker.Date} this
466      */
467     setDisabledDates : function(dd){
468         var me = this;
469
470         if(Ext.isArray(dd)){
471             me.disabledDates = dd;
472             me.disabledDatesRE = null;
473         }else{
474             me.disabledDatesRE = dd;
475         }
476         me.initDisabledDays();
477         me.update(me.value, true);
478         return me;
479     },
480
481 <span id='Ext-picker-Date-method-setDisabledDays'>    /**
482 </span>     * Replaces any existing disabled days (by index, 0-6) with new values and refreshes the DatePicker.
483      * @param {Array} disabledDays An array of disabled day indexes. See the {@link #disabledDays} config
484      * for details on supported values.
485      * @return {Ext.picker.Date} this
486      */
487     setDisabledDays : function(dd){
488         this.disabledDays = dd;
489         return this.update(this.value, true);
490     },
491
492 <span id='Ext-picker-Date-method-setMinDate'>    /**
493 </span>     * Replaces any existing {@link #minDate} with the new value and refreshes the DatePicker.
494      * @param {Date} value The minimum date that can be selected
495      * @return {Ext.picker.Date} this
496      */
497     setMinDate : function(dt){
498         this.minDate = dt;
499         return this.update(this.value, true);
500     },
501
502 <span id='Ext-picker-Date-method-setMaxDate'>    /**
503 </span>     * Replaces any existing {@link #maxDate} with the new value and refreshes the DatePicker.
504      * @param {Date} value The maximum date that can be selected
505      * @return {Ext.picker.Date} this
506      */
507     setMaxDate : function(dt){
508         this.maxDate = dt;
509         return this.update(this.value, true);
510     },
511
512 <span id='Ext-picker-Date-method-setValue'>    /**
513 </span>     * Sets the value of the date field
514      * @param {Date} value The date to set
515      * @return {Ext.picker.Date} this
516      */
517     setValue : function(value){
518         this.value = Ext.Date.clearTime(value, true);
519         return this.update(this.value);
520     },
521
522 <span id='Ext-picker-Date-method-getValue'>    /**
523 </span>     * Gets the current selected value of the date field
524      * @return {Date} The selected date
525      */
526     getValue : function(){
527         return this.value;
528     },
529
530     // private
531     focus : function(){
532         this.update(this.activeDate);
533     },
534
535     // private, inherit docs
536     onEnable: function(){
537         this.callParent();
538         this.setDisabledStatus(false);
539         this.update(this.activeDate);
540
541     },
542
543     // private, inherit docs
544     onDisable : function(){
545         this.callParent();
546         this.setDisabledStatus(true);
547     },
548
549 <span id='Ext-picker-Date-method-setDisabledStatus'>    /**
550 </span>     * Set the disabled state of various internal components
551      * @private
552      * @param {Boolean} disabled
553      */
554     setDisabledStatus : function(disabled){
555         var me = this;
556
557         me.keyNav.setDisabled(disabled);
558         me.prevRepeater.setDisabled(disabled);
559         me.nextRepeater.setDisabled(disabled);
560         if (me.showToday) {
561             me.todayKeyListener.setDisabled(disabled);
562             me.todayBtn.setDisabled(disabled);
563         }
564     },
565
566 <span id='Ext-picker-Date-method-getActive'>    /**
567 </span>     * Get the current active date.
568      * @private
569      * @return {Date} The active date
570      */
571     getActive: function(){
572         return this.activeDate || me.value;
573     },
574
575 <span id='Ext-picker-Date-method-runAnimation'>    /**
576 </span>     * Run any animation required to hide/show the month picker.
577      * @private
578      * @param {Boolean} isHide True if it's a hide operation
579      */
580     runAnimation: function(isHide){
581         var options = {
582                 target: this.monthPicker,
583                 duration: 200
584             };
585
586         Ext.fx.Manager.run();
587         if (isHide) {
588             //TODO: slideout
589         } else {
590             //TODO: slidein
591         }
592         Ext.create('Ext.fx.Anim', options);
593     },
594
595 <span id='Ext-picker-Date-method-hideMonthPicker'>    /**
596 </span>     * Hides the month picker, if it's visible.
597      * @return {Ext.picker.Date} this
598      */
599     hideMonthPicker : function(){
600         var me = this,
601             picker = me.monthPicker;
602
603         if (picker) {
604             if (me.disableAnim) {
605                 picker.hide();
606             } else {
607                 this.runAnimation(true);
608             }
609         }
610         return me;
611     },
612
613 <span id='Ext-picker-Date-method-showMonthPicker'>    /**
614 </span>     * Show the month picker
615      * @return {Ext.picker.Date} this
616      */
617     showMonthPicker : function(){
618
619         var me = this,
620             picker,
621             size,
622             top,
623             left;
624
625
626         if (me.rendered &amp;&amp; !me.disabled) {
627             size = me.getSize();
628             picker = me.createMonthPicker();
629             picker.show();
630             picker.setSize(size);
631             picker.setValue(me.getActive());
632
633             if (me.disableAnim) {
634                 picker.setPosition(-1, -1);
635             } else {
636                 me.runAnimation(false);
637             }
638         }
639         return me;
640     },
641
642 <span id='Ext-picker-Date-method-createMonthPicker'>    /**
643 </span>     * Create the month picker instance
644      * @private
645      * @return {Ext.picker.Month} picker
646      */
647     createMonthPicker: function(){
648         var me = this,
649             picker = me.monthPicker;
650
651         if (!picker) {
652             me.monthPicker = picker = Ext.create('Ext.picker.Month', {
653                 renderTo: me.el,
654                 floating: true,
655                 shadow: false,
656                 small: me.showToday === false,
657                 listeners: {
658                     scope: me,
659                     cancelclick: me.onCancelClick,
660                     okclick: me.onOkClick,
661                     yeardblclick: me.onOkClick,
662                     monthdblclick: me.onOkClick
663                 }
664             });
665
666             me.on('beforehide', me.hideMonthPicker, me);
667         }
668         return picker;
669     },
670
671 <span id='Ext-picker-Date-method-onOkClick'>    /**
672 </span>     * Respond to an ok click on the month picker
673      * @private
674      */
675     onOkClick: function(picker, value){
676         var me = this,
677             month = value[0],
678             year = value[1],
679             date = new Date(year, month, me.getActive().getDate());
680
681         if (date.getMonth() !== month) {
682             // 'fix' the JS rolling date conversion if needed
683             date = new Date(year, month, 1).getLastDateOfMonth();
684         }
685         me.update(date);
686         me.hideMonthPicker();
687     },
688
689 <span id='Ext-picker-Date-method-onCancelClick'>    /**
690 </span>     * Respond to a cancel click on the month picker
691      * @private
692      */
693     onCancelClick: function(){
694         this.hideMonthPicker();
695     },
696
697 <span id='Ext-picker-Date-method-showPrevMonth'>    /**
698 </span>     * Show the previous month.
699      * @return {Ext.picker.Date} this
700      */
701     showPrevMonth : function(e){
702         return this.update(Ext.Date.add(this.activeDate, Ext.Date.MONTH, -1));
703     },
704
705 <span id='Ext-picker-Date-method-showNextMonth'>    /**
706 </span>     * Show the next month.
707      * @return {Ext.picker.Date} this
708      */
709     showNextMonth : function(e){
710         return this.update(Ext.Date.add(this.activeDate, Ext.Date.MONTH, 1));
711     },
712
713 <span id='Ext-picker-Date-method-showPrevYear'>    /**
714 </span>     * Show the previous year.
715      * @return {Ext.picker.Date} this
716      */
717     showPrevYear : function(){
718         this.update(Ext.Date.add(this.activeDate, Ext.Date.YEAR, -1));
719     },
720
721 <span id='Ext-picker-Date-method-showNextYear'>    /**
722 </span>     * Show the next year.
723      * @return {Ext.picker.Date} this
724      */
725     showNextYear : function(){
726         this.update(Ext.Date.add(this.activeDate, Ext.Date.YEAR, 1));
727     },
728
729 <span id='Ext-picker-Date-method-handleMouseWheel'>    /**
730 </span>     * Respond to the mouse wheel event
731      * @private
732      * @param {Ext.EventObject} e
733      */
734     handleMouseWheel : function(e){
735         e.stopEvent();
736         if(!this.disabled){
737             var delta = e.getWheelDelta();
738             if(delta &gt; 0){
739                 this.showPrevMonth();
740             } else if(delta &lt; 0){
741                 this.showNextMonth();
742             }
743         }
744     },
745
746 <span id='Ext-picker-Date-method-handleDateClick'>    /**
747 </span>     * Respond to a date being clicked in the picker
748      * @private
749      * @param {Ext.EventObject} e
750      * @param {HTMLElement} t
751      */
752     handleDateClick : function(e, t){
753         var me = this,
754             handler = me.handler;
755
756         e.stopEvent();
757         if(!me.disabled &amp;&amp; t.dateValue &amp;&amp; !Ext.fly(t.parentNode).hasCls(me.disabledCellCls)){
758             me.cancelFocus = me.focusOnSelect === false;
759             me.setValue(new Date(t.dateValue));
760             delete me.cancelFocus;
761             me.fireEvent('select', me, me.value);
762             if (handler) {
763                 handler.call(me.scope || me, me, me.value);
764             }
765             // event handling is turned off on hide
766             // when we are using the picker in a field
767             // therefore onSelect comes AFTER the select
768             // event.
769             me.onSelect();
770         }
771     },
772
773 <span id='Ext-picker-Date-method-onSelect'>    /**
774 </span>     * Perform any post-select actions
775      * @private
776      */
777     onSelect: function() {
778         if (this.hideOnSelect) {
779              this.hide();
780          }
781     },
782
783 <span id='Ext-picker-Date-method-selectToday'>    /**
784 </span>     * Sets the current value to today.
785      * @return {Ext.picker.Date} this
786      */
787     selectToday : function(){
788         var me = this,
789             btn = me.todayBtn,
790             handler = me.handler;
791
792         if(btn &amp;&amp; !btn.disabled){
793             me.setValue(Ext.Date.clearTime(new Date()));
794             me.fireEvent('select', me, me.value);
795             if (handler) {
796                 handler.call(me.scope || me, me, me.value);
797             }
798             me.onSelect();
799         }
800         return me;
801     },
802
803 <span id='Ext-picker-Date-method-selectedUpdate'>    /**
804 </span>     * Update the selected cell
805      * @private
806      * @param {Date} date The new date
807      * @param {Date} active The active date
808      */
809     selectedUpdate: function(date, active){
810         var me = this,
811             t = date.getTime(),
812             cells = me.cells,
813             cls = me.selectedCls;
814
815         cells.removeCls(cls);
816         cells.each(function(c){
817             if (c.dom.firstChild.dateValue == t) {
818                 me.el.dom.setAttribute('aria-activedescendent', c.dom.id);
819                 c.addCls(cls);
820                 if(me.isVisible() &amp;&amp; !me.cancelFocus){
821                     Ext.fly(c.dom.firstChild).focus(50);
822                 }
823                 return false;
824             }
825         }, this);
826     },
827
828 <span id='Ext-picker-Date-method-fullUpdate'>    /**
829 </span>     * Update the contents of the picker for a new month
830      * @private
831      * @param {Date} date The new date
832      * @param {Date} active The active date
833      */
834     fullUpdate: function(date, active){
835         var me = this,
836             cells = me.cells.elements,
837             textNodes = me.textNodes,
838             disabledCls = me.disabledCellCls,
839             eDate = Ext.Date,
840             i = 0,
841             extraDays = 0,
842             visible = me.isVisible(),
843             sel = +eDate.clearTime(date, true),
844             today = +eDate.clearTime(new Date()),
845             min = me.minDate ? eDate.clearTime(me.minDate, true) : Number.NEGATIVE_INFINITY,
846             max = me.maxDate ? eDate.clearTime(me.maxDate, true) : Number.POSITIVE_INFINITY,
847             ddMatch = me.disabledDatesRE,
848             ddText = me.disabledDatesText,
849             ddays = me.disabledDays ? me.disabledDays.join('') : false,
850             ddaysText = me.disabledDaysText,
851             format = me.format,
852             days = eDate.getDaysInMonth(date),
853             firstOfMonth = eDate.getFirstDateOfMonth(date),
854             startingPos = firstOfMonth.getDay() - me.startDay,
855             previousMonth = eDate.add(date, eDate.MONTH, -1),
856             longDayFormat = me.longDayFormat,
857             prevStart,
858             current,
859             disableToday,
860             tempDate,
861             setCellClass,
862             html,
863             cls,
864             formatValue,
865             value;
866
867         if (startingPos &lt; 0) {
868             startingPos += 7;
869         }
870
871         days += startingPos;
872         prevStart = eDate.getDaysInMonth(previousMonth) - startingPos;
873         current = new Date(previousMonth.getFullYear(), previousMonth.getMonth(), prevStart, me.initHour);
874
875         if (me.showToday) {
876             tempDate = eDate.clearTime(new Date());
877             disableToday = (tempDate &lt; min || tempDate &gt; max ||
878                 (ddMatch &amp;&amp; format &amp;&amp; ddMatch.test(eDate.dateFormat(tempDate, format))) ||
879                 (ddays &amp;&amp; ddays.indexOf(tempDate.getDay()) != -1));
880
881             if (!me.disabled) {
882                 me.todayBtn.setDisabled(disableToday);
883                 me.todayKeyListener.setDisabled(disableToday);
884             }
885         }
886
887         setCellClass = function(cell){
888             value = +eDate.clearTime(current, true);
889             cell.title = eDate.format(current, longDayFormat);
890             // store dateValue number as an expando
891             cell.firstChild.dateValue = value;
892             if(value == today){
893                 cell.className += ' ' + me.todayCls;
894                 cell.title = me.todayText;
895             }
896             if(value == sel){
897                 cell.className += ' ' + me.selectedCls;
898                 me.el.dom.setAttribute('aria-activedescendant', cell.id);
899                 if (visible &amp;&amp; me.floating) {
900                     Ext.fly(cell.firstChild).focus(50);
901                 }
902             }
903             // disabling
904             if(value &lt; min) {
905                 cell.className = disabledCls;
906                 cell.title = me.minText;
907                 return;
908             }
909             if(value &gt; max) {
910                 cell.className = disabledCls;
911                 cell.title = me.maxText;
912                 return;
913             }
914             if(ddays){
915                 if(ddays.indexOf(current.getDay()) != -1){
916                     cell.title = ddaysText;
917                     cell.className = disabledCls;
918                 }
919             }
920             if(ddMatch &amp;&amp; format){
921                 formatValue = eDate.dateFormat(current, format);
922                 if(ddMatch.test(formatValue)){
923                     cell.title = ddText.replace('%0', formatValue);
924                     cell.className = disabledCls;
925                 }
926             }
927         };
928
929         for(; i &lt; me.numDays; ++i) {
930             if (i &lt; startingPos) {
931                 html = (++prevStart);
932                 cls = me.prevCls;
933             } else if (i &gt;= days) {
934                 html = (++extraDays);
935                 cls = me.nextCls;
936             } else {
937                 html = i - startingPos + 1;
938                 cls = me.activeCls;
939             }
940             textNodes[i].innerHTML = html;
941             cells[i].className = cls;
942             current.setDate(current.getDate() + 1);
943             setCellClass(cells[i]);
944         }
945
946         me.monthBtn.setText(me.monthNames[date.getMonth()] + ' ' + date.getFullYear());
947     },
948
949 <span id='Ext-picker-Date-method-update'>    /**
950 </span>     * Update the contents of the picker
951      * @private
952      * @param {Date} date The new date
953      * @param {Boolean} forceRefresh True to force a full refresh
954      */
955     update : function(date, forceRefresh){
956         var me = this,
957             active = me.activeDate;
958
959         if (me.rendered) {
960             me.activeDate = date;
961             if(!forceRefresh &amp;&amp; active &amp;&amp; me.el &amp;&amp; active.getMonth() == date.getMonth() &amp;&amp; active.getFullYear() == date.getFullYear()){
962                 me.selectedUpdate(date, active);
963             } else {
964                 me.fullUpdate(date, active);
965             }
966         }
967         return me;
968     },
969
970     // private, inherit docs
971     beforeDestroy : function() {
972         var me = this;
973
974         if (me.rendered) {
975             Ext.destroy(
976                 me.todayKeyListener,
977                 me.keyNav,
978                 me.monthPicker,
979                 me.monthBtn,
980                 me.nextRepeater,
981                 me.prevRepeater,
982                 me.todayBtn
983             );
984             delete me.textNodes;
985             delete me.cells.elements;
986         }
987     },
988
989     // private, inherit docs
990     onShow: function() {
991         this.callParent(arguments);
992         if (this.focusOnShow) {
993             this.focus();
994         }
995     }
996 },
997
998 // After dependencies have loaded:
999 function() {
1000     var proto = this.prototype;
1001
1002     proto.monthNames = Ext.Date.monthNames;
1003
1004     proto.dayNames = Ext.Date.dayNames;
1005
1006     proto.format = Ext.Date.defaultFormat;
1007 });
1008 </pre>
1009 </body>
1010 </html>