UNPKG

@openui5/sap.m

Version:

OpenUI5 UI Library sap.m

919 lines (741 loc) 29.5 kB
/*! * OpenUI5 * (c) Copyright 2026 SAP SE or an SAP affiliate company. * Licensed under the Apache License, Version 2.0 - see LICENSE.txt. */ // Provides class sap.m.Fiori20Adapter sap.ui.define([ 'sap/ui/base/Object', 'sap/ui/base/EventProvider', 'sap/ui/base/ManagedObjectObserver', 'sap/ui/Device', "sap/base/Log", "sap/ui/core/Element", "sap/ui/thirdparty/jquery" ], function(BaseObject, EventProvider, ManagedObjectObserver, Device, Log, Element, jQuery) { "use strict"; var oEventProvider = new EventProvider(), oInfoToMerge, oChangeListeners, sCurrentlyAdaptedTopNavigableViewId; /** * Static class that contains all the logic for adapting a page header * * * @class text * @version 1.146.0 * @private * @since 1.38 * @alias HeaderAdapter */ var HeaderAdapter = BaseObject.extend("HeaderAdapter", { constructor : function(oHeader, oAdaptOptions) { if (!oHeader || !oAdaptOptions) { Log.error("Cannot initialize: Invalid arguments."); return; } this._oHeader = oHeader; this._oStyledPage = null; this._oTitleInfo = null; this._oSubTitleInfo = null; this._oBackButtonInfo = null; this._oAdaptOptions = oAdaptOptions; } }); HeaderAdapter.prototype.adapt = function() { var bStylePage = this._oAdaptOptions.bStylePage, bCollapseHeader = this._oAdaptOptions.bCollapseHeader; if (bStylePage) { this._toggleStyle("sapF2Adapted", true, true /* suppress invalidate */); } this._adaptTitle(); this._adaptBackButton(); if (bCollapseHeader) { this._collapseHeader(); } // let children know if adaptation was already applied // to avoid redundant processing return this.getAdaptedContent(); }; HeaderAdapter.prototype.getAdaptedContent = function() { return { oTitleInfo: this._oTitleInfo, oSubTitleInfo: this._oSubTitleInfo, oBackButtonInfo: this._oBackButtonInfo, oStyledPage: this._oStyledPage }; }; HeaderAdapter.prototype._adaptTitle = function() { if (!HeaderAdapter._isAdaptableHeader(this._oHeader) || this._oAdaptOptions.bMoveTitle !== true) { return false; } this._oTitleInfo = this._detectTitle(); this._oSubTitleInfo = this._detectSubTitle(); var bSuccess = !!this._oTitleInfo || !!this._oSubTitleInfo; if (this._oTitleInfo) { this._oTitleInfo.oControl.toggleStyleClass("sapF2AdaptedTitle", true); } return bSuccess; }; HeaderAdapter.prototype._adaptBackButton = function() { if (!HeaderAdapter._isAdaptableHeader(this._oHeader) || this._oAdaptOptions.bHideBackButton !== true) { return false; } var bHideBackButton, bBackButtonHidden = false; this._oBackButtonInfo = this._detectBackButton(); if (this._oBackButtonInfo) { bHideBackButton = this._oBackButtonInfo.oControl.getVisible(); this._oBackButtonInfo.oControl.toggleStyleClass("sapF2AdaptedNavigation", bHideBackButton); bBackButtonHidden = true; } return bBackButtonHidden; }; HeaderAdapter.prototype._toggleStyle = function(sStyleClass, bAdd, bSuppressInvalidate) { var oPage = this._oHeader.getParent(); if (!oPage) { return; } this._oStyledPage = oPage; if (bAdd === true) { oPage.addStyleClass(sStyleClass, bSuppressInvalidate); } else if (bAdd === false) { oPage.removeStyleClass(sStyleClass, bSuppressInvalidate); } else if (bAdd === undefined) { oPage.hasStyleClass(sStyleClass) ? oPage.removeStyleClass(sStyleClass, bSuppressInvalidate) : oPage.addStyleClass(sStyleClass, bSuppressInvalidate); } }; HeaderAdapter._isAdaptableHeader = function(oHeader) { if (!oHeader || !isInstanceOf(oHeader, "sap/m/Bar")) { return false; } var oParent = oHeader.getParent(); return oParent && (isInstanceOf(oParent, "sap/m/Page") || isInstanceOf(oParent, "sap/m/MessagePage") || isInstanceOf(oParent, "sap/uxap/ObjectPageHeader")); }; HeaderAdapter.prototype._detectTitle = function() { var oTitleInfo; if (HeaderAdapter._isAdaptableHeader(this._oHeader)) { var aMiddleContent = this._oHeader.getContentMiddle(); if (aMiddleContent.length === 1 && isTextualControl(aMiddleContent[0])) { var oTitle = aMiddleContent[0]; oTitleInfo = { id: oTitle.getId(), text: oTitle.getText(), oControl: oTitle, sChangeEventId: "_change", sPropertyName: "text" }; } } return oTitleInfo; }; HeaderAdapter.prototype._detectSubTitle = function(oPage) { if (isInstanceOf(oPage, "sap/uxap/ObjectPageHeader")) { var oHeaderTitle = oPage.getHeaderTitle(); if (oHeaderTitle){ return { id: oHeaderTitle.getId(), text: oHeaderTitle.getObjectTitle(), oControl: oHeaderTitle, sChangeEventId: "_titleChange", sPropertyName: "objectTitle" }; } } }; HeaderAdapter.prototype._detectBackButton = function () { var aBeginContent, oBackButton; // Check if the header is adaptable if (!HeaderAdapter._isAdaptableHeader(this._oHeader)) { return; } aBeginContent = this._oHeader.getContentLeft(); // Check if the begin content is empty if (aBeginContent.length === 0) { return; } // Check if the first element in the begin content is a button if (!isInstanceOf(aBeginContent[0], "sap/m/Button")) { return; } // Check if the button is a navigation button, has the back icon, or is of type Back/Up if (aBeginContent[0].getId().includes("-navButton") || aBeginContent[0]._getAppliedIcon() === "sap-icon://nav-back" || aBeginContent[0].getType() === "Back" || aBeginContent[0].getType() === "Up") { oBackButton = aBeginContent[0]; // Return the back button details // eslint-disable-next-line consistent-return return { id: oBackButton.getId(), oControl: oBackButton, sChangeEventId: "_change", sPropertyName: "visible" }; } }; HeaderAdapter.prototype._collapseHeader = function() { var bTitleHidden = this._oTitleInfo, bBackButtonHidden = this._oBackButtonInfo, aBeginContent, aMiddleContent, aEndContent, bBeginContentHidden, bMiddleContentHidden, bEndContentHidden, bAllContentHidden; if (HeaderAdapter._isAdaptableHeader(this._oHeader)) { aBeginContent = this._oHeader.getContentLeft(); aMiddleContent = this._oHeader.getContentMiddle(); aEndContent = this._oHeader.getContentRight(); bBeginContentHidden = (aBeginContent.length === 1) && (isHiddenFromAPI(aBeginContent[0]) || bBackButtonHidden); bMiddleContentHidden = (aMiddleContent.length === 1) && (isHiddenFromAPI(aMiddleContent[0]) || bTitleHidden); bEndContentHidden = (aEndContent.length === 1) && isHiddenFromAPI(aEndContent[0]); bAllContentHidden = (aBeginContent.length === 0 || bBeginContentHidden) && (aMiddleContent.length === 0 || bMiddleContentHidden) && (aEndContent.length === 0 || bEndContentHidden); this._toggleStyle("sapF2CollapsedHeader", bAllContentHidden, true); } }; /** * Constructor for an sap.m.Fiori20Adapter. * * @class text * @version 1.146.0 * @private * @since 1.38 * @alias sap.m.Fiori20Adapter */ var Fiori20Adapter = BaseObject.extend("sap.m.Fiori20Adapter", {}); Fiori20Adapter.attachViewChange = function(fnListener, oListener) { oEventProvider.attachEvent("adaptedViewChange", fnListener, oListener); }; Fiori20Adapter.detachViewChange = function(fnListener, oListener) { oEventProvider.detachEvent("adaptedViewChange", fnListener, oListener); }; Fiori20Adapter.traverse = function(oComponentRoot, oAdaptOptions) { /* cache of intermediate adaptation results of the current component used in case user re-visits an already adapted view */ oInfoToMerge = { aViewTitles: {}, aViewSubTitles: {}, aViewBackButtons: {} }; oChangeListeners = {}; sCurrentlyAdaptedTopNavigableViewId = null; this._doBFS([{ oNode: oComponentRoot, oAdaptOptions: oAdaptOptions }]); var sCurrentViewId = this._getCurrentlyAdaptedTopViewId(); if (sCurrentViewId && Element.getElementById(sCurrentViewId)) { this._fireViewChange(sCurrentViewId, oAdaptOptions); } }; /** * Does breath-first search of the control tree */ Fiori20Adapter._doBFS = function(aQueue) { var oNext = aQueue.shift(); if (!oNext) { return; } var oNode = oNext.oNode, oAdaptOptions = oNext.oAdaptOptions, iSearchDepth = oAdaptOptions.iSearchDepth; oAdaptOptions = this._applyRules(oAdaptOptions, oNode); //apply semantic rules specific to controls if (!this._isAdaptationRequired(oNode, oAdaptOptions) || (iSearchDepth <= 0)) { return; } var bIsTopNavigableView = this._isTopNavigableView(oNode); if (bIsTopNavigableView) { this._setAsCurrentlyAdaptedTopViewId(oNode.getId()); } var oNodeAdaptationResult = this._processNode(oNode, oAdaptOptions); var aChildren = this._getNodeChildren(oNode), childAdaptOptions = jQuery.extend({}, oAdaptOptions, {iSearchDepth: this._updateSearchDepth(iSearchDepth, oNode)}); if (oNodeAdaptationResult) { var bTitleHidden = !!oNodeAdaptationResult.oTitleInfo, bBackButtonHidden = !!oNodeAdaptationResult.oBackButton, bPageStyled = !!oNodeAdaptationResult.oStyledPage; childAdaptOptions = jQuery.extend(childAdaptOptions, { bMoveTitle: oAdaptOptions.bMoveTitle && !bTitleHidden, bHideBackButton: oAdaptOptions.bHideBackButton && !bBackButtonHidden, bStylePage: oAdaptOptions.bStylePage && !bPageStyled }); } aChildren.forEach(function(oChild) { if (oChild) { aQueue.push({ oNode: oChild, oAdaptOptions: childAdaptOptions }); } }); this._doBFS(aQueue); // synchronous }; Fiori20Adapter._processNode = function(oControl, oAdaptOptions) { // attach listeners to re-trigger adaptation when content is added at a later stage this._attachDefferedAdaptationListeners(oControl, oAdaptOptions); if (HeaderAdapter._isAdaptableHeader(oControl)) { return this._adaptHeader(oControl, oAdaptOptions); } if (oControl.getParent() && isInstanceOf(oControl.getParent(), "sap/m/NavContainer")) { return this._getCachedViewInfoToMerge(oControl.getId()); //if already adapted in earlier navigation } }; Fiori20Adapter._attachDefferedAdaptationListeners = function(oControl, oAdaptOptions) { this._attachAdaptableContentChange(oControl, oAdaptOptions); this._attachNavigablePageChange(oControl, oAdaptOptions); if (isInstanceOf(oControl, "sap/m/Page") || isInstanceOf(oControl, "sap/ui/core/mvc/XMLView")) { this._observeAddAggregation(oControl, "content", oAdaptOptions); } if (isInstanceOf(oControl, "sap/m/NavContainer")) { this._observeRemoveAggregation(oControl, "pages", oAdaptOptions); } if ((oAdaptOptions.bLateAdaptation === true) && isInstanceOf(oControl, "sap/m/Bar")) { this._observeAddAggregation(oControl, "contentLeft", oAdaptOptions, oControl); this._observeAddAggregation(oControl, "contentMiddle", oAdaptOptions, oControl); this._observeAddAggregation(oControl, "contentRight", oAdaptOptions, oControl); } // special case if (isInstanceOf(oControl, "sap/ui/core/ComponentContainer")) { var oComp = oControl.getComponentInstance(); if (!oComp && oControl.getName() && !oControl.getDomRef()) { //Component not yet initialized -> try again later var that = this; var oDelegate = { onBeforeRendering: function() { oControl.removeEventDelegate(oDelegate); that._doBFS([{ // scan [for adaptable content] the newly added subtree oNode: oControl.getComponentInstance(), oAdaptOptions: oAdaptOptions }]); if (that._getCurrentlyAdaptedTopViewId()) { that._fireViewChange(that._getCurrentlyAdaptedTopViewId(), oAdaptOptions); } } }; oControl.addEventDelegate(oDelegate, this); } } }; Fiori20Adapter._checkHasListener = function(oControl, sEventType) { var oControlListeners = oChangeListeners[oControl.getId()]; return oControlListeners && oControlListeners[sEventType]; }; Fiori20Adapter._setHasListener = function(oControl, sEventType, fnListener) { var oControlListeners = oChangeListeners[oControl.getId()]; if (!oControlListeners) { oControlListeners = {}; oChangeListeners[oControl.getId()] = oControlListeners; } oControlListeners[sEventType] = fnListener; }; // attaches listener for changes in the adaptable content Fiori20Adapter._attachAdaptableContentChange = function(oControl, oAdaptOptions) { if (typeof oControl._getAdaptableContent !== "function") { return; } if (this._checkHasListener(oControl, "_adaptableContentChange")) { // already attached return; } var oOwnerViewId = this._getCurrentlyAdaptedTopViewId(), sCurrentViewId; var fnOnAdaptableContentChange = function(oEvent) { var oChangedContent = oEvent.getParameter("adaptableContent"); this._setAsCurrentlyAdaptedTopViewId(oOwnerViewId); // restore the view context (so that any findings are saved as belonging to that view) this._doBFS([{ // scan [for adaptable content] the newly added subtree oNode: oChangedContent, oAdaptOptions: oAdaptOptions }]); sCurrentViewId = this._getCurrentlyAdaptedTopViewId(); if (sCurrentViewId && Element.getElementById(sCurrentViewId)) { this._fireViewChange(sCurrentViewId, oAdaptOptions); } }.bind(this); oControl.attachEvent("_adaptableContentChange", fnOnAdaptableContentChange); this._setHasListener(oControl, "_adaptableContentChange", fnOnAdaptableContentChange); }; // attaches listener for changes in the nav container current page Fiori20Adapter._attachNavigablePageChange = function(oControl, oAdaptOptions) { if (!isInstanceOf(oControl, "sap/m/NavContainer")) { return; } if (this._checkHasListener(oControl, "navigate")) { return; } var fnOnNavigate = function(oEvent){ var sCurrentViewId, oNode = oEvent.getParameter("to"); oAdaptOptions = this._applyRules(oAdaptOptions, oNode); //update the context-specific options this._doBFS([{ // scan [for adaptable content] the newly added subtree oNode: oNode, oAdaptOptions: oAdaptOptions }]); sCurrentViewId = this._getCurrentlyAdaptedTopViewId(); if (sCurrentViewId && Element.getElementById(sCurrentViewId)) { this._fireViewChange(sCurrentViewId, oAdaptOptions); } }.bind(this); oControl.attachNavigate(fnOnNavigate); this._setHasListener(oControl, "navigate", fnOnNavigate); }; Fiori20Adapter._observeAddAggregation = function(oControl, sAggregationName, oAdaptOptions, oControlToRescan) { if (this._checkHasListener(oControl, sAggregationName)) { return; } var oOwnerViewId = this._getCurrentlyAdaptedTopViewId(), sCurrentViewId, fnOnModifyAggregation = function(oChanges) { var sMutation = oChanges.mutation, oChild = oChanges.object; if ((sMutation === "add") || (sMutation === "insert")) { this._setAsCurrentlyAdaptedTopViewId(oOwnerViewId); // restore the view context (so that any findings are saved as belonging to that view) this._doBFS([{ // scan [for adaptable content] the newly added subtree oNode: oControlToRescan ? oControlToRescan : oChild, oAdaptOptions: oAdaptOptions }]); sCurrentViewId = this._getCurrentlyAdaptedTopViewId(); if (sCurrentViewId && Element.getElementById(sCurrentViewId)) { this._fireViewChange(sCurrentViewId, oAdaptOptions); } } }.bind(this), oObserver = new ManagedObjectObserver(fnOnModifyAggregation); oObserver.observe(oControl, { aggregations: [sAggregationName] }); this._setHasListener(oControl, sAggregationName, oObserver); }; Fiori20Adapter._observeRemoveAggregation = function(oControl, sAggregationName, oAdaptOptions) { if (this._checkHasListener(oControl, sAggregationName)) { return; } var oObserver = new ManagedObjectObserver(this._onRemoveAggregation.bind(this)); oObserver.observe(oControl, { aggregations: [sAggregationName] }); this._setHasListener(oControl, sAggregationName, oObserver); }; Fiori20Adapter._removeFromMergeInfo = function(oMergeInfo, oControl) { Object.keys(oMergeInfo).forEach(function(sKey) { var oControlInfo = oMergeInfo[sKey]; if ((oControlInfo.oControl === oControl) || isChildOf(oControlInfo.oControl, oControl)) { this._detachAllListeners(oControlInfo.oControl); delete oMergeInfo[sKey]; } }, this); }; Fiori20Adapter._detachAllListeners = function(oControl) { var oControlListeners = oChangeListeners[oControl.getId()]; if (!oControlListeners) { return; } Object.keys(oControlListeners).forEach(function(sEventType) { var fnListener = oControlListeners[sEventType]; if (fnListener instanceof ManagedObjectObserver) { fnListener.disconnect(); } else { oControl.detachEvent(sEventType, fnListener); } delete oControlListeners[sEventType]; }); }; Fiori20Adapter._onRemoveAggregation = function(oChanges) { var sMutation = oChanges.mutation, oRemovedControl; if (sMutation === "remove") { oRemovedControl = oChanges.child; this._detachAllListeners(oRemovedControl); this._removeFromMergeInfo(oInfoToMerge.aViewTitles, oRemovedControl); this._removeFromMergeInfo(oInfoToMerge.aViewSubTitles, oRemovedControl); this._removeFromMergeInfo(oInfoToMerge.aViewBackButtons, oRemovedControl); } }; Fiori20Adapter._getNodeChildren = function(oControl) { if (typeof oControl._getAdaptableContent === "function") { var aChildren = [oControl._getAdaptableContent()]; if (isInstanceOf(oControl, "sap/m/Page")) { aChildren = aChildren.concat(oControl.getContent()); //page content can contain other pages that are subject to adaptation } return aChildren; } if (isInstanceOf(oControl, "sap/m/SplitContainer")) { return [].concat(oControl.getAggregation("_navMaster"), oControl.getAggregation("_navDetail")); } if (isInstanceOf(oControl, "sap/uxap/ObjectPageLayout")) { return [oControl.getHeaderTitle()]; } if (isInstanceOf(oControl, "sap/ui/core/ComponentContainer")) { return [oControl.getComponentInstance()]; } if (isInstanceOf(oControl, "sap/ui/core/UIComponent")) { return [oControl.getAggregation("rootControl")]; } return oControl.findAggregatedObjects(false, isNonDependentObject); /* skip objects added via Element.prototype.addDependent e.g. dialogs, since this is not nested content */ }; Fiori20Adapter._updateSearchDepth = function(iSearchDepth, oControl) { if (isInstanceOf(oControl, "sap/ui/core/mvc/View") || isInstanceOf(oControl, "sap/ui/core/Component") || isInstanceOf(oControl, "sap/ui/core/ComponentContainer")) { /* Do not decrease level for views or components/componentContainers */ return iSearchDepth; } return iSearchDepth - 1; }; Fiori20Adapter._getTotalCachedInfoToMerge = function(sViewId) { var oView = Element.getElementById(sViewId), oCachedViewInfo = this._getCachedViewInfoToMerge(sViewId), isMasterView, isDetailView, sSiblingView, sSiblingViewId, oSplitContainer, oParentNavContainer, oCachedSiblingViewInfo; // if this view is part of top-level split-view => merge with info for the sibling view if (!Device.system.phone && this._isTopSplitContainerSubView(oView)) { oParentNavContainer = oView.getParent(); oSplitContainer = oParentNavContainer && oParentNavContainer.getParent(); if (oSplitContainer) { // find which part (master or detail) the view belongs to: // => check if its a child of the master or detail navContainer // (we cannot determine it by checking if it is part of the <code>masterPages</code> or <code>detailPages</code> aggregations of the <code>splitContainer</code>, // because at this [early] stage the view may not be internally registered there yet, but only in its immediate parent aggregation) isMasterView = oSplitContainer._oMasterNav && (oSplitContainer._oMasterNav.getId() === oParentNavContainer.getId()); isDetailView = oSplitContainer._oDetailNav && (oSplitContainer._oDetailNav.getId() === oParentNavContainer.getId()); } } if (isMasterView) { // merge with detail-part info sSiblingView = oSplitContainer.getCurrentDetailPage(); sSiblingViewId = sSiblingView && sSiblingView.getId(); oCachedSiblingViewInfo = this._getCachedViewInfoToMerge(sSiblingViewId); oCachedViewInfo = this._mergeSplitViewInfos(oCachedViewInfo, oCachedSiblingViewInfo); } if (isDetailView) { // merge with master-part info sSiblingView = oSplitContainer.getCurrentMasterPage(); sSiblingViewId = sSiblingView && sSiblingView.getId(); oCachedSiblingViewInfo = this._getCachedViewInfoToMerge(sSiblingViewId); oCachedViewInfo = this._mergeSplitViewInfos(oCachedSiblingViewInfo, oCachedViewInfo); } oCachedViewInfo.sViewId = (isMasterView || isDetailView) ? oSplitContainer.getId() : sViewId; return oCachedViewInfo; }; Fiori20Adapter._isTopSplitContainerSubView = function(oControl) { var oParent = oControl && oControl.getParent(); return this._isTopmostNavContainer(oParent) && isInstanceOf(oParent.getParent(), "sap/m/SplitContainer"); }; Fiori20Adapter._mergeSplitViewInfos = function(oMasterViewInfo, oDetailViewInfo) { jQuery.each(oMasterViewInfo, function(sKey, sValue) { oMasterViewInfo[sKey] = sValue || oDetailViewInfo[sKey]; // detail info complements master info where master info is absent }); return oMasterViewInfo; }; Fiori20Adapter._getCachedViewInfoToMerge = function(sViewId) { var oBackButton = (oInfoToMerge.aViewBackButtons[sViewId]) //skip currently invisible buttons as the app has currently excluded them from the app logic ? oInfoToMerge.aViewBackButtons[sViewId].oControl : undefined; return { oTitleInfo: oInfoToMerge.aViewTitles[sViewId], oSubTitleInfo: oInfoToMerge.aViewSubTitles[sViewId], oBackButton: oBackButton }; }; /** * Apply adaptation rules that are context-specific */ Fiori20Adapter._applyRules = function(oAdaptOptions, oControl) { var oParent = oControl.getParent(); /** * Adaptation rules for children of the SplitContainer */ if (isInstanceOf(oParent, "sap/m/SplitContainer")) { var bIsPhone = Device.system.phone, bMoveTitle = oAdaptOptions.bMoveTitle, bAdaptChildBackButton = oAdaptOptions.bHideBackButton; /** * Rule1: In split-screen, adapt title only on phone */ if (bMoveTitle) { bMoveTitle = bIsPhone; } /** * Rule2: In split-screen, adapt back button only in the following cases: * 2.1. - on phone * 2.2. - on the desktop initial page of either master/detail part */ if (bAdaptChildBackButton && !Device.system.phone) { bAdaptChildBackButton = 'initialPage'; } return jQuery.extend({}, oAdaptOptions, { bMoveTitle: bMoveTitle, bHideBackButton: bAdaptChildBackButton}); } /** * Adaptation rules for children of the NavContainer */ if (isInstanceOf(oParent, "sap/m/NavContainer")) { // this is Rule2.2 from above (desktop scenario) if (oAdaptOptions.bHideBackButton === 'initialPage') { var bIsInitialPage = oParent._getActualInitialPage() && (oParent._getActualInitialPage().getId() === oControl.getId()); return jQuery.extend({}, oAdaptOptions, { bHideBackButton: bIsInitialPage}); } } if ((oAdaptOptions.bMoveTitle === false) || (oAdaptOptions.bHideBackButton === false)) { return jQuery.extend({}, oAdaptOptions, { bCollapseHeader: false}); } return oAdaptOptions; }; Fiori20Adapter._getCurrentlyAdaptedTopViewId = function() { return sCurrentlyAdaptedTopNavigableViewId; }; Fiori20Adapter._setAsCurrentlyAdaptedTopViewId = function(sViewId) { sCurrentlyAdaptedTopNavigableViewId = sViewId; }; Fiori20Adapter._isTopNavigableView = function(oNode) { var oParent = oNode.getParent(); return oParent && this._isTopmostNavContainer(oParent); }; Fiori20Adapter._isTopmostNavContainer = function(oControl) { var oCurrentTopNavContainer, oNext = oControl; while (oNext) { if (isInstanceOf(oNext, "sap/m/NavContainer")) { oCurrentTopNavContainer = oNext; } oNext = oNext.getParent(); } return oCurrentTopNavContainer && (oCurrentTopNavContainer.getId() === oControl.getId()); }; Fiori20Adapter._adaptHeader = function(oHeader, oAdaptOptions) { if (!oHeader || !oAdaptOptions) { return; } var oHeaderAdapter = new HeaderAdapter(oHeader, oAdaptOptions), oAdaptedContent = oHeaderAdapter.adapt(); var sTopViewId = this._getCurrentlyAdaptedTopViewId(); /* cache the identified title */ if (oAdaptedContent.oTitleInfo) { oInfoToMerge.aViewTitles[sTopViewId] = oAdaptedContent.oTitleInfo; this._registerTextChangeListener(oInfoToMerge.aViewTitles, sTopViewId, oAdaptOptions); } /* cache the identified subTitle */ if (oAdaptedContent.oSubTitleInfo) { oInfoToMerge.aViewSubTitles[sTopViewId] = oAdaptedContent.oSubTitleInfo; this._registerTextChangeListener(oInfoToMerge.aViewSubTitles, sTopViewId, oAdaptOptions); } /* cache the identified backButton */ if (oAdaptedContent.oBackButtonInfo) { if (oAdaptedContent.oBackButtonInfo.oControl.getVisible()) { oInfoToMerge.aViewBackButtons[sTopViewId] = oAdaptedContent.oBackButtonInfo; } this._registerVisibilityChangeListener(oAdaptedContent.oBackButtonInfo, oInfoToMerge.aViewBackButtons, sTopViewId, oAdaptOptions); } return oAdaptedContent; }; Fiori20Adapter._registerTextChangeListener = function(aTitleInfoCache, sViewId, oAdaptOptions) { var oTitleInfo = aTitleInfoCache[sViewId]; //get the cached titleInfo for the given view if (oTitleInfo && oTitleInfo.oControl && oTitleInfo.sChangeEventId) { if (this._checkHasListener(oTitleInfo.oControl, oTitleInfo.sChangeEventId)) { return; } var fnChangeListener = function (oEvent) { var oTitleInfo = aTitleInfoCache[sViewId]; if (oEvent.getParameter("name") !== oTitleInfo.sPropertyName) { return; // different property changed } oTitleInfo.text = oEvent.getParameter("newValue"); this._fireViewChange(sViewId, oAdaptOptions); }.bind(this); oTitleInfo.oControl.attachEvent(oTitleInfo.sChangeEventId, fnChangeListener); this._setHasListener(oTitleInfo.oControl, oTitleInfo.sChangeEventId, fnChangeListener); } }; Fiori20Adapter._registerVisibilityChangeListener = function(oControlInfo, aControlInfoCache, sViewId, oAdaptOptions) { var bVisible; if (oControlInfo && oControlInfo.oControl && oControlInfo.sChangeEventId) { if (this._checkHasListener(oControlInfo.oControl, oControlInfo.sChangeEventId)) { return; } var fnChangeListener = function (oEvent) { if (oEvent.getParameter("name") !== oControlInfo.sPropertyName) { return; // different property changed } bVisible = oEvent.getParameter("newValue"); //actualize the value if (!bVisible) { jQuery.each(aControlInfoCache, function(iIndex, oCachedControlInfo) { if (oCachedControlInfo.oControl.getId() === oControlInfo.oControl.getId()) { delete aControlInfoCache[iIndex]; } }); } var oParentControl = oControlInfo.oControl.getParent(); if (HeaderAdapter._isAdaptableHeader(oParentControl)) { // the parent is still an adaptable header Fiori20Adapter._adaptHeader(oParentControl, oAdaptOptions); // re-adapt as visibility of inner content changed this._fireViewChange(sViewId, oAdaptOptions); } }.bind(this); oControlInfo.oControl.attachEvent(oControlInfo.sChangeEventId, fnChangeListener); this._setHasListener(oControlInfo.oControl, oControlInfo.sChangeEventId, fnChangeListener); } }; Fiori20Adapter._fireViewChange = function(sViewId, oAdaptOptions) { var oToMerge = this._getTotalCachedInfoToMerge(sViewId); oToMerge.oAdaptOptions = oAdaptOptions; oEventProvider.fireEvent("adaptedViewChange", oToMerge); }; Fiori20Adapter._isAdaptationRequired = function(oNode, oAdaptOptions) { if (!oNode || this._isNonAdaptableControl(oNode)) { return false; } for (var sOption in oAdaptOptions) { if (oAdaptOptions.hasOwnProperty(sOption) && ((oAdaptOptions[sOption] === true) || (oAdaptOptions[sOption] === "initialPage"))) { return true; } } return false; }; Fiori20Adapter._isNonAdaptableControl = function(oControl) { return isListBasedControl(oControl); }; // utility function function isTextualControl (oControl) { return isInstanceOfGroup(oControl, ["sap/m/Label", "sap/m/Text", "sap/m/Title"]); } function isListBasedControl (oControl) { return isInstanceOfGroup(oControl, ["sap/m/List", "sap/m/SelectList", "sap/m/Table", "sap/ui/table/Table", "sap/ui/table/TreeTable", "sap/ui/comp/variants/VariantManagement"]); } function isInstanceOfGroup(oControl, aTypes) { if (!oControl || !aTypes) { return; } return aTypes.some(function(sType) { return isInstanceOf(oControl, sType); }); } function isInstanceOf (oControl, sType) { var oType = sap.ui.require(sType); return oType && (oControl instanceof oType); } function isNonDependentObject(oObject) { return oObject && (oObject.sParentAggregationName !== "dependents"); } function isHiddenFromAPI(oObject) { return oObject && (typeof oObject.getVisible === "function") && (oObject.getVisible() === false); } function isChildOf(oControl, oRoot) { var oParent = oControl && oControl.getParent(); while (oParent) { if (oParent === oRoot) { return true; } oParent = oParent.getParent(); } return false; } return Fiori20Adapter; });