UNPKG

@openui5/sap.m

Version:

OpenUI5 UI Library sap.m

633 lines (543 loc) 19.6 kB
/*! * OpenUI5 * (c) Copyright 2009-2023 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ // Provides control sap.m.Column. sap.ui.define([ './library', 'sap/ui/core/Element', 'sap/ui/core/Renderer', 'sap/ui/core/library', 'sap/ui/Device', "sap/ui/core/InvisibleText" ], function(library, Element, Renderer, coreLibrary, Device, InvisibleText) { "use strict"; // shortcut for sap.m.PopinDisplay var PopinDisplay = library.PopinDisplay; // shortcut for sap.ui.core.VerticalAlign var VerticalAlign = coreLibrary.VerticalAlign; // shortcut for sap.ui.core.TextAlign var TextAlign = coreLibrary.TextAlign; // shortcut for sap.ui.core.SortOrder var SortOrder = coreLibrary.SortOrder; /** * Constructor for a new Column. * * @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 <code>sap.m.Column</code> allows to define column specific properties that will be applied when rendering the <code>sap.m.Table</code>. * * See section "{@link topic:6f778a805bc3453dbb66e246d8271839 Defining Column Width}" * in the documentation to understand how to define the <code>width</code> property of the <code>sap.m.Column</code> to render a <code>sap.m.Table</code> control properly. * @extends sap.ui.core.Element * * @author SAP SE * @version 1.117.4 * * @constructor * @public * @since 1.12 * @alias sap.m.Column */ var Column = Element.extend("sap.m.Column", /** @lends sap.m.Column.prototype */ { metadata : { library : "sap.m", properties : { /** * Defines the width of the column. If you leave it empty then this column covers the remaining space. * <b>Note:</b> When setting <code>autoPopinMode=true</code> on the table, the columns with a fixed width must * either be in px, rem, or em as the table internally calculates the <code>minScreenWidth</code> property for the column. * If a column has a fixed width, then this width is used to calculate the <code>minScreenWidth</code> for the * <code>autoPopinMode</code>. * If a column has a flexible width, such as % or auto, the <code>autoPopinWidth</code> property is used * to calculate the <code>minScreenWidth</code>. */ width : {type : "sap.ui.core.CSSSize", group : "Dimension", defaultValue : null}, /** * Defines the horizontal alignment of the column content. * * <b>Note:</b> Text controls with a <code>textAlign</code> property inherits the horizontal alignment. */ hAlign : {type : "sap.ui.core.TextAlign", group : "Appearance", defaultValue : TextAlign.Begin}, /** * Defines the vertical alignment of the cells in a column. * This property does not affect the vertical alignment of header and footer. */ vAlign : {type : "sap.ui.core.VerticalAlign", group : "Appearance", defaultValue : VerticalAlign.Inherit}, /** * CSS class name for column contents(header, cells and footer of column). This property can be used for different column styling. If column is shown as pop-in then this class name is applied to related pop-in row. */ styleClass : {type : "string", group : "Appearance", defaultValue : null}, /** * Specifies whether or not the column is visible. Invisible columns are not rendered. */ visible : {type : "boolean", group : "Appearance", defaultValue : true}, /** * Defines the minimum screen width to show or hide this column. By default column is always shown. * The responsive behavior of the <code>sap.m.Table</code> is determined by this property. As an example by setting <code>minScreenWidth</code> property to "40em" (or "640px" or "Tablet") shows this column on tablet (and desktop) but hides on mobile. * As you can give specific CSS sizes (e.g: "480px" or "40em"), you can also use the {@link sap.m.ScreenSize} enumeration (e.g: "Phone", "Tablet", "Desktop", "Small", "Medium", "Large", ....). * Please also see <code>demandPopin</code> property for further responsive design options. * <b>Note:</b> This property gets overwritten if the <code>sap.m.Table</code> control * is configured with <code>autoPopinMode=true</code>. * See {@link sap.m.Table#getAutoPopinMode} */ minScreenWidth : {type : "string", group : "Behavior", defaultValue : null}, /** * According to your minScreenWidth settings, the column can be hidden in different screen sizes. * Setting this property to true, shows this column as pop-in instead of hiding it. * <b>Note:</b> This property gets overwritten if the <code>sap.m.Table</code> control * is configured with <code>autoPopinMode=true</code>. * See {@link sap.m.Table#getAutoPopinMode} */ demandPopin : {type : "boolean", group : "Behavior", defaultValue : false}, /** * Horizontal alignment of the pop-in content. Available alignment settings are "Begin", "Center", "End", "Left", and "Right". * * <b>Note:</b> Controls with a text align do not inherit the horizontal alignment. * @deprecated Since version 1.14. * Use popinDisplay property instead. */ popinHAlign : {type : "sap.ui.core.TextAlign", group : "Appearance", defaultValue : TextAlign.Begin, deprecated: true}, /** * Defines enumerated display options for the pop-in. * @since 1.13.2 */ popinDisplay : {type : "sap.m.PopinDisplay", group : "Appearance", defaultValue : PopinDisplay.Block}, /** * Set <code>true</code> to merge repeating/duplicate cells into one cell block. See <code>mergeFunctionName</code> property to customize. * * <b>Note:</b> * Merging only happens when rendering the <code>sap.m.Table</code> control, subsequent changes on the cell or item do not have any * effect on the merged state of the cells, therefore this feature should not be used together with two-way binding. * This property is ignored if any column is configured to be shown as a pop-in. * Don't set this property for cells for which the content provides a user interaction, such as <code>sap.m.Link</code>. * * @since 1.16 */ mergeDuplicates : {type : "boolean", group : "Behavior", defaultValue : false}, /** * Defines the control serialization function if <code>mergeDuplicates</code> property is set to <code>true</code>. The control itself uses this function to compare values of two repeating cells. * Default value "getText" is suitable for <code>sap.m.Label</code> and <code>sap.m.Text</code> controls but for the <code>sap.ui.core.Icon</code> control "getSrc" function should be used to merge icons. * <b>Note:</b> You can pass one string parameter to given function after "#" sign. e.g. "data#myparameter" * @since 1.16 */ mergeFunctionName : {type : "string", group : "Misc", defaultValue : 'getText'}, /** * Defines if a column is sorted by setting the sort indicator for this column. * * <b>Note:</b> Defining this property does not trigger the sorting. * @since 1.61 */ sortIndicator : {type : "sap.ui.core.SortOrder", group : "Appearance", defaultValue : SortOrder.None}, /** * Defines the column importance. * * If the <code>sap.m.Table</code> control is configured with <code>autoPopinMode=true</code>, * then the column importance is taken into consideration for calculating the <code>minScreenWidth</code> * property and for setting the <code>demandPopin</code> property of the column. * See {@link sap.m.Table#getAutoPopinMode} * * @since 1.76 */ importance : {type : "sap.ui.core.Priority", group : "Behavior", defaultValue : "None"}, /** * Defines the auto pop-in width for the column. * * If the <code>sap.m.Table</code> control is configured with <code>autoPopinMode=true</code>, * then the <code>autoPopinWidth</code> property is used to calculate the <code>minScreenWidth</code> * property of the column in case a fixed width is not set for the column. * See {@link sap.m.Column#getWidth} and {@link sap.m.Table#getAutoPopinMode}. * <b>Note:</b> A float value is set for the <code>autoPopinWidth</code> property * which is internally treated as a rem value. * * @since 1.76 */ autoPopinWidth : {type : "float", group : "Behavior", defaultValue : 8} }, defaultAggregation : "header", aggregations : { /** * Control to be displayed in the column header. */ header : {type : "sap.ui.core.Control", multiple : false}, /** * Control to be displayed in the column footer. */ footer : {type : "sap.ui.core.Control", multiple : false} }, associations: { /** * Provides a menu that is used by the column. * The given menu has to follow the same pattern as the <code>sap.ui.core.IColumnHeaderMenu</code> interface. * * @since 1.98.0 */ headerMenu: {type: "sap.ui.core.IColumnHeaderMenu", multiple: false} }, designtime: "sap/m/designtime/Column.designtime" }}); // default index Column.prototype._index = -1; // default media value Column.prototype._media = null; // default forced column value Column.prototype._bForcedColumn = false; Column.prototype.exit = function() { this._clearMedia(); }; Column.prototype.setParent = function(oParent) { Element.prototype.setParent.apply(this, arguments); if (!oParent) { delete this._initialOrder; } return this; }; Column.prototype.getTable = function() { var oParent = this.getParent(); if (oParent && oParent.isA("sap.m.Table")) { return oParent; } }; Column.prototype.informTable = function(sEvent, vParam1, vParam2) { var oTable = this.getTable(); if (oTable) { var sMethod = "onColumn" + sEvent; if (oTable[sMethod]) { oTable[sMethod](this, vParam1, vParam2); } } }; Column.prototype.ontouchstart = function(oEvent) { this._bTouchStartMarked = oEvent.isMarked(); }; Column.prototype.ontap = function(oEvent) { if (!this._bTouchStartMarked && !oEvent.isMarked()) { this.informTable("Press"); } }; Column.prototype.onsapspace = function(oEvent) { if (oEvent.srcControl === this) { this.informTable("Press"); oEvent.preventDefault(); } }; Column.prototype.onsapenter = Column.prototype.onsapspace; Column.prototype.oncontextmenu = function (oEvent) { var oMenu = this._getHeaderMenuInstance(); if (oMenu) { oMenu.openBy(this); oEvent.preventDefault(); } }; Column.prototype.invalidate = function() { var oParent = this.getParent(); if (oParent && oParent.bOutput) { Element.prototype.invalidate.apply(this, arguments); } }; Column.prototype._clearMedia = function() { if (this._media && this._minWidth) { this._detachMediaContainerWidthChange(this._notifyResize, this, this.getId()); Device.media.removeRangeSet(this.getId()); this._media = null; } }; Column.prototype._addMedia = function() { delete this._bShouldAddMedia; if (this._minWidth) { Device.media.initRangeSet(this.getId(), [parseFloat(this._minWidth)]); this._attachMediaContainerWidthChange(this._notifyResize, this, this.getId()); this._media = this._getCurrentMediaContainerRange(this.getId()); if (this._media) { this._media.matches = !!this._media.from; } } }; /** * Notify table to re-render * * @private */ Column.prototype._notifyResize = function(oMedia) { // do nothing if media did not change if (this._media.from === oMedia.from) { return; } // keep media info this._media = oMedia; this._media.matches = !!oMedia.from; if (this.getVisible()) { this.informTable("Resize"); } }; Column.prototype._validateMinWidth = function(sWidth) { if (!sWidth) { return; } if (Object.prototype.toString.call(sWidth) != "[object String]") { throw new Error('expected string for property "minScreenWidth" of ' + this); } if (Object.keys(library.ScreenSizes).indexOf(sWidth.toLowerCase()) != -1) { return; } if (!/^\d+(\.\d+)?(px|em|rem)$/i.test(sWidth)) { throw new Error('invalid CSS size("px", "em", "rem" required) or sap.m.ScreenSize enumeration for property "minScreenWidth" of ' + this); } }; /** * Returns CSS alignment according to column hAlign setting or given parameter * for Begin/End values checks the locale settings * * @param {string} [sAlign] TextAlign enumeration * @return {string} left|center|right * @protected */ Column.prototype.getCssAlign = function(sAlign) { sAlign = sAlign || this.getHAlign(); if (sAlign === TextAlign.Begin || sAlign === TextAlign.End || sAlign === TextAlign.Initial) { sAlign = Renderer.getTextAlign(sAlign); } return sAlign.toLowerCase(); }; /** * Sets the visible column index * Negative index values can be used to clear * * @param {int} nIndex index of the visible column * @protected */ Column.prototype.setIndex = function(nIndex) { this._index = +nIndex; }; /** * Gets the rendering index of the column * * @protected */ Column.prototype.getIndex = function() { return this._index; }; /** * Sets the order of the column * Does not do the visual effect * Table should be invalidate to re-render * * @param {int} nOrder order of the column * @protected */ Column.prototype.setOrder = function(nOrder) { this._order = +nOrder; }; /** * Gets the order of the column * * @returns {int} nOrder order of the column * @protected */ Column.prototype.getOrder = function() { return this.hasOwnProperty("_order") ? this._order : this.getInitialOrder(); }; /** * Sets the initial order of the column * * @param {int} nOrder initial order of the column * @protected */ Column.prototype.setInitialOrder = function(nOrder) { this._initialOrder = +nOrder; }; /** * Gets the initial order of the column * * @returns {int} initial order of the column * @protected */ Column.prototype.getInitialOrder = function() { if (this.hasOwnProperty("_initialOrder")) { return this._initialOrder; } var oTable = this.getTable(); if (!oTable) { return -1; } return oTable.indexOfColumn(this); }; // sets the internals for the minScreenWidth property Column.prototype._setMinScreenWidth = function(sWidth) { // initialize this._clearMedia(); this._minWidth = 0; if (sWidth) { // check given width is known screen-size sWidth = sWidth.toLowerCase(); var sPredefinedWidth = library.ScreenSizes[sWidth]; if (sPredefinedWidth) { this._minWidth = sPredefinedWidth + "px"; } else if (sWidth.endsWith("px")) { this._minWidth = sWidth; } else { var fBaseFontSize = parseFloat(library.BaseFontSize); this._minWidth = parseFloat(sWidth) * fBaseFontSize + "px"; } var oTable = this.getTable(); if (oTable && oTable.isActive()) { this._addMedia(); } else { this._bShouldAddMedia = true; } } }; /* * Decides if we need media query or not according to given settings * Checks the given width is known screen size */ Column.prototype.setMinScreenWidth = function(sWidth) { sWidth = sWidth || ""; // check if setting the old value if (sWidth == this.getMinScreenWidth()) { return this; } // first validate the value this._validateMinWidth(sWidth); // set internal values this._setMinScreenWidth(sWidth); return this.setProperty("minScreenWidth", sWidth); }; Column.prototype.setSortIndicator = function(sSortIndicator) { this.setProperty("sortIndicator", sSortIndicator, true); this.$().attr("aria-sort", this.getSortIndicator().toLowerCase()); return this; }; /** * Determines whether the column is shown as pop-in or not * * @protected */ Column.prototype.isPopin = function() { if (!this.getDemandPopin()) { return false; } var oTable = this.getTable(); if (oTable) { var aHiddenInPopin = oTable.getHiddenInPopin() || []; var bHideColumn = aHiddenInPopin.includes(this.getImportance()); if (bHideColumn) { return false; } } return this.isHidden(); }; /** * Determines whether the column is hidden without being in the popin area * * @protected */ Column.prototype.isHidden = function() { return (this._media) ? !this._media.matches : false; }; /** * Sets the last value of the column if mergeDuplicates property is true * * @param {any} value Any Value * @returns {this} * @since 1.16 * @protected */ Column.prototype.setLastValue = function(value) { this._lastValue = value; return this; }; /** * Clears the last value of the column if mergeDuplicates property is true * * @returns {this} * @since 1.20.4 * @protected */ Column.prototype.clearLastValue = function() { return this.setLastValue(NaN); }; /** * Gets the last value of the column * * @since 1.16 * @protected */ Column.prototype.getLastValue = function() { return this._lastValue; }; /** * Gets called from the Table when the all items are removed * * @since 1.16 * @protected */ Column.prototype.onItemsRemoved = function() { this.clearLastValue(); }; Column.prototype.onTableRendering = function() { this.clearLastValue(); if (this._bShouldAddMedia) { this._addMedia(); } }; // when the popover opens and later closed, the focus is lost // hence overwriting the getFocusDomRef to restore the focus on the active column header Column.prototype.getFocusDomRef = function() { var oParent = this.getParent(); if (oParent && (oParent.bActiveHeaders || oParent.bFocusableHeaders || this.getHeaderMenu())) { var oColumnDomRef = this.getDomRef(); if (oColumnDomRef) { return oColumnDomRef.firstChild; } } return Element.prototype.getFocusDomRef.apply(this, arguments); }; // returns the minScreenWidth property in pixel as integer Column.prototype.getCalculatedMinScreenWidth = function() { return parseInt(this._minWidth) || 0; }; // forces the column not to be shown as a popin Column.prototype.setForcedColumn = function(bForcedColumn) { if (this._bForcedColumn == bForcedColumn) { return; } this._bForcedColumn = bForcedColumn; this._setMinScreenWidth(bForcedColumn ? "" : this.getMinScreenWidth()); }; /** * Returns the column header menu instance that this column is associated with via the <code>headerMenu</code> association. * * @returns {sap.ui.core.IColumnHeaderMenu | undefined} The column header menu instance * @private */ Column.prototype._getHeaderMenuInstance = function () { return sap.ui.getCore().byId(this.getHeaderMenu()); }; Column.prototype.setHeader = function (oControl) { var oOldHeader = this.getHeader(); if (oOldHeader && oOldHeader.isA("sap.m.Label")) { oOldHeader.detachEvent("_change", this._onLabelPropertyChange, this); oOldHeader.setIsInColumnHeaderContext(false); } this.setAggregation("header", oControl); var oNewHeader = this.getHeader(); if (oNewHeader && oNewHeader.isA("sap.m.Label")) { oNewHeader.attachEvent("_change", this._onLabelPropertyChange, this); oNewHeader.setIsInColumnHeaderContext(true); } return this; }; Column.prototype._onLabelPropertyChange = function (oEvent) { if (oEvent.getParameter("name") != "required") { return; } if (this.getTable().bActiveHeaders || this._getHeaderMenuInstance()) { this.$("ah")[oEvent.getSource().getRequired() ? "addAriaDescribedBy" : "removeAriaDescribedBy"](InvisibleText.getStaticId("sap.m", "CONTROL_IN_COLUMN_REQUIRED")); } }; return Column; });