Upgrade to ExtJS 4.0.7 - Released 10/19/2011
[extjs.git] / docs / source / Time2.html
index 5a9b078..fcb11d8 100644 (file)
@@ -3,8 +3,8 @@
 <head>
   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
   <title>The source code</title>
-  <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
-  <script type="text/javascript" src="../prettify/prettify.js"></script>
+  <link href="../resources/prettify/prettify.css" type="text/css" rel="stylesheet" />
+  <script type="text/javascript" src="../resources/prettify/prettify.js"></script>
   <style type="text/css">
     .highlight { display: block; background-color: #ddd; }
   </style>
   </script>
 </head>
 <body onload="prettyPrint(); highlight();">
-  <pre class="prettyprint lang-js"><span id='Ext-form-field-Time'>/**
-</span> * @class Ext.form.field.Time
- * @extends Ext.form.field.Picker
- * &lt;p&gt;Provides a time input field with a time dropdown and automatic time validation.&lt;/p&gt;
- * &lt;p&gt;This field recognizes and uses JavaScript Date objects as its main {@link #value} type (only the time
- * portion of the date is used; the month/day/year are ignored). In addition, it recognizes string values which
- * are parsed according to the {@link #format} and/or {@link #altFormats} configs. These may be reconfigured
- * to use time formats appropriate for the user's locale.&lt;/p&gt;
- * &lt;p&gt;The field may be limited to a certain range of times by using the {@link #minValue} and {@link #maxValue}
- * configs, and the interval between time options in the dropdown can be changed with the {@link #increment} config.&lt;/p&gt;
- * {@img Ext.form.Time/Ext.form.Time.png Ext.form.Time component}
- * &lt;p&gt;Example usage:&lt;/p&gt;
- * &lt;pre&gt;&lt;code&gt;
-Ext.create('Ext.form.Panel', {
-    title: 'Time Card',
-    width: 300,
-    bodyPadding: 10,
-    renderTo: Ext.getBody(),        
-    items: [{
-        xtype: 'timefield',
-        name: 'in',
-        fieldLabel: 'Time In',
-        minValue: '6:00 AM',
-        maxValue: '8:00 PM',
-        increment: 30,
-        anchor: '100%'
-    }, {
-        xtype: 'timefield',
-        name: 'out',
-        fieldLabel: 'Time Out',
-        minValue: '6:00 AM',
-        maxValue: '8:00 PM',
-        increment: 30,
-        anchor: '100%'
-   }]
-});
-&lt;/code&gt;&lt;/pre&gt;
+  <pre class="prettyprint lang-js"><span id='Ext-picker-Time'>/**
+</span> * A time picker which provides a list of times from which to choose. This is used by the Ext.form.field.Time
+ * class to allow browsing and selection of valid times, but could also be used with other components.
+ *
+ * By default, all times starting at midnight and incrementing every 15 minutes will be presented. This list of
+ * available times can be controlled using the {@link #minValue}, {@link #maxValue}, and {@link #increment}
+ * configuration properties. The format of the times presented in the list can be customized with the {@link #format}
+ * config.
+ *
+ * To handle when the user selects a time from the list, you can subscribe to the {@link #selectionchange} event.
+ *
+ *     @example
+ *     Ext.create('Ext.picker.Time', {
+ *        width: 60,
+ *        minValue: Ext.Date.parse('04:30:00 AM', 'h:i:s A'),
+ *        maxValue: Ext.Date.parse('08:00:00 AM', 'h:i:s A'),
+ *        renderTo: Ext.getBody()
+ *     });
  */
-Ext.define('Ext.form.field.Time', {
-    extend:'Ext.form.field.Picker',
-    alias: 'widget.timefield',
-    requires: ['Ext.form.field.Date', 'Ext.picker.Time', 'Ext.view.BoundListKeyNav', 'Ext.Date'],
-    alternateClassName: ['Ext.form.TimeField', 'Ext.form.Time'],
-
-<span id='Ext-form-field-Time-cfg-triggerCls'>    /**
-</span>     * @cfg {String} triggerCls
-     * An additional CSS class used to style the trigger button.  The trigger will always get the
-     * {@link #triggerBaseCls} by default and &lt;tt&gt;triggerCls&lt;/tt&gt; will be &lt;b&gt;appended&lt;/b&gt; if specified.
-     * Defaults to &lt;tt&gt;'x-form-time-trigger'&lt;/tt&gt; for the Time field trigger.
-     */
-    triggerCls: Ext.baseCSSPrefix + 'form-time-trigger',
-
-<span id='Ext-form-field-Time-cfg-minValue'>    /**
-</span>     * @cfg {Date/String} minValue
-     * The minimum allowed time. Can be either a Javascript date object with a valid time value or a string
-     * time in a valid format -- see {@link #format} and {@link #altFormats} (defaults to undefined).
-     */
-
-<span id='Ext-form-field-Time-cfg-maxValue'>    /**
-</span>     * @cfg {Date/String} maxValue
-     * The maximum allowed time. Can be either a Javascript date object with a valid time value or a string
-     * time in a valid format -- see {@link #format} and {@link #altFormats} (defaults to undefined).
-     */
+Ext.define('Ext.picker.Time', {
+    extend: 'Ext.view.BoundList',
+    alias: 'widget.timepicker',
+    requires: ['Ext.data.Store', 'Ext.Date'],
 
-<span id='Ext-form-field-Time-cfg-minText'>    /**
-</span>     * @cfg {String} minText
-     * The error text to display when the entered time is before {@link #minValue} (defaults to
-     * 'The time in this field must be equal to or after {0}').
+<span id='Ext-picker-Time-cfg-minValue'>    /**
+</span>     * @cfg {Date} minValue
+     * The minimum time to be shown in the list of times. This must be a Date object (only the time fields will be
+     * used); no parsing of String values will be done.
      */
-    minText : &quot;The time in this field must be equal to or after {0}&quot;,
 
-<span id='Ext-form-field-Time-cfg-maxText'>    /**
-</span>     * @cfg {String} maxText
-     * The error text to display when the entered time is after {@link #maxValue} (defaults to
-     * 'The time in this field must be equal to or before {0}').
+<span id='Ext-picker-Time-cfg-maxValue'>    /**
+</span>     * @cfg {Date} maxValue
+     * The maximum time to be shown in the list of times. This must be a Date object (only the time fields will be
+     * used); no parsing of String values will be done.
      */
-    maxText : &quot;The time in this field must be equal to or before {0}&quot;,
 
-<span id='Ext-form-field-Time-cfg-invalidText'>    /**
-</span>     * @cfg {String} invalidText
-     * The error text to display when the time in the field is invalid (defaults to
-     * '{value} is not a valid time').
+<span id='Ext-picker-Time-cfg-increment'>    /**
+</span>     * @cfg {Number} increment
+     * The number of minutes between each time value in the list.
      */
-    invalidText : &quot;{0} is not a valid time&quot;,
+    increment: 15,
 
-<span id='Ext-form-field-Time-cfg-format'>    /**
+<span id='Ext-picker-Time-cfg-format'>    /**
 </span>     * @cfg {String} format
-     * The default time format string which can be overriden for localization support.  The format must be
-     * valid according to {@link Ext.Date#parse} (defaults to 'g:i A', e.g., '3:15 PM').  For 24-hour time
-     * format try 'H:i' instead.
+     * The default time format string which can be overriden for localization support. The format must be valid
+     * according to {@link Ext.Date#parse} (defaults to 'g:i A', e.g., '3:15 PM'). For 24-hour time format try 'H:i'
+     * instead.
      */
     format : &quot;g:i A&quot;,
 
-<span id='Ext-form-field-Time-cfg-submitFormat'>    /**
-</span>     * @cfg {String} submitFormat The date format string which will be submitted to the server.
-     * The format must be valid according to {@link Ext.Date#parse} (defaults to &lt;tt&gt;{@link #format}&lt;/tt&gt;).
-     */
-
-<span id='Ext-form-field-Time-cfg-altFormats'>    /**
-</span>     * @cfg {String} altFormats
-     * Multiple date formats separated by &quot;|&quot; to try when parsing a user input value and it doesn't match the defined
-     * format (defaults to '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').
+<span id='Ext-picker-Time-property-displayField'>    /**
+</span>     * @hide
+     * The field in the implicitly-generated Model objects that gets displayed in the list. This is
+     * an internal field name only and is not useful to change via config.
      */
-    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;,
+    displayField: 'disp',
 
-<span id='Ext-form-field-Time-cfg-increment'>    /**
-</span>     * @cfg {Number} increment
-     * The number of minutes between each time value in the list (defaults to 15).
-     */
-    increment: 15,
-
-<span id='Ext-form-field-Time-cfg-pickerMaxHeight'>    /**
-</span>     * @cfg {Number} pickerMaxHeight
-     * The maximum height of the {@link Ext.picker.Time} dropdown. Defaults to 300.
+<span id='Ext-picker-Time-property-initDate'>    /**
+</span>     * @private
+     * Year, month, and day that all times will be normalized into internally.
      */
-    pickerMaxHeight: 300,
+    initDate: [2008,0,1],
 
-<span id='Ext-form-field-Time-cfg-selectOnTab'>    /**
-</span>     * @cfg {Boolean} selectOnTab
-     * Whether the Tab key should select the currently highlighted item. Defaults to &lt;tt&gt;true&lt;/tt&gt;.
-     */
-    selectOnTab: true,
+    componentCls: Ext.baseCSSPrefix + 'timepicker',
 
-<span id='Ext-form-field-Time-property-initDate'>    /**
-</span>     * @private
-     * This is the date to use when generating time values in the absence of either minValue
-     * or maxValue.  Using the current date causes DST issues on DST boundary dates, so this is an
-     * arbitrary &quot;safe&quot; date that can be any date aside from DST boundary dates.
+<span id='Ext-picker-Time-property-loadMask'>    /**
+</span>     * @hide
      */
-    initDate: '1/1/2008',
-    initDateFormat: 'j/n/Y',
-
+    loadMask: false,
 
     initComponent: function() {
         var me = this,
-            min = me.minValue,
-            max = me.maxValue;
-        if (min) {
-            me.setMinValue(min);
-        }
-        if (max) {
-            me.setMaxValue(max);
-        }
-        this.callParent();
-    },
+            dateUtil = Ext.Date,
+            clearTime = dateUtil.clearTime,
+            initDate = me.initDate;
 
-    initValue: function() {
-        var me = this,
-            value = me.value;
+        // Set up absolute min and max for the entire day
+        me.absMin = clearTime(new Date(initDate[0], initDate[1], initDate[2]));
+        me.absMax = dateUtil.add(clearTime(new Date(initDate[0], initDate[1], initDate[2])), 'mi', (24 * 60) - 1);
 
-        // If a String value was supplied, try to convert it to a proper Date object
-        if (Ext.isString(value)) {
-            me.value = me.rawToValue(value);
-        }
+        me.store = me.createStore();
+        me.updateList();
 
         me.callParent();
     },
 
-<span id='Ext-form-field-Time-method-setMinValue'>    /**
-</span>     * Replaces any existing {@link #minValue} with the new time and refreshes the picker's range.
-     * @param {Date/String} value The minimum time that can be selected
+<span id='Ext-picker-Time-method-setMinValue'>    /**
+</span>     * Set the {@link #minValue} and update the list of available times. This must be a Date object (only the time
+     * fields will be used); no parsing of String values will be done.
+     * @param {Date} value
      */
     setMinValue: function(value) {
-        var me = this,
-            picker = me.picker;
-        me.setLimit(value, true);
-        if (picker) {
-            picker.setMinValue(me.minValue);
-        }
+        this.minValue = value;
+        this.updateList();
     },
 
-<span id='Ext-form-field-Time-method-setMaxValue'>    /**
-</span>     * Replaces any existing {@link #maxValue} with the new time and refreshes the picker's range.
-     * @param {Date/String} value The maximum time that can be selected
+<span id='Ext-picker-Time-method-setMaxValue'>    /**
+</span>     * Set the {@link #maxValue} and update the list of available times. This must be a Date object (only the time
+     * fields will be used); no parsing of String values will be done.
+     * @param {Date} value
      */
     setMaxValue: function(value) {
-        var me = this,
-            picker = me.picker;
-        me.setLimit(value, false);
-        if (picker) {
-            picker.setMaxValue(me.maxValue);
-        }
-    },
-
-<span id='Ext-form-field-Time-method-setLimit'>    /**
-</span>     * @private
-     * Updates either the min or max value. Converts the user's value into a Date object whose
-     * year/month/day is set to the {@link #initDate} so that only the time fields are significant.
-     */
-    setLimit: function(value, isMin) {
-        var me = this,
-            d, val;
-        if (Ext.isString(value)) {
-            d = me.parseDate(value);
-        }
-        else if (Ext.isDate(value)) {
-            d = value;
-        }
-        if (d) {
-            val = Ext.Date.clearTime(new Date(me.initDate));
-            val.setHours(d.getHours(), d.getMinutes(), d.getSeconds(), d.getMilliseconds());
-            me[isMin ? 'minValue' : 'maxValue'] = val;
-        }
-    },
-
-    rawToValue: function(rawValue) {
-        return this.parseDate(rawValue) || rawValue || null;
-    },
-
-    valueToRaw: function(value) {
-        return this.formatDate(this.parseDate(value));
-    },
-
-<span id='Ext-form-field-Time-method-getErrors'>    /**
-</span>     * Runs all of Time's validations and returns an array of any errors. Note that this first
-     * runs Text's validations, so the returned array is an amalgamation of all field errors.
-     * The additional validation checks are testing that the time format is valid, that the chosen
-     * time is within the {@link #minValue} and {@link #maxValue} constraints set.
-     * @param {Mixed} value The value to get errors for (defaults to the current field value)
-     * @return {Array} All validation errors for this field
-     */
-    getErrors: function(value) {
-        var me = this,
-            format = Ext.String.format,
-            errors = me.callParent(arguments),
-            minValue = me.minValue,
-            maxValue = me.maxValue,
-            date;
-
-        value = me.formatDate(value || me.processRawValue(me.getRawValue()));
-
-        if (value === null || value.length &lt; 1) { // if it's blank and textfield didn't flag it then it's valid
-             return errors;
-        }
-
-        date = me.parseDate(value);
-        if (!date) {
-            errors.push(format(me.invalidText, value, me.format));
-            return errors;
-        }
-
-        if (minValue &amp;&amp; date &lt; minValue) {
-            errors.push(format(me.minText, me.formatDate(minValue)));
-        }
-
-        if (maxValue &amp;&amp; date &gt; maxValue) {
-            errors.push(format(me.maxText, me.formatDate(maxValue)));
-        }
-
-        return errors;
-    },
-
-    formatDate: function() {
-        return Ext.form.field.Date.prototype.formatDate.apply(this, arguments);
+        this.maxValue = value;
+        this.updateList();
     },
 
-<span id='Ext-form-field-Time-method-parseDate'>    /**
+<span id='Ext-picker-Time-method-normalizeDate'>    /**
 </span>     * @private
-     * Parses an input value into a valid Date object.
-     * @param {String/Date} value
+     * Sets the year/month/day of the given Date object to the {@link #initDate}, so that only
+     * the time fields are significant. This makes values suitable for time comparison.
+     * @param {Date} date
      */
-    parseDate: function(value) {
-        if (!value || Ext.isDate(value)) {
-            return value;
-        }
-
-        var me = this,
-            val = me.safeParse(value, me.format),
-            altFormats = me.altFormats,
-            altFormatsArray = me.altFormatsArray,
-            i = 0,
-            len;
-
-        if (!val &amp;&amp; altFormats) {
-            altFormatsArray = altFormatsArray || altFormats.split('|');
-            len = altFormatsArray.length;
-            for (; i &lt; len &amp;&amp; !val; ++i) {
-                val = me.safeParse(value, altFormatsArray[i]);
-            }
-        }
-        return val;
+    normalizeDate: function(date) {
+        var initDate = this.initDate;
+        date.setFullYear(initDate[0], initDate[1], initDate[2]);
+        return date;
     },
 
-    safeParse: function(value, format){
-        var me = this,
-            utilDate = Ext.Date,
-            parsedDate,
-            result = null;
-
-        if (utilDate.formatContainsDateInfo(format)) {
-            // assume we've been given a full date
-            result = utilDate.parse(value, format);
-        } else {
-            // Use our initial safe date
-            parsedDate = utilDate.parse(me.initDate + ' ' + value, me.initDateFormat + ' ' + format);
-            if (parsedDate) {
-                result = parsedDate;
-            }
-        }
-        return result;
-    },
-
-    // @private
-    getSubmitValue: function() {
-        var me = this,
-            format = me.submitFormat || me.format,
-            value = me.getValue();
-
-        return value ? Ext.Date.format(value, format) : null;
-    },
-
-<span id='Ext-form-field-Time-method-createPicker'>    /**
-</span>     * @private
-     * Creates the {@link Ext.picker.Time}
+<span id='Ext-picker-Time-method-updateList'>    /**
+</span>     * Update the list of available times in the list to be constrained within the {@link #minValue}
+     * and {@link #maxValue}.
      */
-    createPicker: function() {
+    updateList: function() {
         var me = this,
-            picker = Ext.create('Ext.picker.Time', {
-                selModel: {
-                    mode: 'SINGLE'
-                },
-                floating: true,
-                hidden: true,
-                minValue: me.minValue,
-                maxValue: me.maxValue,
-                increment: me.increment,
-                format: me.format,
-                ownerCt: this.ownerCt,
-                renderTo: document.body,
-                maxHeight: me.pickerMaxHeight,
-                focusOnToFront: false
-            });
+            min = me.normalizeDate(me.minValue || me.absMin),
+            max = me.normalizeDate(me.maxValue || me.absMax);
 
-        me.mon(picker.getSelectionModel(), {
-            selectionchange: me.onListSelect,
-            scope: me
+        me.store.filterBy(function(record) {
+            var date = record.get('date');
+            return date &gt;= min &amp;&amp; date &lt;= max;
         });
-
-        return picker;
     },
 
-<span id='Ext-form-field-Time-method-onExpand'>    /**
+<span id='Ext-picker-Time-method-createStore'>    /**
 </span>     * @private
-     * Enables the key nav for the Time picker when it is expanded.
-     * TODO this is largely the same logic as ComboBox, should factor out.
+     * Creates the internal {@link Ext.data.Store} that contains the available times. The store
+     * is loaded with all possible times, and it is later filtered to hide those times outside
+     * the minValue/maxValue.
      */
-    onExpand: function() {
+    createStore: function() {
         var me = this,
-            keyNav = me.pickerKeyNav,
-            selectOnTab = me.selectOnTab,
-            picker = me.getPicker(),
-            lastSelected = picker.getSelectionModel().lastSelected,
-            itemNode;
-
-        if (!keyNav) {
-            keyNav = me.pickerKeyNav = Ext.create('Ext.view.BoundListKeyNav', this.inputEl, {
-                boundList: picker,
-                forceKeyDown: true,
-                tab: function(e) {
-                    if (selectOnTab) {
-                        if(me.picker.highlightedItem) {
-                            this.selectHighlighted(e);
-                        } else {
-                            me.collapse();
-                        }
-                        me.triggerBlur();
-                    }
-                    // Tab key event is allowed to propagate to field
-                    return true;
-                }
+            utilDate = Ext.Date,
+            times = [],
+            min = me.absMin,
+            max = me.absMax;
+
+        while(min &lt;= max){
+            times.push({
+                disp: utilDate.dateFormat(min, me.format),
+                date: min
             });
-            // stop tab monitoring from Ext.form.field.Trigger so it doesn't short-circuit selectOnTab
-            if (selectOnTab) {
-                me.ignoreMonitorTab = true;
-            }
-        }
-        Ext.defer(keyNav.enable, 1, keyNav); //wait a bit so it doesn't react to the down arrow opening the picker
-
-        // Highlight the last selected item and scroll it into view
-        if (lastSelected) {
-            itemNode = picker.getNode(lastSelected);
-            if (itemNode) {
-                picker.highlightItem(itemNode);
-                picker.el.scrollChildIntoView(itemNode, false);
-            }
-        }
-    },
-
-<span id='Ext-form-field-Time-method-onCollapse'>    /**
-</span>     * @private
-     * Disables the key nav for the Time picker when it is collapsed.
-     */
-    onCollapse: function() {
-        var me = this,
-            keyNav = me.pickerKeyNav;
-        if (keyNav) {
-            keyNav.disable();
-            me.ignoreMonitorTab = false;
-        }
-    },
-
-<span id='Ext-form-field-Time-method-onChange'>    /**
-</span>     * @private
-     * Clears the highlighted item in the picker on change.
-     * This prevents the highlighted item from being selected instead of the custom typed in value when the tab key is pressed.
-     */
-    onChange: function() {
-        var me = this,
-            picker = me.picker;
-
-        me.callParent(arguments);
-        if(picker) {
-            picker.clearHighlight();
+            min = utilDate.add(min, 'mi', me.increment);
         }
-    },
 
-<span id='Ext-form-field-Time-method-onListSelect'>    /**
-</span>     * @private
-     * Handles a time being selected from the Time picker.
-     */
-    onListSelect: function(list, recordArray) {
-        var me = this,
-            record = recordArray[0],
-            val = record ? record.get('date') : null;
-        me.setValue(val);
-        me.fireEvent('select', me, val);
-        me.picker.clearHighlight();
-        me.collapse();
-        me.inputEl.focus();
+        return Ext.create('Ext.data.Store', {
+            fields: ['disp', 'date'],
+            data: times
+        });
     }
-});
 
+});
 </pre>
 </body>
 </html>