@openui5/sap.m
Version:
OpenUI5 UI Library sap.m
1,679 lines (1,402 loc) • 54.1 kB
JavaScript
/*!
* 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.IconTabHeader.
sap.ui.define([
'./library',
'sap/ui/core/Core',
'sap/ui/core/Control',
'sap/ui/core/EnabledPropagator',
'sap/ui/core/delegate/ItemNavigation',
"sap/ui/core/InvisibleText",
'sap/ui/core/ResizeHandler',
'sap/ui/Device',
'sap/m/Button',
'sap/m/IconTabFilter',
'sap/m/IconTabSeparator',
'sap/m/IconTabBarDragAndDropUtil',
'sap/ui/core/library',
'sap/m/IconTabHeaderRenderer',
"sap/ui/thirdparty/jquery",
"sap/base/Log",
"sap/ui/events/KeyCodes"
], function(
library,
Core,
Control,
EnabledPropagator,
ItemNavigation,
InvisibleText,
ResizeHandler,
Device,
Button,
IconTabFilter,
IconTabSeparator,
IconTabBarDragAndDropUtil,
coreLibrary,
IconTabHeaderRenderer,
jQuery,
Log,
KeyCodes
) {
"use strict";
// shortcut for sap.ui.core.dnd.DropPosition
var DropPosition = coreLibrary.dnd.DropPosition;
// shortcut for sap.m.BackgroundDesign
var BackgroundDesign = library.BackgroundDesign;
// shortcut for sap.m.IconTabHeaderMode
var IconTabHeaderMode = library.IconTabHeaderMode;
// shortcut for sap.m.IconTabDensityMode
var IconTabDensityMode = library.IconTabDensityMode;
// shortcut for sap.m.TabsOverflowMode
var TabsOverflowMode = library.TabsOverflowMode;
/**
* Constructor for a new IconTabHeader.
*
* @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
* This control displays a number of IconTabFilters and IconTabSeparators. If the available horizontal
* space is exceeded, an overflow tab appears.
*
* <h3>Usage</h3>
* Use <code>IconTabHeader</code> if you need it as a standalone header.
* If you need to manage content use {@link sap.m.IconTabBar} instead.
*
* @extends sap.ui.core.Control
*
* @author SAP SE
* @version 1.117.4
*
* @constructor
* @public
* @since 1.15
* @alias sap.m.IconTabHeader
*/
var IconTabHeader = Control.extend("sap.m.IconTabHeader", /** @lends sap.m.IconTabHeader.prototype */ {
metadata : {
library : "sap.m",
properties : {
/**
* Defines whether the current selection is visualized.
* @deprecated As of 1.15.0.
* Regarding to changes of this control this property is not needed anymore.
*/
showSelection : {type : "boolean", group : "Misc", defaultValue : true, deprecated: true},
/**
* Key of the selected item.
*
* If the key has no corresponding aggregated item, no changes will apply.
* If duplicate keys exists the first item matching, the key is used.
* @since 1.15.0
*/
selectedKey : {type : "string", group : "Data", defaultValue : null},
/**
* Specifies whether the control is rendered.
* @since 1.15.0
*/
visible : {type : "boolean", group : "Behavior", defaultValue : true},
/**
* Specifies the header mode.
*
* @since 1.40
*/
mode : {type : "sap.m.IconTabHeaderMode", group : "Appearance", defaultValue : IconTabHeaderMode.Standard},
/**
* Specifies if the overflow select list is displayed.
*
* The overflow select list represents a list, where all tab filters are displayed,
* so the user can select specific tab filter easier.
* @deprecated as of 1.75
*/
showOverflowSelectList : {type : "boolean", group : "Appearance", defaultValue : false, deprecated: true},
/**
* Specifies the background color of the header.
*
* Depending on the theme, you can change the state of the background color to "Solid", "Translucent", or "Transparent".
* <b>Note:</b> In SAP Belize Deep (sap_belize_plus) theme this property should be set to "Solid".
* @since 1.44
*/
backgroundDesign : {type : "sap.m.BackgroundDesign", group : "Appearance", defaultValue : BackgroundDesign.Solid},
/**
* Specifies whether tab reordering is enabled. Relevant only for desktop devices.
* The {@link sap.m.IconTabSeparator sap.m.IconTabSeparator} cannot be dragged and dropped
* Items can be moved around {@link sap.m.IconTabSeparator sap.m.IconTabSeparator}
* Reordering is enabled via keyboard using <code>Ctrl</code> + arrow keys (Windows) and <code>Control</code> + arrow keys (Mac OS)
* @since 1.46
*/
enableTabReordering : {type : "boolean", group : "Behavior", defaultValue : false},
/**
* Specifies the allowed level of tabs nesting within one another using drag and drop.
* Default value is 0 which means nesting via interaction is not allowed. Maximum value is 100.
* This property allows nesting via user interaction only, and does not restrict adding items
* to the <code>items</code> aggregation of {@link sap.m.IconTabFilter sap.m.IconTabFilter}.
* @since 1.79
*/
maxNestingLevel: { type: "int", group : "Behavior", defaultValue: 0},
/**
* Specifies the visual density mode of the tabs.
*
* The values that can be applied are <code>Cozy</code>, <code>Compact</code> and <code>Inherit</code>.
* <code>Cozy</code> and <code>Compact</code> render the control in one of these modes independent of the global density settings.
* The <code>Inherit</code> value follows the global density settings which are applied.
* For compatibility reasons, the default value is <code>Cozy</code>.
* @since 1.56
*/
tabDensityMode :{type : "sap.m.IconTabDensityMode", group : "Appearance", defaultValue : IconTabDensityMode.Cozy},
/**
* Specifies optional texts for the screen reader.
*
* The given object can contain the following keys:
* <code>headerLabel</code> - text to serve as a label for the header,
* <code>headerDescription</code> - text to serve as a description for the header.
* @since 1.80
*/
ariaTexts : {type : "object", group : "Accessibility", defaultValue : null},
/**
* Specifies the overflow mode of the header.
*
* The default <code>End</code> mode shows as many tabs that can fit on the screen, then shows one overflow at the end
* containing the remaining items.
* The <code>StartAndEnd</code> is used to keep the order of tabs intact and offers overflow tabs on both ends of the bar.
* @since 1.90
*/
tabsOverflowMode: {type : "sap.m.TabsOverflowMode", group : "Behavior", defaultValue : TabsOverflowMode.End}
},
aggregations : {
/**
* The items displayed in the IconTabHeader.
*/
items : {type : "sap.m.IconTab", multiple : true, singularName : "item", dnd : {draggable: true, droppable: true, layout: "Horizontal"} },
/**
* Internal aggregation for managing the overflow tab.
*/
_overflow : {type : "sap.m.IconTabFilter", multiple : false, visibility : "hidden"},
/**
* Internal aggregation for managing the start overflow tab.
*/
_startOverflow : {type : "sap.m.IconTabFilter", multiple : false, visibility : "hidden"}
},
events : {
/**
* Fires when an item is selected.
*/
select : {
parameters : {
/**
* The selected item
* @since 1.15.0
*/
item : {type : "sap.m.IconTabFilter"},
/**
* The key of the selected item
* @since 1.15.0
*/
key : {type : "string"},
/**
* The key of the previous selected item
* @since 1.96
*/
previousKey : {type : "string"}
}
}
}
},
renderer: IconTabHeaderRenderer
});
/**
* Sets a new value for property {@link #setAriaTexts ariaTexts}.
*
* Specifies optional texts for the screen reader.
*
* The given object can contain the following keys: <code>headerLabel</code> - text to serve as a label for the header, <code>headerDescription</code> - text to serve as a description for the header.
*
* When called with a value of <code>null</code> or <code>undefined</code>, the default value of the property will be restored.
*
* @method
* @param {{headerLabel: string, headerDescription: string}} [oAriaTexts] New value for property <code>ariaTexts</code>
* @public
* @name sap.m.IconTabHeader#setAriaTexts
* @returns {this} Reference to <code>this</code> in order to allow method chaining
*/
/**
* Gets current value of property {@link #getAriaTexts ariaTexts}.
*
* Specifies optional texts for the screen reader.
*
* The given object can contain the following keys: <code>headerLabel</code> - text to serve as a label for the header, <code>headerDescription</code> - text to serve as a description for the header.
*
* @method
* @returns {{headerLabel: string, headerDescription: string}|null} Value of property <code>ariaTexts</code>
* @public
* @name sap.m.IconTabHeader#getAriaTexts
*/
/**
* Library internationalization resource bundle.
*
* @type {module:sap/base/i18n/ResourceBundle}
*/
var oResourceBundle = Core.getLibraryResourceBundle("sap.m");
EnabledPropagator.apply(IconTabHeader.prototype, [true]);
IconTabHeader.prototype.init = function () {
// if it is "true", the "select" event will be fired
// even when the "selectedKey" property is changed via API (without user interaction).
this._bFireSelectEvent = false;
this._aTabKeys = [];
this._oAriaHeadText = null;
this._bIsRendered = false;
};
IconTabHeader.prototype.exit = function () {
if (this._oItemNavigation) {
this.removeDelegate(this._oItemNavigation);
this._oItemNavigation.destroy();
delete this._oItemNavigation;
}
if (this._sResizeListenerId) {
ResizeHandler.deregister(this._sResizeListenerId);
this._sResizeListenerId = null;
}
if (this._aTabKeys) {
this._aTabKeys = null;
}
if (this._oOverflow) {
this._oOverflow.removeEventDelegate(this._oOverflowEventDelegate);
this._oOverflowEventDelegate = null;
this._oOverflow = null;
}
if (this._oStartOverflow) {
this._oStartOverflow.removeEventDelegate(this._oStartOverflowEventDelegate);
this._oStartOverflowEventDelegate = null;
this._oStartOverflow = null;
}
if (this._oAriaHeadText) {
this._oAriaHeadText.destroy();
this._oAriaHeadText = null;
}
this._bRtl = null;
};
IconTabHeader.prototype.onBeforeRendering = function () {
this._bIsRendered = false;
this._bRtl = Core.getConfiguration().getRTL();
if (this._sResizeListenerId) {
ResizeHandler.deregister(this._sResizeListenerId);
this._sResizeListenerId = null;
}
this._updateSelection();
this.destroyDragDropConfig();
this._setsDragAndDropConfigurations();
};
IconTabHeader.prototype.onAfterRendering = function () {
this._applyTabDensityMode();
if (this.oSelectedItem) {
this._applySelectionToFilters();
this.oSelectedItem._hideBadge();
}
if (Core.isThemeApplied()) {
this._setItemsForStrip();
} else {
Core.attachThemeChanged(this._handleThemeLoad, this);
}
this._initItemNavigation();
//listen to resize
this._sResizeListenerId = ResizeHandler.register(this.getDomRef(), jQuery.proxy(this._fnResize, this));
// notify items that they are rendered
this.getItems().forEach(function (oItem) {
if (oItem._onAfterParentRendering) {
oItem._onAfterParentRendering();
}
});
this._bIsRendered = true;
};
/**
* Returns if the control is rendered
* @private
*/
IconTabHeader.prototype._isRendered = function () {
return this._bIsRendered;
};
/**
* Returns overflow select list
* @private
*/
IconTabHeader.prototype._getSelectList = function () {
return this._getOverflow()._getSelectList();
};
/**
* @private
* @returns {sap.m.IconTabFilter} The overflow tab instance
*/
IconTabHeader.prototype._getOverflow = function () {
var oOverflow = this.getAggregation("_overflow");
if (!oOverflow) {
oOverflow = new IconTabFilter({
id: this.getId() + '-overflow',
text: oResourceBundle.getText("ICONTABHEADER_OVERFLOW_MORE")
});
oOverflow._bIsOverflow = true;
this._oOverflowEventDelegate = {
onsapnext: oOverflow.onsapdown
};
oOverflow.addEventDelegate(this._oOverflowEventDelegate, oOverflow);
this.setAggregation("_overflow", oOverflow);
this._oOverflow = oOverflow;
}
return oOverflow;
};
/**
* @private
* @returns {sap.m.IconTabFilter} The start overflow tab instance
*/
IconTabHeader.prototype._getStartOverflow = function () {
var oStartOverflow = this.getAggregation("_startOverflow");
if (!oStartOverflow) {
oStartOverflow = new IconTabFilter({
id: this.getId() + '-startOverflow',
text: oResourceBundle.getText("ICONTABHEADER_OVERFLOW_MORE")
});
oStartOverflow._bIsStartOverflow = true;
this._oStartOverflowEventDelegate = {
onsapprevious: oStartOverflow.onsapdown
};
oStartOverflow.addEventDelegate(this._oStartOverflowEventDelegate, oStartOverflow);
this.setAggregation("_startOverflow", oStartOverflow);
this._oStartOverflow = oStartOverflow;
}
return oStartOverflow;
};
/**
* Returns invisible text, used for the head.
* @returns {sap.ui.core.InvisibleText} InvisibleText
* @private
*/
IconTabHeader.prototype._getInvisibleHeadText = function () {
var mAriaTexts = this.getAriaTexts() || {};
if (!this._oAriaHeadText) {
this._oAriaHeadText = new InvisibleText({
id: this.getId() + "-ariaHeadText"
});
}
this._oAriaHeadText.setText(mAriaTexts.headerDescription);
return this._oAriaHeadText;
};
IconTabHeader.prototype._onItemNavigationFocusLeave = function () {
// BCP: 1570034646
if (!this.oSelectedItem) {
return;
}
var iIndex = this._oItemNavigation.getItemDomRefs().indexOf(this.oSelectedItem._getRootTab().getDomRef());
this._oItemNavigation.setFocusedIndex(iIndex);
};
/**
* Returns all tab filters, without the tab separators.
* @private
*/
IconTabHeader.prototype.getTabFilters = function () {
var aTabFilters = [];
this.getItems().forEach(function(oItem) {
if (oItem instanceof IconTabFilter) {
aTabFilters.push(oItem);
}
});
return aTabFilters;
};
/**
* Sets or remove Drag and Drop configurations.
* @private
*/
IconTabHeader.prototype._setsDragAndDropConfigurations = function () {
// Adding Drag&Drop configuration to the dragDropConfig aggregation
if (this.getEnableTabReordering() && !this.getDragDropConfig().length) {
IconTabBarDragAndDropUtil.setDragDropAggregations(this, "Horizontal", this._getDropPosition());
}
};
/**
* Returns the correct DropPosition configuration based on the maxNestingLevel.
* @private
*/
IconTabHeader.prototype._getDropPosition = function () {
return this.getMaxNestingLevel() === 0 ? DropPosition.Between : DropPosition.OnOrBetween;
};
/**
* Sets the selected item based on key.
* @override
* @public
* @param {string} sKey The key of the item to be selected
* @return {this} this pointer for chaining
*/
IconTabHeader.prototype.setSelectedKey = function (sKey) {
if (sKey === this.getSelectedKey()) {
if (this._isInsideIconTabBar()) {
this.getParent().setProperty("selectedKey", sKey, true);
}
return this;
}
var aItems = this.getTabFilters(),
bIsParentIconTabBar = this._isInsideIconTabBar(),
bApiChange = true,
oSelectedItem;
if (aItems.length > 0) {
sKey = sKey || aItems[0]._getNonEmptyKey();
}
// adjust UI and internal variables if already rendered (otherwise taken care by onBeforeRendering)
if (this.$().length) {
oSelectedItem = this._findItemByKey(sKey);
if (oSelectedItem) {
this.setSelectedItem(oSelectedItem, bApiChange);
} else if (!bIsParentIconTabBar && sKey) {
this.setSelectedItem(null);
}
}
// set internal property
this.setProperty("selectedKey", sKey, true);
return this;
};
/**
* Sets the selected item, updates the UI, and fires the select event.
* @private
* @param {sap.m.IconTabFilter} oItem The item to be selected
* @param {boolean} bAPIChange whether this function is called through the API
* @returns {this} this pointer for chaining
*/
IconTabHeader.prototype.setSelectedItem = function (oItem, bAPIChange) {
if (!oItem) {
if (this.oSelectedItem) {
this._removeSelectionFromFilters();
this.oSelectedItem = null;
}
return this;
}
if (this._isUnselectable(oItem)) {
return this;
}
var oParent = this.getParent();
var bIsParentIconTabBar = this._isInsideIconTabBar();
var sPrevKey = this.getSelectedKey();
//if the old selected tab and the new selected tab both have no own content, which means they both use the same content from the icontabbar
//there is no need to rerender the content
//fix for xml views css: 0120061532 0001427250 2014
var bIsContentTheSame = false;
if (oItem.getContent().length === 0 && this.oSelectedItem && this.oSelectedItem.getContent().length === 0) {
bIsContentTheSame = true;
}
if (this.oSelectedItem &&
this.oSelectedItem.getVisible() &&
(!bAPIChange && bIsParentIconTabBar && oParent.getExpandable() || this.oSelectedItem !== oItem)) {
this._removeSelectionFromFilters();
}
if (oItem.getVisible()) {
//click on already selected item leads to expanding/collapsing of the content (if expandable enabled)
if (this.oSelectedItem === oItem) {
//if content is not expandable nothing should happen otherwise content will be expanded/collapsed
if (!bAPIChange && bIsParentIconTabBar && oParent.getExpandable()) {
oParent._toggleExpandCollapse();
}
//click on other item leads to showing the right content of this item
} else {
//change the content aria-labelled by the newly selected tab;
if (bIsParentIconTabBar) {
oParent.$("content").attr('aria-labelledby', oItem.sId);
}
// set new item
this.oSelectedItem = oItem;
this._applySelectionToFilters();
this.setProperty("selectedKey", this.oSelectedItem._getNonEmptyKey(), true);
//if the IconTabBar is not expandable and the content not expanded (which means content can never be expanded), we do not need
//to visualize the selection and we do not need to render the content
if (bIsParentIconTabBar && (oParent.getExpandable() || oParent.getExpanded())) {
//if item has own content, this content is shown
var oSelectedItemContent = this.oSelectedItem.getContent();
if (oSelectedItemContent.length > 0) {
oParent._rerenderContent(oSelectedItemContent);
//if item has not own content, general content of the icontabbar is shown
} else {
//if the general content was already shown there is no need to rerender
if (!bIsContentTheSame) {
oParent._rerenderContent(oParent.getContent());
}
}
//if content is not expanded, content will be expanded (first click on item always leads to expanding the right content)
if (!bAPIChange && oParent.getExpandable() && !oParent.getExpanded()) {
oParent._toggleExpandCollapse(true);
}
}
}
}
this.oSelectedItem = oItem;
var sSelectedKey = this.oSelectedItem._getNonEmptyKey();
this.setProperty("selectedKey", sSelectedKey, true);
if (bIsParentIconTabBar) {
oParent.setProperty("selectedKey", sSelectedKey, true);
}
if (bIsParentIconTabBar) {
bAPIChange = bAPIChange && !oParent._bFireSelectEvent;
} else {
bAPIChange = bAPIChange && !this._bFireSelectEvent;
}
if (!bAPIChange) {
// fire event on iconTabBar
if (bIsParentIconTabBar) {
oParent.fireSelect({
selectedItem: this.oSelectedItem,
selectedKey: sSelectedKey,
item: this.oSelectedItem,
key: sSelectedKey,
previousKey: sPrevKey
});
} else {
// fire event on header
this.fireSelect({
selectedItem: this.oSelectedItem,
selectedKey: sSelectedKey,
item: this.oSelectedItem,
key: sSelectedKey,
previousKey: sPrevKey
});
}
}
this.oSelectedItem._startBadgeHiding();
var oSelectedRootItemDomRef = this.oSelectedItem._getRootTab().getDomRef();
if (!oSelectedRootItemDomRef ||
oSelectedRootItemDomRef.classList.contains("sapMITBFilterHidden") ||
this.getTabsOverflowMode() === TabsOverflowMode.End) {
this._setItemsForStrip();
}
return this;
};
/**
* Returns all the visible tab filters.
* @private
* @returns {Array} Array of visible items.
*/
IconTabHeader.prototype.getVisibleTabFilters = function () {
return this.getTabFilters().filter(function (oFilter) {
return oFilter.getVisible();
});
};
IconTabHeader.prototype._initItemNavigation = function () {
var aTabDomRefs = [],
iSelectedDomIndex = -1,
oSelectedRootItem = this.oSelectedItem && this.oSelectedItem._getRootTab();
if (this.$().hasClass("sapMITHStartOverflowList")) {
var oStartOverflowDomRef = this._getStartOverflow().getFocusDomRef();
oStartOverflowDomRef.setAttribute("tabindex", "-1");
aTabDomRefs.push(oStartOverflowDomRef);
}
// find a collection of all tabs
this.getTabFilters().forEach(function (oItem) {
var oItemDomRef = this.getFocusDomRef(oItem);
if (!oItemDomRef) {
return;
}
oItemDomRef.setAttribute("tabindex", "-1");
aTabDomRefs.push(oItemDomRef);
if (oItem === oSelectedRootItem || oItem === this.oSelectedItem) {
iSelectedDomIndex = aTabDomRefs.indexOf(oItemDomRef);
}
}.bind(this));
if (this.$().hasClass("sapMITHEndOverflowList")) {
var oOverflowDomRef = this._getOverflow().getFocusDomRef();
oOverflowDomRef.setAttribute("tabindex", "-1");
aTabDomRefs.push(oOverflowDomRef);
}
//Initialize the ItemNavigation
if (!this._oItemNavigation) {
this._oItemNavigation = new ItemNavigation()
.setCycling(false)
.attachEvent(ItemNavigation.Events.FocusLeave, this._onItemNavigationFocusLeave, this)
.setDisabledModifiers({
sapnext : ["alt", "meta"],
sapprevious : ["alt", "meta"]
});
this.addDelegate(this._oItemNavigation);
}
//Reinitialize the ItemNavigation after rendering
this._oItemNavigation.setRootDomRef(this.getDomRef())
.setItemDomRefs(aTabDomRefs)
.setPageSize(aTabDomRefs.length) // set the page size equal to the tab number so when we press pageUp/pageDown to focus first/last tab
.setSelectedIndex(iSelectedDomIndex);
};
IconTabHeader.prototype.onThemeChanged = function () {
this._applyTabDensityMode();
};
IconTabHeader.prototype._applyTabDensityMode = function () {
var sTabDensityMode = this.getTabDensityMode();
this.$().removeClass("sapUiSizeCompact");
switch (sTabDensityMode) {
case IconTabDensityMode.Compact:
this.$().addClass("sapUiSizeCompact");
break;
case IconTabDensityMode.Inherit:
if (this.$().closest(".sapUiSizeCompact").length) {
this.$().addClass("sapUiSizeCompact");
}
break;
}
};
/**
* Fired when the theme is loaded
*
* @private
*/
IconTabHeader.prototype._handleThemeLoad = function () {
setTimeout(this._setItemsForStrip.bind(this), 350);
Core.detachThemeChanged(this._handleThemeLoad, this);
};
/*
* Destroys the item aggregation.
*/
IconTabHeader.prototype.destroyItems = function () {
this.oSelectedItem = null;
this._aTabKeys = [];
this.destroyAggregation("items");
return this;
};
IconTabHeader.prototype.addItem = function (oItem) {
if (!(oItem instanceof IconTabSeparator)) {
var sKey = oItem.getKey();
// check if key is a duplicate
if (this._aTabKeys.indexOf(sKey) !== -1) {
Log.warning("sap.m.IconTabHeader: duplicate key '" + sKey + "' inside the IconTabFilter. Please use unique keys.");
}
this._aTabKeys.push(sKey);
}
this.addAggregation("items", oItem);
this._invalidateParentIconTabBar();
return this;
};
IconTabHeader.prototype.insertItem = function (oItem, iIndex) {
if (!(oItem instanceof IconTabSeparator)) {
var sKey = oItem.getKey();
//check if key is a duplicate
if (this._aTabKeys.indexOf(sKey) !== -1) {
Log.warning("sap.m.IconTabHeader: duplicate key '" + sKey + "' inside the IconTabFilter. Please use unique keys.");
}
this._aTabKeys.push(sKey);
}
this.insertAggregation("items", oItem, iIndex);
this._invalidateParentIconTabBar();
};
IconTabHeader.prototype.removeAllItems = function () {
var oResult = this.removeAllAggregation("items");
this._aTabKeys = [];
this.oSelectedItem = null;
this._invalidateParentIconTabBar();
return oResult;
};
IconTabHeader.prototype.removeItem = function (oItem) {
// Make sure we have the actual Item and not just an ID
oItem = this.removeAggregation("items", oItem);
if (oItem && !(oItem instanceof IconTabSeparator)) {
var sKey = oItem.getKey();
this._aTabKeys.splice(this._aTabKeys.indexOf(sKey) , 1);
}
if (this.oSelectedItem === oItem) {
this.oSelectedItem = null;
}
this._invalidateParentIconTabBar();
// Return the original value from removeAggregation
return oItem;
};
IconTabHeader.prototype.updateAggregation = function () {
this.oSelectedItem = null;
Control.prototype.updateAggregation.apply(this, arguments);
this.invalidate();
};
IconTabHeader.prototype.removeAggregation = function (sAggregationName, oObject, bSuppressInvalidate) {
var aItems = this.getTabFilters();
var oItem = Control.prototype.removeAggregation.apply(this, arguments);
if (bSuppressInvalidate) {
return oItem;
}
if (!this._getPreserveSelection() && oItem && oItem == this.oSelectedItem && sAggregationName == 'items') {
var iIndexOf = (aItems ? Array.prototype.indexOf.call(aItems, oItem) : -1);
aItems = this.getTabFilters();
iIndexOf = Math.max(0, Math.min(iIndexOf, aItems.length - 1));
var oSelectedItem = aItems[iIndexOf];
if (oSelectedItem) {
this.setSelectedItem(oSelectedItem, true);
} else {
var oIconTabBar = this.getParent();
if (this._isInsideIconTabBar() && oIconTabBar.getExpanded()) {
oIconTabBar.$("content").children().remove();
}
}
}
return oItem;
};
IconTabHeader.prototype.removeAllAggregation = function (sAggregationName, bSuppressInvalidate) {
if (sAggregationName == 'items') {
var oIconTabBar = this.getParent();
if (this._isInsideIconTabBar() && oIconTabBar.getExpanded()) {
oIconTabBar.$("content").children().remove();
}
}
return Control.prototype.removeAllAggregation.apply(this, arguments);
};
/**
* Returns whether the currently selected item is preserved.
* @private
*/
IconTabHeader.prototype._getPreserveSelection = function () {
return this._bPreserveSelection;
};
/**
* Sets whether the currently selected item is preserved.
* @param {boolean} bPreserveSelection The new value
* @private
*/
IconTabHeader.prototype._setPreserveSelection = function (bPreserveSelection) {
this._bPreserveSelection = bPreserveSelection;
};
/**
* Returns the displayed text - text or text + (count)
* @private
*/
IconTabHeader.prototype._getDisplayText = function (oItem) {
var sText = oItem.getText();
if (this.isInlineMode()) {
var sCount = oItem.getCount();
if (sCount) {
if (this._bRtl) {
sText = '(' + sCount + ') ' + sText;
} else {
sText += ' (' + sCount + ')';
}
}
}
return sText;
};
/**
* Returns if the header is in inline mode.
* @private
*/
IconTabHeader.prototype.isInlineMode = function () {
return this.getMode() === IconTabHeaderMode.Inline;
};
/**
* Checks if all tabs are textOnly version.
* @private
* @returns {boolean} True if all tabs are textOnly version, otherwise false
*/
IconTabHeader.prototype._checkTextOnly = function () {
this._bTextOnly = this.getItems().every(function (oItem) {
return oItem instanceof IconTabSeparator || !oItem.getIcon();
});
return this._bTextOnly;
};
/**
* Checks if all tabs are noText version.
* @private
* @returns True if all tabs are noText version, otherwise false
*/
IconTabHeader.prototype._checkNoText = function (aItems) {
if (aItems.length > 0) {
for (var i = 0; i < aItems.length; i++) {
if (!(aItems[i] instanceof IconTabSeparator)) {
if (aItems[i].getText().length > 0) {
return false;
}
}
}
}
return true;
};
/**
* Checks if all tabs are in line version.
* @private
* @returns True if all tabs are in line version, otherwise false
*/
IconTabHeader.prototype._checkInLine = function (aItems) {
var oItem;
if (aItems.length > 0) {
for (var i = 0; i < aItems.length; i++) {
oItem = aItems[i];
if (!(oItem instanceof IconTabSeparator)) {
if (oItem.getIcon() || oItem.getCount()) {
this._bInLine = false;
return false;
}
}
}
}
this._bInLine = true;
return true;
};
/**
* @private
*/
IconTabHeader.prototype._getItemsInStrip = function () {
return this.getItems().filter(function (oItem) {
var oItemDomRef = oItem.getDomRef();
return oItemDomRef && !oItemDomRef.classList.contains("sapMITBFilterHidden");
});
};
/**
* @private
*/
IconTabHeader.prototype._setItemsForStrip = function () {
var aTabFilters = this.getVisibleTabFilters();
if (!Core.isThemeApplied() || !aTabFilters.length) {
return;
}
var oTabStrip = this.getDomRef("head");
if (!oTabStrip) {
// control has not been rendered, exit
return;
}
var oStartOverflow = this._getStartOverflow(),
oOverflow = this._getOverflow(),
aItems = this.getItems()
.filter(function (oItem) { return oItem.getDomRef(); })
.map(function (oItem) { return oItem.getDomRef(); }),
oSelectedItem = (this.oSelectedItem && this.oSelectedItem.getVisible()) ? this.oSelectedItem : aTabFilters[0],
oSelectedItemDomRef = (oSelectedItem._getRootTab() || oSelectedItem).getDomRef();
if (!aItems.length || !oSelectedItemDomRef) {
return;
}
// hide overflow tabs
oStartOverflow.$().removeClass("sapMITHOverflowVisible");
oOverflow.$().removeClass("sapMITHOverflowVisible");
this.$().removeClass("sapMITHStartOverflowList");
this.$().removeClass("sapMITHEndOverflowList");
// reset all display styles and their initial order to calculate items' width
aItems.forEach(function (oItem) {
oItem.classList.remove("sapMITBFilterHidden");
});
var iTotalWidthItems = aItems.reduce(function (iSum, oDomRef) {
return iSum + jQuery(oDomRef).outerWidth(true);
}, 0),
bHasOverflow = iTotalWidthItems > oTabStrip.offsetWidth;
if (!bHasOverflow) {
return;
}
switch (this.getTabsOverflowMode()) {
case TabsOverflowMode.StartAndEnd:
this._updateStartAndEndOverflow(aItems, oSelectedItemDomRef);
break;
case TabsOverflowMode.End:
default:
this._updateEndOverflow(aItems, oSelectedItemDomRef);
break;
}
};
IconTabHeader.prototype._updateEndOverflow = function (aItems, oSelectedItemDomRef) {
var oOverflow = this._getOverflow(),
oTabStrip = this.getDomRef("head"),
iTabStripWidth,
iLastVisible,
mSelectedItem,
i;
oOverflow.$().addClass("sapMITHOverflowVisible");
this.$().addClass("sapMITHEndOverflowList");
iTabStripWidth = oTabStrip.offsetWidth;
mSelectedItem = this._getSelectedItemIndexAndSize(aItems, oSelectedItemDomRef);
iLastVisible = this._findLastVisibleItem(aItems, iTabStripWidth, mSelectedItem.width);
for (i = iLastVisible + 1; i < aItems.length; i++) {
aItems[i].classList.add("sapMITBFilterHidden");
}
oOverflow._updateExpandButtonBadge();
};
IconTabHeader.prototype._updateStartAndEndOverflow = function (aItems, oSelectedItemDomRef) {
var oStartOverflow = this._getStartOverflow(),
oOverflow = this._getOverflow(),
oTabStrip = this.getDomRef("head"),
iTabStripWidth = oTabStrip.offsetWidth,
mSelectedItem = this._getSelectedItemIndexAndSize(aItems, oSelectedItemDomRef),
bHasStartOverflow = this._hasStartOverflow(iTabStripWidth, aItems, mSelectedItem),
bHasEndOverflow = this._hasEndOverflow(iTabStripWidth, aItems, mSelectedItem),
iFirstVisible,
iLastVisible,
i;
// has "end", but no "start" overflow
if (!bHasStartOverflow) {
oOverflow.$().addClass("sapMITHOverflowVisible");
this.$().addClass("sapMITHEndOverflowList");
// width has changed after the overflow became visible
iTabStripWidth = oTabStrip.offsetWidth;
iLastVisible = this._findLastVisibleItem(aItems, iTabStripWidth, mSelectedItem.width);
for (i = iLastVisible + 1; i < aItems.length; i++) {
aItems[i].classList.add("sapMITBFilterHidden");
}
oOverflow._updateTabCountText();
oOverflow._updateExpandButtonBadge();
return;
}
// has "start", but no "end" overflow
if (!bHasEndOverflow) {
oStartOverflow.$().addClass("sapMITHOverflowVisible");
this.$().addClass("sapMITHStartOverflowList");
// width has changed after the overflow became visible
iTabStripWidth = oTabStrip.offsetWidth;
iFirstVisible = this._findFirstVisibleItem(aItems, iTabStripWidth, mSelectedItem.width);
for (i = iFirstVisible - 1; i >= 0; i--) {
aItems[i].classList.add("sapMITBFilterHidden");
}
oStartOverflow._updateTabCountText();
oStartOverflow._updateExpandButtonBadge();
return;
}
// has "start" and "end" overflows
oStartOverflow.$().addClass("sapMITHOverflowVisible");
this.$().addClass("sapMITHStartOverflowList");
oOverflow.$().addClass("sapMITHOverflowVisible");
this.$().addClass("sapMITHEndOverflowList");
// width has changed after the overflow became visible
iTabStripWidth = oTabStrip.offsetWidth;
iFirstVisible = this._findFirstVisibleItem(aItems, iTabStripWidth, mSelectedItem.width, mSelectedItem.index - 1);
iLastVisible = this._findLastVisibleItem(aItems, iTabStripWidth, mSelectedItem.width, iFirstVisible);
for (i = iFirstVisible - 1; i >= 0; i--) {
aItems[i].classList.add("sapMITBFilterHidden");
}
for (i = iLastVisible + 1; i < aItems.length; i++) {
aItems[i].classList.add("sapMITBFilterHidden");
}
oStartOverflow._updateExpandButtonBadge();
oStartOverflow._updateTabCountText();
oOverflow._updateTabCountText();
oOverflow._updateExpandButtonBadge();
};
IconTabHeader.prototype._hasStartOverflow = function (iTabStripWidth, aItems, mSelectedItem) {
if (mSelectedItem.index === 0) {
return false;
}
var i,
iLeftItemsWidth = 0;
for (i = mSelectedItem.index - 1; i >= 0; i--) {
iLeftItemsWidth += this._getItemSize(aItems[i]);
}
var bHasStartOverflow = iTabStripWidth < iLeftItemsWidth + mSelectedItem.width;
// if there is no "start" overflow, it has "end" overflow
// check it again with the "end" overflow
if (!bHasStartOverflow) {
this._getOverflow().$().addClass("sapMITHOverflowVisible");
this.$().addClass("sapMITHEndOverflowList");
iTabStripWidth = this.getDomRef("head").offsetWidth;
bHasStartOverflow = iTabStripWidth < iLeftItemsWidth + mSelectedItem.width;
this._getOverflow().$().removeClass("sapMITHOverflowVisible");
this.$().removeClass("sapMITHEndOverflowList");
}
return bHasStartOverflow;
};
IconTabHeader.prototype._hasEndOverflow = function (iTabStripWidth, aItems, mSelectedItem) {
if (mSelectedItem.index >= aItems.length) {
return false;
}
var i,
iRightItemsWidth = 0;
for (i = mSelectedItem.index; i < aItems.length; i++) {
iRightItemsWidth += this._getItemSize(aItems[i]);
}
var bHasEndOverflow = iTabStripWidth < iRightItemsWidth + mSelectedItem.width;
// if there is no "end" overflow, it has "start" overflow
// check it again with the "start" overflow
if (!bHasEndOverflow) {
this._getStartOverflow().$().addClass("sapMITHOverflowVisible");
this.$().addClass("sapMITHStartOverflowList");
iTabStripWidth = this.getDomRef("head").offsetWidth;
bHasEndOverflow = iTabStripWidth < iRightItemsWidth + mSelectedItem.width;
this._getStartOverflow().$().removeClass("sapMITHOverflowVisible");
this.$().removeClass("sapMITHStartOverflowList");
}
return bHasEndOverflow;
};
IconTabHeader.prototype._getSelectedItemIndexAndSize = function (aItems, oSelectedItemDomRef) {
var iSelectedItemIndex = aItems.indexOf(oSelectedItemDomRef),
iSelectedItemSize = this._getItemSize(oSelectedItemDomRef),
oSelectedSeparator;
if (aItems[iSelectedItemIndex - 1] && aItems[iSelectedItemIndex - 1].classList.contains("sapMITBSep")) {
oSelectedSeparator = aItems[iSelectedItemIndex - 1];
iSelectedItemSize += this._getItemSize(oSelectedSeparator);
}
aItems.splice(iSelectedItemIndex, 1);
// if previous item is a separator - remove it
if (oSelectedSeparator) {
aItems.splice(iSelectedItemIndex - 1, 1);
iSelectedItemIndex--;
}
return {
index: iSelectedItemIndex,
width: iSelectedItemSize
};
};
IconTabHeader.prototype._findFirstVisibleItem = function (aItems, iTabStripWidth, iSelectedItemWidth, iStartIndex) {
var iLastVisible,
iIndex,
iItemSize;
if (iStartIndex === undefined) {
iStartIndex = aItems.length - 1;
}
iLastVisible = iStartIndex + 1;
for (iIndex = iStartIndex; iIndex >= 0; iIndex--) {
iItemSize = this._getItemSize(aItems[iIndex]);
if (iTabStripWidth < iSelectedItemWidth + iItemSize) {
break;
}
iSelectedItemWidth += iItemSize;
iLastVisible = iIndex;
}
return iLastVisible;
};
IconTabHeader.prototype._findLastVisibleItem = function (aItems, iTabStripWidth, iSelectedItemWidth, iStartIndex) {
var iLastVisible,
iIndex,
iItemSize;
iStartIndex = iStartIndex || 0;
iLastVisible = iStartIndex - 1;
for (iIndex = iStartIndex; iIndex < aItems.length; iIndex++) {
iItemSize = this._getItemSize(aItems[iIndex]);
if (iTabStripWidth < iSelectedItemWidth + iItemSize) {
break;
}
iSelectedItemWidth += iItemSize;
iLastVisible = iIndex;
}
// if prev item is separator - hide it
var oPrevItem = aItems[iIndex - 1];
if (oPrevItem && oPrevItem.classList.contains("sapMITBSep")) {
iLastVisible -= 1;
}
return iLastVisible;
};
IconTabHeader.prototype._getItemSize = function (oItemDomRef) {
var oStyle = window.getComputedStyle(oItemDomRef),
iWidth = oItemDomRef.offsetWidth,
iMargins = Number.parseInt(oStyle.marginLeft) + Number.parseInt(oStyle.marginRight);
return iWidth + iMargins;
};
IconTabHeader.prototype._hasSubItems = function () {
var aTabFilters = this.getTabFilters(),
i;
for (i = 0; i < aTabFilters.length; i++) {
if (aTabFilters[i].getItems().length > 0) {
return true;
}
}
return false;
};
/**
* Handles the activation of the tabs and arrows.
* @private
*/
IconTabHeader.prototype._handleActivation = function(oEvent) {
var sTargetId = oEvent.target.id,
oControl = oEvent.srcControl,
sControlId,
$target = jQuery(oEvent.target);
if (oControl instanceof Button) {
return;
}
var $sTargetId = jQuery(document.getElementById(sTargetId));
/*eslint-disable no-empty */
// TODO check better implementation
if ($sTargetId.parents() && Array.prototype.indexOf.call($sTargetId.parents(), this.$("content")[0]) > -1) {
/*eslint-enable no-empty */
//do nothing because element is inside content
} else {
if (sTargetId) {
// For items: do not navigate away! Stay on the page and handle the click in-place. Right-click + "Open in new Tab" still works.
oEvent.preventDefault();
// should be one of the items - select it
if ($target.hasClass('sapMITBFilterIcon') || $target.hasClass('sapMITBCount') || $target.hasClass('sapMITBText') || $target.hasClass('sapMITBTab') || $target.hasClass('sapMITBContentArrow') || $target.hasClass('sapMITBSep') || $target.hasClass('sapMITBSepIcon')) {
// click on icon: fetch filter instead
sControlId = oEvent.srcControl.getId().replace(/-icon$/, "");
oControl = Core.byId(sControlId);
if (oControl.getMetadata().isInstanceOf("sap.m.IconTab") && !(oControl instanceof IconTabSeparator)) {
if (this._isUnselectable(oControl)) {
if (oControl.getItems().length || oControl._isOverflow()) {
oControl._expandButtonPress();
}
return;
}
if ((oControl === this._getOverflow()) || (oControl === this._getStartOverflow())) {
oControl._expandButtonPress();
return;
}
this.setSelectedItem(oControl);
}
} else if (oControl.getMetadata().isInstanceOf("sap.m.IconTab") && !(oControl instanceof IconTabSeparator)) {
// select item if it is an iconTab but not a separator
if (this._isUnselectable(oControl)) {
if (oControl.getItems().length || oControl._isOverflow()) {
oControl._expandButtonPress();
}
return;
}
if ((oControl === this._getOverflow()) || (oControl === this._getStartOverflow())) {
oControl._expandButtonPress();
return;
}
this.setSelectedItem(oControl);
}
} else {
//no target id, so we have to check if showAll is set or it's a text only item, because clicking on the number then also leads to selecting the item
if (oControl.getMetadata().isInstanceOf("sap.m.IconTab") && !(oControl instanceof IconTabSeparator)) {
if (this._isUnselectable(oControl)) {
if (oControl.getItems().length || oControl._isOverflow()) {
oControl._expandButtonPress();
}
return;
}
if ((oControl === this._getOverflow()) || (oControl === this._getStartOverflow())) {
oControl._expandButtonPress();
return;
}
this.setSelectedItem(oControl);
}
}
}
};
/**
* Resize handling.
* @private
*/
IconTabHeader.prototype._fnResize = function() {
if (this._getOverflow()._oPopover) {
this._getOverflow()._oPopover.close();
}
if (this._getStartOverflow()._oPopover) {
this._getStartOverflow()._oPopover.close();
}
this._setItemsForStrip();
this._initItemNavigation();
};
/**
* Checks if a IconTabFilter is unable to be selected.
* This instance of the IconTabHeader must be within an IconTabBar and the IconTabBar must have no content aggregation set.
* The passed IconTabFilter instance must not be nested, has to have its items aggregation set and not have content aggregation set.
* @private
* @param {sap.m.IconTabFilter} oIconTabFilter The instance to check
* @returns {boolean}
*/
IconTabHeader.prototype._isUnselectable = function (oIconTabFilter) {
var oFilter = oIconTabFilter._getRealTab();
return !oFilter.getEnabled() || (this._isInsideIconTabBar() && !this.getParent().getContent().length &&
oFilter._getNestedLevel() === 1 && oFilter.getItems().length && !oFilter.getContent().length) ||
oFilter._isOverflow();
};
/**
* Returns if the control is inside an IconTabBar.
* @private
*/
IconTabHeader.prototype._isInsideIconTabBar = function() {
var oParent = this.getParent();
return oParent instanceof Control && oParent.isA('sap.m.IconTabBar');
};
/**
* Returns if the control is inside a sap.tnt.ToolHeader.
* @private
*/
IconTabHeader.prototype._isInsideToolHeader = function() {
var oParent = this.getParent();
return oParent instanceof Control && oParent.isA('sap.tnt.ToolHeader');
};
/**
* Invalidates the parent if it is an IconTabBar
* @private
*/
IconTabHeader.prototype._invalidateParentIconTabBar = function() {
if (this._isInsideIconTabBar()) {
this.getParent().invalidate();
}
};
/**
* @override
*/
//overwritten method, returns for most cases the iconDomRef. if the given tab has no icon, the textDomRef is returned.
IconTabHeader.prototype.getFocusDomRef = function (oFocusTab) {
var oTab = oFocusTab || this.oSelectedItem;
if (!oTab) {
return null;
}
return oTab.getDomRef();
};
IconTabHeader.prototype.applyFocusInfo = function (oFocusInfo) {
//sets the focus depending on the used IconTabFilter
if (oFocusInfo.focusDomRef) {
jQuery(oFocusInfo.focusDomRef).trigger("focus");
}
};
/**
* Sets a selected item.
* If no key is provided, or if the item is not visible, the first visible item will be selected.
*
* @private
*/
IconTabHeader.prototype._updateSelection = function () {
var aItems = this.getItems(),
sSelectedKey = this.getSelectedKey(),
i = 0,
bIsParentIconTabBar = this._isInsideIconTabBar(),
bIsParentToolHeader = this._isInsideToolHeader();
if (!aItems.length) {
return;
}
if (!this.oSelectedItem || sSelectedKey && sSelectedKey !== this.oSelectedItem._getNonEmptyKey()) {
// selected key is specified by API: set oSelectedItem to the item specified by key
if (sSelectedKey) {
this.oSelectedItem = this._findItemByKey(sSelectedKey);
}
// no key and no item, we set the first visible item as selected
if (!this.oSelectedItem && (bIsParentIconTabBar || !sSelectedKey)) {
for (i = 0; i < aItems.length; i++) { // tab item
if (!(aItems[i] instanceof IconTabSeparator) && aItems[i].getVisible()) {
this.oSelectedItem = aItems[i];
break;
}
}
}
}
//in case the selected tab is not visible anymore, the selected tab will change to the first visible tab
if (!bIsParentToolHeader && this.oSelectedItem && !this.oSelectedItem.getVisible()) {
for (i = 0; i < aItems.length; i++) { // tab item
if (!(aItems[i] instanceof IconTabSeparator) && aItems[i].getVisible()) {
this.oSelectedItem = aItems[i];
break;
}
}
}
if (!this.oSelectedItem) {
return;
}
// if candidate selected item is unselectable, instead select its first available child item that has content
if (this._isUnselectable(this.oSelectedItem)) {
this.setSelectedItem(this.oSelectedItem._getFirstAvailableSubFilter(), true);
return;
}
this.setProperty("selectedKey", this.oSelectedItem._getNonEmptyKey(), true);
};
/**
* Returns the item or nested item with the given key.
* @private
* @param {string} sKey The key to search with.
* @returns {sap.m.IconTabFilter} The found item.
*/
IconTabHeader.prototype._findItemByKey = function (sKey) {
var aTabFilters = this.getTabFilters(),
aSubFilters;
for (var i = 0; i < aTabFilters.length; i++) {
if (aTabFilters[i]._getNonEmptyKey() === sKey) {
return aTabFilters[i];
}
aSubFilters = aTabFilters[i]._getAllSubFilters();
for (var j = 0; j < aSubFilters.length; j++) {
if (aSubFilters[j]._getNonEmptyKey() === sKey) {
return aSubFilters[j];
}
}
}
};
/**
* Applies classes and attributes to the selected item.
* If the item is nested, it also applies them to the root of the item.
* @private
*/
IconTabHeader.prototype._applySelectionToFilters = function () {
if (this._isInsideIconTabBar() && !this.getParent().getExpanded()) {
return;
}
this.oSelectedItem.$()
.addClass("sapMITBSelected")
.attr({ 'aria-selected': true });
if (this.oSelectedItem._getNestedLevel() !== 1) {
var oSelectedRootItem = this.oSelectedItem._getRootTab();
oSelectedRootItem.$()
.addClass("sapMITBSelected")
.attr({ "aria-selected": true });
}
};
/**
* Removes classes and attributes added by "_applySelectionToFilters"
* @private
*/
IconTabHeader.prototype._removeSelectionFromFilters = function () {
this.oSelectedItem.$()
.removeClass("sapMITBSelected")
.attr({ 'aria-selected': false });
if (this.oSelectedItem._getNestedLevel() !== 1) {
var oSelectedRootItem = this.oSelectedItem._getRootTab();
oSelectedRootItem.$()
.removeClass("sapMITBSelected")
.attr({ "aria-selected": false });
}
};
IconTabHeader.prototype._getItemsForOverflow = function (bIsStartOverflow, bTopLevelTabs) {
var aItemsInStrip = this._getItemsInStrip(),
bIsStartAndEndMode = this.getTabsOverflowMode() === TabsOverflowMode.StartAndEnd,
iIndex,
aItems = this.getItems(),
aItemsForList = [];
if (bIsStartAndEndMode) {
iIndex = aItems.indexOf(aItemsInStrip[0]);
aItems = bIsStartOverflow ? aItems.slice(0, iIndex) : aItems.slice(iIndex, aItems.length);
}
aItems.forEach(function (oItem) {
// If tab is an overflow tab and oItem is already in Tab Strip, do not add it to list
// on a mobile device, this behavior doesn't occur, and all items are shown
if (!Device.system.phone && aItemsInStrip.indexOf(oItem) > -1) {
return;
}
aItemsForList.push(oItem);
if (oItem.isA("sap.m.IconTabFilter") && !bTopLevelTabs) {
oItem._getAllSubItems().forEach(function (oSubItem) {
aItemsForList.push(oSubItem);
});
}
});
return aItemsForList;
};
/* =========================================================== */
/* begin: event handlers */
/* =========================================================== */
/**
* Initializes activating a tab on the IconTabHeader.
*
* @param {jQuery.Event} oEvent
* @private
*/
IconTabHeader.prototype.ontouchstart = function(oEvent) {
var oTargetTouch = oEvent.targetTouches[0];
// store touch state
this._iActiveTouch = oTargetTouch.identifier;
};
/**
* Handles touch end and events and triggers selection if bar was not dragged.
*
* @param {jQuery.Event} oEvent
* @private
*/
IconTabHeader.prototype.ontouchend = function(oEvent) {
if (this._iActiveTouch === undefined) {
return;
}
var MOBILE_TAP = 0;
var LEFT_MOUSE_CLICK = 1;
var LUMIA_TOUCH; // undefined on Lumia phone
if (oEvent.which === LUMIA_TOUCH || oEvent.which === MOBILE_TAP || oEvent.which === LEFT_MOUSE_CLICK) {
this._handleActivation(oEvent);
}
this._iActiveTouch = undefined;
};
/**
* Handles the touch cancel event.
*
* @param {jQuery.Event} oEvent The event object
* @private
*/
IconTabHeader.prototype.ontouchcancel = IconTabHeader.prototype.ontouchend;
/**
* Handle the key down event for SPACE and ENTER.
* @param {jQuery.Event} oEvent - the keyboard event.
* @private
*/
IconTabHeader.prototype.onkeydown = function(oEvent) {
switch (oEvent.which) {
case KeyCodes.ENTER:
this._handleActivation(oEvent);
oEvent.preventDefault();
break;
case KeyCodes.SPACE:
oEvent.preventDefault(); //