UNPKG

@openui5/sap.m

Version:

OpenUI5 UI Library sap.m

432 lines (366 loc) 14.3 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.Panel. sap.ui.define([ './library', 'sap/ui/core/Configuration', 'sap/ui/core/Control', 'sap/ui/core/IconPool', 'sap/ui/Device', './PanelRenderer', 'sap/m/Button' ], function(library, Configuration, Control, IconPool, Device, PanelRenderer, Button) { "use strict"; // shortcut for sap.m.PanelAccessibleRole var PanelAccessibleRole = library.PanelAccessibleRole; // shortcut for sap.m.BackgroundDesign var BackgroundDesign = library.BackgroundDesign; // shortcut for sap.m.ButtonType var ButtonType = library.ButtonType; /** * Constructor for a new Panel. * * @param {string} [sId] ID for the new control, generated automatically if no ID is given * @param {object} [mSettings] Initial settings for the new control * * @class * A container control which has a header and content. * <h3>Overview</h3> * The panel is a container for grouping and displaying information. It can be collapsed to save space on the screen. * <h4>Guidelines:</h4> * <ul> * <li>Nesting two or more panels is not recommended.</li> * <li>Do not stack too many panels on one page.</li> * </ul> * <h3>Structure</h3> * A panel consists of a title bar with a header text or header toolbar, an info toolbar (optional), and a content area. * Using the <code>headerToolbar</code> aggregation, you can add a toolbar with any toolbar content (i.e. custom buttons, spacers, titles) inside the title bar. * * There are two types of panels: fixed and expandable. Expendable panels are enabled by the <code>expandable</code> property. * Furthermore you can define an expand animation with the property <code>expandAnimation</code>. * <h3>Usage</h3> * <h4>When to use:</h4> * <ul> * <li>You need to group or display information and want to give users the option of hiding this information.</li> * <li>You want to show additional information on demand (for example, a panel could show optional input fields for an advanced search).</li> * <li>You want to create a panel with controls that do not require user interaction and are not part of a form. Depending on the usage, change the <code>accessibleRole</code> property from the default <code>{@link sap.m.PanelAccessibleRole Form}</code> to <code>{@link sap.m.PanelAccessibleRole Region}</code> or <code>{@link sap.m.PanelAccessibleRole Complementary}</code>.</li> * </ul> * <h3>Responsive Behavior</h3> * <ul> * <li>If the width of the panel is set to 100% (default), the panel and its children are resized responsively, depending on its parent container.</li> * <li>If the panel has a fixed defined height, it will take up the space, even if the panel is collapsed.</li> * <li>When the panel is expandable, an arrow icon (pointing to the right) appears in front of the header.</li> * <li>When the animation is activated, expand/collapse uses a smooth animation to open or close the content area.</li> * <li>When the panel expands/collapses, the arrow icon rotates 90 degrees clockwise/counter-clockwise.</li> * <li>When the height uses the default property <code>auto</code>, the height of the content area is automatically adjusted to match the height of its content.</li> * <li>When the height of the panel is set to a fixed size, the content area can be scrolled through.</li> * </ul> * @extends sap.ui.core.Control * * @author SAP SE * @version 1.117.4 * * @constructor * @public * @since 1.16 * @alias sap.m.Panel * @see {@link fiori:https://experience.sap.com/fiori-design-web/panel/ Panel} */ var Panel = Control.extend("sap.m.Panel", /** @lends sap.m.Panel.prototype */ { metadata: { library: "sap.m", properties: { /** * This property is used to set the header text of the Panel. * The "headerText" is visible in both expanded and collapsed state. * Note: This property is overwritten by the "headerToolbar" aggregation. */ headerText: {type: "string", group: "Data", defaultValue: ""}, /** * Determines the Panel width. */ width: {type: "sap.ui.core.CSSSize", group: "Appearance", defaultValue: "100%"}, /** * Determines the Panel height. */ height: {type: "sap.ui.core.CSSSize", group: "Appearance", defaultValue: "auto"}, /** * Specifies whether the control is expandable. * This allows for collapsing or expanding the infoToolbar (if available) and content of the Panel. * Note: If expandable is set to false, the Panel will always be rendered expanded. * @since 1.22 */ expandable: {type: "boolean", group: "Appearance", defaultValue: false}, /** * Indicates whether the Panel is expanded or not. * If expanded is set to true, then both the infoToolbar (if available) and the content are rendered. * If expanded is set to false, then only the headerText or headerToolbar is rendered. * @since 1.22 */ expanded: {type: "boolean", group: "Appearance", defaultValue: false}, /** * Indicates whether the transition between the expanded and the collapsed state of the control is animated. * By default the animation is enabled. * @since 1.26 */ expandAnimation: {type: "boolean", group: "Behavior", defaultValue: true}, /** * This property is used to set the background color of the Panel. * Depending on the theme you can change the state of the background from "Solid" over "Translucent" to "Transparent". * @since 1.30 */ backgroundDesign: {type: "sap.m.BackgroundDesign", group: "Appearance", defaultValue: BackgroundDesign.Translucent}, /** * This property is used to set the accessible aria role of the Panel. * Depending on the usage you can change the role from the default <code>Form</code> to <code>Region</code> or <code>Complementary</code>. * @since 1.46 */ accessibleRole: {type: "sap.m.PanelAccessibleRole", group: "Accessibility", defaultValue: PanelAccessibleRole.Form}, /** * Indicates whether the Panel header is sticky or not. * If stickyHeader is set to true, then whenever you scroll the content or * the application, the header of the panel will be always visible and * a solid color will be used for its design. * @since 1.117 */ stickyHeader: {type: "boolean", group: "Appearance", defaultValue: false} }, defaultAggregation: "content", aggregations: { /** * Determines the content of the Panel. * The content will be visible only when the Panel is expanded. */ content: {type: "sap.ui.core.Control", multiple: true, singularName: "content"}, /** * This aggregation allows the use of a custom Toolbar as header for the Panel. * The "headerToolbar" is visible in both expanded and collapsed state. * Use it when you want to add extra controls for user interactions in the header. * Note: This aggregation overwrites "headerText" property. * @since 1.16 */ headerToolbar: {type: "sap.m.Toolbar", multiple: false}, /** * This aggregation allows the use of a custom Toolbar as information bar for the Panel. * The "infoToolbar" is placed below the header and is visible only in expanded state. * Use it when you want to show extra information to the user. * @since 1.16 */ infoToolbar: {type: "sap.m.Toolbar", multiple: false} }, events: { /** * Indicates that the panel will expand or collapse. * @since 1.22 */ expand: { parameters: { /** * If the panel will expand, this is true. * If the panel will collapse, this is false. */ expand: {type : "boolean"}, /** * Identifies whether the event is triggered by an user interaction or by calling setExpanded. * @since 1.50 */ triggeredByInteraction: {type: "boolean"} } } }, dnd: { draggable: true, droppable: true }, designtime: "sap/m/designtime/Panel.designtime" }, renderer: PanelRenderer }); Panel.prototype.init = function () { // identifies whether the last expand action is triggered by a user interaction or by calling setExpanded setter this._bInteractiveExpand = false; this.data("sap-ui-fastnavgroup", "true", true); // Define group for F6 handling }; Panel.prototype.onThemeChanged = function () { this._setContentHeight(); }; /** * Sets the expanded property of the control. * @param {boolean} bExpanded Defines whether control is expanded or not. * @returns {this} Pointer to the control instance to allow method chaining. * @public */ Panel.prototype.setExpanded = function (bExpanded) { var that = this; if (bExpanded === this.getExpanded()) { return this; } this.setProperty("expanded", bExpanded, true); if (!this.getExpandable()) { return this; } this._toggleExpandCollapse(function () { // invalidate once the animation is over so rerendering could be smoоth that.invalidate(); }); this._toggleButtonIcon(bExpanded); this.fireExpand({ expand: bExpanded, triggeredByInteraction: this._bInteractiveExpand }); this._bInteractiveExpand = false; return this; }; /** * Called before the control is rendered. * * @private */ Panel.prototype.onBeforeRendering = function () { if (this.getExpandable() && !this._oExpandButton) { this._oExpandButton = this._createExpandButton(); } if (Configuration.getAccessibility()) { this.$().attr("role", this.getAccessibleRole().toLowerCase()); } }; Panel.prototype.onAfterRendering = function () { var $this = this.$(), oPanelContent = this.getDomRef("content"), sHeight, oDomRef = this.getDomRef(); if (oDomRef) { oDomRef.style.width = this.getWidth(); sHeight = this.getHeight(); oDomRef.style.height = sHeight; if (parseFloat(sHeight) != 0) { oDomRef.querySelector(".sapMPanelContent").style.height = sHeight; } } this._setContentHeight(); if (this.getExpandable()) { this.getHeaderToolbar() && oPanelContent && this._oExpandButton.$().attr("aria-controls", oPanelContent.id); if (!this.getExpanded()) { // hide those parts which are collapsible (w/o animation, otherwise initial loading doesn't look good ...) $this.children(".sapMPanelExpandablePart").css("display", "none"); } } }; /** * Called when the <code>Panel</code> is clicked/tapped. * * @param {jQuery.Event} oEvent - the keyboard event. * @private */ Panel.prototype.ontap = function (oEvent) { var oDomRef = this.getDomRef(), oWrapperDomRef = oDomRef && oDomRef.querySelector(".sapMPanelWrappingDiv"); if (!this.getExpandable() || this.getHeaderToolbar() || !oWrapperDomRef) { return; } if (oWrapperDomRef.contains(oEvent.target)) { this._bInteractiveExpand = true; this.setExpanded(!this.getExpanded()); } }; /** * Event handler called when the SPACE key is pressed. * * @param {jQuery.Event} oEvent The event object. * @private */ Panel.prototype.onsapspace = function(oEvent) { var aHeaderTargets = [ this.getDomRef().querySelector(".sapMPanelWrappingDiv"), this.getDomRef("expandButton") ]; if (aHeaderTargets.includes(oEvent.target)) { // prevent browser scrolling oEvent.preventDefault(); } this.ontap(oEvent); }; /** * Event handler called when the ENTER key is pressed. * * @param {jQuery.Event} oEvent The ENTER keyboard key event object */ Panel.prototype.onsapenter = function(oEvent) { this.ontap(oEvent); }; Panel.prototype.exit = function () { if (this._oExpandButton) { this._oExpandButton.destroy(); this._oExpandButton = null; } }; Panel.prototype._createExpandButton = function () { var that = this, sIconURI = this.getExpanded() ? IconPool.getIconURI("slim-arrow-down") : IconPool.getIconURI("slim-arrow-right"), sTooltipBundleText = sap.ui.getCore().getLibraryResourceBundle("sap.m").getText("PANEL_ICON"), oButton; if (!this.getHeaderToolbar()) { return IconPool.createControlByURI({ src: sIconURI, tooltip: sTooltipBundleText }); } oButton = new Button(this.getId() + "-expandButton", { icon: sIconURI, tooltip: sTooltipBundleText, type: ButtonType.Transparent, press: function () { that._bInteractiveExpand = true; that.setExpanded(!that.getExpanded()); } }).addEventDelegate({ onAfterRendering: function() { oButton.$().attr("aria-expanded", this.getExpanded()); }.bind(this) }, this); this.addDependent(oButton); return oButton; }; Panel.prototype._toggleButtonIcon = function (bIsExpanded) { var sIconURI = bIsExpanded ? IconPool.getIconURI("slim-arrow-down") : IconPool.getIconURI("slim-arrow-right"); if (!this._oExpandButton) { return; } if (this.getHeaderToolbar()) { this._oExpandButton.setIcon(sIconURI); } else { this._oExpandButton.setSrc(sIconURI); } }; Panel.prototype._setContentHeight = function () { var sAdjustedContentHeight, thisDomRef = this.getDomRef(), oPanelContent = thisDomRef && thisDomRef.querySelector(".sapMPanelContent"); if (this.getHeight() === "auto" || !oPanelContent) { return; } // 'offsetTop' measures the vertical space occupied by siblings before this one // Earlier each previous sibling's height was calculated separately and then all height values were summed up sAdjustedContentHeight = 'calc(' + "100%" + ' - ' + oPanelContent.offsetTop + 'px)'; oPanelContent.style.height = sAdjustedContentHeight; }; Panel.prototype._toggleExpandCollapse = function (fnAnimationComplete) { var oOptions = { complete: fnAnimationComplete }; if (!this.getExpandAnimation()) { oOptions.duration = 0; } this.$().children(".sapMPanelExpandablePart").slideToggle(oOptions); }; Panel.prototype._getLabellingElementId = function () { var oHeaderToolbar = this.getHeaderToolbar(), sHeaderText = this.getHeaderText(), id = null; if (oHeaderToolbar) { id = oHeaderToolbar.getTitleId(); } else if (sHeaderText) { id = this.getId() + "-header"; } return id; }; return Panel; });