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>
|