| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493 | <!DOCTYPE html><html><head>  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />  <title>The source code</title>  <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 type="text/javascript">    function highlight() {      document.getElementById(location.hash.replace(/#/, "")).className = "highlight";    }  </script></head><body onload="prettyPrint(); highlight();">  <pre class="prettyprint lang-js"><span id='Ext-form-field-Time'>/**</span> * Provides a time input field with a time dropdown and automatic time validation. * * 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. * * 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. * * Example usage: * *     @example *     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%' *        }] *     }); */Ext.define('Ext.form.field.Time', {    extend:'Ext.form.field.ComboBox',    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='x-form-time-trigger']     * An additional CSS class used to style the trigger button. The trigger will always get the {@link #triggerBaseCls}     * by default and triggerCls will be **appended** if specified.     */    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}.     */<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}.     */    //<locale><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}.     */    minText : "The time in this field must be equal to or after {0}",    //</locale>    //<locale><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}.     */    maxText : "The time in this field must be equal to or before {0}",    //</locale>    //<locale><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.     */    invalidText : "{0} is not a valid time",    //</locale>    //<locale><span id='Ext-form-field-Time-cfg-format'>    /**</span>     * @cfg {String} [format=undefined]     * 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 : "g:i A",    //</locale>    //<locale><span id='Ext-form-field-Time-cfg-submitFormat'>    /**</span>     * @cfg {String} [submitFormat=undefined]     * The date format string which will be submitted to the server. The format must be valid according to     * {@link Ext.Date#parse}.     *     * Defaults to {@link #format}.     */    //</locale>    //<locale><span id='Ext-form-field-Time-cfg-altFormats'>    /**</span>     * @cfg {String} altFormats     * Multiple date formats separated by "|" to try when parsing a user input value and it doesn't match the defined     * format.     */    altFormats : "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",    //</locale><span id='Ext-form-field-Time-cfg-increment'>    /**</span>     * @cfg {Number} increment     * The number of minutes between each time value in the list.     */    increment: 15,<span id='Ext-form-field-Time-cfg-pickerMaxHeight'>    /**</span>     * @cfg {Number} pickerMaxHeight     * The maximum height of the {@link Ext.picker.Time} dropdown.     */    pickerMaxHeight: 300,<span id='Ext-form-field-Time-cfg-selectOnTab'>    /**</span>     * @cfg {Boolean} selectOnTab     * Whether the Tab key should select the currently highlighted item.     */    selectOnTab: true,    <span id='Ext-form-field-Time-cfg-snapToIncrement'>    /**</span>     * @cfg {Boolean} [snapToIncrement=false]     * Specify as `true` to enforce that only values on the {@link #increment} boundary are accepted.     */    snapToIncrement: false,<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 "safe" date that can be any date aside from DST boundary dates.     */    initDate: '1/1/2008',    initDateFormat: 'j/n/Y',        ignoreSelection: 0,    queryMode: 'local',    displayField: 'disp',    valueField: 'date',    initComponent: function() {        var me = this,            min = me.minValue,            max = me.maxValue;        if (min) {            me.setMinValue(min);        }        if (max) {            me.setMaxValue(max);        }        me.displayTpl = new Ext.XTemplate(            '<tpl for=".">' +                '{[typeof values === "string" ? values : this.formatDate(values["' + me.displayField + '"])]}' +                '<tpl if="xindex < xcount">' + me.delimiter + '</tpl>' +            '</tpl>', {            formatDate: Ext.Function.bind(me.formatDate, me)        });        this.callParent();    },<span id='Ext-form-field-Time-method-transformOriginalValue'>    /**</span>     * @private     */    transformOriginalValue: function(value) {        if (Ext.isString(value)) {            return this.rawToValue(value);        }        return value;    },<span id='Ext-form-field-Time-method-isEqual'>    /**</span>     * @private     */    isEqual: function(v1, v2) {        return Ext.Date.isEqual(v1, v2);    },<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     */    setMinValue: function(value) {        var me = this,            picker = me.picker;        me.setLimit(value, true);        if (picker) {            picker.setMinValue(me.minValue);        }    },<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     */    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());        }        // Invalid min/maxValue config should result in a null so that defaulting takes over        else {            val = null;        }        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 {Object} [value] The value to get errors for (defaults to the current field value)     * @return {String[]} 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 < 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, Ext.Date.unescapeFormat(me.format)));            return errors;        }        if (minValue && date < minValue) {            errors.push(format(me.minText, me.formatDate(minValue)));        }        if (maxValue && date > maxValue) {            errors.push(format(me.maxText, me.formatDate(maxValue)));        }        return errors;    },    formatDate: function() {        return Ext.form.field.Date.prototype.formatDate.apply(this, arguments);    },<span id='Ext-form-field-Time-method-parseDate'>    /**</span>     * @private     * Parses an input value into a valid Date object.     * @param {String/Date} value     */    parseDate: function(value) {        var me = this,            val = value,            altFormats = me.altFormats,            altFormatsArray = me.altFormatsArray,            i = 0,            len;        if (value && !Ext.isDate(value)) {            val = me.safeParse(value, me.format);            if (!val && altFormats) {                altFormatsArray = altFormatsArray || altFormats.split('|');                len = altFormatsArray.length;                for (; i < len && !val; ++i) {                    val = me.safeParse(value, altFormatsArray[i]);                }            }        }        // If configured to snap, snap resulting parsed Date to the closest increment.        if (val && me.snapToIncrement) {            val = new Date(Ext.Number.snap(val.getTime(), me.increment * 60 * 1000));        }        return val;    },    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}     */    createPicker: function() {        var me = this,            picker;        me.listConfig = Ext.apply({            xtype: 'timepicker',            selModel: {                mode: 'SINGLE'            },            cls: undefined,            minValue: me.minValue,            maxValue: me.maxValue,            increment: me.increment,            format: me.format,            maxHeight: me.pickerMaxHeight        }, me.listConfig);        picker = me.callParent();        me.store = picker.store;        return picker;    },        onItemClick: function(picker, record){        // The selection change events won't fire when clicking on the selected element. Detect it here.        var me = this,            selected = picker.getSelectionModel().getSelection();        if (selected.length > 0) {            selected = selected[0];            if (selected && Ext.Date.isEqual(record.get('date'), selected.get('date'))) {                me.collapse();            }        }    },<span id='Ext-form-field-Time-method-onListSelectionChange'>    /**</span>     * @private     * Handles a time being selected from the Time picker.     */    onListSelectionChange: function(list, recordArray) {        var me = this,            record = recordArray[0],            val = record ? record.get('date') : null;                    if (!me.ignoreSelection) {            me.skipSync = true;            me.setValue(val);            me.skipSync = false;            me.fireEvent('select', me, val);            me.picker.clearHighlight();            me.collapse();            me.inputEl.focus();        }    },    <span id='Ext-form-field-Time-method-syncSelection'>    /**</span>     * @private      * Synchronizes the selection in the picker to match the current value     */    syncSelection: function() {        var me = this,            picker = me.picker,            toSelect,            selModel,            value,            data, d, dLen, rec;                    if (picker && !me.skipSync) {            picker.clearHighlight();            value = me.getValue();            selModel = picker.getSelectionModel();            // Update the selection to match            me.ignoreSelection++;            if (value === null) {                selModel.deselectAll();            } else if(Ext.isDate(value)) {                // find value, select it                data = picker.store.data.items;                dLen = data.length;                for (d = 0; d < dLen; d++) {                    rec = data[d];                    if (Ext.Date.isEqual(rec.get('date'), value)) {                       toSelect = rec;                       break;                   }                }                selModel.select(toSelect);            }            me.ignoreSelection--;        }    },    postBlur: function() {        var me = this;        me.callParent(arguments);        me.setRawValue(me.formatDate(me.getValue()));    },    setValue: function() {        // Store MUST be created for parent setValue to function        this.getPicker();        this.callParent(arguments);    },    getValue: function() {        return this.parseDate(this.callParent(arguments));    }});</pre></body></html>
 |