@openui5/sap.m
Version:
OpenUI5 UI Library sap.m
1,449 lines (1,280 loc) • 77.4 kB
JavaScript
/*!
* OpenUI5
* (c) Copyright 2026 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
// Provides control sap.m.DynamicDateRange.
sap.ui.define([
'sap/base/Log',
'sap/base/i18n/date/CalendarWeekNumbering',
'sap/ui/core/InvisibleText',
'sap/ui/core/Element',
'sap/ui/core/Control',
"sap/ui/core/Lib",
'sap/ui/core/ListItem',
'sap/ui/core/library',
'sap/ui/core/Renderer',
'sap/ui/core/message/MessageMixin',
'sap/m/DynamicDateFormat',
'sap/ui/core/IconPool',
'sap/ui/core/Icon',
'sap/ui/core/LabelEnablement',
"sap/ui/core/date/UniversalDate",
'sap/ui/core/format/DateFormat',
'sap/ui/base/ManagedObjectObserver',
'sap/ui/Device',
'./Label',
'./GroupHeaderListItem',
'./StandardListItem',
'./StandardListItemRenderer',
'./Button',
'./List',
'./Input',
'./InputRenderer',
'./Toolbar',
'./ResponsivePopover',
'./Page',
'./NavContainer',
'./DynamicDateRangeRenderer',
'./StandardDynamicDateOption',
'./library',
'sap/ui/thirdparty/jquery',
'sap/ui/unified/calendar/CalendarUtils',
'sap/ui/core/CustomData'
], function(
Log,
_CalendarWeekNumbering, // implicitly required as type of `calendarWeekNumbering`
InvisibleText,
Element,
Control,
Library,
ListItem,
coreLibrary,
Renderer,
MessageMixin,
DynamicDateFormat,
IconPool,
Icon,
LabelEnablement,
UniversalDate,
DateFormat,
ManagedObjectObserver,
Device,
Label,
GroupHeaderListItem,
StandardListItem,
StandardListItemRenderer,
Button,
List,
Input,
InputRenderer,
Toolbar,
ResponsivePopover,
Page,
NavContainer,
DynamicDateRangeRenderer,
StandardDynamicDateOption,
library,
jQuery,
CalendarUtils,
CustomData
) {
"use strict";
// shortcut for sap.ui.core.ValueState
var ValueState = coreLibrary.ValueState,
ToolbarDesign = library.ToolbarDesign,
ToolbarStyle = library.ToolbarStyle,
ListType = library.ListType,
ListMode = library.ListMode,
ListSeparators = library.ListSeparators,
oResourceBundle = Library.getResourceBundleFor("sap.m");
var oStandardOptionsObjects = {
"TODAY": new StandardDynamicDateOption({ key: "TODAY", valueTypes: [] }),
"YESTERDAY": new StandardDynamicDateOption({ key: "YESTERDAY", valueTypes: [] }),
"TOMORROW": new StandardDynamicDateOption({ key: "TOMORROW", valueTypes: [] }),
"FIRSTDAYWEEK": new StandardDynamicDateOption({ key: "FIRSTDAYWEEK", valueTypes: [] }),
"LASTDAYWEEK": new StandardDynamicDateOption({ key: "LASTDAYWEEK", valueTypes: [] }),
"FIRSTDAYMONTH":new StandardDynamicDateOption({ key: "FIRSTDAYMONTH", valueTypes: [] }),
"LASTDAYMONTH":new StandardDynamicDateOption({ key: "LASTDAYMONTH", valueTypes: [] }),
"FIRSTDAYQUARTER":new StandardDynamicDateOption({ key: "FIRSTDAYQUARTER", valueTypes: [] }),
"LASTDAYQUARTER":new StandardDynamicDateOption({ key: "LASTDAYQUARTER", valueTypes: [] }),
"FIRSTDAYYEAR":new StandardDynamicDateOption({ key: "FIRSTDAYYEAR", valueTypes: [] }),
"LASTDAYYEAR":new StandardDynamicDateOption({ key: "LASTDAYYEAR", valueTypes: [] }),
"THISWEEK": new StandardDynamicDateOption({ key: "THISWEEK", valueTypes: [] }),
"THISMONTH": new StandardDynamicDateOption({ key: "THISMONTH", valueTypes: [] }),
"THISQUARTER": new StandardDynamicDateOption({ key: "THISQUARTER", valueTypes: [] }),
"THISYEAR": new StandardDynamicDateOption({ key: "THISYEAR", valueTypes: [] }),
"LASTWEEK": new StandardDynamicDateOption({ key: "LASTWEEK", valueTypes: [] }),
"LASTMONTH": new StandardDynamicDateOption({ key: "LASTMONTH", valueTypes: [] }),
"LASTQUARTER": new StandardDynamicDateOption({ key: "LASTQUARTER", valueTypes: [] }),
"LASTYEAR": new StandardDynamicDateOption({ key: "LASTYEAR", valueTypes: [] }),
"NEXTWEEK": new StandardDynamicDateOption({ key: "NEXTWEEK", valueTypes: [] }),
"NEXTMONTH": new StandardDynamicDateOption({ key: "NEXTMONTH", valueTypes: [] }),
"NEXTQUARTER": new StandardDynamicDateOption({ key: "NEXTQUARTER", valueTypes: [] }),
"NEXTYEAR": new StandardDynamicDateOption({ key: "NEXTYEAR", valueTypes: [] }),
"LASTMINUTES": new StandardDynamicDateOption({ key: "LASTMINUTES", valueTypes: ["int"] }),
"LASTHOURS": new StandardDynamicDateOption({ key: "LASTHOURS", valueTypes: ["int"] }),
"LASTDAYS": new StandardDynamicDateOption({ key: "LASTDAYS", valueTypes: ["int"] }),
"LASTWEEKS": new StandardDynamicDateOption({ key: "LASTWEEKS", valueTypes: ["int"] }),
"LASTMONTHS": new StandardDynamicDateOption({ key: "LASTMONTHS", valueTypes: ["int"] }),
"LASTQUARTERS": new StandardDynamicDateOption({ key: "LASTQUARTERS", valueTypes: ["int"] }),
"LASTYEARS": new StandardDynamicDateOption({ key: "LASTYEARS", valueTypes: ["int"] }),
"NEXTMINUTES": new StandardDynamicDateOption({ key: "NEXTMINUTES", valueTypes: ["int"] }),
"NEXTHOURS": new StandardDynamicDateOption({ key: "NEXTHOURS", valueTypes: ["int"] }),
"NEXTDAYS": new StandardDynamicDateOption({ key: "NEXTDAYS", valueTypes: ["int"] }),
"NEXTWEEKS": new StandardDynamicDateOption({ key: "NEXTWEEKS", valueTypes: ["int"] }),
"NEXTMONTHS": new StandardDynamicDateOption({ key: "NEXTMONTHS", valueTypes: ["int"] }),
"NEXTQUARTERS": new StandardDynamicDateOption({ key: "NEXTQUARTERS", valueTypes: ["int"] }),
"NEXTYEARS": new StandardDynamicDateOption({ key: "NEXTYEARS", valueTypes: ["int"] }),
"LASTMINUTESINCLUDED": new StandardDynamicDateOption({ key: "LASTMINUTESINCLUDED", valueTypes: ["int", "included"] }),
"LASTHOURSINCLUDED": new StandardDynamicDateOption({ key: "LASTHOURSINCLUDED", valueTypes: ["int", "included"] }),
"LASTDAYSINCLUDED": new StandardDynamicDateOption({ key: "LASTDAYSINCLUDED", valueTypes: ["int", "included"] }),
"LASTWEEKSINCLUDED": new StandardDynamicDateOption({ key: "LASTWEEKSINCLUDED", valueTypes: ["int", "included"] }),
"LASTMONTHSINCLUDED": new StandardDynamicDateOption({ key: "LASTMONTHSINCLUDED", valueTypes: ["int", "included"] }),
"LASTQUARTERSINCLUDED": new StandardDynamicDateOption({ key: "LASTQUARTERSINCLUDED", valueTypes: ["int", "included"] }),
"LASTYEARSINCLUDED": new StandardDynamicDateOption({ key: "LASTYEARSINCLUDED", valueTypes: ["int", "included"] }),
"NEXTMINUTESINCLUDED": new StandardDynamicDateOption({ key: "NEXTMINUTESINCLUDED", valueTypes: ["int", "included"] }),
"NEXTHOURSINCLUDED": new StandardDynamicDateOption({ key: "NEXTHOURSINCLUDED", valueTypes: ["int", "included"] }),
"NEXTDAYSINCLUDED": new StandardDynamicDateOption({ key: "NEXTDAYSINCLUDED", valueTypes: ["int", "included"] }),
"NEXTWEEKSINCLUDED": new StandardDynamicDateOption({ key: "NEXTWEEKSINCLUDED", valueTypes: ["int", "included"] }),
"NEXTMONTHSINCLUDED": new StandardDynamicDateOption({ key: "NEXTMONTHSINCLUDED", valueTypes: ["int", "included"] }),
"NEXTQUARTERSINCLUDED": new StandardDynamicDateOption({ key: "NEXTQUARTERSINCLUDED", valueTypes: ["int", "included"] }),
"NEXTYEARSINCLUDED": new StandardDynamicDateOption({ key: "NEXTYEARSINCLUDED", valueTypes: ["int", "included"] }),
"FROM": new StandardDynamicDateOption({ key: "FROM", valueTypes: ["date"] }),
"TO": new StandardDynamicDateOption({ key: "TO", valueTypes: ["date"] }),
"FROMDATETIME": new StandardDynamicDateOption({ key: "FROMDATETIME", valueTypes: ["datetime"] }),
"TODATETIME": new StandardDynamicDateOption({ key: "TODATETIME", valueTypes: ["datetime"] }),
"YEARTODATE": new StandardDynamicDateOption({ key: "YEARTODATE", valueTypes: [] }),
"DATETOYEAR": new StandardDynamicDateOption({ key: "DATETOYEAR", valueTypes: [] }),
"TODAYFROMTO": new StandardDynamicDateOption({ key: "TODAYFROMTO", valueTypes: ["int", "int"] }),
"QUARTER1": new StandardDynamicDateOption({ key: "QUARTER1", valueTypes: [] }),
"QUARTER2": new StandardDynamicDateOption({ key: "QUARTER2", valueTypes: [] }),
"QUARTER3": new StandardDynamicDateOption({ key: "QUARTER3", valueTypes: [] }),
"QUARTER4": new StandardDynamicDateOption({ key: "QUARTER4", valueTypes: [] }),
"SPECIFICMONTH": new StandardDynamicDateOption({ key: "SPECIFICMONTH", valueTypes: ["int"] }),
"SPECIFICMONTHINYEAR": new StandardDynamicDateOption({ key: "SPECIFICMONTHINYEAR", valueTypes: ["int", "int"] }),
"DATERANGE": new StandardDynamicDateOption({ key: "DATERANGE", valueTypes: ["date", "date"] }),
"DATE": new StandardDynamicDateOption({ key: "DATE", valueTypes: ["date"] }),
"DATETIME": new StandardDynamicDateOption({ key: "DATETIME", valueTypes: ["datetime"] }),
"DATETIMERANGE": new StandardDynamicDateOption({ key: "DATETIMERANGE", valueTypes: ["datetime", "datetime"] })
};
var aStandardOptionsKeys = [
"DATE",
"TODAY",
"YESTERDAY",
"TOMORROW",
"FIRSTDAYWEEK",
"LASTDAYWEEK",
"FIRSTDAYMONTH",
"LASTDAYMONTH",
"FIRSTDAYQUARTER",
"LASTDAYQUARTER",
"FIRSTDAYYEAR",
"LASTDAYYEAR",
"DATERANGE",
"DATETIMERANGE",
"FROM",
"TO",
"FROMDATETIME",
"TODATETIME",
"YEARTODATE",
"DATETOYEAR",
"LASTMINUTES",
"LASTHOURS",
"LASTDAYS",
"LASTWEEKS",
"LASTMONTHS",
"LASTQUARTERS",
"LASTYEARS",
"NEXTMINUTES",
"NEXTHOURS",
"NEXTDAYS",
"NEXTWEEKS",
"NEXTMONTHS",
"NEXTQUARTERS",
"NEXTYEARS",
"LASTMINUTESINCLUDED",
"LASTHOURSINCLUDED",
"LASTDAYSINCLUDED",
"LASTWEEKSINCLUDED",
"LASTMONTHSINCLUDED",
"LASTQUARTERSINCLUDED",
"LASTYEARSINCLUDED",
"NEXTMINUTESINCLUDED",
"NEXTHOURSINCLUDED",
"NEXTDAYSINCLUDED",
"NEXTWEEKSINCLUDED",
"NEXTMONTHSINCLUDED",
"NEXTQUARTERSINCLUDED",
"NEXTYEARSINCLUDED",
"TODAYFROMTO",
"THISWEEK",
"LASTWEEK",
"NEXTWEEK",
"SPECIFICMONTH",
"SPECIFICMONTHINYEAR",
"THISMONTH",
"LASTMONTH",
"NEXTMONTH",
"THISQUARTER",
"LASTQUARTER",
"NEXTQUARTER",
"QUARTER1",
"QUARTER2",
"QUARTER3",
"QUARTER4",
"THISYEAR",
"LASTYEAR",
"NEXTYEAR",
"DATETIME"
];
var oDynamicDateRangeGroups = {
SingleDates: 1,
DateRanges: 2,
Weeks: 3,
Month: 4,
Quarters: 5,
Years: 6
};
/**
* Constructor for a new DynamicDateRange.
*
* @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 control base type.
*
* <h3>Overview</h3>
*
* The dynamic date range is a control that offers a choice of absolute and relative dates,
* using different offset from the current date. The list of values offered must be defined by the application.
*
* <h3>Usage</h3>
*
* The control usage is recommended when:
* <ul>
* <li>Flexibility of choosing from absolute or relative dates and date ranges.</li>
* <li>The relative representation of a date should be reused. (For example, show values from today regardless of when you open the application)</li>
* </ul>
*
* The <code>DynamicDateRange</code> control supports a number of standard options:
* see {@link sap.m.StandardDynamicDateRangeKeys}.
* A custom option could be defined by extending the <code>sap.m.DynamicDateOption</code> class and
* adding an instance of this class into the <code>sap.m.DynamicDateRange</code> customOptions aggregation.
* In order for a specific option to be used its key should be added into the <code>standardOptions</code> property
* of the control. No options are added by default.
*
* <b>Note:</b> Property binding with the <code>value</code> and <code>formatter</code> properties is not supported.
* Instead, you should use their public getter and setter methods.
*
* Suggestions are available when the user types in the control input field.
*
* <h3>Responsive behavior</h3>
*
* On mobile devices, when user taps on the <code>DynamicDateRange</code> input icon a full screen dialog
* is opened. The dialog is closed via a date time period value selection or by pressing the "Cancel" button.
*
* @author SAP SE
* @version 1.146.0
*
* @constructor
* @public
* @since 1.92.0
* @alias sap.m.DynamicDateRange
* @extends sap.ui.core.Control
*/
var DynamicDateRange = Control.extend("sap.m.DynamicDateRange", /** @lends sap.m.DynamicDateRange.prototype */ {
metadata: {
library: "sap.m",
properties: {
/**
* Defines the control value. The object has two properties
* 'operator' - a string, the key of a DynamicDateOption and
* 'values' - an array of parameters for the same option.
* The control uses a special wrong-value object, when the input receives
* an unrecognized string - { operator: "PARSEERROR", values: [...]}
*
* <b>Note:</b> Data binding for the <code>value</code> property is not supported. Instead,
* you should use DynamicDateRange's <code>getValue</code> and <code>setValue</code> methods.
*
* @since 1.92
* @private
* @ui5-restricted sap.m.DynamicDateRange
*/
value: { type: "object", group: "Data"},
/**
* Defines the width of the control.
*
* @since 1.92
*/
width: { type: "sap.ui.core.CSSSize", group: "Dimension", defaultValue: null },
/**
* Indicates whether the user can interact with the control or not.
* <b>Note:</b> Disabled controls cannot be focused and they are out of the tab-chain.
*
* @since 1.92
*/
enabled: { type: "boolean", group: "Behavior", defaultValue: true },
/**
* Accepts the core enumeration ValueState.type that supports <code>None</code>, <code>Error</code>, <code>Warning</code> and <code>Success</code>.
* ValueState is managed internally only when validation is triggered by user interaction.
*
* @since 1.92
*/
valueState: { type: "sap.ui.core.ValueState", group: "Appearance", defaultValue: ValueState.None },
/**
* Defines the name of the control for the purposes of form submission.
*
* @since 1.92
*/
name: { type: "string", group: "Misc", defaultValue: null },
/**
* Defines a short hint intended to aid the user with data entry when the control has no value.
*
* @since 1.92
*/
placeholder: { type: "string", group: "Misc", defaultValue: null },
/**
* Defines whether the control can be modified by the user or not.
* <b>Note:</b> A user can tab to the non-editable control, highlight it, and copy the text from it.
*
* @since 1.92
*/
editable: { type: "boolean", group: "Behavior", defaultValue: true },
/**
* Defines the text that appears in the value state message popup.
*
* @since 1.92
*/
valueStateText: { type: "string", group: "Misc", defaultValue: null },
/**
* Indicates that user input is required. This property is only needed for accessibility purposes when a single relationship between
* the field and a label (see aggregation <code>labelFor</code> of <code>sap.m.Label</code>) cannot be established
* (e.g. one label should label multiple fields).
* @since 1.92
*/
required : {type : "boolean", group : "Misc", defaultValue : false},
/**
* Disable list group headers.
*
* @since 1.92
*/
enableGroupHeaders: { type: "boolean", group: "Behavior", defaultValue: true },
/**
* An instance of sap.m.DynamicDateFormat or a user defined format object with the
* corresponding formatting and parsing functionality.
*
* <b>Note:</b> Data binding for the <code>formatter</code> property is not supported. Instead,
* you should use DynamicDateRange's <code>getFormatter</code> and <code>setFormatter</code> methods.
*
* @since 1.92
* @private
* @ui5-restricted sap.m.DynamicDateRange
*/
formatter: { type: "object" },
/**
* Array of standard option keys
*
* @since 1.92
*/
standardOptions: {
type: "string[]", group: "Behavior",
defaultValue: [
"DATE",
"TODAY",
"YESTERDAY",
"TOMORROW",
"FIRSTDAYWEEK",
"LASTDAYWEEK",
"FIRSTDAYMONTH",
"LASTDAYMONTH",
"FIRSTDAYQUARTER",
"LASTDAYQUARTER",
"FIRSTDAYYEAR",
"LASTDAYYEAR",
"DATERANGE",
"DATETIMERANGE",
"FROM",
"TO",
"FROMDATETIME",
"TODATETIME",
"YEARTODATE",
"DATETOYEAR",
"LASTMINUTES",
"LASTHOURS",
"LASTDAYS",
"LASTWEEKS",
"LASTMONTHS",
"LASTQUARTERS",
"LASTYEARS",
"LASTMINUTESINCLUDED",
"LASTHOURSINCLUDED",
"LASTDAYSINCLUDED",
"LASTWEEKSINCLUDED",
"LASTMONTHSINCLUDED",
"LASTQUARTERSINCLUDED",
"LASTYEARSINCLUDED",
"NEXTMINUTES",
"NEXTHOURS",
"NEXTDAYS",
"NEXTWEEKS",
"NEXTMONTHS",
"NEXTQUARTERS",
"NEXTYEARS",
"NEXTMINUTESINCLUDED",
"NEXTHOURSINCLUDED",
"NEXTDAYSINCLUDED",
"NEXTWEEKSINCLUDED",
"NEXTMONTHSINCLUDED",
"NEXTQUARTERSINCLUDED",
"NEXTYEARSINCLUDED",
"TODAYFROMTO",
"THISWEEK",
"LASTWEEK",
"NEXTWEEK",
"SPECIFICMONTH",
"SPECIFICMONTHINYEAR",
"THISMONTH",
"LASTMONTH",
"NEXTMONTH",
"THISQUARTER",
"LASTQUARTER",
"NEXTQUARTER",
"QUARTER1",
"QUARTER2",
"QUARTER3",
"QUARTER4",
"THISYEAR",
"LASTYEAR",
"NEXTYEAR",
"DATETIME"
]
},
/**
* Determines whether the input field of the control is hidden or visible.
* When set to <code>true</code>, the input field becomes invisible and there is no way to open the value help popover.
* In that case it can be opened by another control through calling of control's <code>openBy</code> method, and
* the opening control's DOM reference must be provided as parameter.
*
* Note: Since the Dynamic Date Range is not responsible for accessibility attributes of the control which opens its popover,
* those attributes should be added by the application developer. The following is recommended to be added to the
* opening control: a text or tooltip that describes the action (example: "Open Dynamic Date Range"), and also aria-haspopup
* attribute with value of <code>true</code>.
*
* @since 1.105
*/
hideInput: { type: "boolean", group: "Misc", defaultValue: false },
/**
* If set, the calendar week numbering is used for display.
* If not set, the calendar week numbering of the global configuration is used.
* @since 1.111.0
*/
calendarWeekNumbering : { type : "sap.base.i18n.date.CalendarWeekNumbering", group : "Appearance", defaultValue: null},
/**
* Specifies whether clear icon is shown.
* Pressing the icon will clear input's value and fire the liveChange event.
* @since 1.117
*/
showClearIcon: { type: "boolean", defaultValue: false }
},
aggregations: {
/**
* Custom options for the <code>DynamicDateRange</code>.
*
*/
customOptions: { type: "sap.m.DynamicDateOption", multiple: true },
_input: { type: "sap.m.Input", multiple: false, visibility: "hidden" },
_popup: { type: "sap.m.ResponsivePopover", multiple: false, visibility: "hidden" }
},
associations: {
/**
* Association to controls / IDs that label this control (see WAI-ARIA attribute aria-labelledby).
* @since 1.92
*/
ariaLabelledBy: { type: "sap.ui.core.Control", multiple: true, singularName: "ariaLabelledBy" },
/**
* Association to controls / IDs that describe this control (see WAI-ARIA attribute aria-describedby).
* @since 1.92
*/
ariaDescribedBy: { type: "sap.ui.core.Control", multiple: true, singularName: "ariaDescribedBy" }
},
events: {
/**
* Is fired when the text in the input field has changed and the focus leaves the input field or the Enter key is pressed.
*/
change: {
parameters: {
/**
* The current value of the control.
*/
value: { type: "object" },
/**
* Whether the new value is valid.
*/
valid: { type: "boolean"}
}
}
}
},
renderer: DynamicDateRangeRenderer
});
MessageMixin.call(DynamicDateRange.prototype);
var aLastDateTimeOperators = [
"LASTMINUTES",
"LASTHOURS",
"LASTMINUTESINCLUDED",
"LASTHOURSINCLUDED"
];
var aNextDateTimeOperators = [
"NEXTMINUTES",
"NEXTHOURS",
"NEXTMINUTESINCLUDED",
"NEXTHOURSINCLUDED"
];
var aDateTimeOperators = aLastDateTimeOperators.concat(aNextDateTimeOperators);
var aLastOptions = ["LASTMINUTES", "LASTHOURS", "LASTDAYS", "LASTWEEKS", "LASTMONTHS", "LASTQUARTERS", "LASTYEARS"];
var aNextOptions = ["NEXTMINUTES", "NEXTHOURS", "NEXTDAYS", "NEXTWEEKS", "NEXTMONTHS", "NEXTQUARTERS", "NEXTYEARS"];
var aLastIncludedOptions = ["LASTMINUTESINCLUDED", "LASTHOURSINCLUDED", "LASTDAYSINCLUDED", "LASTWEEKSINCLUDED", "LASTMONTHSINCLUDED", "LASTQUARTERSINCLUDED", "LASTYEARSINCLUDED"];
var aNextIncludedOptions = ["NEXTMINUTESINCLUDED", "NEXTHOURSINCLUDED", "NEXTDAYSINCLUDED", "NEXTWEEKSINCLUDED", "NEXTMONTHSINCLUDED", "NEXTQUARTERSINCLUDED", "NEXTYEARSINCLUDED"];
const POPUP_MAX_HEIGHT = 512;
const POPUP_HEADER_HEIGHT = 45;
const POPUP_LIST_ITEM_HEIGHT = 51;
const POPUP_LIST_ITEM_COMPACT_HEIGHT = 49;
DynamicDateRange.prototype.init = function() {
var bValueHelpDecorative = !Device.support.touch || Device.system.desktop ? true : false;
this._oInput = new DynamicDateRangeInput(this.getId() + "-input", {
valueHelpIconSrc: IconPool.getIconURI("sap-icon://check-availability"),
valueHelpRequest: this._toggleOpen.bind(this),
showSuggestion: true,
suggest: this._handleSuggest.bind(this)
});
this._oListItemDelegate = undefined;
this._onBeforeInputRenderingDelegate = {
onBeforeRendering: function() {
this._oInput._getValueHelpIcon().setVisible(true);
}
};
this._oInput._getValueHelpIcon().setDecorative(bValueHelpDecorative);
this._oInput._getValueHelpIcon().setTooltip(oResourceBundle.getText("OPEN_PICKER_TEXT"));
this._oInput.addDelegate(this._onBeforeInputRenderingDelegate, this);
this.setAggregation("_input", this._oInput, false);
this._oInput._setControlOrigin(this);
this._oInput.attachChange(this._handleInputChange, this);
this.oValueObserver = new ManagedObjectObserver(function() {
delete this.oBoundValueFormatter;
}.bind(this));
this.oValueObserver.observe(this, {
bindings: ["value"]
});
};
DynamicDateRange.prototype.exit = function() {
this._oInput.removeDelegate(this._onBeforeInputRenderingDelegate);
this._onBeforeInputRenderingDelegate = undefined;
this.oValueObserver.destroy();
if (this._oInvisibleLabelText) {
this._oInvisibleLabelText.destroy();
this._oInvisibleLabelText = undefined;
}
this._infoDatesFooter = undefined;
this.aInputControls = undefined;
this._removeAllListItemDelegates();
};
DynamicDateRange.prototype._removeAllListItemDelegates = function() {
if (this._oOptionsList) {
this._oOptionsList.getItems().forEach(function(oItem) {
oItem.removeDelegate(this._oListItemDelegate);
}, this);
}
};
/**
* Getter for the <code>value</code> of the control.
* @returns {sap.m.DynamicDateRangeValue} A <code>sap.m.DynamicDateRangeValue</code>
* @public
*/
DynamicDateRange.prototype.getValue = function() {
return this.getProperty("value");
};
/**
* Getter for the <code>formatter</code> of the control.
* @returns {sap.m.DynamicDateFormat} A <code>sap.m.DynamicDateFormat</code>
* @public
*/
DynamicDateRange.prototype.getFormatter = function() {
return this.getProperty("formatter");
};
/**
* Setter for the <code>formatter</code> of the control.
* @returns {sap.m.DynamicDateFormat} A <code>sap.m.DynamicDateFormat</code>
* @param {sap.m.DynamicDateFormat} oFormatter A <code>sap.m.DynamicDateFormat</code>
* @returns {this} Reference to <code>this</code> for method chaining
* @public
*/
DynamicDateRange.prototype.setFormatter = function(oFormatter) {
this.setProperty("formatter", oFormatter);
return this;
};
/**
* Sets the tooltip for the <code>DynamicDateRange</code>.
* @param {sap.ui.core.TooltipBase|string} vTooltip The tooltip that should be shown.
* @returns {this} Reference to <code>this</code> for method chaining
* @public
* @override
*/
DynamicDateRange.prototype.setTooltip = function(vTooltip) {
this._oInput.setTooltip(vTooltip);
return Control.prototype.setTooltip.apply(this, arguments);
};
/**
* Sets the showClearIcon for the <code>DynamicDateRange</code>.
* @param {boolean} bShowClearIcon Whether to show clear icon.
* @returns {this} Reference to <code>this</code> for method chaining
* @public
* @override
*/
DynamicDateRange.prototype.setShowClearIcon = function(bShowClearIcon) {
this.setProperty("showClearIcon", bShowClearIcon);
this._oInput.setShowClearIcon(bShowClearIcon);
return this;
};
DynamicDateRange.prototype.onBeforeRendering = function() {
this._updateInputValue(this.getValue());
this._oInput.setEditable(this.getEditable());
this._oInput.setEnabled(this.getEnabled());
this._oInput.setRequired(this.getRequired());
this._oInput.setName(this.getName());
this._oInput.setWidth(this.getWidth());
this._oInput.setPlaceholder(this.getPlaceholder());
this._oInput.setValueState(this.getValueState());
this._oInput.setValueStateText(this.getValueStateText());
this.setValue(this._substituteMissingValue(this.getValue()));
};
/**
* Setter for the <code>value</code> control property.
* @param {sap.m.DynamicDateRangeValue} oValue A <code>sap.m.DynamicDateRangeValue</code>
* @returns {this} Reference to <code>this</code> for method chaining
* @public
*/
DynamicDateRange.prototype.setValue = function(oValue) {
var sOptionKey = oValue && oValue.operator;
// substitute the semantically equivalent values
oValue = this._substituteValue(oValue);
this.setProperty("value", oValue);
this._oSelectedOption = this.getOption(sOptionKey);
// Forward Dynamic Date Range control property values to inner sap.m.Input instance.
this._updateInputValue(oValue);
return this;
};
DynamicDateRange.prototype._toggleOpen = function() {
if (this._oPopup && this._oPopup.isOpen()) {
this._closePopup();
} else {
this.open();
}
};
/**
* Opens the value help dialog.
*
* @param {HTMLElement} oDomRef DOM reference of the opening control. On tablet or desktop, the popover is positioned relatively to this control.
* @returns {void}
* @since 1.92
* @public
*/
DynamicDateRange.prototype.open = function(oDomRef) {
if (this.getEditable() && this.getEnabled()) {
this._createPopup();
this._createPopupContent();
if (!this._oListItemDelegate) {
this._oListItemDelegate = {
// Handle when F4 or Alt + DOWN arrow are pressed.
onsapshow: this._closePopup.bind(this),
// Handle when Alt + UP arrow are pressed.
onsaphide: this._closePopup.bind(this)
};
}
//re-create items
this._removeAllListItemDelegates();
this._oOptionsList.destroyAggregation("items");
let oCurrentGroupHeader;
this._collectValueHelpItems(this._getOptions(), true).forEach(function(vOption) {
let oItem;
// check if it's a group header
if (typeof (vOption) === "string") {
// Create and add group header using ListBase.addItemGroup
const oGroupData = { text: vOption };
oCurrentGroupHeader = this._oOptionsList.addItemGroup(oGroupData, null, true);
oCurrentGroupHeader.addDelegate(this._oListItemDelegate, this);
} else {
if (vOption.getKey() === "FROMDATETIME") {
vOption._bAdditionalTimeText = !!this._findOption("FROM");
} else if (vOption.getKey() === "TODATETIME") {
vOption._bAdditionalTimeText = !!this._findOption("TO");
} else if (vOption.getKey() === "DATETIMERANGE") {
vOption._bAdditionalTimeText = !!this._findOption("DATERANGE");
}
oItem = this._createListItem(vOption);
oItem.addDelegate(this._oListItemDelegate, this);
this._oOptionsList.addItem(oItem);
}
}, this);
//reset value help page
this._oNavContainer.to(this._oNavContainer.getPages()[0]);
this._openPopup(oDomRef);
}
};
/**
* Searches if there is an option with the given key included.
*
* @param {string} sKey option key to be searched against
* @returns {object|undefined} object if the object exists
* @private
*/
DynamicDateRange.prototype._findOption = function(sKey) {
return this._getOptions().find(function(oOption) {
return oOption.getKey() === sKey;
});
};
/**
* Appends an option key, identifying an additional standard option to be used by the control.
*
* @param {string} sKey option key
* @returns {void}
* @since 1.92
* @public
*/
DynamicDateRange.prototype.addStandardOption = function(sKey) {
var aOptions = this.getStandardOptions();
if (aOptions.indexOf(sKey) === -1) {
aOptions.push(sKey);
}
this.setStandardOptions(aOptions);
};
DynamicDateRange.prototype.getFocusDomRef = function(){
return this.getAggregation("_input") && this.getAggregation("_input").getFocusDomRef();
};
DynamicDateRange.prototype._updateInputValue = function(oValue) {
var sInputValue;
if (oValue && oValue.operator !== "PARSEERROR") {
sInputValue = this._enhanceInputValue(this._formatValue(oValue), oValue);
this._oInput.setValue(sInputValue);
} else if (oValue === undefined) {
this._oInput.setValue("");
}
};
/**
* Handles suggestions when user types into the control input field.
*
* @param {sap.ui.base.Event} oEvent Input's suggest event
* @private
*/
DynamicDateRange.prototype._handleSuggest = function(oEvent) {
this._bSuggestionMode = true;
if (this._oPopup && this._oPopup.isOpen()) {
this._closePopup();
}
var sQuery = oEvent.getParameter("suggestValue");
this._oInput.removeAllSuggestionItems();
// find all options that match the search string from the start
var aSuggestionItems = this._getOptions().filter(function(option) {
var oSuggestValue = { operator: option.getKey(), values: [] },
aUITypes = option.getValueHelpUITypes(this);
if (aUITypes.length && aUITypes[0].getType()) {
return false;
}
var sSuggestedValue = this.getOption(oSuggestValue.operator)
.format(oSuggestValue, this._getFormatter()).toLowerCase();
var iIndexOfQuery = sSuggestedValue
.indexOf(sQuery.toLowerCase());
return iIndexOfQuery === 0 || (iIndexOfQuery > 0 && sSuggestedValue[iIndexOfQuery - 1] === " ");
}, this);
this._collectValueHelpItems(aSuggestionItems, true).forEach(function(option) {
if (option.getKey) {
var oSuggestValue = { operator: option.getKey(), values: [] };
this._addSuggestionItem(oSuggestValue);
} else {
this._addSuggestionGroupItem(option);
}
}, this);
var aMatchDigit = sQuery.match(/\d+/);
if (!aMatchDigit) {
this._bSuggestionMode = false;
return;
}
// also add all options with one integer parameter if the term is an integer
aSuggestionItems = this._getOptions().filter(function(option) {
return option.getValueHelpUITypes(this).length === 1 && option.getValueHelpUITypes(this)[0].getType() === "int";
}, this);
this._collectValueHelpItems(aSuggestionItems, false).forEach(function(option) {
if (option.getKey) {
var oSuggestValue = {
operator: option.getKey(),
values: [
parseInt(aMatchDigit[0])
]
};
this._addSuggestionItem(oSuggestValue);
} else {
this._addSuggestionGroupItem(option);
}
}, this);
this._bSuggestionMode = false;
};
/**
* Gets an option object by its key.
*
* @param {string} sKey The option key
* @returns {sap.m.DynamicDateOption} The option
* @public
*/
DynamicDateRange.prototype.getOption = function(sKey) {
return this._getOptions().find(function(option) {
return option.getKey() === sKey;
});
};
/**
* Calculates a date range from a provided object in the format of the DynamicDateRange's value.
*
* @param {sap.m.DynamicDateRangeValue} oValue A <code>sap.m.DynamicDateRangeValue</code>
* @returns {sap.ui.core.date.UniversalDate[]} An array of two date objects - start and end date
* @public
*/
DynamicDateRange.prototype.toDates = function(oValue) {
var sKey = oValue.operator;
return this.getOption(sKey).toDates(oValue, this.getCalendarWeekNumbering());
};
/**
* Returns enumeration containing the current groups in <code>sap.m.DynamicDateRange</code>
*
* @private
*/
DynamicDateRange.prototype._getGroups = function() {
if (!this.oDynamicDateRangeGroups) {
this.oDynamicDateRangeGroups = JSON.parse(JSON.stringify(oDynamicDateRangeGroups)); // making a copy of the object to break the reference
}
return this.oDynamicDateRangeGroups;
};
/**
* Returns the header of a custom group.
*
* @private
*/
DynamicDateRange.prototype._getCustomGroupHeader = function(sGroupName) {
var oGroup = this._customGroupHeaders.find( (x) => {
return x.name === sGroupName;
});
return oGroup.header;
};
/**
* Adds a group to the enumeration containing the current groups in <code>sap.m.DynamicDateRange</code>
* @param {string} sGroupName the name that the group will be selected by.
* @param {string} sGroupHeader the group header that will be presented in the list.
* @returns {void}
* @public
* @since 1.118
*/
DynamicDateRange.prototype.addGroup = function(sGroupName, sGroupHeader) {
this._getGroups()[sGroupName] = Object.keys(this._getGroups()).length + 1;
if (!this._customGroupHeaders) {
this._customGroupHeaders = [];
}
this._customGroupHeaders.push({
name: sGroupName,
header: sGroupHeader
});
};
/**
* Sets a new header to an existing custom group.
* @param {string} sGroupName the name that the group will be selected by.
* @param {string} sGroupHeader the group header that will be presented in the list.
* @returns {void}
* @public
*/
DynamicDateRange.prototype.setGroupHeader = function(sGroupName, sGroupHeader) {
this._customGroupHeaders.find((group) => group.name === sGroupName).header = sGroupHeader;
};
/**
* Removes all additionally added groups
* @returns {void}
* @public
*/
DynamicDateRange.prototype.removeCustomGroups = function() {
const iCountOfStandardGroups = Object.keys(oDynamicDateRangeGroups).length;
for (const group in this._getGroups()) {
if (this._getGroups()[group] > iCountOfStandardGroups) {
delete this._getGroups()[group];
}
}
delete this._customGroupHeaders;
};
/**
* Returns an array of <code>sap.m.DynamicDateOptions</code> (standard and custom) instances used in the control.
*
* @private
*/
DynamicDateRange.prototype._getOptions = function() {
var aOptionKeys = this.getStandardOptions();
var aOptions = aOptionKeys.map(function(sKey) {
return oStandardOptionsObjects[sKey];
}, this);
// filter out the non-existent options (such option key is not known in the global util)
var aStandardOptions = aOptions.filter(Boolean);
var aCustomOptions = this.getAggregation("customOptions");
if (aCustomOptions) {
return aStandardOptions.concat(aCustomOptions);
}
return aStandardOptions;
};
DynamicDateRange.prototype._getValueHelpTypeForFormatter = function() {
var sOptionKey = this._oSelectedOption ? this._oSelectedOption.getKey() : '',
aLastOptionsSelectedIndex = this.lastOptionsIndex(sOptionKey),
aNextOptionsSelectedIndex = this.nextOptionsIndex(sOptionKey),
aPopupContent = this._oNavContainer ? this._oNavContainer.getPages()[1].getContent()[3] || [] : [],
oSelect = aPopupContent,
aSuggestionItems = this.getAggregation('_input').getAggregation('suggestionItems'),
oValue = this.getValue(),
aOptionKeys = this.getStandardOptions(),
sActualSelectedOptionKey = "",
aLastActualOrder = [],
aNextActualOrder = [],
oCustomData,
aValueHelpTypes,
sType,
sSuggestionOptionKey;
if (
!oValue &&
!oSelect &&
aSuggestionItems && aSuggestionItems.length &&
aSuggestionItems[aSuggestionItems.length - 1].getCustomData
) {
oCustomData = aSuggestionItems[aSuggestionItems.length - 1].getCustomData()[0];
}
if (
this._bSuggestionMode &&
aSuggestionItems && aSuggestionItems.length &&
aSuggestionItems[aSuggestionItems.length - 1].getCustomData
) {
oCustomData = aSuggestionItems[aSuggestionItems.length - 1].getCustomData()[0];
}
aOptionKeys.forEach(function(sOption) {
if (this.lastOptionsIndex(sOption) > -1) {
aLastActualOrder.push(sOption);
} else if (this.nextOptionsIndex(sOption) > -1) {
aNextActualOrder.push(sOption);
}
}.bind(this));
if (oCustomData) {
sSuggestionOptionKey = oCustomData.getValue();
aLastOptionsSelectedIndex = aLastDateTimeOperators.indexOf(sSuggestionOptionKey);
aNextOptionsSelectedIndex = aNextDateTimeOperators.indexOf(sSuggestionOptionKey);
}
if (oCustomData && sSuggestionOptionKey) {
if (aDateTimeOperators.indexOf(sSuggestionOptionKey) > -1) {
sType = 'datetime';
return sType;
}
}
//if option requires extra formatting.
if (
this._oNavContainer ||
(this._oNavContainer && (aLastOptionsSelectedIndex > -1 || aNextOptionsSelectedIndex > -1))
) {
if ((aLastDateTimeOperators.indexOf(sOptionKey) > -1 || aNextDateTimeOperators.indexOf(sOptionKey) > -1) && oSelect) {
sActualSelectedOptionKey = this._oSelectedOption.getKey().slice(0, 4) + oSelect.getSelectedKey();
}
if (aDateTimeOperators.indexOf(sActualSelectedOptionKey) > -1) {
sType = 'datetime';
return sType;
}
}
aValueHelpTypes = this._oSelectedOption ? this._oSelectedOption.getValueHelpUITypes() : [];
return aValueHelpTypes && aValueHelpTypes.length ? aValueHelpTypes[0].getType() : "";
};
DynamicDateRange.prototype._getDatesLabelFormatter = function() {
var oFormatOptions,
sType = this._getValueHelpTypeForFormatter();
switch (sType) {
case "datetime":
oFormatOptions = Object.create(this._getFormatter()._dateTimeFormatter.oFormatOptions);
oFormatOptions.singleIntervalValue = true;
oFormatOptions.interval = true;
this._oDatesLabelFormatter = DateFormat.getDateTimeInstance(oFormatOptions);
break;
default:
oFormatOptions = Object.create(this._getFormatter()._dateFormatter.oFormatOptions);
oFormatOptions.singleIntervalValue = true;
oFormatOptions.interval = true;
this._oDatesLabelFormatter = DateFormat.getInstance(oFormatOptions);
}
return this._oDatesLabelFormatter;
};
DynamicDateRange.prototype._destroyInputControls = function() {
if (!this.aInputControls) {
return;
}
this.aInputControls.forEach(function(oCtrl) {
oCtrl.destroy();
});
this.aInputControls = undefined;
};
/**
* Creates and adds a suggestion item to the internal input, based on a given value.
*
* @param {object} oSuggestValue A value object with the same interface as the control's value
* @private
*/
DynamicDateRange.prototype._addSuggestionItem = function(oSuggestValue) {
var aValueDates = this.toDates(oSuggestValue, this.getCalendarWeekNumbering());
var aResultingDates = [];
for (var i = 0; i < aValueDates.length; i++) {
aResultingDates[i] = aValueDates[i];
}
var oItem = new ListItem({
text: this.getOption(oSuggestValue.operator).format(oSuggestValue, this._getFormatter()),
additionalText: '',
customData: [
new CustomData({
key : "operator",
value: oSuggestValue.operator
})
]
});
this._oInput.addSuggestionItem(oItem);
// Called after addSuggestionItem because the suggested items are needed in _getDatesLabelFormatter.
if (aResultingDates.length > 0) {
oItem.setAdditionalText(this._getDatesLabelFormatter().format(aResultingDates));
}
};
/**
* Creates and adds a suggestion group item to the internal input, based on a given value.
*
* @param {string} sGroupValue The value to be set
* @private
*/
DynamicDateRange.prototype._addSuggestionGroupItem = function(sGroupValue) {
this._oInput.addSuggestionItemGroup({text: sGroupValue});
};
/**
* Handles input field change.
*
* @param {sap.ui.base.Event} oEvent Change event object
* @private
*/
DynamicDateRange.prototype._handleInputChange = function(oEvent) {
var sInputValue = oEvent.getParameter("value");
var oVal = this._parseValue(this._stripValue(sInputValue));
var oPrevValue = this.getValue();
var bValid = sInputValue.trim() === "" || !!oVal;
if (this._isDateRange(oVal)) {
this._swapDates(oVal.values);
}
if (!bValid) {
this.setValue({ operator: "PARSEERROR", values: [oResourceBundle.getText("DDR_WRONG_VALUE"), sInputValue] });
} else {
this.setValue(oVal);
}
this.fireChange({ value: this.getValue(), prevValue: oPrevValue, valid: bValid });
};
/**
* Checks if the <code>value</code> property operator corresponds to a date range.
* @param {sap.m.DynamicDateRangeValue} oValue A <code>sap.m.DynamicDateRangeValue</code>
* @returns {boolean} True in case of a date range
* @private
*/
DynamicDateRange.prototype._isDateRange = function(oValue) {
return Boolean(oValue && (oValue.operator === "DATERANGE" || oValue.operator === "DATETIMERANGE"));
};
/**
* Swaps the start and end date of the value if the start date is after the end date.
* @param {Array<Date>} aValues An array of JS Dates
* @private
*/
DynamicDateRange.prototype._swapDates = function(aValues) {
if (aValues.length > 1 && aValues[0].getTime() > aValues[1].getTime()) {
aValues.reverse();
}
};
DynamicDateRange.prototype._enhanceInputValue = function(sFormattedValue, oVal) {
var oOption = this.getOption(oVal.operator);
if (!oOption) {
return null;
}
if (oOption.enhanceFormattedValue()
|| (oVal.operator === "LASTDAYS" && oVal.values[0] <= 1)
|| (oVal.operator === "NEXTDAYS" && oVal.values[0] <= 1)) {
return sFormattedValue + " (" + this._toDatesString(oVal) + ")";
}
return sFormattedValue;
};
/**
/* Removes the string found in brackets and trims the value.
*/
DynamicDateRange.prototype._stripValue = function(sValue) {
var iOpeningBracket = sValue.indexOf("(");
var iClosingBracket = sValue.lastIndexOf(")");
var sResult = sValue;
if (iOpeningBracket !== -1 && iClosingBracket !== -1 && iOpeningBracket < iClosingBracket) {
sResult = sValue.slice(0, iOpeningBracket) + sValue.slice(iClosingBracket + 1);
sResult = sResult.trim();
}
return sResult;
};
DynamicDateRange.prototype._toDatesString = function(oValue) {
var aValueDates = this.toDates(oValue, this.getCalendarWeekNumbering());
var aDates = [];
for (var i = 0; i < aValueDates.length; i++) {
aDates[i] = aValueDates[i];
}
return this._getDatesLabelFormatter().format(aDates);
};
DynamicDateRange.prototype._getPickerParser = function() {
if (!this._calendarParser) {
this._calendarParser = DateFormat.getDateTimeWithTimezoneInstance({ showTimezone: false });
}
return this._calendarParser;
};
DynamicDateRange.prototype._getPopupHeight = function() {
let height;
if (document.body.classList.contains("sapUiSizeCompact") || this.hasStyleClass("sapUiSizeCompact") || this.getDomRef()?.closest(".sapUiSizeCompact")) {
height = this.getStandardOptions().length * POPUP_LIST_ITEM_COMPACT_HEIGHT + POPUP_HEADER_HEIGHT;
} else {
height = this.getStandardOptions().length * POPUP_LIST_ITEM_HEIGHT + POPUP_HEADER_HEIGHT;
}
return (height < POPUP_MAX_HEIGHT) ? height + "px" : POPUP_MAX_HEIGHT + "px";
};
DynamicDateRange.prototype._createPopup = function() {
if (!this._oPopup) {
this._oPopup = new ResponsivePopover(this.getId() + "-RP", {
//read the documentation about those two - the page addapts its size to its container...
contentHeight: this._getPopupHeight(),
contentWidth: '320px',
showCloseButton: false,
showArrow: false,
showHeader: false,
placement: library.PlacementType.VerticalPreferedBottom,
ariaLabelledBy: [
InvisibleText.getStaticId("sap.m", "INPUT_AVALIABLE_VALUES")
]
});
this._oPopup.addStyleClass("sapMDDRPopover");
// This event handler prevents bubbling of the validationError events. In case when DynamicDateRange control is registered in the
// Message Manager, it will not receive and add validationError message generated by the DynamicDateRange options, as there is
// internal validation and it is not possible to set wrong value because in case of validation error, the Apply button is disabled.
this._oPopup.attachValidationError(function(oEvent) {
oEvent.bCancelBubble = true;
});
if (Device.system.phone) {
this._oPopup.addStyleClass("sapUiNoContentPadding");
} else {
// We don't need the sap.m.Popover control to apply focus inside NavContainer pages,
// as we apply custom focus handling logic.
this._oPopup._oControl._getSingleNavContent = function() {
return null;
};
}
this._oPopup.attachBeforeOpen(function() {
var oValue = this.getValue(),
oItem;
if (!oValue) {
return;
}
oItem = this._determineOptionFocus(oValue);
if (oItem && oValue.operator !== "PARSEERROR") {
oItem.setSelected(true);
}
}, this);
this._oPopup.attachAfterOpen(function() {
var oToPage = this._oNavContainer.getPages()[0];
this._applyNavContainerPageFocus(oToPage);
}, this);
this._oPopup.attachAfterClose(function() {
this._oPreviousSelectedOption = this._oSelectedOption;
this._setFooterVisibility(false);
}, this);
this._oPopup.setBeginButton(new Button({
type: library.ButtonType.Emphasized,
text: oResourceBundle.getText("DYNAMIC_DATE_RANGE_CONFIRM"),
press: this._applyValue.bind(this)
}));
this._oPopup.setEndButton(new Button({
text: oResourceBundle.getText("DYNAMIC_DATE_RANGE_CANCEL"),
press: function() {
this._oSelectedOption = this._oPreviousSelectedOption;
this._oDatesLabelFormatter = null;
this._closePopup();
}.bind(this)
}));
this._setFooterVisibility(false);
this._oPopup._getPopup().setAutoClose(true);
// define a parent-child relationship between the control's and the _picker popup
this.setAggregation("_popup", this._oPopup, true);
}
};
/**
* Sorts, groups and reduces the items to be shown as suggestions.
*
* @param {array} aArray The array to be reworked
* @param {boolean} bReduce If reducing is needed
* @returns {array} The array with the objects to be displayed
* @private
*/
DynamicDateRange.prototype._collectValueHelpItems = function(aArray, bReduce) {
var lastXOption;
var nextXOption;
var aGroupHeaders = [];
// get the control options' metadata
var aOptions = aArray;
// sort by group
aOptions.sort(function(a, b) {
var iGroupA = Number(a.getGroup()) ? a.getGroup() : this._getGroups()[a.getGroup()];
var iGroupB = Number(b.getGroup()) ? b.getGroup() : this._getGroups()[b.getGroup()];
var iGroupDiff = iGroupA - iGroupB;
if (iGroupDiff) {
return iGroupDiff;
}
return aStandardOptionsKeys.indexOf(a.getKey()) - aStandardOptionsKeys.indexOf(b.getKey());
}.bind(this));
if (bReduce) {
// for last x/next x options leave only the first of each, remove the rest
aOptions = aOptions.reduce(function(aResult, oCurrent) {
if (StandardDynamicDateOption.LastXKeys.indexOf(oCurrent.getKey()) !== -1) {
if (lastXOption) {
return aResult;
}
lastXOption = true;
}
if (StandardDynamicDateOption.NextXKeys.indexOf(oCurrent.getKey()) !== -1) {
if (nextXOption) {
return aResult;
}
nextXOption = true;
}
aResult.push(oCurrent);
return aResult;
}, []);
}
if (this.getEnableGroupHeaders()) {
// insert a group header string before the options from each group
aOptions = aOptions.reduce(function(aResult, oCurrent) {
var iGroup = Number(oCurrent.getGroup()) ? oCurrent.getGroup() : this._getGroups()[oCurrent.getGroup()];
var sGroupName = Object.keys(this._getGroups()).find((key) => this._getGroups()[key] === iGroup);
var bGroupHasHeader = this._customGroupHeaders && this._customGroupHeaders.find((group) => group.name === sGroupName);
var sGroupHeader = bGroupHasHeader ? this.getGroupHeader(sGroupName) : oCurrent.getGroupHeader();
if (aGroupHeaders.indexOf(sGroupHeader) === -1) {
aGroupHeaders.push(sGroupHeader);
aResult.push(sGroupHeader);
}
aResult.push(oCurrent);
return aResult;
}.bind(this), []);
}
return aOptions;
};
/**
* Provides the option's group header text.
*
* @returns {string} A group header
* @public
* @since 1.118
*/
DynamicDateRange.prototype.getGroupHeader = function(sGroupName) {
var iGroupId = this._getGroups()[sGro