UNPKG

@openui5/sap.m

Version:

OpenUI5 UI Library sap.m

1,028 lines (849 loc) 33.6 kB
/*! * UI development toolkit for HTML5 (OpenUI5) * (c) Copyright 2009-2022 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ // Provides control sap.m.DateRangeSelection. sap.ui.define([ 'sap/ui/Device', './DatePicker', './library', 'sap/ui/core/LocaleData', 'sap/ui/core/format/DateFormat', './DateRangeSelectionRenderer', "sap/base/util/deepEqual", "sap/base/Log", "sap/base/assert", "sap/ui/dom/jquery/cursorPos" // jQuery Plugin "cursorPos" ], function( Device, DatePicker, library, LocaleData, DateFormat, DateRangeSelectionRenderer, deepEqual, Log, assert ) { "use strict"; /** * Constructor for a new <code>DateRangeSelection</code>. * * @param {string} [sId] ID for the new control, generated automatically if no ID is given * @param {object} [mSettings] Initial settings for the new control * * @class * A single-field input control that enables the users to enter a localized date range. * * <h3>Overview</h3> * * The <code>DateRangeSelection</code> enables the users to enter a localized * date range using touch, mouse, keyboard input, or by selecting a date range in * the calendar. They can also navigate directly from one month or year to another. * * <b>Note:</b> The {@link sap.ui.unified.Calendar} is used internally only if the * <code>DateRangeSelection</code> is opened (not used for the initial rendering). * If the <code>sap.ui.unified</code> library is not loaded before the * <code>DateRangeSelection</code> is opened, it will be loaded upon opening. * This could lead to a waiting time when the <code>DateRangeSelection</code> is * opened for the first time. To prevent this, apps using the * <code>DateRangeSelection</code> should also load the <code>sap.ui.unified</code> * library. * * <h3>Usage</h3> * * <i>When to use?</i> * * If you need a time range and know that your user is a power user who has to * input lots of data. If the keyboard is the primary device used for navigating * the app, use two input fields. This allows the user to quickly jump from field * to field. By selecting a date in one of the fields, the other field should * recognize the information and jump to the same selection. * * <i>When not to use?</i> * * If the user's primary goal is not to select ranges or if you just want to enter * a date and a time. For such cases, use the {@link sap.m.DatePicker} or * {@link sap.m.TimePicker}. * * The user can enter a date by: * <ul><li>Using the calendar that opens in a popup</li> * <li>Typing it in directly in the input field (not available for mobile devices)</li></ul> * * On app level, there are two options to provide a date for the * <code>DateRangeSelection</code> - date range as a string to the * <code>value</code> property or JavaScript Date objects to the * <code>dateValue</code> and <code>secondDateValue</code> properties (only one of * these options should be used at a time): * * <ul><li>Use the <code>value</code> property if the date range is already provided as * a formatted string</li> * <li>Use the <code>dateValue</code> and <code>secondDateValue</code> properties * if the date range is already provided as JavaScript Date objects or you want to * work with JavaScript Date objects</li></ul> * * <h3>Formatting</h3> * * All formatting and parsing of dates from and to strings is done using the * {@link sap.ui.core.format.DateFormat}. If a date is entered by typing it into * the input field, it must fit to the used date format and locale. * * Supported format options are pattern-based on Unicode LDML Date Format notation. * See {@link http://unicode.org/reports/tr35/#Date_Field_Symbol_Table} * * For example, if the <code>displayFormat</code> is "MMM d, y", delimiter is "-", * and the used locale is English, a valid value string is "Jul 29, 2015 - Jul 31, * 2015" and it is displayed in the same way in the input field. * * If no placeholder is set to the <code>DateRangeSelection</code>, the used * <code>displayFormat</code> is displayed as a placeholder. If another placeholder * is needed, it must be set. * * <b>Note:</b> If the string does NOT match the <code>displayFormat</code> * (from user input) or the <code>valueFormat</code> (on app level), the * {@link sap.ui.core.format.DateFormat} makes an attempt to parse it based on the * locale settings. For more information, see the respective documentation in the * API Reference. * * <h3>Responsive behavior</h3> * * The <code>DateRangeSelection</code> is fully responsive. It is smaller in * compact mode and provides a touch-friendly size in cozy mode. * * @extends sap.m.DatePicker * @version 1.60.39 * @version 1.60.39 * * @constructor * @public * @since 1.22.0 * @alias sap.m.DateRangeSelection * @ui5-metamodel This control/element also will be described in the UI5 (legacy) designtime metamodel */ var DateRangeSelection = DatePicker.extend("sap.m.DateRangeSelection", /** @lends sap.m.DateRangeSelection.prototype */ { metadata : { library : "sap.m", properties : { /** * Delimiter between start and end date. Default value is "-". * If no delimiter is given, the one defined for the used locale is used. */ delimiter : {type : "string", group : "Misc", defaultValue : '-'}, /** * The end date of the range as JavaScript Date object. This is independent from any formatter. * * <b>Note:</b> If this property is used, the <code>value</code> property should not be changed from the caller. */ secondDateValue : {type : "object", group : "Data", defaultValue : null}, /** * Start date of the range. * @deprecated since version 1.22.0, replaced by <code>dateValue</code> property of the {@link sap.m.DateTimeField} */ from : {type : "object", group : "Misc", defaultValue : null, deprecated: true}, /** * End date of the range. * @deprecated since version 1.22.0, replaced by <code>secondDateValue</code> property */ to : {type : "object", group : "Misc", defaultValue : null, deprecated: true} }, designtime: "sap/m/designtime/DateRangeSelection.designtime" }}); /** * This file defines behavior for the control * @public */ /* eslint-disable no-lonely-if */ DateRangeSelection.prototype.init = function(){ DatePicker.prototype.init.apply(this, arguments); this._bIntervalSelection = true; }; DateRangeSelection.prototype.onkeypress = function(oEvent){ // the keypress event should be fired only when a character key is pressed, // unfortunately some browsers fire the keypress event for control keys as well. if (!oEvent.charCode || oEvent.metaKey || oEvent.ctrlKey) { return; } var oFormatter = _getFormatter.call(this); var sDelimiter = _getDelimiter.call(this); var sAllowedCharacters = oFormatter.sAllowedCharacters + sDelimiter + " "; var sChar = String.fromCharCode(oEvent.charCode); if (sChar && oFormatter.sAllowedCharacters && sAllowedCharacters.indexOf(sChar) < 0) { oEvent.preventDefault(); } }; DateRangeSelection.prototype._getPlaceholder = function() { var sPlaceholder = this.getPlaceholder(), oBinding, oBindingType, oLocale, oLocaleData; if (!sPlaceholder) { oBinding = this.getBinding("value"); oLocale = sap.ui.getCore().getConfiguration().getFormatSettings().getFormatLocale(); oLocaleData = LocaleData.getInstance(oLocale); if (oBinding && oBinding.getType() instanceof sap.ui.model.type.DateInterval) { oBindingType = oBinding.getType(); if (oBindingType.oFormatOptions && oBindingType.oFormatOptions.format) { sPlaceholder = oLocaleData.getCustomDateTimePattern(oBindingType.oFormatOptions.format); } else { sPlaceholder = oLocaleData.getDatePattern("medium"); } } else { sPlaceholder = this.getDisplayFormat(); if (!sPlaceholder) { sPlaceholder = "medium"; } if (this._checkStyle(sPlaceholder)) { sPlaceholder = oLocaleData.getDatePattern(sPlaceholder); } } var sDelimiter = _getDelimiter.call(this); if (sDelimiter && sDelimiter !== "") { sPlaceholder = sPlaceholder + " " + sDelimiter + " " + sPlaceholder; } } return sPlaceholder; }; // Overwrite DatePicker's setValue to support two date range processing /** * Getter for property <code>value</code>. * * Returns a date as a string in the format defined in property <code>displayFormat</code>. * * <b>Note:</b> As the value string always used the <code>displayFormat</code>, it is both locale-dependent and calendar-type-dependent. * * If this property is used, the <code>dateValue</code> property should not be changed from the caller. * * @returns {string} the value of property <code>value</code> * @public * @name sap.m.DateRangeSelection#getValue * @function */ /** * Setter for property <code>value</code>. * * Expects a date as a string in the format defined in property <code>displayFormat</code>. * * <b>Note:</b> As the value string always used the <code>displayFormat</code>, it is both locale-dependent and calendar-type-dependent. * * If this property is used, the <code>dateValue</code> property should not be changed from the caller. * * @param {string} sValue The new value of the input. * @return {sap.m.DateRangeSelection} <code>this</code> to allow method chaining. * @public */ DateRangeSelection.prototype.setValue = function(sValue) { if (sValue !== this.getValue()) { this._lastValue = sValue; } else { return this; } // Set the property in any case but check validity on output this.setProperty("value", sValue); this._bValid = true; // Convert to date object(s) var aDates = [undefined, undefined]; if (sValue) { aDates = this._parseValue(sValue); if (!_dateRangeValidityCheck.call(this, aDates[0], aDates[1])[0]) {//aDates can be undefined if don't fit to the min/max range this._bValid = false; Log.warning("Value can not be converted to a valid dates", this); } } this.setProperty("dateValue", _normalizeDateValue(aDates[0])); this.setProperty("secondDateValue", _normalizeDateValue(aDates[1])); // Do not call InputBase.setValue because the displayed value and the output value might have different pattern if (this.getDomRef()) { // Convert to output var sOutputValue = this._formatValue(aDates[0], aDates[1]); if (this._$input.val() !== sOutputValue) { this._$input.val(sOutputValue); this._curpos = this._$input.cursorPos(); } } return this; }; /** * Converts the parameter to a Javascript Date, if it is a timestamp integer. * @param {object|int} vBindingDate A timestamp or a Javascript Date * @returns {object} A Javascript Date object * @private */ function _normalizeDateValue(vBindingDate) { return (typeof vBindingDate === 'number') ? new Date(vBindingDate) : vBindingDate; } /** * Converts the parameter to a timestamp integer, if it is a Javascript Date. * @param {object|int} vBindingDate A timestamp or a Javascript Date * @returns {object} A timestamp integer * @private */ function _denormalizeDateValue(vBindingDate) { return (vBindingDate && vBindingDate.getTime) ? vBindingDate.getTime() : vBindingDate; } /** * Getter for property <code>valueFormat</code>. * * <b>Note:</b> Property <code>valueFormat</code> is not supported in the <code>sap.m.DateRangeSelection</code> control. * * @return {string} the value of property valueFormat * @public * @name sap.m.DateRangeSelection#getValueFormat * @function */ /** * Setter for property <code>valueFormat</code>. * * <b>Note:</b> Property <code>valueFormat</code> is not supported in the <code>sap.m.DateRangeSelection</code> control. * * @param {string} sValueFormat New value for property valueFormat * @return {sap.m.DateRangeSelection} <code>this</code> to allow method chaining * @public */ DateRangeSelection.prototype.setValueFormat = function(sValueFormat) { // if valueFormat changes the value must be parsed again this.setProperty("valueFormat", sValueFormat, true); // no rerendering Log.warning("Property valueFormat is not supported in sap.m.DateRangeSelection control.", this); return this; }; DateRangeSelection.prototype.setDisplayFormat = function(sDisplayFormat) { // if displayFormat changes the value must be formatted again this.setProperty("displayFormat", sDisplayFormat, true); // no rerendering var sOutputValue = this._formatValue(this.getDateValue(), this.getSecondDateValue()); // as value also used displayFormat update value too this.setProperty("value", sOutputValue, true); // no rerendering if (this.getDomRef() && (this._$input.val() !== sOutputValue)) { this._$input.val(sOutputValue); this._curpos = this._$input.cursorPos(); } return this; }; //Following setters/getters are due to backward compatibility with original primary version of composite sap.m.DateRangeSelection, //that consisted of original primary sap.m.DateRangeSelection DateRangeSelection.prototype.setFrom = function(oFrom) { this.setDateValue(oFrom); return this; }; DateRangeSelection.prototype.getFrom = function() { return this.getDateValue(); }; DateRangeSelection.prototype.setTo = function(oTo) { this.setSecondDateValue(oTo); return this; }; DateRangeSelection.prototype.getTo = function() { return this.getSecondDateValue(); }; // Overwrite DatePicker's setDateValue to support two date range processing /** * Getter for property <code>dateValue</code>. * * The start date of the range as JavaScript Date object. This is independent from any formatter. * * <b>Note:</b> If this property is used, the <code>value</code> property should not be changed from the caller. * * @returns {object} the value of property <code>dateValue</code> * @public * @name sap.m.DateRangeSelection#getDateValue * @function */ /** * Setter for property <code>dateValue</code>. * * The start date of the range as JavaScript Date object. This is independent from any formatter. * * <b>Note:</b> If this property is used, the <code>value</code> property should not be changed from the caller. * * @param {object} oDateValue New value for property <code>dateValue</code> * @return {sap.m.DateRangeSelection} <code>this</code> to allow method chaining. * @public */ DateRangeSelection.prototype.setDateValue = function(oDateValue) { if (this._isValidDate(oDateValue)) { throw new Error("Date must be a JavaScript date object; " + this); } if (deepEqual(this.getDateValue(), oDateValue)) { return this; } DatePicker.prototype._dateValidation.call(this, oDateValue); //will handle everything related to set a dateValue this._syncDateObjectsToValue(oDateValue, this.getSecondDateValue()); return this; }; DateRangeSelection.prototype.setSecondDateValue = function(oSecondDateValue) { if (this._isValidDate(oSecondDateValue)) { throw new Error("Date must be a JavaScript date object; " + this); } if (deepEqual(this.getSecondDateValue(), oSecondDateValue)) { return this; } this._bValid = true; if (oSecondDateValue && (oSecondDateValue.getTime() < this._oMinDate.getTime() || oSecondDateValue.getTime() > this._oMaxDate.getTime())) { this._bValid = false; assert(this._bValid, "Date must be in valid range"); } this.setProperty("secondDateValue", oSecondDateValue); this._syncDateObjectsToValue(this.getDateValue(), oSecondDateValue); return this; }; DateRangeSelection.prototype.setMinDate = function(oDate) { DatePicker.prototype.setMinDate.apply(this, arguments); if (oDate) { var oSecondDateValue = this.getSecondDateValue(); if (oSecondDateValue && oSecondDateValue.getTime() < this._oMinDate.getTime()) { Log.warning("SecondDateValue not in valid date range", this); } } return this; }; DateRangeSelection.prototype.setMaxDate = function(oDate) { DatePicker.prototype.setMaxDate.apply(this, arguments); if (oDate) { var oSecondDateValue = this.getSecondDateValue(); if (oSecondDateValue && oSecondDateValue.getTime() > this._oMaxDate.getTime()) { Log.warning("SecondDateValue not in valid date range", this); } } return this; }; DateRangeSelection.prototype._checkMinMaxDate = function() { DatePicker.prototype._checkMinMaxDate.apply(this, arguments); var oSecondDate = this.getSecondDateValue(); if (oSecondDate && (oSecondDate.getTime() < this._oMinDate.getTime() || oSecondDate.getTime() > this._oMaxDate.getTime())) { Log.error("secondDateValue " + oSecondDate.toString() + "(value=" + this.getValue() + ") does not match " + "min/max date range(" + this._oMinDate.toString() + " - " + this._oMaxDate.toString() + "). App. " + "developers should take care to maintain secondDateValue/value accordingly.", this); } }; //Support of two date range version added into original DatePicker's version DateRangeSelection.prototype._parseValue = function(sValue) { var oFormat; var aDates = []; var oDate1, oDate2; var oBinding = this.getBinding("value"); if (oBinding && oBinding.getType() instanceof sap.ui.model.type.DateInterval) { aDates = oBinding.getType().parseValue(sValue, "string"); /** DateRangeSelection control uses local dates for its properties, so make sure returned values from * binding type formatter are restored to local dates if necessary. **/ if (oBinding.getType().oFormatOptions && oBinding.getType().oFormatOptions.UTC) { aDates = aDates.map(function (oUTCDate) { return new Date(oUTCDate.getUTCFullYear(), oUTCDate.getUTCMonth(), oUTCDate.getUTCDate(), oUTCDate.getUTCHours(), oUTCDate.getUTCMinutes(), oUTCDate.getUTCSeconds()); }); } return aDates; } //If we have version of control with delimiter, then sValue should consist of two dates delimited with delimiter, //hence we have to split the value to these dates var sDelimiter = _getDelimiter.call(this); if (sDelimiter && sValue) { sValue = sValue.trim(); sValue = _trim(sValue, [sDelimiter, " "]); aDates = sValue.split(sDelimiter); if (aDates.length === 2) { // if delimiter only appears once in value (not part of date pattern) remove " " to be more flexible for input if (aDates[0].slice(aDates[0].length - 1,aDates[0].length) == " ") { aDates[0] = aDates[0].slice(0, aDates[0].length - 1); } if (aDates[1].slice(0,1) == " ") { aDates[1] = aDates[1].slice(1); } } else { aDates = sValue.split(" " + sDelimiter + " ");// Delimiter appears more than once -> try with separators } if (sValue.indexOf(sDelimiter) === -1) { // no delimiter found -> maybe only " " is used var aDates2 = sValue.split(" "); if (aDates2.length === 2) { aDates = aDates2; } } } if (sValue && aDates.length <= 2) { oFormat = _getFormatter.call(this); //Convert to date object(s) if ((!sDelimiter || sDelimiter === "") || aDates.length === 1) { oDate1 = oFormat.parse(sValue); } else if (aDates.length === 2) { oDate1 = oFormat.parse(aDates[0]); oDate2 = oFormat.parse(aDates[1]); if (!oDate1 || !oDate2) { // at least one date can not be parsed -> whole value is incorrect oDate1 = undefined; oDate2 = undefined; } } } return [oDate1, oDate2]; }; //Support of two date range version added into original DatePicker's version DateRangeSelection.prototype._formatValue = function(oDateValue, oSecondDateValue) { var sValue = "", sDelimiter = _getDelimiter.call(this), oFormat, oBinding, oDate1, oDate2; oDate1 = oDateValue; oDate2 = oSecondDateValue; if (oDate1) { oBinding = this.getBinding("value"); if (oBinding && oBinding.getType() instanceof sap.ui.model.type.DateInterval) { if (oBinding.getType().oFormatOptions && oBinding.getType().oFormatOptions.source && oBinding.getType().oFormatOptions.source.pattern === "timestamp") { sValue = oBinding.getType().formatValue([_denormalizeDateValue(oDateValue), _denormalizeDateValue(oSecondDateValue)], "string"); } else { /** DateRangeSelection control uses local dates for its properties, so make sure they are converted * to UTC dates if the binding type formatter expects them in UTC **/ if (oBinding.getType().oFormatOptions && oBinding.getType().oFormatOptions.UTC) { oDate1 = new Date(Date.UTC(oDateValue.getFullYear(), oDateValue.getMonth(), oDateValue.getDate(), oDateValue.getHours(), oDateValue.getMinutes(), oDateValue.getSeconds())); if (oSecondDateValue) { oDate2 = new Date(Date.UTC(oSecondDateValue.getFullYear(), oSecondDateValue.getMonth(), oSecondDateValue.getDate(), oSecondDateValue.getHours(), oSecondDateValue.getMinutes(), oSecondDateValue.getSeconds())); } } sValue = oBinding.getType().formatValue([oDate1, oDate2], "string"); } } else { oFormat = _getFormatter.call(this); if (sDelimiter && sDelimiter !== "" && oDate2) { sValue = oFormat.format(oDate1) + " " + sDelimiter + " " + oFormat.format(oDate2); } else { sValue = oFormat.format(oDate1); } } } return sValue; }; DateRangeSelection.prototype.onChange = function() { // check the control is editable or not if (!this.getEditable() || !this.getEnabled()) { return; } var sValue = this._$input.val(); var aDates = [undefined, undefined]; this._bValid = true; if (sValue != "") { aDates = this._parseValue(sValue); aDates[1] && aDates[1].setHours(23, 59, 59, 999); aDates = _dateRangeValidityCheck.call(this, aDates[0], aDates[1]);//aDates can be undefined if don't fit to the min/max range if (aDates[0]) { sValue = this._formatValue( aDates[0], aDates[1] ); // to have the right output format if entered different } else { this._bValid = false; } } if (sValue !== this._lastValue) { if (this.getDomRef() && (this._$input.val() !== sValue)) { this._$input.val(sValue); this._curpos = this._$input.cursorPos(); } this._lastValue = sValue; this.setProperty("value", sValue, true); if (this._bValid) { this.setProperty("dateValue", _normalizeDateValue(aDates[0]), true); this.setProperty("secondDateValue", _normalizeDateValue(aDates[1]), true); } if (this._oPopup && this._oPopup.isOpen()) { var oStartDate = this.getDateValue(); if (oStartDate) { if (!this._oDateRange.getStartDate() || this._oDateRange.getStartDate().getTime() !== oStartDate.getTime()) { this._oDateRange.setStartDate(new Date(oStartDate.getTime())); this._oCalendar.focusDate(oStartDate); } } else { if (this._oDateRange.getStartDate()) { this._oDateRange.setStartDate(undefined); } } var oEndDate = this.getSecondDateValue(); if (oEndDate) { if (!this._oDateRange.getEndDate() || this._oDateRange.getEndDate().getTime() !== oEndDate.getTime()) { this._oDateRange.setEndDate(new Date(oEndDate.getTime())); this._oCalendar.focusDate(oEndDate); } } else { if (this._oDateRange.getEndDate()) { this._oDateRange.setEndDate(undefined); } } } _fireChange.call(this, this._bValid); } }; // Overwrite DatePicker's _getInputValue to support two date range processing DateRangeSelection.prototype._getInputValue = function(sValue) { sValue = (typeof sValue == "undefined") ? this._$input.val() : sValue.toString(); if (!sValue) { return ""; } var aDates = this._parseValue(sValue); sValue = this._formatValue( aDates[0], aDates[1]); return sValue; }; // overwrite _getInputValue to do the output conversion DateRangeSelection.prototype.updateDomValue = function(sValue) { // dom value updated other than value property this._bCheckDomValue = true; sValue = (typeof sValue == "undefined") ? this._$input.val() : sValue.toString(); this._curpos = this._$input.cursorPos(); var aDates = this._parseValue(sValue); sValue = this._formatValue( aDates[0], aDates[1]); // update the DOM value when necessary // otherwise cursor can goto end of text unnecessarily if (this.isActive() && (this._$input.val() !== sValue)) { this._$input.val(sValue); this._$input.cursorPos(this._curpos); } return this; }; //Do nothing in case of PageUp DateRangeSelection.prototype.onsappageup = function(){}; //EXC_JSLINT_021 DateRangeSelection.prototype.onsappageupmodifiers = function(){}; //EXC_JSLINT_021 //Do nothing in case of PageDown DateRangeSelection.prototype.onsappagedown = function(){}; //EXC_JSLINT_021 DateRangeSelection.prototype.onsappagedownmodifiers = function(){}; //EXC_JSLINT_021 //Support of two date range version of Calendar added into original DatePicker's version DateRangeSelection.prototype._fillDateRange = function(){ DatePicker.prototype._fillDateRange.apply(this, arguments); var oEndDate = this.getSecondDateValue(); if (oEndDate && oEndDate.getTime() >= this._oMinDate.getTime() && oEndDate.getTime() <= this._oMaxDate.getTime()) { if (!this._oDateRange.getEndDate() || this._oDateRange.getEndDate().getTime() !== oEndDate.getTime()) { this._oDateRange.setEndDate(new Date(oEndDate.getTime())); } } else { if (this._oDateRange.getEndDate()) { this._oDateRange.setEndDate(undefined); } } }; DateRangeSelection.prototype._selectDate = function(oEvent){ var aSelectedDates = this._oCalendar.getSelectedDates(); if (aSelectedDates.length > 0) { var oDate1 = aSelectedDates[0].getStartDate(); var oDate2 = aSelectedDates[0].getEndDate(); if (oDate1 && oDate2) { var oDate1Old = this.getDateValue(); var oDate2Old = this.getSecondDateValue(); // the selected range includes all of the hours from the second date oDate2.setHours(23, 59, 59, 999); var sValue; if (!deepEqual(oDate1, oDate1Old) || !deepEqual(oDate2, oDate2Old)) { // compare Dates because value can be the same if only 2 digits for year if (deepEqual(oDate2, oDate2Old)) { this.setDateValue(oDate1); } else { this.setProperty("dateValue", oDate1, true); // no rerendering this.setSecondDateValue(oDate2); } sValue = this.getValue(); _fireChange.call(this, true); if (Device.system.desktop || !Device.support.touch) { this._curpos = sValue.length; this._$input.cursorPos(this._curpos); } }else if (!this._bValid){ // wrong input before open calendar sValue = this._formatValue( oDate1, oDate2 ); if (sValue != this._$input.val()) { this._bValid = true; if (this.getDomRef()) { // as control could be destroyed during update binding this._$input.val(sValue); } _fireChange.call(this, true); } } // close popup and focus input after change event to allow application to reset value state or similar things this._oPopup.close(); } } }; /** * @see sap.ui.core.Control#getAccessibilityInfo * @returns {Object} Current accessibility state of the control * @protected */ DateRangeSelection.prototype.getAccessibilityInfo = function() { var oRenderer = this.getRenderer(); var oInfo = DatePicker.prototype.getAccessibilityInfo.apply(this, arguments); var sValue = this.getValue() || ""; if (this._bValid) { var oDate = this.getDateValue(); if (oDate) { sValue = this._formatValue(oDate, this.getSecondDateValue()); } } oInfo.description = [sValue, oRenderer.getLabelledByAnnouncement(this), oRenderer.getDescribedByAnnouncement(this)].join(" ").trim(); return oInfo; }; /** * Convert date object(s) to value and sets it to property <value>, rrespectively updates the DOM */ DateRangeSelection.prototype._syncDateObjectsToValue = function (oDateValue, oSecondDateValue){ var sValue = this._formatValue(oDateValue, oSecondDateValue); if (sValue !== this.getValue()) { this._lastValue = sValue; } // Set the property in any case but check validity on output this.setProperty("value", sValue); if (this.getDomRef()) { // convert to output var sOutputValue = this._formatValue(oDateValue, oSecondDateValue); if (this._$input.val() !== sOutputValue) { this._$input.val(sOutputValue); this._curpos = this._$input.cursorPos(); } } }; function _fireChange(bValid) { this.fireChangeEvent(this.getValue(), { from: this.getDateValue(), to: this.getSecondDateValue(), valid: bValid }); } function _dateRangeValidityCheck(oDate, oSecondDate) { var iFirstTimestamp, iSecondTimestamp; if (oDate && oDate.getTime) { iFirstTimestamp = oDate.getTime(); } else if (typeof oDate === 'number') { iFirstTimestamp = oDate; } if (oSecondDate && oSecondDate.getTime) { iSecondTimestamp = oSecondDate.getTime(); } else if (typeof oSecondDate === 'number') { iSecondTimestamp = oSecondDate; } if (oDate && oSecondDate && iFirstTimestamp > iSecondTimestamp) { // dates are in wrong oder -> just switch var oTmpDate = oDate; oDate = oSecondDate; oSecondDate = oTmpDate; } if ((oDate && ( iFirstTimestamp < this._oMinDate.getTime() || iFirstTimestamp > this._oMaxDate.getTime())) || (oSecondDate && ( iSecondTimestamp < this._oMinDate.getTime() || iSecondTimestamp > this._oMaxDate.getTime()))) { return [undefined, undefined]; }else { return [oDate, oSecondDate]; } } function _getDelimiter() { var sDelimiter = this.getDelimiter(); if (!sDelimiter) { if (!this._sLocaleDelimiter) { var oLocale = sap.ui.getCore().getConfiguration().getFormatSettings().getFormatLocale(); var oLocaleData = LocaleData.getInstance(oLocale); var sPattern = oLocaleData.getIntervalPattern(); var iIndex1 = sPattern.indexOf("{0}") + 3; var iIndex2 = sPattern.indexOf("{1}"); sDelimiter = sPattern.slice(iIndex1, iIndex2); if (sDelimiter.length > 1) { if (sDelimiter.slice(0,1) == " ") { sDelimiter = sDelimiter.slice(1); } if (sDelimiter.slice(sDelimiter.length - 1,sDelimiter.length) == " ") { sDelimiter = sDelimiter.slice(0, sDelimiter.length - 1); } } this._sLocaleDelimiter = sDelimiter; } else { sDelimiter = this._sLocaleDelimiter; } } return sDelimiter; } function _getFormatter() { var sPattern = ( this.getDisplayFormat() || "medium" ); var oFormat; var sCalendarType = this.getDisplayFormatType(); if (sPattern == this._sUsedDisplayPattern && sCalendarType == this._sUsedDisplayCalendarType) { oFormat = this._oDisplayFormat; } else { if (this._checkStyle(sPattern)) { oFormat = DateFormat.getInstance({style: sPattern, strictParsing: true, calendarType: sCalendarType}); } else { oFormat = DateFormat.getInstance({pattern: sPattern, strictParsing: true, calendarType: sCalendarType}); } this._sUsedDisplayPattern = sPattern; this._sUsedDisplayCalendarType = sCalendarType; this._oDisplayFormat = oFormat; } return oFormat; } function _endsWith(sValue, sEndStr) { return sValue && sEndStr && sValue.lastIndexOf(sEndStr) === sValue.length - sEndStr.length; } function _startsWith(sValue, sStartStr) { return sValue && sStartStr && sValue.indexOf(sStartStr) === 0; } /** * Trims all occurrences of the given string values from both ends of the specified string. * @param {string} sValue The value to be trimmed * @param {string[]} aParams All values to be removed * @returns {string} The trimmed value * @private */ function _trim(sValue, aParams) { var i = 0, aTrims = aParams; if (!aTrims) { aTrims = [" "]; } while (i < aTrims.length) { if (_endsWith(sValue, aTrims[i])) { sValue = sValue.substring(0, sValue.length - aTrims[i].length); i = 0; continue; } i++; } i = 0; while (i < aTrims.length) { if (_startsWith(sValue, aTrims[i])) { sValue = sValue.substring(aTrims[i].length); i = 0; continue; } i++; } return sValue; } // to overwrite JS doc /** * On change of date range event. * * @name sap.m.DateRangeSelection#change * @event * @param {sap.ui.base.Event} oControlEvent * @param {sap.ui.base.EventProvider} oControlEvent.getSource * @param {object} oControlEvent.getParameters * @param {string} oControlEvent.getParameters.value The new value of the <code>sap.m.DateRangeSelection</code>. * @param {boolean} oControlEvent.getParameters.valid Indicator for a valid date. * @param {object} oControlEvent.getParameters.from Current start date after change. * @param {object} oControlEvent.getParameters.to Current end date after change. * @public */ /** * Fire event change to attached listeners. * * Expects following event parameters: * <ul> * <li>'value' of type <code>string</code> The new value of the <code>sap.m.DateRangeSelection</code>.</li> * <li>'valid' of type <code>boolean</code> Indicator for a valid date.</li> * <li>'from' of type <code>object</code> Current start date after change.</li> * <li>'to' of type <code>object</code> Current end date after change.</li> * </ul> * * @param {Map} [mArguments] The arguments to pass along with the event. * @return {sap.m.DateRangeSelection} <code>this</code> to allow method chaining * @protected * @name sap.m.DateRangeSelection#fireChange * @function */ return DateRangeSelection; });