@openui5/sap.m
Version:
OpenUI5 UI Library sap.m
1,612 lines (1,411 loc) • 104 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.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