/*!
* UI development toolkit for HTML5 (OpenUI5)
* (c) Copyright 2009-2018 SAP SE or an SAP affiliate company.
* Licensed under the Apache License, Version 2.0 - see LICENSE.txt.
*/
// Provides control sap.m.Menu.
sap.ui.define([
'./library',
'sap/ui/core/Control',
'./Button',
'./Dialog',
'./NavContainer',
'./List',
'./Page',
'./MenuListItem',
'sap/ui/unified/Menu',
'sap/ui/unified/MenuItem',
'sap/ui/Device',
'sap/ui/core/EnabledPropagator',
'sap/ui/core/CustomData',
"sap/ui/thirdparty/jquery"
],
function(
library,
Control,
Button,
Dialog,
NavContainer,
List,
Page,
MenuListItem,
UfdMenu,
UfdMenuItem,
Device,
EnabledPropagator,
CustomData,
jQuery
) {
"use strict";
// shortcut for sap.m.ListType
var ListType = library.ListType;
// shortcut for sap.m.ListMode
var ListMode = library.ListMode;
/**
* Constructor for a new Menu.
*
* @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 sap.m.Menu
control represents a hierarchical menu.
* When opened on mobile devices it occupies the whole screen.
* @extends sap.ui.core.Control
* @implements sap.ui.core.IContextMenu
*
* @author SAP SE
* @version 1.60.23
*
* @constructor
* @public
* @alias sap.m.Menu
* @ui5-metamodel This control/element also will be described in the UI5 (legacy) designtime metamodel
*/
var Menu = Control.extend("sap.m.Menu", /** @lends sap.m.Menu.prototype */ { metadata : {
interfaces: [
"sap.ui.core.IContextMenu"
],
library : "sap.m",
properties : {
/**
* Defines the Menu
title.
*/
title : { type : "string", group : "Misc", defaultValue : null }
},
defaultAggregation: "items",
aggregations: {
/**
* Defines the items contained within this control.
*/
items: { type: "sap.m.MenuItem", multiple: true, singularName: "item", bindable: "bindable" },
/**
* Internal aggregation that contains the inner sap.m.Dialog
for mobile.
*/
_dialog: { type: "sap.m.Dialog", multiple: false, visibility: "hidden" },
/**
* Internal aggregation that contains the inner sap.ui.unified.Menu
for desktop and tablet.
*/
_menu: { type: "sap.ui.unified.Menu", multiple: false, visibility: "hidden" }
},
events: {
/**
* Fired when a MenuItem
is selected.
*/
itemSelected: {
parameters: {
/**
* The MenuItem
which was selected.
*/
item : {type : "sap.m.MenuItem" }
}
},
/**
* Fired when the menu is closed.
*/
closed: {}
}
}});
EnabledPropagator.call(Menu.prototype);
/**
* Unified Menu items ID prefix.
*
* @type {string}
*/
Menu.UNIFIED_MENU_ITEMS_ID_SUFFIX = '-unifiedmenu';
/**
* Map of all available properties in the sap.ui.unified.MenuItem.
* Needed when syncs between sap.m.MenuItem and unified.MenuItem are performed.
* @type {map}
* @private
*/
Menu.UNFIFIED_MENU_ITEMS_PROPS = UfdMenuItem.getMetadata().getAllProperties();
/**
* List items ID prefix.
*
* @type {string}
*/
Menu.LIST_ITEMS_ID_SUFFIX = '-menuinnerlist';
/**
* Map of all available properties in the sap.m.MenuListItem
* Needed when syncs between sap.m.MenuItem and sap.m.MenuListItem are performed.
* @type {map}
* @private
*/
Menu.MENU_LIST_ITEMS_PROPS = MenuListItem.getMetadata().getAllProperties();
/**
* Initializes the control.
* @public
*/
Menu.prototype.init = function() {
if (Device.system.phone) {
this._initDialog();
}
this._bIsInitialized = false;
};
/**
* Called from parent if the control is destroyed.
*/
Menu.prototype.exit = function() {
if (this._navContainerId) {
this._navContainerId = null;
}
if (this._bIsInitialized) {
this._bIsInitialized = null;
}
if (this._getMenu() && this._getMenu().getPopup()) {
this._getMenu().getPopup().detachClosed(this._menuClosed, this);
}
};
Menu.prototype.invalidate = function() {
//the parent control is most probably the menu opener, so do not invalidate it,
//let it do it's own changes when the menu is open
};
/**
* Sets the title of the Menu
.
* @param {String} sTitle The new title of the Menu
* @returns {sap.m.Menu} this
to allow method chaining
* @public
*/
Menu.prototype.setTitle = function(sTitle) {
var oNavContainer = this._getNavContainer();
this.setProperty("title", sTitle, true);
if (oNavContainer && oNavContainer.getPages().length) {
oNavContainer.getPages()[0].setTitle(sTitle);
}
return this;
};
/**
* Opens the Menu
next to the given control.
* @param {object} oControl The control that defines the position for the menu
* @param {boolean} bWithKeyboard Whether the menu is opened with a shortcut or not
* @param {sap.ui.core.Dock} [sDockMy=sap.ui.core.Popup.Dock.BeginTop] The reference docking location
* of the Menu
for positioning the menu on the screen
* @param {sap.ui.core.Dock} [sDockAt=sap.ui.core.Popup.Dock.BeginBottom] The oControl
* reference docking location for positioning the menu on the screen
* @param {string} [sOffset="0 -2"] The offset relative to the docking point,
* specified as a string with space-separated pixel values (e.g. "0 10" to move the popup 10 pixels to the right).
* If the docking of both "my" and "at" is RTL-sensitive ("begin" or "end"), this offset is automatically mirrored in the RTL case as well.
* @public
*/
Menu.prototype.openBy = function(oControl, bWithKeyboard, sDockMy, sDockAt, sOffset) {
if (Device.system.phone) {
this._openDialog();
} else {
if (!this._bIsInitialized) {
this._initAllMenuItems();
this._bIsInitialized = true;
}
var eDock = sap.ui.core.Popup.Dock;
if (!sDockMy) {
sDockMy = eDock.BeginTop;
}
if (!sDockAt) {
sDockAt = eDock.BeginBottom;
}
if (!sOffset) {
sOffset = "0 -2";
}
this._getMenu().open(bWithKeyboard, oControl, sDockMy, sDockAt, oControl, sOffset);
}
};
/**
* Closes the Menu
.
* @public
*/
Menu.prototype.close = function() {
if (Device.system.phone) {
this._getDialog().close();
} else {
this._getVisualParent().close();
}
};
/**
* Creates the dialog that contains the actual menu for mobile.
* @private
*/
Menu.prototype._initDialog = function() {
var oDialog = new Dialog({
showHeader: false,
stretch: true,
content: this._initNavContainer(),
buttons: [
this._initCloseButton()
]
});
oDialog.addStyleClass("sapMRespMenuDialog");
// remove padding for the menu on phone
oDialog.removeStyleClass("sapUiPopupWithPadding");
this.setAggregation("_dialog", oDialog, true);
};
/**
* Gets the internal dialog.
* @returns {sap.m.Dialog} The internal _dialog aggregation
* @private
*/
Menu.prototype._getDialog = function() {
return this.getAggregation("_dialog");
};
/**
* Opens the internal dialog.
* @private
*/
Menu.prototype._openDialog = function() {
if (!this._bIsInitialized) {
this._initAllPages();
this._bIsInitialized = true;
}
//reset to first page
this._getNavContainer().to(this._getNavContainer().getPages()[0]);
this._getDialog().open();
};
Menu.prototype._initAllMenuItems = function() {
this._initMenuForItems(this.getItems());
};
/*
* Allows for any custom function to be called back when accessibility attributes
* of underlying menu are about to be rendered.
* The function is called once per MenuItem
*
* @param {function} fn The callback function
* @protected
* @sap-restricted ObjectPageLayoutABHelper
* @returns void
*/
Menu.prototype._setCustomEnhanceAccStateFunction = function(fn) {
this._fnEnhanceUnifiedMenuAccState = fn;
};
Menu.prototype._initMenuForItems = function(aItems, oParentMenuItem) {
var oMenu = new UfdMenu();
oMenu._setCustomEnhanceAccStateFunction(this._fnEnhanceUnifiedMenuAccState);
oMenu.isCozy = this._isMenuCozy.bind(this, oMenu);
// Keep in mind that we are adding the style class to sap.m.Menu as the CustomStyleClassSupport is sync
// in a Mimic mode so only styles added to sap.m.Menu will be applied.
this.addStyleClass('sapMMenu');
// Every new menu style class properties should be a reference to the control style class properties.
// This is needed because every menu level has a new popup like DOM structure in the static area and it's
// a sibling and not a child of the previous menu. Keep in mind that if the sap.m.Menu introduces a renderer
// in the future this must not be propagated like this not to pollute the control itself with classes
// from the children.
oMenu.aCustomStyleClasses = this.aCustomStyleClasses;
oMenu.mCustomStyleClassMap = this.mCustomStyleClassMap;
aItems.forEach(function(oItem) {
this._addVisualMenuItemFromItem(oItem, oMenu);
}.bind(this));
if (oParentMenuItem) {
oParentMenuItem.setSubmenu(oMenu);
} else {
oMenu.getPopup().attachClosed(this._menuClosed, this);
this.setAggregation('_menu', oMenu, true);
}
oMenu.attachItemSelect(this._handleMenuItemSelect, this);
};
Menu.prototype._menuClosed = function() {
this.fireClosed();
};
Menu.prototype._getMenu = function() {
return this.getAggregation("_menu");
};
Menu.prototype._initCloseButton = function() {
var oRB = sap.ui.getCore().getLibraryResourceBundle("sap.m");
return new Button({
text: oRB.getText("MENU_CLOSE"),
press: fnBtnClosePressHandler.bind(this)
});
};
function fnBtnClosePressHandler() {
this._getDialog().close();
}
Menu.prototype._initNavContainer = function() {
var oNavContainer = new NavContainer();
this._navContainerId = oNavContainer.getId();
return oNavContainer;
};
/**
* Gets the internal sap.m.NavContainer
for mobile.
* @returns {sap.m.NavContainer} The sap.m.NavContainer
* @private
*/
Menu.prototype._getNavContainer = function() {
return sap.ui.getCore().byId(this._navContainerId);
};
Menu.prototype._initAllPages = function() {
this._initPageForParent(this);
};
Menu.prototype._initPageForParent = function(oParent) {
var aItems = oParent.getItems(),
isRootPage = oParent instanceof Menu,
sPageTitle = isRootPage ? oParent.getTitle() : oParent.getText(),
oList = new List({
mode: ListMode.None
}),
oPage = new Page({
title: sPageTitle,
showNavButton: !isRootPage,
content: oList
});
if (!isRootPage) {
this._setBackButtonTooltipForPageWithParent(oParent, oPage);
}
oPage.attachNavButtonPress(function() {
this._getNavContainer().back();
}, this);
this._getNavContainer().addPage(oPage);
aItems.forEach(function(oItem) {
this._addListItemFromItem(oItem, oPage);
}, this);
this._updateListInset(oList);
oList.attachEvent("itemPress", this._handleListItemPress, this);
return oPage;
};
Menu.prototype._handleListItemPress = function(oEvent) {
var oListItem = oEvent.getParameter("listItem"),
oMenuItem = sap.ui.getCore().byId(oListItem.getMenuItem()),
pageId = oMenuItem._getVisualChild();
if (pageId) {
this._getNavContainer().to(pageId);
} else {
this._getDialog().close();
this.fireItemSelected({ item: oMenuItem });
}
oMenuItem.firePress();
};
/**
* Sets an ARIA tooltip for a back button of a page.
* @param {object} oParent The parent item for the page
* @param {object} oPage The page
* @private
*/
Menu.prototype._setBackButtonTooltipForPageWithParent = function(oParent, oPage) {
var oParentParent = oParent.getParent(),
oRb = sap.ui.getCore().getLibraryResourceBundle("sap.m"),
sParentPageTitle;
sParentPageTitle = oParentParent instanceof Menu ? oParentParent.getTitle() : oParentParent.getText();
sParentPageTitle = oRb.getText("MENU_PAGE_BACK_BUTTON") + " " + sParentPageTitle;
oPage.setNavButtonTooltip(sParentPageTitle);
};
Menu.prototype._createMenuListItemFromItem = function(oItem) {
return new MenuListItem({
id : this._generateListItemId(oItem.getId()),
type: ListType.Active,
icon: oItem.getIcon(),
title: oItem.getText(),
startsSection: oItem.getStartsSection(),
menuItem: oItem,
tooltip: oItem.getTooltip(),
visible: oItem.getVisible()
});
};
Menu.prototype._createVisualMenuItemFromItem = function(oItem) {
var oUfdMenuItem = new UfdMenuItem({
id : this._generateUnifiedMenuItemId(oItem.getId()),
icon: oItem.getIcon(),
text: oItem.getText(),
startsSection: oItem.getStartsSection(),
tooltip: oItem.getTooltip(),
visible: oItem.getVisible(),
enabled: oItem.getEnabled()
}),
aCustomData = oItem.getCustomData();
aCustomData.forEach(function(oData) {
oUfdMenuItem.addCustomData(new CustomData({
key: oData.getKey(),
value: oData.getValue()
}));
});
return oUfdMenuItem;
};
Menu.prototype._addVisualMenuItemFromItem = function(oItem, oMenu, iIndex) {
var oMenuItem = this._createVisualMenuItemFromItem(oItem);
oItem._setVisualParent(oMenu);
oItem._setVisualControl(oMenuItem);
// attach event handlers responsible for keeping separate instances at sync
var aEvents = ['aggregationChanged', 'propertyChanged'];
aEvents.forEach(function (sEvent) {
var sEventHandlerName = '_on' + sEvent.slice(0, 1).toUpperCase() + sEvent.slice(1); // capitalize
oItem.attachEvent(sEvent, this[sEventHandlerName], this);
}, this);
if (oItem.getItems().length !== 0) {
this._initMenuForItems(oItem.getItems(), oMenuItem);
oItem._setVisualChild(oItem.getItems()[0]._getVisualParent());
}
if (iIndex === undefined) {
oMenu.addItem(oMenuItem);
} else {
oMenu.insertItem(oMenuItem, iIndex);
}
};
Menu.prototype._addListItemFromItem = function(oItem, oPage, iIndex) {
var oMenuListItem = this._createMenuListItemFromItem(oItem),
oList = oPage.getContent()[0];
oItem._setVisualParent(oPage);
oItem._setVisualControl(oMenuListItem);
// attach event handlers responsible for keeping separate instances at sync
var aEvents = ['aggregationChanged', 'propertyChanged'];
aEvents.forEach(function (sEvent) {
var sEventHandlerName = '_on' + sEvent.slice(0, 1).toUpperCase() + sEvent.slice(1); // capitalize
oItem.attachEvent(sEvent, this[sEventHandlerName], this);
}, this);
if (oItem.getItems().length !== 0) {
this._initPageForParent(oItem);
oItem._setVisualChild(oItem.getItems()[0]._getVisualParent());
}
if (iIndex === undefined) {
oList.addItem(oMenuListItem);
} else {
oList.insertItem(oMenuListItem, iIndex);
}
oList.rerender();
};
/**
* Connects an instance of sap.ui.unified.MenuItem for given sap.m.MenuItem.
* The sap.ui.unified.MenuItem is rendered to the end-user.
* If there is an instance of sap.ui.unified.MenuItem already connected, this method does nothing.
* @param {sap.m.MenuItem} oItem the item to assign a visual item for
* @param {sap.ui.core.Control} oControl the container control
* @param {int} iIndex the index of the given item inside the aggregation
* @private
*/
Menu.prototype._connectVisualItem = function(oItem, oControl, iIndex) {
if (!oControl || sap.ui.getCore().byId(oItem._getVisualControl())) {
return;
}
if (Device.system.phone) {
this._addListItemFromItem(oItem, oControl, iIndex);
var oList = oControl.getContent()[0];
this._updateListInset(oList);
} else { //desktop & tablet
this._addVisualMenuItemFromItem(oItem, oControl, iIndex);
}
};
Menu.prototype._updateListInset = function(oList) {
var bHasIcons = false,
sInsetClass = "sapMListIcons",
aItems = oList.getItems();
for (var i = 0; i < aItems.length; i++) {
if (aItems[i].getIcon()) {
bHasIcons = true;
break;
}
}
if (bHasIcons) {
oList.addStyleClass(sInsetClass);
} else {
oList.removeStyleClass(sInsetClass);
}
};
Menu.prototype._handleMenuItemSelect = function(oEvent) {
var oUnfdItem = oEvent.getParameter("item"),
oMenuItem;
if (!oUnfdItem) {
return;
}
oMenuItem = this._findMenuItemByUnfdMenuItem(oUnfdItem);
if (oMenuItem && !oMenuItem.getItems().length) {
this.fireItemSelected({item: oMenuItem});
}
if (oMenuItem) {
oMenuItem.firePress();
}
};
Menu.prototype._generateListItemId = function (sMenuItemId) {
return sMenuItemId + Menu.LIST_ITEMS_ID_SUFFIX;
};
Menu.prototype._generateUnifiedMenuItemId = function (sMenuItemId) {
return sMenuItemId + Menu.UNIFIED_MENU_ITEMS_ID_SUFFIX;
};
Menu.prototype._findMenuItemByUnfdMenuItem = function(oUnfdMenuItem) {
var aUnfdMenuItemStack = [],
oCurrentUnfdMenuItem = oUnfdMenuItem,
aItems,
iCurrentUnfdMenuItemId,
i;
do {
aUnfdMenuItemStack.push(oCurrentUnfdMenuItem.getId());
oCurrentUnfdMenuItem = oCurrentUnfdMenuItem.getParent().getParent();
} while (oCurrentUnfdMenuItem instanceof UfdMenuItem);
aItems = this.getItems();
do {
iCurrentUnfdMenuItemId = aUnfdMenuItemStack.pop();
for (i = 0; i < aItems.length; i++) {
if (aItems[i]._getVisualControl() === iCurrentUnfdMenuItemId) {
if (aUnfdMenuItemStack.length === 0) {
return aItems[i];
} else {
aItems = aItems[i].getItems();
break;
}
}
}
} while (aUnfdMenuItemStack.length);
return null;
};
/**
* Checks whether the Menu
should run with cozy design.
* This function must only be called on the root menu (getRootMenu
) to get proper results.
* @param {object} oMenu The Menu
which is checked
* @returns {boolean} If the Menu
should run with cozy design
* @private
*/
Menu.prototype._isMenuCozy = function(oMenu) {
if (!oMenu.bCozySupported) {
return false;
}
if (oMenu.hasStyleClass("sapUiSizeCozy")) {
return true;
}
if (checkCozyMode(oMenu.oOpenerRef)) {
return true;
}
return false;
};
function checkCozyMode(oRef) {
if (!oRef) {
return false;
}
oRef = oRef.$ ? oRef.$() : jQuery(oRef);
var $ClosestParent = oRef.closest(".sapUiSizeCompact,.sapUiSizeCondensed,.sapUiSizeCozy");
return (!$ClosestParent.hasClass("sapUiSizeCompact") && !$ClosestParent.hasClass("sapUiSizeCondensed"))
|| $ClosestParent.hasClass("sapUiSizeCozy");
}
Menu.prototype.addAggregation = function(sAggregationName, oObject, bSuppressInvalidate) {
Control.prototype.addAggregation.apply(this, arguments);
if (sAggregationName === "items") {
this._connectVisualItem(oObject, this._getVisualParent());
}
return this;
};
Menu.prototype.insertAggregation = function(sAggregationName, oObject, iIndex, bSuppressInvalidate) {
Control.prototype.insertAggregation.apply(this, arguments);
if (sAggregationName === "items") {
this._connectVisualItem(oObject, this._getVisualParent(), iIndex);
}
return this;
};
Menu.prototype.removeAggregation = function(sAggregationName, vObject, bSuppressInvalidate) {
var oItem = Control.prototype.removeAggregation.apply(this, arguments);
if (sAggregationName === "items") {
this._removeVisualItem(oItem);
}
return oItem;
};
Menu.prototype.removeAllAggregation = function(sAggregationName, bSuppressInvalidate) {
var aItems = Control.prototype.removeAllAggregation.apply(this, arguments);
if (sAggregationName === "items") {
for (var i = 0; i < aItems.length; i++) {
this._removeVisualItem(aItems[i]);
}
}
return aItems;
};
Menu.prototype._removeVisualItem = function(oItem, oParentItem) {
var oVisualItem = sap.ui.getCore().byId(oItem._getVisualControl()),
vMenuOrList;
if (oVisualItem) {
vMenuOrList = oVisualItem.getParent();
vMenuOrList.removeItem(oVisualItem);
if (Device.system.phone) {
this._removeSubPageForItem(oItem);
//if this is the last item in the page, remove the page
if (vMenuOrList.getItems().length === 0) {
// now we need to update its parent list item - no to render its arrow and reset its visual child ref
if (oParentItem) {
oParentItem._setVisualChild(null);
sap.ui.getCore().byId(oParentItem._getVisualControl()).rerender();
}
}
if (vMenuOrList) { //if it is not destroyed already in the statement above
vMenuOrList.rerender();
}
}
}
};
Menu.prototype.destroyAggregation = function(sAggregationName, bSuppressInvalidate) {
if (sAggregationName === "items") {
for (var i = 0; i < this.getItems().length; i++) {
this._removeVisualItem(this.getItems()[i]);
}
}
return Control.prototype.destroyAggregation.apply(this, arguments);
};
Menu.prototype._removeSubPageForItem = function(oItem, bSkipChildren) {
var oSubMenuPage;
if (!bSkipChildren) {
for (var i = 0; i < oItem.getItems().length; i++) {
this._removeSubPageForItem(oItem.getItems()[i]);
}
}
if (oItem._getVisualChild()) {
oSubMenuPage = sap.ui.getCore().byId(oItem._getVisualChild());
if (this._getNavContainer() && oSubMenuPage) {
this._getNavContainer().removePage(oSubMenuPage);
}
!!oSubMenuPage && oSubMenuPage.destroy();
}
};
Menu.prototype._getVisualParent = function() {
var oNavContainer = this._getNavContainer(),
oMenu = this._getMenu();
if (oNavContainer && oNavContainer.getPages().length) { //mobile
return oNavContainer.getPages()[0];
} else {
return oMenu;
}
};
/**
* Handle the event of changing any property of any menu items and sub-items.
* @param {object} oEvent The event data object
* @private
*/
Menu.prototype._onPropertyChanged = function (oEvent) {
var sPropertyKey = oEvent.getParameter("propertyKey"),
oPropertyValue = oEvent.getParameter("propertyValue"),
mTargetMenuItemProps = Device.system.phone ? Menu.MENU_LIST_ITEMS_PROPS : Menu.UNFIFIED_MENU_ITEMS_PROPS,
fnGenerateTargetItemId = Device.system.phone ? this._generateListItemId : this._generateUnifiedMenuItemId,
sTargetItemId;
if (Device.system.phone && sPropertyKey === 'text') {
sPropertyKey = 'title';
}
if (!mTargetMenuItemProps[sPropertyKey]) {
return;
}
sTargetItemId = fnGenerateTargetItemId(oEvent.getSource().getId());
if (sTargetItemId) {
sap.ui.getCore().byId(sTargetItemId).setProperty(sPropertyKey, oPropertyValue);
if (Device.system.phone && this._getDialog().isOpen()) {
this._getDialog().close();
}
}
};
/**
* Handle the event of changing any aggregation of any menu items and sub-items.
* @param {object} oEvent The event data object
* @private
*/
Menu.prototype._onAggregationChanged = function(oEvent) {
var sAggregationname = oEvent.getParameter("aggregationName");
switch (sAggregationname) {
case 'items':
this._onItemsAggregationChanged(oEvent);
break;
}
};
/**
* Handle the event of changing the "items" aggregation of any menu items and sub-items.
* @param {object} oEvent The event data object
* @private
*/
Menu.prototype._onItemsAggregationChanged = function(oEvent) {
var oItem = oEvent.getSource(),
methodName = oEvent.getParameter("methodName"),
methodParams = oEvent.getParameter("methodParams"),
iInsertIndex;
if (methodName === "add" || methodName === "insert") {
if (methodName === "insert") {
iInsertIndex = methodParams.index;
}
this._addOrInsertItem(oItem, methodParams.item, iInsertIndex);
}
if (methodName === "remove") {
this._removeVisualItem(methodParams.item, oItem);
}
if (methodName === "removeall") {
for (var i = 0; i < methodParams.items.length; i++) {
this._removeVisualItem(methodParams.items[i], oItem);
}
}
if (methodName === "destroy") {
this._destroyItem(oItem);
}
};
Menu.prototype._addOrInsertItem = function(oParentItem, oNewItem, iInsertIndex) {
var oLI;
if (oParentItem._getVisualChild()) { //this is not the first sub-item that is added
this._connectVisualItem(oNewItem, sap.ui.getCore().byId(oParentItem._getVisualChild()), iInsertIndex);
} else {
if (Device.system.phone) {
this._initPageForParent(oParentItem);
oParentItem._setVisualChild(oParentItem.getItems()[0]._getVisualParent());
oLI = sap.ui.getCore().byId(oParentItem._getVisualControl());
oLI.rerender();
} else {
this._initMenuForItems(oParentItem.getItems(), sap.ui.getCore().byId(oParentItem._getVisualControl()));
oParentItem._setVisualChild(oParentItem.getItems()[0]._getVisualParent());
}
}
};
Menu.prototype._destroyItem = function(oItem) {
//destroy is handled recursively from the item itself (managed object)
//so here we receive multiple aggregationChanged events, each one for a separate item
//in the time we re-render the visual item, it's menuitem still has its subitems, so remove the ref for a while
var oVisualItem = sap.ui.getCore().byId(oItem._getVisualControl());
if (oVisualItem && oVisualItem.setMenuItem) {
oVisualItem.setMenuItem(null);
}
this._removeSubPageForItem(oItem, true);
// now we need to update its parent list item - no to render its arrow and reset its visual child ref
oItem._setVisualChild(null);
if (oVisualItem && oVisualItem.setMenuItem) {
oVisualItem.rerender();
oVisualItem.setMenuItem(oItem);
}
};
/**
* Provides a DOM reference ID of the menu container.
* @returns {string} The DOM reference ID of the menu container
*/
Menu.prototype.getDomRefId = function() {
if (Device.system.phone) {
return this._getDialog().getId();
} else {
return this._getMenu().getId();
}
};
/**
* Opens the menu as a context menu.
* @param {jQuery.Event | object} oEvent The event object or an object containing offsetX, offsetY
* values and left, top values of the element's position
* @param {object} oOpenerRef The reference of the opener
*/
Menu.prototype.openAsContextMenu = function(oEvent, oOpenerRef) {
if (Device.system.phone) {
this._openDialog();
} else {
if (!this._bIsInitialized) {
this._initAllMenuItems();
this._bIsInitialized = true;
}
this._getMenu().openAsContextMenu(oEvent, oOpenerRef);
}
};
/**
* Override mutator public methods for CustomStyleClassSupport so it's properly propagated to the dialog.
* Keep in mind we don't overwrite hasStyleClass
method - we are only propagating the state
* we don't mimic the dialog custom style class support.
* @override
*/
["addStyleClass", "removeStyleClass", "toggleStyleClass"].forEach(function (sMethodName) {
Menu.prototype[sMethodName] = function (sClass, bSuppressInvalidate) {
var oDialog = this._getDialog();
Control.prototype[sMethodName].apply(this, arguments);
if (oDialog) {
oDialog[sMethodName].apply(oDialog, arguments);
}
return this;
};
});
return Menu;
});