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