UNPKG

@openui5/sap.m

Version:

OpenUI5 UI Library sap.m

1,612 lines (1,411 loc) 104 kB
/*! * 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.P13nConditionPanel sap.ui.define([ './library', "sap/ui/core/Lib", 'sap/ui/core/library', 'sap/ui/core/Control', 'sap/ui/core/IconPool', 'sap/ui/Device', 'sap/ui/core/InvisibleText', 'sap/ui/core/ResizeHandler', 'sap/ui/core/Item', 'sap/ui/core/ListItem', 'sap/ui/model/odata/type/Boolean', 'sap/ui/model/type/String', 'sap/ui/model/odata/type/String', 'sap/ui/model/type/Date', 'sap/ui/model/type/Time', 'sap/ui/model/odata/type/DateTime', 'sap/ui/model/type/Float', 'sap/ui/layout/library', 'sap/ui/layout/Grid', 'sap/ui/layout/GridData', 'sap/ui/layout/HorizontalLayout', './Button', './OverflowToolbar', './OverflowToolbarLayoutData', './ToolbarSpacer', './Text', './SearchField', './CheckBox', './ComboBox', './Select', './Label', './Input', './DatePicker', './TimePicker', './DateTimePicker', 'sap/base/Log', 'sap/ui/thirdparty/jquery', './P13nOperationsHelper', 'sap/m/P13nConditionPanelRenderer' ], function( library, Library, coreLibrary, Control, IconPool, Device, InvisibleText, ResizeHandler, Item, ListItem, BooleanOdataType, StringType, StringOdataType, DateType, TimeType, DateTimeOdataType, FloatType, layoutLibrary, Grid, GridData, HorizontalLayout, Button, OverflowToolbar, OverflowToolbarLayoutData, ToolbarSpacer, Text, SearchField, CheckBox, ComboBox, Select, Label, Input, DatePicker, TimePicker, DateTimePicker, Log, jQuery, P13nOperationsHelper, P13nConditionPanelRenderer ) { "use strict"; // shortcut for sap.ui.core.ValueState var ValueState = coreLibrary.ValueState; // shortcut for sap.m.ButtonType var ButtonType = library.ButtonType; // shortcut for sap.m.ToolbarDesign var ToolbarDesign = library.ToolbarDesign; // shortcut for sap.ui.core.TextAlign var TextAlign = coreLibrary.TextAlign; // shortcut for sap.m.OverflowToolbarPriority var OverflowToolbarPriority = library.OverflowToolbarPriority; // shortcut for sap.m.P13nConditionOperation var P13nConditionOperation = library.P13nConditionOperation; /** * Constructor for a new P13nConditionPanel. * * @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 The ConditionPanel Control will be used to implement the Sorting, Filtering and Grouping panel of the new Personalization dialog. * @extends sap.ui.core.Control * @version 1.146.0 * @constructor * @public * @since 1.26.0 * @alias sap.m.P13nConditionPanel * @deprecated As of version 1.124, replaced by the artifacts in {@link sap.m.p13n}. */ var P13nConditionPanel = Control.extend("sap.m.P13nConditionPanel", /** @lends sap.m.P13nConditionPanel.prototype */ { metadata: { library: "sap.m", properties: { /** * defines the max number of conditions on the ConditionPanel */ maxConditions: { type: "string", group: "Misc", defaultValue: '-1' }, /** * exclude options for filter */ exclude: { type: "boolean", group: "Misc", defaultValue: false }, /** * defines if the mediaQuery or a ContainerResize will be used for layout update. * When the <code>P13nConditionPanel</code> is used on a dialog the property should be set to <code>true</code>! */ containerQuery: { type: "boolean", group: "Misc", defaultValue: false }, /** * adds initial a new empty condition row */ autoAddNewRow: { type: "boolean", group: "Misc", defaultValue: false }, /** * makes the remove icon on the first condition row disabled when only one condition exist. */ disableFirstRemoveIcon: { type: "boolean", group: "Misc", defaultValue: false }, /** * makes the Add icon visible on each condition row. If is set to false the Add is only visible at the end and you can only append a * new condition. */ alwaysShowAddIcon: { type: "boolean", group: "Misc", defaultValue: true }, /** * new added condition use the settings from the previous condition as default. */ usePrevConditionSetting: { type: "boolean", group: "Misc", defaultValue: true }, /** * KeyField value can only be selected once. When you set the property to <code>true</code> the ConditionPanel will automatically offers on the * KeyField drop down only the keyFields which are not used. The default behavior is that in each keyField dropdown all keyfields are * listed. */ autoReduceKeyFieldItems: { type: "boolean", group: "Misc", defaultValue: false }, /** * can be used to control the layout behavior. Default is "" which will automatically change the layout. With "Desktop", "Table" * or "Phone" you can set a fixed layout. */ layoutMode: { type: "string", group: "Misc", defaultValue: null }, /** * show additional labels in the condition */ showLabel: { type: "boolean", group: "Misc", defaultValue: false }, /** * This represents the displayFormat of the condition Values. With the value "UpperCase" the entered value of the condition will be * converted to upperCase. */ displayFormat: { type: "string", group: "Misc", defaultValue: null }, /** * Calls the validation listener tbd... */ validationExecutor: { type: "object", group: "Misc", defaultValue: null } }, aggregations: { /** * Content for the ConditionPanel. This aggregation is not public! */ content: { type: "sap.ui.core.Control", multiple: true, singularName: "content", visibility: "hidden" } }, events: { /** * Workaround for updating the binding */ dataChange: {} } }, renderer: P13nConditionPanelRenderer.renderer }); // EXC_ALL_CLOSURE_003 /** * This method must be used to assign a list of conditions. * * @param {object[]} aConditions array of Conditions. * @public */ P13nConditionPanel.prototype.setConditions = function(aConditions) { if (!aConditions) { Log.error("sap.m.P13nConditionPanel : aCondition is not defined"); } if (this._bIgnoreSetConditions) { return; } this._oConditionsMap = {}; this._aConditionKeys = []; this._iConditions = 0; for (var i = 0; i < aConditions.length; i++) { this._addCondition2Map(aConditions[i]); } this._clearConditions(); this._fillConditions(); }; /** * remove all conditions. * * @public */ P13nConditionPanel.prototype.removeAllConditions = function() { this._oConditionsMap = {}; this._aConditionKeys = []; this._iConditions = 0; this._clearConditions(); this._fillConditions(); }; /** * add a single condition. * * @param {object} oCondition the new condition of type <code>{ "key": "007", "operation": sap.m.P13nConditionOperation.Ascending, "keyField": * "keyFieldKey", "value1": "", "value2": ""};</code> * @public */ P13nConditionPanel.prototype.addCondition = function(oCondition) { if (this._bIgnoreSetConditions) { return; } oCondition.index = this._iConditions; this._addCondition2Map(oCondition); this._addCondition(oCondition); }; /** * insert a single condition. * * @param {object} oCondition the new condition of type <code>{ "key": "007", "operation": sap.m.P13nConditionOperation.Ascending, "keyField": * "keyFieldKey", "value1": "", "value2": ""};</code> * @param {int} index of the new condition * @public */ P13nConditionPanel.prototype.insertCondition = function(oCondition, index) { if (this._bIgnoreSetConditions) { return; } if (index !== undefined) { oCondition.index = index; } this._addCondition2Map(oCondition); this._addCondition(oCondition); }; /** * remove a single condition. * * @param {object} vCondition is the condition which should be removed. can be either a string with the key of the condition of the condition * object itself. * @public */ P13nConditionPanel.prototype.removeCondition = function(vCondition) { this._clearConditions(); if (typeof vCondition == "string") { this._removeConditionFromMap(vCondition); } if (typeof vCondition == "object") { this._removeConditionFromMap(vCondition.key); } this._fillConditions(); }; /** * add a single condition into the _oConditionMap. * * @private * @param {object} oCondition the new condition of type <code>{ "key": "007", "operation": sap.m.P13nConditionOperation.Ascending, "keyField": * "keyFieldKey", "value1": "", "value2": ""};</code> */ P13nConditionPanel.prototype._addCondition2Map = function(oCondition) { if (!oCondition.key) { oCondition.key = "condition_" + this._iConditions; if (this.getExclude()) { oCondition.key = "x" + oCondition.key; } } this._iConditions++; this._oConditionsMap[oCondition.key] = oCondition; this._aConditionKeys.push(oCondition.key); }; P13nConditionPanel.prototype._removeConditionFromMap = function(sKey) { this._iConditions--; delete this._oConditionsMap[sKey]; var i = this._aConditionKeys.indexOf(sKey); if (i >= 0) { this._aConditionKeys.splice(i, 1); } }; /** * returns array of all defined conditions. * * @public * @returns {object[]} array of Conditions */ P13nConditionPanel.prototype.getConditions = function() { var oCondition; var aConditions = []; if (this._oConditionsMap) { for (var conditionId in this._oConditionsMap) { oCondition = this._oConditionsMap[conditionId]; var sValue = oCondition.value; if (!sValue) { sValue = this._getFormatedConditionText(oCondition.operation, oCondition.value1, oCondition.value2, oCondition.exclude, oCondition.keyField, oCondition.showIfGrouped); } if (!oCondition._oGrid || oCondition._oGrid.select.getSelected()) { aConditions.push({ "key": conditionId, "text": sValue, "exclude": oCondition.exclude, "operation": oCondition.operation, "keyField": oCondition.keyField, "value1": oCondition.value1, "value2": this._hasSecondValue(oCondition.operation) ? oCondition.value2 : null, "showIfGrouped": oCondition.showIfGrouped }); } } } return aConditions; }; /** * setter for the supported operations which we show per condition row. This array of "default" operations will only be used when we do not have * on the keyfield itself some specific operations and a keyfield is of not of type date or numeric. * * @public * @param {sap.m.P13nConditionOperation[]} aOperations array of operations <code>[sap.m.P13nConditionOperation.BT, sap.m.P13nConditionOperation.EQ]</code> * @param {string} sType defines the type for which this operations will be used. is <code>sType</code> is not defined the operations will be used as default * operations. */ P13nConditionPanel.prototype.setOperations = function(aOperations, sType) { sType = sType || "default"; this._oTypeOperations[sType] = aOperations; this._updateAllOperations(); }; P13nConditionPanel.prototype.setValues = function(aValues, sType) { sType = sType || "default"; this._oTypeValues[sType] = aValues; // this._updateAllOperations(); }; /** * add a single operation * * @public * @param {sap.m.P13nConditionOperation} oOperation * @param {string} sType defines the type for which this operations will be used. */ P13nConditionPanel.prototype.addOperation = function(oOperation, sType) { sType = sType || "default"; this._oTypeOperations[sType].push(oOperation); this._updateAllOperations(); }; /** * remove all operations * * @public * @param {string} sType defines the type for which all operations should be removed */ P13nConditionPanel.prototype.removeAllOperations = function(sType) { sType = sType || "default"; this._oTypeOperations[sType] = []; this._updateAllOperations(); }; /** * returns the default array of operations * * @public * @param {string} [sType=default] defines the type for which the operations should be returned. * @returns {sap.m.P13nConditionOperation[]} array of operations */ P13nConditionPanel.prototype.getOperations = function(sType) { sType = sType || "default"; return this._oTypeOperations[sType]; }; /** * This method allows you to specify the KeyFields for the conditions. You can set an array of object with Key and Text properties to define the * keyfields. * * @public * @param {array} aKeyFields array of KeyFields <code>[{key: "CompanyCode", text: "ID"}, {key:"CompanyName", text : "Name"}]</code> */ P13nConditionPanel.prototype.setKeyFields = function(aKeyFields) { this._aKeyFields = aKeyFields; this._aKeyFields.forEach(function(oKeyField) { P13nConditionPanel._createKeyFieldTypeInstance(oKeyField); }, this); this._updateKeyFieldItems(this._oConditionsGrid, true); this._updateAllConditionsEnableStates(); this._createAndUpdateAllKeyFields(); this._updateAllOperations(); }; /** * add a single KeyField * * @public * @param {object} oKeyField {key: "CompanyCode", text: "ID"} */ P13nConditionPanel.prototype.addKeyField = function(oKeyField) { this._aKeyFields.push(oKeyField); P13nConditionPanel._createKeyFieldTypeInstance(oKeyField); this._updateKeyFieldItems(this._oConditionsGrid, true, true); this._updateAllConditionsEnableStates(); this._createAndUpdateAllKeyFields(); this._updateAllOperations(); }; P13nConditionPanel._createKeyFieldTypeInstance = function(oKeyField) { var oConstraints; //check if typeInstance exists, if not create the type instance if (!oKeyField.typeInstance) { switch (oKeyField.type) { case "boolean": //TODO in case the model is not an ODataModel we should use the sap.ui.model.type.Boolean oKeyField.typeInstance = new BooleanOdataType(); break; case "numc": if (!(oKeyField.formatSettings && oKeyField.formatSettings.isDigitSequence)) { Log.error("sap.m.P13nConditionPanel", "NUMC type support requires isDigitSequence==true!"); oKeyField.formatSettings = Object.assign({}, oKeyField.formatSettings, { isDigitSequence: true }); } oConstraints = oKeyField.formatSettings; if (oKeyField.maxLength) { oConstraints = Object.assign({}, oConstraints, { maxLength: oKeyField.maxLength }); } if (!oConstraints.maxLength) { Log.error("sap.m.P13nConditionPanel", "NUMC type suppport requires maxLength!"); } oKeyField.typeInstance = new StringOdataType({}, oConstraints); break; case "date": //TODO we should use the none odata date type, otherwise the returned oValue1 is not a date object oKeyField.typeInstance = new DateType(Object.assign({}, oKeyField.formatSettings, { strictParsing: true }), {}); break; case "time": //TODO we should use the none odata date type, otherwise the returned oValue1 is not a date object oKeyField.typeInstance = new TimeType(Object.assign({}, oKeyField.formatSettings, { strictParsing: true }), {}); break; case "datetime": oKeyField.typeInstance = new DateTimeOdataType(Object.assign({}, oKeyField.formatSettings, { strictParsing: true }), { displayFormat: "Date" }); // when the type is a DateTime type and isDateOnly==true, the type internal might use UTC=true // result is that date values which we format via formatValue(oDate, "string") are shown as the wrong date. // The current Date format is yyyy-mm-ddT00:00:00 GMT+01 // Workaround: changing the oFormat.oFormatOptions.UTC to false! var oType = oKeyField.typeInstance; if (!oType.oFormat) { // create a oFormat of the type by formating a dummy date oType.formatValue(new Date(), "string"); } if (oType.oFormat) { oType.oFormat.oFormatOptions.UTC = false; } break; case "numeric": if (oKeyField.precision || oKeyField.scale) { oConstraints = {}; if (oKeyField.precision) { oConstraints["maxIntegerDigits"] = parseInt(oKeyField.precision); } if (oKeyField.scale) { oConstraints["maxFractionDigits"] = parseInt(oKeyField.scale); } } oKeyField.typeInstance = new FloatType(oConstraints); break; default: var oFormatOptions = oKeyField.formatSettings; if (oKeyField.maxLength) { oFormatOptions = Object.assign({}, oFormatOptions, { maxLength: oKeyField.maxLength }); } oKeyField.typeInstance = new StringType({}, oFormatOptions); break; } } }; /** * removes all KeyFields * * @public */ P13nConditionPanel.prototype.removeAllKeyFields = function() { this._aKeyFields = []; this._updateKeyFieldItems(this._oConditionsGrid, true); }; /** * getter for KeyFields array * * @public * @returns {object[]} array of KeyFields <code>[{key: "CompanyCode", text: "ID"}, {key:"CompanyName", text : "Name"}]</code> */ P13nConditionPanel.prototype.getKeyFields = function() { return this._aKeyFields; }; /** * sets the AlwaysShowAddIcon. * * @private * @param {boolean} bEnabled makes the Add icon visible for each condition row. */ P13nConditionPanel.prototype.setAlwaysShowAddIcon = function(bEnabled) { this.setProperty("alwaysShowAddIcon", bEnabled); if (this._oConditionsGrid) { this._oConditionsGrid.toggleStyleClass("conditionRootGrid", this.getLayoutMode() !== "Desktop"); // && !this.getAlwaysShowAddIcon()); } return this; }; /** * sets the LayoutMode. If not set the layout depends on the size of the browser or the container. see ContainerQuery * * @private * @param {string} sLayoutMode define the layout mode for the condition row. The value can be Desktop, Tablet or Phone. * @returns {this} <code>this</code> to allow method chaining */ P13nConditionPanel.prototype.setLayoutMode = function(sLayoutMode) { this.setProperty("layoutMode", sLayoutMode); if (this._oConditionsGrid) { this._oConditionsGrid.toggleStyleClass("conditionRootGrid", sLayoutMode !== "Desktop"); // && !this.getAlwaysShowAddIcon()); } this._updateConditionFieldSpans(sLayoutMode); // we have to refill the content grids this._clearConditions(); this._fillConditions(); return this; }; /** * sets the ContainerQuery. defines if the mediaQuery or a ContainerResize will be used for layout update. When the P13nConditionPanel is used on * a dialog the property should be set to <code>true</code>! * * @private * @since 1.30.0 * @param {boolean} bEnabled enables or disables the <code>ContainerQuery</code> * @returns {this} <code>this</code> to allow method chaining */ P13nConditionPanel.prototype.setContainerQuery = function(bEnabled) { this._unregisterResizeHandler(); this.setProperty("containerQuery", bEnabled); this._registerResizeHandler(); // we have to refill the content grids this._clearConditions(); this._fillConditions(); return this; }; /** * sets the LayoutMode. * * @private * @param {string} sMode define the layout mode for the condition row. The value can be "Desktop", "Tablet" or "Phone". */ P13nConditionPanel.prototype._updateConditionFieldSpans = function(sMode) { if (this._aConditionsFields) { var bDesktop = sMode === "Desktop"; if (bDesktop) { // this._aConditionsFields[1].SpanFilter = "L1 M1 S1"; Label this._aConditionsFields[2].SpanFilter = "L3 M3 S3"; // this._aConditionsFields[3].SpanFilter = "L1 M1 S1"; Label this._aConditionsFields[4].SpanFilter = "L2 M2 S2"; this._aConditionsFields[5].SpanFilter = "L3 M3 S3"; this._aConditionsFields[6].SpanFilter = "L2 M2 S2"; this._aConditionsFields[7].SpanFilter = "L1 M1 S1"; } var bTablet = sMode === "Tablet"; if (bTablet) { // this._aConditionsFields[1].SpanFilter = "L1 M1 S1"; Label this._aConditionsFields[2].SpanFilter = "L5 M5 S5"; // this._aConditionsFields[3].SpanFilter = "L1 M1 S1"; Label this._aConditionsFields[4].SpanFilter = "L5 M5 S5"; this._aConditionsFields[5].SpanFilter = "L10 M10 S10"; this._aConditionsFields[6].SpanFilter = "L10 M10 S10"; this._aConditionsFields[7].SpanFilter = "L1 M1 S1"; } } }; /* * Initialize the control * @private */ P13nConditionPanel.prototype.init = function() { // init some resources this._oRb = Library.getResourceBundleFor("sap.m"); this._sFromLabelText = this._oRb.getText("CONDITIONPANEL_LABELFROM"); this._sToLabelText = this._oRb.getText("CONDITIONPANEL_LABELTO"); this._sValueLabelText = this._oRb.getText("CONDITIONPANEL_LABELVALUE"); this._sShowIfGroupedLabelText = this._oRb.getText("CONDITIONPANEL_LABELGROUPING"); this._sValidationDialogFieldMessage = this._oRb.getText("CONDITIONPANEL_FIELDMESSAGE"); this._oOperationsHelper = new P13nOperationsHelper(); this._oTypeOperations = { "default": [] }; this._oTypeValues = { "default": [] }; this._aKeyFields = []; this._oConditionsMap = {}; this._aConditionKeys = []; this._iConditions = 0; this._sLayoutMode = "Desktop"; this._sConditionType = "Filter"; this._sAddRemoveIconTooltip = "FILTER"; this._iBreakPointTablet = Device.media._predefinedRangeSets[Device.media.RANGESETS.SAP_STANDARD].points[0]; this._iBreakPointDesktop = Device.media._predefinedRangeSets[Device.media.RANGESETS.SAP_STANDARD].points[1]; // create the main grid and add it into the hidden content aggregation this._oConditionsGrid = new Grid({ width: "100%", defaultSpan: "L12 M12 S12", hSpacing: 0, vSpacing: 0 }).toggleStyleClass("conditionRootGrid", this.getLayoutMode() !== "Desktop"); // && !this.getAlwaysShowAddIcon()); this._oConditionsGrid.addStyleClass("sapUiRespGridOverflowHidden"); this._iFirstConditionIndex = 0; this._iConditionPageSize = 10; this._oInvisibleTextField = new InvisibleText({ text: this._oRb.getText("CONDITIONPANEL_FIELD_LABEL") }); this._oInvisibleTextOperatorInputValue = new InvisibleText({ text: this._oRb.getText("CONDITIONPANEL_FIELD_VALUE_ARIA_LABEL") }); this._oInvisibleTextOperator = new InvisibleText({ text: this._oRb.getText("CONDITIONPANEL_OPERATOR_ARIA_LABEL") }); this._oInvisibleTextOperatorAddButton = new InvisibleText({ text: this._oRb.getText("CONDITIONPANEL_ADD_SCREENREADER_DESCRIPTION") }); this.addAggregation("content", this._oInvisibleTextField); this.addAggregation("content", this._oInvisibleTextOperatorInputValue); this.addAggregation("content", this._oInvisibleTextOperator); this.addAggregation("content", this._oInvisibleTextOperatorAddButton); this.addAggregation("content", this._oConditionsGrid); this._registerResizeHandler(); this._aConditionsFields = this._createConditionsFields(); this._oButtonGroupSpan = { "SpanFilter": "L2 M2 S2", "SpanSort": Device.system.phone ? "L2 M2 S4" : "L2 M2 S3", "SpanGroup": "L2 M2 S3" }; this._updateConditionFieldSpans(this.getLayoutMode()); // fill/update the content "oConditionGrid"s this._fillConditions(); }; /* * create the paginator toolbar * @private */ P13nConditionPanel.prototype._createPaginatorToolbar = function() { this._bPaginatorButtonsVisible = false; var that = this; this._oPrevButton = new Button({ icon: IconPool.getIconURI("navigation-left-arrow"), tooltip: this._oRb.getText("p13n.PREVIOUS"), visible: true, press: function(oEvent) { that._iFirstConditionIndex = Math.max(0, that._iFirstConditionIndex - that._iConditionPageSize); that._clearConditions(); that._fillConditions(); }, layoutData: new OverflowToolbarLayoutData({ priority: OverflowToolbarPriority.NeverOverflow }) }); this._oNextButton = new Button({ icon: IconPool.getIconURI("navigation-right-arrow"), tooltip: this._oRb.getText("p13n.NEXT"), visible: true, press: function(oEvent) { that._iFirstConditionIndex += that._iConditionPageSize; that._clearConditions(); that._fillConditions(); }, layoutData: new OverflowToolbarLayoutData({ priority: OverflowToolbarPriority.NeverOverflow }) }); this._oRemoveAllButton = new Button({ text: this._oRb.getText("CONDITIONPANEL_REMOVE_ALL"), // "Remove All", //icon: sap.ui.core.IconPool.getIconURI("decline"), //tooltip: "Remove All", visible: true, press: function() { that._aConditionKeys.forEach(function(sKey) { this.fireDataChange({ key: sKey, index: 0, operation: "remove", newData: null }); }, that); this._iFirstConditionIndex = 0; that.removeAllConditions(); }, layoutData: new OverflowToolbarLayoutData({ priority: OverflowToolbarPriority.Low }) }); this._oAddButton = new Button({ icon: IconPool.getIconURI("add"), visible: true, press: function(oEvent) { var oConditionGrid = that._createConditionRow(that._oConditionsGrid, undefined, null, 0); that._changeField(oConditionGrid); // set the focus in a fields of the newly added condition setTimeout(function() { oConditionGrid.keyField.focus(); }); that._updatePaginatorToolbar(); }, layoutData: new OverflowToolbarLayoutData({ priority: OverflowToolbarPriority.Low }), ariaDescribedBy: this._oInvisibleTextOperatorAddButton }); this._oHeaderText = new Text({ wrapping: false, layoutData: new OverflowToolbarLayoutData({ priority: OverflowToolbarPriority.NeverOverflow }) }); this._oPageText = new Text({ wrapping: false, textAlign: TextAlign.Center, layoutData: new OverflowToolbarLayoutData({ priority: OverflowToolbarPriority.NeverOverflow }) }); this._oFilterField = new SearchField({ width: "12rem", layoutData: new OverflowToolbarLayoutData({ priority: OverflowToolbarPriority.High }) }); this._oPaginatorToolbar = new OverflowToolbar({ height: "3rem", design: ToolbarDesign.Transparent, content: [ this._oHeaderText, new ToolbarSpacer(), this._oFilterField, this._oPrevButton, this._oPageText, this._oNextButton, this._oRemoveAllButton, this._oAddButton ] }); }; /* * update the paginator toolbar element * @private */ P13nConditionPanel.prototype._updatePaginatorToolbar = function() { if (this._sConditionType !== "Filter" || this.getMaxConditions() !== "-1") { return; } var iItems = this._aConditionKeys.length; var iPages = 1 + Math.floor(Math.max(0, iItems - 1) / this._iConditionPageSize); var iPage = 1 + Math.floor(this._iFirstConditionIndex / this._iConditionPageSize); var oParent = this.getParent(); if (!this._oPaginatorToolbar) { if (iItems > this._iConditionPageSize) { this._createPaginatorToolbar(); this.insertAggregation("content", this._oPaginatorToolbar, 0); this._onGridResize(); } else { if (oParent && oParent.setHeaderText) { if (this._sOrgHeaderText == undefined) { this._sOrgHeaderText = oParent.getHeaderText(); } oParent.setHeaderText(this._sOrgHeaderText + (iItems > 0 ? " (" + iItems + ")" : "")); } return; } } this._oPrevButton.setEnabled(this._iFirstConditionIndex > 0); this._oNextButton.setEnabled(this._iFirstConditionIndex + this._iConditionPageSize < iItems); if (oParent && oParent.setHeaderToolbar) { if (!oParent.getHeaderToolbar()) { this.removeAggregation("content", this._oPaginatorToolbar); oParent.setHeaderToolbar(this._oPaginatorToolbar); oParent.attachExpand(function(oEvent) { this._setToolbarElementVisibility(oEvent.getSource().getExpanded() && this._bPaginatorButtonsVisible); }.bind(this)); } } if (oParent && oParent.setHeaderText) { if (this._sOrgHeaderText == undefined) { this._sOrgHeaderText = oParent.getHeaderText(); } var sHeader = this._sOrgHeaderText + (iItems > 0 ? " (" + iItems + ")" : ""); oParent.setHeaderText(sHeader); this._oHeaderText.setText(sHeader); } else { this._oHeaderText.setText(iItems + " Conditions"); } this._oPageText.setText(iPage + "/" + iPages); this._bPaginatorButtonsVisible = this._bPaginatorButtonsVisible || iPages > 1; this._setToolbarElementVisibility(this._bPaginatorButtonsVisible); if (iPage > iPages) { // update the FirstConditionIndex and rerender this._iFirstConditionIndex -= Math.max(0, this._iConditionPageSize); this._clearConditions(); this._fillConditions(); } var nValidGrids = 0; this._oConditionsGrid.getContent().forEach(function(oGrid) { if (oGrid.select.getSelected()) { nValidGrids++; } }, this); if (iPages == iPage && (iItems - this._iFirstConditionIndex) > nValidGrids) { // check if we have to rerender the current last page this._clearConditions(); this._fillConditions(); } }; /* * make all toolbar elements visible or invisible * @private */ P13nConditionPanel.prototype._setToolbarElementVisibility = function(bVisible) { this._oPrevButton.setVisible(bVisible); this._oNextButton.setVisible(bVisible); this._oPageText.setVisible(bVisible); this._oFilterField.setVisible(false); //bVisible); this._oAddButton.setVisible(bVisible); this._oRemoveAllButton.setVisible(bVisible); }; /* * destroy and remove all internal references * @private */ P13nConditionPanel.prototype.exit = function() { this._clearConditions(); this._unregisterResizeHandler(); this._aConditionsFields = null; this._aKeys = null; this._aKeyFields = null; this._oTypeOperations = null; this._oRb = null; this._sFromLabelText = null; this._sToLabelText = null; this._sValueLabelText = null; this._sValidationDialogFieldMessage = null; this._oConditionsMap = null; this._aConditionKeys = []; }; /* * removes all condition rows from the main ConditionGrid. * @private */ P13nConditionPanel.prototype._clearConditions = function() { var aGrid = this._oConditionsGrid.getContent(); aGrid.forEach(function(oGrid) { for (var iField in this._aConditionsFields) { var field = this._aConditionsFields[iField]; if (oGrid[field["ID"]] && oGrid.getContent().indexOf(oGrid[field["ID"]]) === -1) { // TODO: notice that since these fields could have been removed from // the inner aggregation, and thus would not be destroyed otherwise, // we destroy them separately here oGrid[field["ID"]].destroy(); } } }, this); this._oConditionsGrid.destroyContent(); }; /* * creates all condition rows and updated the values of the fields. * @private */ P13nConditionPanel.prototype._fillConditions = function() { var oCondition, sConditionKey; var i = 0, iMaxConditions = this._getMaxConditionsAsNumber(), n = this._aConditionKeys.length; // fill existing conditions if (this._oConditionsMap) { var iPageSize = this._sConditionType !== "Filter" || this.getMaxConditions() !== "-1" ? 9999 : this._iConditionPageSize; n = Math.min(n, Math.min(iMaxConditions, this._iFirstConditionIndex + iPageSize)); for (i = this._iFirstConditionIndex; i < n; i++) { sConditionKey = this._aConditionKeys[i]; oCondition = this._oConditionsMap[sConditionKey]; this._createConditionRow(this._oConditionsGrid, oCondition, sConditionKey); } } this._updatePaginatorToolbar(); // create empty Conditions row/fields if ((this.getAutoAddNewRow() || this._oConditionsGrid.getContent().length === 0) && this._oConditionsGrid.getContent().length < iMaxConditions) { this._createConditionRow(this._oConditionsGrid); } }; /* * add one condition * @private */ P13nConditionPanel.prototype._addCondition = function(oCondition) { var i = 0; var iMaxConditions = this._getMaxConditionsAsNumber(); //TODO page handling missing if (this._oConditionsMap) { for (var conditionId in this._oConditionsMap) { if (i < iMaxConditions && oCondition === this._oConditionsMap[conditionId]) { this._createConditionRow(this._oConditionsGrid, oCondition, conditionId, i); } i++; } } this._updatePaginatorToolbar(); }; P13nConditionPanel.prototype._getMaxConditionsAsNumber = function() { return this.getMaxConditions() === "-1" ? 9999 : parseInt(this.getMaxConditions()); }; P13nConditionPanel.prototype.onAfterRendering = function() { if (this.getLayoutMode()) { this._sLayoutMode = this.getLayoutMode(); return; } }; P13nConditionPanel.prototype._handleMediaChange = function(p) { this._sLayoutMode = p.name; // if (window.console) { // window.console.log(" ---> MediaChange " + p.name); // } this._updateLayout(p); }; P13nConditionPanel.prototype._unregisterResizeHandler = function() { if (this._sContainerResizeListener) { ResizeHandler.deregister(this._sContainerResizeListener); this._sContainerResizeListener = null; } Device.media.detachHandler(this._handleMediaChange, this, Device.media.RANGESETS.SAP_STANDARD); }; P13nConditionPanel.prototype._registerResizeHandler = function() { if (this.getContainerQuery()) { this._sContainerResizeListener = ResizeHandler.register(this._oConditionsGrid, this._onGridResize.bind(this)); this._onGridResize(); } else { Device.media.attachHandler(this._handleMediaChange, this, Device.media.RANGESETS.SAP_STANDARD); } }; /** * returns the key of the condition grid or creates a new key * * @private * @param {object} oConditionGrid * @returns {string} the new or existing key */ P13nConditionPanel.prototype._getKeyFromConditionGrid = function(oConditionGrid) { var sKey = oConditionGrid.data("_key"); if (!sKey) { sKey = this._createConditionKey(); } return sKey; }; /** * creates a new key for the condition grids * * @private * @returns {string} the new key */ P13nConditionPanel.prototype._createConditionKey = function() { var i = 0; var sKey; do { sKey = "condition_" + i; if (this.getExclude()) { sKey = "x" + sKey; } i++; } while (this._oConditionsMap[sKey]); return sKey; }; /** * appends a new condition grid with all containing controls in the main grid * * @private * @param {sap.ui.layout.Grid} oTargetGrid the main grid in which the new condition grid will be added * @param {object} oConditionGridData the condition data for the new added condition grid controls * @param {string} sKey the key for the new added condition grid * @param {int} iPos the index of the new condition in the targetGrid * @param {boolean} bUseRowFromAbove use the key from the row above for creating a new row */ P13nConditionPanel.prototype._createConditionRow = function(oTargetGrid, oConditionGridData, sKey, iPos, bUseRowFromAbove) { var oGrid, that = this; if (iPos === undefined) { iPos = oTargetGrid.getContent().length; } var oConditionGrid = new Grid({ width: "100%", defaultSpan: "L12 M12 S12", hSpacing: 1, vSpacing: 0, containerQuery: this.getContainerQuery() }).data("_key", sKey); oConditionGrid.addStyleClass("sapUiRespGridOverflowHidden"); /* eslint-disable no-loop-func */ for (var iField in this._aConditionsFields) { var oControl; var field = this._aConditionsFields[iField]; switch (field["Control"]) { case "CheckBox": // the CheckBox is not visible and only used internal to validate if a condition is // filled correct. oControl = new CheckBox({ enabled: false, layoutData: new GridData({ span: field["Span" + this._sConditionType] }) }); this._setLayoutVisible(oControl, false); if (field["ID"] === "showIfGrouped") { oControl.setEnabled(true); oControl.setText(field["Label"]); oControl.attachSelect(function() { that._changeField(oConditionGrid); }); oControl.setSelected(oConditionGridData ? oConditionGridData.showIfGrouped : true); } else { if (oConditionGridData) { oControl.setSelected(true); oControl.setEnabled(true); } } break; case "ComboBox": if (field["ID"] === "keyField") { oControl = new ComboBox({ // before we used the new sap.m.Select control width: "100%", ariaLabelledBy: this._oInvisibleTextField }); var fOriginalKey = oControl.setSelectedKey.bind(oControl); oControl.setSelectedKey = function(sKey) { fOriginalKey(sKey); var fValidate = that.getValidationExecutor(); if (fValidate) { fValidate(); } }; var fOriginalItem = oControl.setSelectedItem.bind(oControl); oControl.setSelectedItem = function(oItem) { fOriginalItem(oItem); var fValidate = that.getValidationExecutor(); if (fValidate) { fValidate(); } }; oControl.setLayoutData(new GridData({ span: field["Span" + this._sConditionType] })); this._fillKeyFieldListItems(oControl, this._aKeyFields); if (oControl.attachSelectionChange) { oControl.attachSelectionChange(function(oEvent) { var fValidate = that.getValidationExecutor(); if (fValidate) { fValidate(); } that._handleSelectionChangeOnKeyField(oTargetGrid, oConditionGrid); }); } if (oControl.attachChange) { oControl.attachChange(function(oEvent) { oConditionGrid.keyField.close(); that._handleChangeOnKeyField(oTargetGrid, oConditionGrid); }); } if (oControl.setSelectedItem) { if (oConditionGridData) { oControl.setSelectedKey(oConditionGridData.keyField); this._aKeyFields.forEach(function(oKeyField, index) { var key = oKeyField.key; if (key === undefined) { key = oKeyField; } if (oConditionGridData.keyField === key) { oControl.setSelectedItem(oControl.getItems()[index]); } }, this); } else { if (this.getUsePrevConditionSetting() && !this.getAutoReduceKeyFieldItems()) { // select the key from the condition above if (iPos > 0 && !sKey && bUseRowFromAbove) { //bUseRowFromAbove determines, if the default needs to be used oGrid = oTargetGrid.getContent()[iPos - 1]; if (oGrid.keyField.getSelectedKey()) { oControl.setSelectedKey(oGrid.keyField.getSelectedKey()); } else { // if no item is selected, we have to select at least the first keyFieldItem if (!oControl.getSelectedItem() && oControl.getItems().length > 0) { oControl.setSelectedItem(oControl.getItems()[0]); } } } else { this._aKeyFields.some(function(oKeyField, index) { if (oKeyField.isDefault) { oControl.setSelectedItem(oControl.getItems()[index]); return true; } if (!oControl.getSelectedItem() && oKeyField.type !== "boolean") { oControl.setSelectedItem(oControl.getItems()[index]); } }, this); // if no item is selected, we have to select at least the first keyFieldItem if (!oControl.getSelectedItem() && oControl.getItems().length > 0) { oControl.setSelectedItem(oControl.getItems()[0]); } } } else { this._aKeyFields.forEach(function(oKeyField, index) { if (oKeyField.isDefault) { oControl.setSelectedItem(oControl.getItems()[index]); } }, this); } } } } if (field["ID"] === "operation") { oControl = new Select({ width: "100%", ariaLabelledBy: this._oInvisibleTextOperator, layoutData: new GridData({ span: field["Span" + this._sConditionType] }) }); oControl.attachChange(function() { that._handleChangeOnOperationField(oTargetGrid, oConditionGrid); }); // fill some operations to the control to be able to set the selected items oConditionGrid[field["ID"]] = oControl; this._updateOperationItems(oTargetGrid, oConditionGrid); if (oConditionGridData) { var oKeyField = this._getCurrentKeyFieldItem(oConditionGrid.keyField), aOperations = this._getRelevantOperations(oKeyField), sCurrOperation = this.getCurrentOparation(oConditionGridData); aOperations.some(function(oOperation) { if (sCurrOperation === oOperation) { oControl.setSelectedKey(oOperation); return true; } }, this); } else { if (this.getUsePrevConditionSetting()) { // select the key from the condition above if (iPos > 0 && sKey === null) { var oGrid = oTargetGrid.getContent()[iPos - 1]; oControl.setSelectedKey(oGrid.operation.getSelectedKey()); } } } } // init tooltip of select control if (oControl.getSelectedItem && oControl.getSelectedItem() && oControl.getMetadata()._sUIDToken !== "box") { oControl.setTooltip(oControl.getSelectedItem().getTooltip() || oControl.getSelectedItem().getText()); } break; case "TextField": var oCurrentKeyField = this._getCurrentKeyFieldItem(oConditionGrid.keyField); oControl = this._createValueField(oCurrentKeyField, field, oConditionGrid); oControl.oTargetGrid = oTargetGrid; if (oConditionGridData && oConditionGridData[field["ID"]] !== undefined) { var vValue = oConditionGridData[field["ID"]]; if (oControl instanceof Select) { if (typeof vValue === "string") { vValue = oConditionGrid.oType.parseValue(vValue, "string"); } if (typeof vValue === "boolean") { oControl.setSelectedIndex(vValue ? 2 : 1); } } else if (vValue !== null && oConditionGrid.oType) { // In case vValue is of type string, and type is StringDate we can set the value without formatting. if (typeof vValue === "string" && oConditionGrid.oType.getName() === "sap.ui.comp.odata.type.StringDate") { oControl.setValue(vValue); } else { // In case vValue is of type string, we try to convert it into the type based format. if (typeof vValue === "string" && ["String", "sap.ui.model.odata.type.String", "sap.ui.model.odata.type.Decimal"].indexOf(oConditionGrid.oType.getName()) == -1) { try { vValue = oConditionGrid.oType.parseValue(vValue, "string"); oControl.setValue(oConditionGrid.oType.formatValue(vValue, "string")); } catch (err) { Log.error("sap.m.P13nConditionPanel", "Value '" + vValue + "' does not have the expected type format for " + oConditionGrid.oType.getName() + ".parseValue()"); } } else { oControl.setValue(oConditionGrid.oType.formatValue(vValue, "string")); } } } else { oControl.setValue(vValue); } } break; case "Label": oControl = new Label({ text: field["Text"] + ":", visible: this.getShowLabel(), layoutData: new GridData({ span: field["Span" + this._sConditionType] }) }).addStyleClass("conditionLabel"); oControl.oTargetGrid = oTargetGrid; break; } oConditionGrid[field["ID"]] = oControl; oConditionGrid.addContent(oControl); } /* eslint-enable no-loop-func */ this._addButtons(oConditionGrid, oTargetGrid); // Add the new create condition oTargetGrid.insertContent(oConditionGrid, iPos); // update Operations for all conditions this._updateOperationItems(oTargetGrid, oConditionGrid); this._changeOperationValueFields(oTargetGrid, oConditionGrid); // disable fields if the selectedKeyField value is none this._updateAllConditionsEnableStates(); // update the add/remove buttons visibility this._updateConditionButtons(oTargetGrid); if (this.getAutoReduceKeyFieldItems()) { this._updateKeyFieldItems(oTargetGrid, false); } if (this._sLayoutMode) { this._updateLayout({ name: this._sLayoutMode }); } if (oConditionGridData) { var sConditionText = this._getFormatedConditionText(oConditionGridData.operation, oConditionGridData.value1, oConditionGridData.value2, oConditionGridData.exclude, oConditionGridData.keyField, oConditionGridData.showIfGrouped); oConditionGridData._oGrid = oConditionGrid; oConditionGridData.value = sConditionText; this._oConditionsMap[sKey] = oConditionGridData; } var sOperation = oConditionGrid.operation.getSelectedKey(); // in case of a BT and a Date type try to set the minDate/maxDate for the From/To value datepicker if (sOperation === "BT" && oConditionGrid.value1.setMinDate && oConditionGrid.value2.setMaxDate) { var oValue1 = oConditionGrid.value1.getDateValue(); var oValue2 = oConditionGrid.value2.getDateValue(); this._updateMinMaxDate(oConditionGrid, oValue1, oValue2); } else { this._updateMinMaxDate(oConditionGrid, null, null); } return oConditionGrid; }; /** * press handler for the remove Condition buttons * * @private * @param {sap.ui.layout.Grid} oTargetGrid the main grid * @param {sap.ui.layout.Grid} oConditionGrid from where the Remove is triggered */ P13nConditionPanel.prototype._handleRemoveCondition = function(oTargetGrid, oConditionGrid) { // search index of the condition grid to set the focus later to the previous condition var idx = oTargetGrid.getContent().indexOf(oConditionGrid); this._removeCondition(oTargetGrid, oConditionGrid); if (this.getAutoReduceKeyFieldItems()) { this._updateKeyFieldItems(oTargetGrid, false); } // set the focus on the remove button of the newly added condition if (idx >= 0) { idx = Math.min(idx, oTargetGrid.getContent().length - 1); var oConditionGrid = oTargetGrid.getContent()[idx]; setTimeout(function() { oConditionGrid.remove.focus(); }); } this._updatePaginatorToolbar(); }; /** * press handler for the add condition buttons * * @private * @param {sap.ui.layout.Grid} oTargetGrid the main grid * @param {sap.ui.layout.Grid} oSourceConditionGrid from where the Add is triggered * @param {boolean} bUseRowFromAbove use the key from the row above for creating a new row */ P13nConditionPanel.prototype._handleAddCondition = function(oTargetGrid, oSourceConditionGrid, bUseRowFromAbove) { var iPos = oTargetGrid.getContent().indexOf(oSourceConditionGrid); var oConditionGrid = this._createConditionRow(oTargetGrid, undefined, null, iPos + 1, bUseRowFromAbove); this._changeField(oConditionGrid); // set the focus in a fields of the newly added condition setTimeout(function() { if (oConditionGrid.keyField.getVisible()) { oConditionGrid.keyField.focus(); return; } if (oConditionGrid.operation.getVisible()) { oConditionGrid.operation.focus(); } }); this._updatePaginatorToolbar(); }; /** * returns the selectedKeyFields item from the KeyField control. * * @private * @param {sap.ui.core.Control} oKeyFieldCtrl the Select/ComboBox * @returns {object} the selected Keyfields object */ P13nConditionPanel.prototype._getCurrentKeyFieldItem = function(oKeyFieldCtrl) { if (oKeyFieldCtrl.getSelectedKey && oKeyFieldCtrl.getSelectedKey()) { var sKey = oKeyFieldCtrl.getSelectedKey(); var aItems = this._aKeyFields; for (var iItem in aItems) { var oItem = aItems[iItem]; if (oItem.key === sKey) { return oItem; } } } return null; }; /** * creates a new control for the condition value1 and value2 field. Control can be an Input or DatePicker * * @private * @param {object} oCurrentKeyField object of the current selected KeyField which contains type of the column ("string", "date", "time", "numeric" or "boolean") and * a maxLength information * @param {object} oFieldInfo * @param {sap.ui.layout.Grid} oConditionGrid which should contain the new created field * @returns {sap.ui.core.Control} the created control instance either Input or DatePicker */ P13nConditionPanel.prototype._createValueField = function(oCurrentKeyField, oFieldInfo, oConditionGrid) { var oControl; var sCtrlType; var that = this; var params = { value: oFieldInfo["Value"], width: "100%", placeholder: oFieldInfo["Label"], change: function(oEvent) { that._validateAndFormatFieldValue(oEvent); that._changeField(oConditionGrid, oEvent); }, layoutData: new GridData({ span: oFieldInfo["Span" + this._sConditionType] }) }; if (oCurrentKeyField && oCurrentKeyField.typeInstance) { var oType = oCurrentKeyField.typeInstance; sCtrlType = this._findConfig(oType, "ctrl"); // use the DatePicker when type is sap.ui.model.odata.type.DateTime and displayFormat = Date if (sCtrlType === "DateTimePicker" && oType.getMetadata().getName() === "sap.ui.model.odata.type.DateTime") { if (!(oType.oConstraints && oType.oConstraints.isDateOnly)) { Log.error("sap.m.P13nConditionPanel", "sap.ui.model.odata.type.DateTime without displayFormat = Date is not supported!"); oType.oConstraints = Object.assign({}, oType.oConstraints, { isDateOnly : true }); } sCtrlType = "DatePicker"; } //var aOperators = this._findConfig(oType, "operators"); oConditionGrid.oType = oType; if (sCtrlType == "select") { var aItems = []; var aValues = oCurrentKeyField.values || this._oTypeValues[sCtrlType] || [ "", oType.formatValue(false, "string"), oType.formatValue(true, "string") ]; aValues.forEach(function(oValue, index) { aItems.push(new Item({ key: index.toString(), text: oValue.toString() })); }); params = { width: "100%", items: aItem