UNPKG

@openui5/sap.m

Version:

OpenUI5 UI Library sap.m

229 lines (190 loc) 8.09 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._overflowToolbarHelpers.OverflowToolbarAssociativePopover. sap.ui.define(['sap/ui/core/Element', './Popover', './OverflowToolbarAssociativePopoverControls', './OverflowToolbarAssociativePopoverRenderer', './OverflowToolbarLayoutData', 'sap/m/library'], function(Element, Popover, OverflowToolbarAssociativePopoverControls, OverflowToolbarAssociativePopoverRenderer, OverflowToolbarLayoutData, library) { "use strict"; // shortcut for sap.m.PlacementType var PlacementType = library.PlacementType; // shortcut for sap.m.OverflowToolbarPriority var OverflowToolbarPriority = library.OverflowToolbarPriority; /** * Constructor for a new OverflowToolbarAssociativePopover. * * @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 * OverflowToolbarAssociativePopover is a version of Popover that uses an association in addition to the aggregation * @extends sap.m.Popover * * @author SAP SE * @version 1.117.4 * * @constructor * @private * @since 1.30 * @alias sap.m._overflowToolbarHelpers.OverflowToolbarAssociativePopover */ var OverflowToolbarAssociativePopover = Popover.extend("sap.m._overflowToolbarHelpers.OverflowToolbarAssociativePopover", /** @lends sap.m._overflowToolbarHelpers.OverflowToolbarAssociativePopover.prototype */ { metadata : { library: "sap.m", associations : { /** * The same as content, but provided in the form of an association */ associatedContent: {type: "sap.ui.core.Control", multiple: true} } }, renderer: OverflowToolbarAssociativePopoverRenderer }); OverflowToolbarAssociativePopover.prototype.init = function() { Popover.prototype.init.apply(this, arguments); // Instantiate the helper that will manage controls entering/leaving the popover this.oControlsManager = new OverflowToolbarAssociativePopoverControls(); }; OverflowToolbarAssociativePopover.prototype.onBeforeRendering = function() { Popover.prototype.onBeforeRendering.apply(this, arguments); this.addStyleClass("sapMOTAPopover"); this.addStyleClass("sapMOverflowToolbarMenu-CTX"); }; /* Override API methods */ OverflowToolbarAssociativePopover.prototype.addAssociatedContent = function(oControl) { this.addAssociation("associatedContent",oControl, true); this._preProcessControl(oControl); return this; }; OverflowToolbarAssociativePopover.prototype.removeAssociatedContent = function(oControl) { var sResult = this.removeAssociation("associatedContent",oControl, true), oControlObject; if (sResult) { oControlObject = Element.registry.get(sResult); if (oControlObject) { this._postProcessControl(oControlObject); } } return sResult; }; /** * Use the helper to modify controls that are about to enter the popover, so that they look good there * @param oControl * @returns {*} * @private */ OverflowToolbarAssociativePopover.prototype._preProcessControl = function(oControl){ var oCtrlConfig = OverflowToolbarAssociativePopoverControls.getControlConfig(oControl), sAttachFnName; // For each event that must close the popover, attach a handler oCtrlConfig.listenForEvents.forEach(function(sEventType) { sAttachFnName = "attach" + fnCapitalize(sEventType); if (oControl[sAttachFnName]) { oControl[sAttachFnName](this._closeOnInteraction.bind(this, oControl)); } else { oControl.attachEvent(sEventType, this._closeOnInteraction.bind(this, oControl)); } }, this); // Call preprocessor function, if any if (typeof oCtrlConfig.preProcess === "function") { oCtrlConfig.preProcess.call(this.oControlsManager, oControl); } var oLayoutData = oControl.getLayoutData(); if (oLayoutData instanceof OverflowToolbarLayoutData && oLayoutData.getPriority() === OverflowToolbarPriority.Disappear) { oControl.addStyleClass("sapMOTAPHidden"); } return this; }; /** * Use the helper to restore controls that leave the popover to their previous state * @param oControl * @returns {*} * @private */ OverflowToolbarAssociativePopover.prototype._postProcessControl = function(oControl) { var oCtrlConfig = OverflowToolbarAssociativePopoverControls.getControlConfig(oControl), sDetachFnName; // For each event that must close the popover, detach the handler oCtrlConfig.listenForEvents.forEach(function(sEventType) { sDetachFnName = "detach" + fnCapitalize(sEventType); if (oControl[sDetachFnName]) { oControl[sDetachFnName](this._closeOnInteraction, this); } else { oControl.detachEvent(sEventType, this._closeOnInteraction, this); } }, this); // Call preprocessor function, if any if (typeof oCtrlConfig.postProcess === "function") { oCtrlConfig.postProcess.call(this.oControlsManager, oControl); } oControl.removeStyleClass("sapMOTAPHidden"); // It is important to explicitly destroy the control from the popover's DOM when using associations, because the toolbar will render it again and there will be a DOM duplication side effect oControl.$().remove(); return this; }; /** * Many of the controls that enter the popover attach this function to some of their interaction events, such as button click, select choose, etc... * @private */ OverflowToolbarAssociativePopover.prototype._closeOnInteraction = function(oControl) { var oLayoutData = oControl.getLayoutData(); if (!oLayoutData || !(oLayoutData instanceof OverflowToolbarLayoutData) || oLayoutData.getCloseOverflowOnInteraction()) { this.close(); } }; /** * Creates a hash of the ids of the controls in the content association, f.e. "__button1.__button2.__button3" * Useful to check if the same controls are in the popover in the same order compared to a point in the past * @returns {*|string|!Array.<T>} * @private */ OverflowToolbarAssociativePopover.prototype._getContentIdsHash = function () { return this._getAllContent().join("."); }; /** * Recalculate the margin offsets so the Popover will never cover the control that opens it. * Overrides the popovers placement rules only for PlacementType.Top * * @param {sap.m.PlacementType} sCalculatedPlacement Calculated placement of the Popover * @param {object} oPosParams used to calculate actual values for the screen margins, so the Popover will never cover the Opener control or goes outside of the viewport * @override * @private */ OverflowToolbarAssociativePopover.prototype._recalculateMargins = function (sCalculatedPlacement, oPosParams) { if (sCalculatedPlacement !== PlacementType.Top){ return Popover.prototype._recalculateMargins.apply(this, arguments); } oPosParams._fPopoverMarginBottom = oPosParams._fWindowHeight - oPosParams._$parent.offset().top + this._arrowOffset + oPosParams._fPopoverOffsetY; return oPosParams; }; /** * Returns the content from the aggregation and association combined * @returns {(Array.<T>|string|*|!Array)} * @private */ OverflowToolbarAssociativePopover.prototype._getAllContent = function () { var aAssociatedContent = this.getAssociatedContent().map(function(sId) { return Element.registry.get(sId); }); if (this.getPlacement() === PlacementType.Top) { aAssociatedContent.reverse(); } return this.getContent().concat(aAssociatedContent); }; /** * Friendly function to be used externally to get the calculated popover position, if the position is not * calculated yet, calling _calcPlacment() will force the popover to calculate it * @returns {Popover._oCalcedPos|*} */ OverflowToolbarAssociativePopover.prototype.getCurrentPosition = function() { if (!this._oCalcedPos) { this._calcPlacement(); } return this._oCalcedPos; }; function fnCapitalize(sName) { return sName.substring(0, 1).toUpperCase() + sName.substring(1); } return OverflowToolbarAssociativePopover; });