Ext.ns('Zarafa.common.ui'); /** * @class Zarafa.common.ui.DateTimeField * @extends Zarafa.common.ui.CompositeField * @xtype zarafa.datetimefield * * This class can be used to construct a {@link Ext.form.Field field} * which contains a {@link Ext.form.DateField DateField} and a {@link Ext.ux.form.Spinner Spinner} * {@link Ext.form.Field field} for the time. */ Zarafa.common.ui.DateTimeField = Ext.extend(Zarafa.common.ui.CompositeField, { /** * @cfg {Boolean} enableTimeSelection Enable the time selection components * to appear, otherwise the period will only exist between dates. */ enableTimeSelection: true, /** * @cfg {Date/String} defaultValue The default value which must be applied * to the date */ defaultValue: undefined, /** * @cfg {Date/String} minValue The minimum value which can be used. */ minValue : undefined, /** * @cfg {Date/String} maxValue The maximum value which can be used. */ maxValue : undefined, /** * @cfg {String} dateFormat The format in which the date appears in the * {@link Ext.form.DateField DateField}. */ // # TRANSLATORS: See http://docs.sencha.com/ext-js/3-4/#!/api/Date for the meaning of these formatting instructions dateFormat : _('d/m/Y'), /** * @cfg {String} timeFormat The format in which the time appears in the * time {@link Ext.ux.form.Spinner Spinner}. */ timeFormat : _('G:i'), /** * @cfg {Number} timeIncrement The number of minutes to increase/decrease * when the time {@link Ext.ux.form.Spinner Spinner} is used. */ timeIncrement : 15, /** * @cfg {Object} dateFieldConfig The way by which one can pass the configuration options of {@link Ext.form.DateField}. */ dateFieldConfig : {}, /** * @cfg {Object} timeFieldConfig The way by which one can pass the configuration options of {@link #this.TimeField}. */ timeFieldConfig : {}, /** * @constructor * @param {Object} Configuration object */ constructor : function(config) { config = config || {}; Ext.apply(this, config); if (Ext.isDefined(this.defaultValue) && !Ext.isDate(this.defaultValue)) { this.defaultValue = Date.parseDate(this.defaultValue, this.dateFormat + ' ' + this.timeFormat); } if (Ext.isDefined(this.minValue) && !Ext.isDate(this.minValue)) { this.minValue = Date.parseDate(this.minValue, this.dateFormat + ' ' + this.timeFormat); } if (Ext.isDefined(this.maxValue) && !Ext.isDate(this.maxValue)) { this.maxValue = Date.parseDate(this.maxValue, this.dateFormat + ' ' + this.timeFormat); } // Hide the labels, as we will draw them ourself to have more control over them config.hideLabels = true; var items = []; if ( !config.hideLabel && config.fieldLabel && this.ownerCt.layout!=='form' ){ var labelConfig = config.labelConfig || {}; labelConfig = Ext.applyIf(labelConfig, { xtype : 'label', text : config.fieldLabel + (config.labelSeparator || ':') || '' }); if ( config.labelWidth ){ labelConfig.width = config.labelWidth; } else { labelConfig.autoWidth = true; } items.push(labelConfig); } items = items.concat([ Ext.apply({ xtype: 'datefield', ref: 'dateField', flex: 1, format: this.dateFormat, value : this.defaultValue, minValue: this.minValue, maxValue: this.maxValue, listeners: { change: this.onDateChange, select: this.onDateSelect, scope: this }, hideLabel : true, hideLabels : true }, this.dateFieldConfig ), Ext.apply({ xtype: 'zarafa.spinnerfield', ref: 'timeField', width: 85, defaultValue : this.defaultValue, minValue: this.minValue, maxValue: this.maxValue, incrementValue: this.timeIncrement, alternateIncrementValue: 1, plugins: [{ ptype: 'zarafa.timespinner', format: this.timeFormat }], listeners: { change: this.onTimeChange, spin: this.onTimeSpin, scope: this } }, this.timeFieldConfig ) ]); config = Ext.applyIf(config, { isSingleValued : true, hideLabels : true, items: items }); Ext.apply(this, config); Zarafa.common.ui.DateTimeField.superclass.constructor.call(this, config); }, /** * Called by {@link #onDateChange} or {@link #onDateSelect} when the {@link #dateField} * has a new value. This will construct a new value for the {@link #timeField} and * fire the {@link #change} event. * @param {Date} newValue The new Date inside the DateField * @param {Date} oldValue The old Date from the DateField * @private */ doDateChange : function(newValue, oldValue) { var oldDate; var newDate; if (this.enableTimeSelection) { var curTime = this.timeField.getValue(); oldDate = this.combineDateAndTime(oldValue, curTime); newDate = this.combineDateAndTime(newValue, curTime); } else { oldDate = oldValue; newDate = newValue; } // Restrict value to minimum and maximum value. Both the Time and // Date fields already enforce their individual restriction, but // it is still possible to create a value outside of the range // when the individual values are combined. if(Ext.isDefined(newDate)) { if (newDate > this.maxValue) { newDate = this.maxValue; } else if (newDate < this.minValue) { newDate = this.minValue; } // Enforce the new date to the timeField, this way the // timeField holds the full date value for this entire // component. this.timeField.setValue(newDate); this.fireEvent('change', this, newDate, oldDate); } }, /** * Called by {@link #onTimeChange} or {@link #onTimeSpin} when the {@link #timeField} * has a new value. This will update the {@link #dateField} and fire the {@link #change} * event. * @param {Date} newValue The new Date inside the SpinnerField * @param {Date} oldValue The old Date from the SpinnerField * @private */ doTimeChange : function(newValue, oldValue) { // While spinning the date could have changed, // update the dateField with the new date. this.dateField.setValue(newValue); this.fireEvent('change', this, newValue, oldValue); }, /** * Event handler which is raised when the date has been changed (by typing), * this will call {@link #doDateChange} for updating the new Field value * and firing the {@link #change} event. * @param {Ext.form.DateField} field The field which has fired the event * @param {Date} newValue The new Date inside the DateField * @param {Date} oldValue The old Date from the DateField * @private */ onDateChange : function(field, newValue, oldValue) { this.doDateChange(newValue, oldValue); }, /** * Event handler which is raised when the date has been selected * this will call {@link #doDateChange} for updating the new Field value * and firing the {@link #change} event. * @param {Ext.form.DateField} field The field which has fired the event * @param {Date} date The new value for the field * @pivate */ onDateSelect : function(field, date) { var oldValue = field.startValue; var newValue = date; this.doDateChange(newValue, oldValue); }, /** * Event handler which is raised when the timefield has been changed (by typing), * this will call {@link #doTimeChange} for updating the new Field value * and firing the {@link #change} event. * @param {Zarafa.common.ui.SpinnerField} field The field which fired the event * @param {Date} newValue The new Date inside the SpinnerField * @param {Date} oldValue The old Date from the SpinnerField * @private */ onTimeChange : function(field, newValue, oldValue) { this.doTimeChange(newValue, oldValue); }, /** * Event handler which is raised when the timeSpinner has been spinned * this will call {@link #doTimeChange} for updating the new Field value * and firing the {@link #change} event. * @param {Zarafa.common.plugins.TimeSpinner} spinner The spinner plugin * @private */ onTimeSpin : function(spinner) { var oldValue = spinner.field.startValue; var newValue = spinner.field.getValue(); this.doTimeChange(newValue, oldValue); }, /** * Sets a data value into the field and validates it. To set the value directly * without validation see {@link #setRawValue}. * @param {Date} The value to set */ setValue : function(value) { this.dateField.setValue(value); if (this.enableTimeSelection) { this.timeField.setValue(value); } }, /** * Sets the underlying DOM field's value directly, bypassing validation. * To set the value with validation see {@link #setValue}. */ setRawValue : function(value) { this.dateField.setRawValue(value); if (this.enableTimeSelection) { this.timeField.setRawValue(value); } }, /** * Returns the normalized data value (undefined or emptyText will be returned as ''). * To return the raw value see {@link #getRawValue}. * @return {Date} The date object */ getValue : function() { if (this.enableTimeSelection) { return this.timeField.getValue(); } else { return this.dateField.getValue(); } }, /** * Returns the raw data value which may or may not be a valid, defined value. * To return a normalized value see {@link #getValue}. * @return {Date} The date object */ getRawValue : function() { if (this.enableTimeSelection) { return this.timeField.getRawValue(); } else { return this.dateField.getRawValue(); } }, /** * Combine the date value together with a time value * and return the corresponding {@link Date date} object. * @param {Date/String} dateObject The date object, either a string (containing * a date formatted using {@link #dateFormat} or a {@link Date date} object. * @param {Date/String} timeObject The object containing the time * @return {Date} The date object */ combineDateAndTime : function(dateObject, timeObject) { // A bit silly, but dateField returns the Date object, // but to add the time information we must convert it // to a string, append the time, and convert it into // a Date object again. if (Ext.isDate(dateObject)) { dateObject = dateObject.format(this.dateFormat); } if (Ext.isDate(timeObject)) { timeObject = timeObject.format(this.timeFormat); } if(Ext.isDefined(dateObject) && Ext.isDefined(timeObject)) { return Date.parseDate(dateObject + ' ' + timeObject, this.dateFormat + ' ' + this.timeFormat); } else { return undefined; } }, /** * Toggle the enabled state of the {@link Zarafa.common.ui.SpinnerField SpinnerField} * for setting the time. * @param {Boolean} enabled True to enable the selection of time */ setEnabledTimeSelection : function(enabled) { this.enableTimeSelection = enabled; if (this.rendered) { this.timeField.setVisible(enabled); this.doLayout(); } }, /** * Function add css class to the {@link Zarafa.common.ui.DateTimeField dateTimeField} * @param {String} cls CSS class name */ addClass: function (cls) { this.timeField.addClass(cls); this.dateField.addClass(cls); }, /** * Function remove css class to the {@link Zarafa.common.ui.DateTimeField dateTimeField} * @param {String} cls CSS class name */ removeClass: function (cls) { this.timeField.removeClass(cls); this.dateField.removeClass(cls); } }); Ext.reg('zarafa.datetimefield', Zarafa.common.ui.DateTimeField);