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