Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / Time.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-Time'>/**
19 </span> * Provides a time input field with a time dropdown and automatic time validation.
20  *
21  * This field recognizes and uses JavaScript Date objects as its main {@link #value} type (only the time portion of the
22  * date is used; the month/day/year are ignored). In addition, it recognizes string values which are parsed according to
23  * the {@link #format} and/or {@link #altFormats} configs. These may be reconfigured to use time formats appropriate for
24  * the user's locale.
25  *
26  * The field may be limited to a certain range of times by using the {@link #minValue} and {@link #maxValue} configs,
27  * and the interval between time options in the dropdown can be changed with the {@link #increment} config.
28  *
29  * Example usage:
30  *
31  *     @example
32  *     Ext.create('Ext.form.Panel', {
33  *         title: 'Time Card',
34  *         width: 300,
35  *         bodyPadding: 10,
36  *         renderTo: Ext.getBody(),
37  *         items: [{
38  *             xtype: 'timefield',
39  *             name: 'in',
40  *             fieldLabel: 'Time In',
41  *             minValue: '6:00 AM',
42  *             maxValue: '8:00 PM',
43  *             increment: 30,
44  *             anchor: '100%'
45  *         }, {
46  *             xtype: 'timefield',
47  *             name: 'out',
48  *             fieldLabel: 'Time Out',
49  *             minValue: '6:00 AM',
50  *             maxValue: '8:00 PM',
51  *             increment: 30,
52  *             anchor: '100%'
53  *        }]
54  *     });
55  */
56 Ext.define('Ext.form.field.Time', {
57     extend:'Ext.form.field.Picker',
58     alias: 'widget.timefield',
59     requires: ['Ext.form.field.Date', 'Ext.picker.Time', 'Ext.view.BoundListKeyNav', 'Ext.Date'],
60     alternateClassName: ['Ext.form.TimeField', 'Ext.form.Time'],
61
62 <span id='Ext-form-field-Time-cfg-triggerCls'>    /**
63 </span>     * @cfg {String} triggerCls
64      * An additional CSS class used to style the trigger button. The trigger will always get the {@link #triggerBaseCls}
65      * by default and triggerCls will be **appended** if specified. Defaults to 'x-form-time-trigger' for the Time field
66      * trigger.
67      */
68     triggerCls: Ext.baseCSSPrefix + 'form-time-trigger',
69
70 <span id='Ext-form-field-Time-cfg-minValue'>    /**
71 </span>     * @cfg {Date/String} minValue
72      * The minimum allowed time. Can be either a Javascript date object with a valid time value or a string time in a
73      * valid format -- see {@link #format} and {@link #altFormats}.
74      */
75
76 <span id='Ext-form-field-Time-cfg-maxValue'>    /**
77 </span>     * @cfg {Date/String} maxValue
78      * The maximum allowed time. Can be either a Javascript date object with a valid time value or a string time in a
79      * valid format -- see {@link #format} and {@link #altFormats}.
80      */
81
82 <span id='Ext-form-field-Time-cfg-minText'>    /**
83 </span>     * @cfg {String} minText
84      * The error text to display when the entered time is before {@link #minValue}.
85      */
86     minText : &quot;The time in this field must be equal to or after {0}&quot;,
87
88 <span id='Ext-form-field-Time-cfg-maxText'>    /**
89 </span>     * @cfg {String} maxText
90      * The error text to display when the entered time is after {@link #maxValue}.
91      */
92     maxText : &quot;The time in this field must be equal to or before {0}&quot;,
93
94 <span id='Ext-form-field-Time-cfg-invalidText'>    /**
95 </span>     * @cfg {String} invalidText
96      * The error text to display when the time in the field is invalid.
97      */
98     invalidText : &quot;{0} is not a valid time&quot;,
99
100 <span id='Ext-form-field-Time-cfg-format'>    /**
101 </span>     * @cfg {String} format
102      * The default time format string which can be overriden for localization support. The format must be valid
103      * according to {@link Ext.Date#parse} (defaults to 'g:i A', e.g., '3:15 PM'). For 24-hour time format try 'H:i'
104      * instead.
105      */
106     format : &quot;g:i A&quot;,
107
108 <span id='Ext-form-field-Time-cfg-submitFormat'>    /**
109 </span>     * @cfg {String} submitFormat
110      * The date format string which will be submitted to the server. The format must be valid according to {@link
111      * Ext.Date#parse} (defaults to {@link #format}).
112      */
113
114 <span id='Ext-form-field-Time-cfg-altFormats'>    /**
115 </span>     * @cfg {String} altFormats
116      * Multiple date formats separated by &quot;|&quot; to try when parsing a user input value and it doesn't match the defined
117      * format.
118      */
119     altFormats : &quot;g:ia|g:iA|g:i a|g:i A|h:i|g:i|H:i|ga|ha|gA|h a|g a|g A|gi|hi|gia|hia|g|H|gi a|hi a|giA|hiA|gi A|hi A&quot;,
120
121 <span id='Ext-form-field-Time-cfg-increment'>    /**
122 </span>     * @cfg {Number} increment
123      * The number of minutes between each time value in the list.
124      */
125     increment: 15,
126
127 <span id='Ext-form-field-Time-cfg-pickerMaxHeight'>    /**
128 </span>     * @cfg {Number} pickerMaxHeight
129      * The maximum height of the {@link Ext.picker.Time} dropdown.
130      */
131     pickerMaxHeight: 300,
132
133 <span id='Ext-form-field-Time-cfg-selectOnTab'>    /**
134 </span>     * @cfg {Boolean} selectOnTab
135      * Whether the Tab key should select the currently highlighted item.
136      */
137     selectOnTab: true,
138
139 <span id='Ext-form-field-Time-property-initDate'>    /**
140 </span>     * @private
141      * This is the date to use when generating time values in the absence of either minValue
142      * or maxValue.  Using the current date causes DST issues on DST boundary dates, so this is an
143      * arbitrary &quot;safe&quot; date that can be any date aside from DST boundary dates.
144      */
145     initDate: '1/1/2008',
146     initDateFormat: 'j/n/Y',
147
148
149     initComponent: function() {
150         var me = this,
151             min = me.minValue,
152             max = me.maxValue;
153         if (min) {
154             me.setMinValue(min);
155         }
156         if (max) {
157             me.setMaxValue(max);
158         }
159         this.callParent();
160     },
161
162     initValue: function() {
163         var me = this,
164             value = me.value;
165
166         // If a String value was supplied, try to convert it to a proper Date object
167         if (Ext.isString(value)) {
168             me.value = me.rawToValue(value);
169         }
170
171         me.callParent();
172     },
173
174 <span id='Ext-form-field-Time-method-setMinValue'>    /**
175 </span>     * Replaces any existing {@link #minValue} with the new time and refreshes the picker's range.
176      * @param {Date/String} value The minimum time that can be selected
177      */
178     setMinValue: function(value) {
179         var me = this,
180             picker = me.picker;
181         me.setLimit(value, true);
182         if (picker) {
183             picker.setMinValue(me.minValue);
184         }
185     },
186
187 <span id='Ext-form-field-Time-method-setMaxValue'>    /**
188 </span>     * Replaces any existing {@link #maxValue} with the new time and refreshes the picker's range.
189      * @param {Date/String} value The maximum time that can be selected
190      */
191     setMaxValue: function(value) {
192         var me = this,
193             picker = me.picker;
194         me.setLimit(value, false);
195         if (picker) {
196             picker.setMaxValue(me.maxValue);
197         }
198     },
199
200 <span id='Ext-form-field-Time-method-setLimit'>    /**
201 </span>     * @private
202      * Updates either the min or max value. Converts the user's value into a Date object whose
203      * year/month/day is set to the {@link #initDate} so that only the time fields are significant.
204      */
205     setLimit: function(value, isMin) {
206         var me = this,
207             d, val;
208         if (Ext.isString(value)) {
209             d = me.parseDate(value);
210         }
211         else if (Ext.isDate(value)) {
212             d = value;
213         }
214         if (d) {
215             val = Ext.Date.clearTime(new Date(me.initDate));
216             val.setHours(d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
217             me[isMin ? 'minValue' : 'maxValue'] = val;
218         }
219     },
220
221     rawToValue: function(rawValue) {
222         return this.parseDate(rawValue) || rawValue || null;
223     },
224
225     valueToRaw: function(value) {
226         return this.formatDate(this.parseDate(value));
227     },
228
229 <span id='Ext-form-field-Time-method-getErrors'>    /**
230 </span>     * Runs all of Time's validations and returns an array of any errors. Note that this first runs Text's validations,
231      * so the returned array is an amalgamation of all field errors. The additional validation checks are testing that
232      * the time format is valid, that the chosen time is within the {@link #minValue} and {@link #maxValue} constraints
233      * set.
234      * @param {Object} [value] The value to get errors for (defaults to the current field value)
235      * @return {String[]} All validation errors for this field
236      */
237     getErrors: function(value) {
238         var me = this,
239             format = Ext.String.format,
240             errors = me.callParent(arguments),
241             minValue = me.minValue,
242             maxValue = me.maxValue,
243             date;
244
245         value = me.formatDate(value || me.processRawValue(me.getRawValue()));
246
247         if (value === null || value.length &lt; 1) { // if it's blank and textfield didn't flag it then it's valid
248              return errors;
249         }
250
251         date = me.parseDate(value);
252         if (!date) {
253             errors.push(format(me.invalidText, value, me.format));
254             return errors;
255         }
256
257         if (minValue &amp;&amp; date &lt; minValue) {
258             errors.push(format(me.minText, me.formatDate(minValue)));
259         }
260
261         if (maxValue &amp;&amp; date &gt; maxValue) {
262             errors.push(format(me.maxText, me.formatDate(maxValue)));
263         }
264
265         return errors;
266     },
267
268     formatDate: function() {
269         return Ext.form.field.Date.prototype.formatDate.apply(this, arguments);
270     },
271
272 <span id='Ext-form-field-Time-method-parseDate'>    /**
273 </span>     * @private
274      * Parses an input value into a valid Date object.
275      * @param {String/Date} value
276      */
277     parseDate: function(value) {
278         if (!value || Ext.isDate(value)) {
279             return value;
280         }
281
282         var me = this,
283             val = me.safeParse(value, me.format),
284             altFormats = me.altFormats,
285             altFormatsArray = me.altFormatsArray,
286             i = 0,
287             len;
288
289         if (!val &amp;&amp; altFormats) {
290             altFormatsArray = altFormatsArray || altFormats.split('|');
291             len = altFormatsArray.length;
292             for (; i &lt; len &amp;&amp; !val; ++i) {
293                 val = me.safeParse(value, altFormatsArray[i]);
294             }
295         }
296         return val;
297     },
298
299     safeParse: function(value, format){
300         var me = this,
301             utilDate = Ext.Date,
302             parsedDate,
303             result = null;
304
305         if (utilDate.formatContainsDateInfo(format)) {
306             // assume we've been given a full date
307             result = utilDate.parse(value, format);
308         } else {
309             // Use our initial safe date
310             parsedDate = utilDate.parse(me.initDate + ' ' + value, me.initDateFormat + ' ' + format);
311             if (parsedDate) {
312                 result = parsedDate;
313             }
314         }
315         return result;
316     },
317
318     // @private
319     getSubmitValue: function() {
320         var me = this,
321             format = me.submitFormat || me.format,
322             value = me.getValue();
323
324         return value ? Ext.Date.format(value, format) : null;
325     },
326
327 <span id='Ext-form-field-Time-method-createPicker'>    /**
328 </span>     * @private
329      * Creates the {@link Ext.picker.Time}
330      */
331     createPicker: function() {
332         var me = this,
333             picker = Ext.create('Ext.picker.Time', {
334                 pickerField: me,
335                 selModel: {
336                     mode: 'SINGLE'
337                 },
338                 floating: true,
339                 hidden: true,
340                 minValue: me.minValue,
341                 maxValue: me.maxValue,
342                 increment: me.increment,
343                 format: me.format,
344                 ownerCt: this.ownerCt,
345                 renderTo: document.body,
346                 maxHeight: me.pickerMaxHeight,
347                 focusOnToFront: false
348             });
349
350         me.mon(picker.getSelectionModel(), {
351             selectionchange: me.onListSelect,
352             scope: me
353         });
354
355         return picker;
356     },
357
358 <span id='Ext-form-field-Time-method-onExpand'>    /**
359 </span>     * @private
360      * Enables the key nav for the Time picker when it is expanded.
361      * TODO this is largely the same logic as ComboBox, should factor out.
362      */
363     onExpand: function() {
364         var me = this,
365             keyNav = me.pickerKeyNav,
366             selectOnTab = me.selectOnTab,
367             picker = me.getPicker(),
368             lastSelected = picker.getSelectionModel().lastSelected,
369             itemNode;
370
371         if (!keyNav) {
372             keyNav = me.pickerKeyNav = Ext.create('Ext.view.BoundListKeyNav', this.inputEl, {
373                 boundList: picker,
374                 forceKeyDown: true,
375                 tab: function(e) {
376                     if (selectOnTab) {
377                         if(me.picker.highlightedItem) {
378                             this.selectHighlighted(e);
379                         } else {
380                             me.collapse();
381                         }
382                         me.triggerBlur();
383                     }
384                     // Tab key event is allowed to propagate to field
385                     return true;
386                 }
387             });
388             // stop tab monitoring from Ext.form.field.Trigger so it doesn't short-circuit selectOnTab
389             if (selectOnTab) {
390                 me.ignoreMonitorTab = true;
391             }
392         }
393         Ext.defer(keyNav.enable, 1, keyNav); //wait a bit so it doesn't react to the down arrow opening the picker
394
395         // Highlight the last selected item and scroll it into view
396         if (lastSelected) {
397             itemNode = picker.getNode(lastSelected);
398             if (itemNode) {
399                 picker.highlightItem(itemNode);
400                 picker.el.scrollChildIntoView(itemNode, false);
401             }
402         }
403     },
404
405 <span id='Ext-form-field-Time-method-onCollapse'>    /**
406 </span>     * @private
407      * Disables the key nav for the Time picker when it is collapsed.
408      */
409     onCollapse: function() {
410         var me = this,
411             keyNav = me.pickerKeyNav;
412         if (keyNav) {
413             keyNav.disable();
414             me.ignoreMonitorTab = false;
415         }
416     },
417
418 <span id='Ext-form-field-Time-method-onChange'>    /**
419 </span>     * @private
420      * Clears the highlighted item in the picker on change.
421      * This prevents the highlighted item from being selected instead of the custom typed in value when the tab key is pressed.
422      */
423     onChange: function() {
424         var me = this,
425             picker = me.picker;
426
427         me.callParent(arguments);
428         if(picker) {
429             picker.clearHighlight();
430         }
431     },
432
433 <span id='Ext-form-field-Time-method-onListSelect'>    /**
434 </span>     * @private
435      * Handles a time being selected from the Time picker.
436      */
437     onListSelect: function(list, recordArray) {
438         var me = this,
439             record = recordArray[0],
440             val = record ? record.get('date') : null;
441         me.setValue(val);
442         me.fireEvent('select', me, val);
443         me.picker.clearHighlight();
444         me.collapse();
445         me.inputEl.focus();
446     }
447 });
448
449 </pre>
450 </body>
451 </html>