@openui5/sap.m
Version:
OpenUI5 UI Library sap.m
792 lines (639 loc) • 22 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.
*/
sap.ui.define([
'./library',
'sap/ui/core/Core',
'sap/ui/core/Element',
'sap/ui/Device',
"sap/ui/dom/isHidden",
'sap/ui/core/ResizeHandler',
'./ListItemBase',
'./Button',
'./ToolbarSeparator',
'sap/m/OverflowToolbar',
'sap/m/OverflowToolbarLayoutData',
'sap/ui/events/KeyCodes',
'sap/ui/core/IconPool',
'sap/ui/core/Icon',
'sap/ui/core/library'
],
function (library,
Core,
Element,
Device,
isHidden,
ResizeHandler,
ListItemBase,
Button,
ToolbarSeparator,
OverflowToolbar,
OverflowToolbarLayoutData,
KeyCodes,
IconPool,
Icon,
coreLibrary) {
'use strict';
var NLI_RANGE_SET = "NLIRangeSet";
Device.media.initRangeSet(NLI_RANGE_SET, [600], "px", ["S", "M"], true);
// shortcut for sap.ui.core.Priority
var Priority = coreLibrary.Priority;
// shortcut for sap.m.ButtonType
var ButtonType = library.ButtonType;
// shortcut for sap.m.ToolbarStyle
var ToolbarStyle = library.ToolbarStyle;
// shortcut for sap.m.OverflowToolbarPriority
var OverflowToolbarPriority = library.OverflowToolbarPriority;
var resourceBundle = Core.getLibraryResourceBundle('sap.m'),
closeText = resourceBundle.getText('NOTIFICATION_LIST_ITEM_CLOSE'), // this is used for tooltip for the "X" button and the text of the button "X" when it is in the overflow toolbar on mobile
closeAllText = resourceBundle.getText('NOTIFICATION_LIST_GROUP_CLOSE'); // this is used for tooltip for the "X" button and the text of the button "X" when it is in the overflow toolbar on mobile
/**
* Constructor for a new <code>NotificationListBase</code>.
*
* @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 NotificationListBase is the abstract base class for {@link sap.m.NotificationListItem} and {@link sap.m.NotificationListGroup}.
*
* The NotificationList controls are designed for the SAP Fiori notification center.
* <h4>Overview</h4>
* NotificationListBase defines the general structure of a notification item. Most of the behavioral logic is defined for the single items or groups.
*
* <h4>Structure</h4>
* The base holds properties for the following elements:
* <ul>
* <li>Author name</li>
* <li>Author picture</li>
* <li>Time stamp</li>
* <li>Priority</li>
* <li>Title</li>
* </ul>
* Additionally, by setting these properties you can determine if buttons are shown:
* <ul>
* <li><code>showButtons</code> - action buttons visibility</li>
* <li><code>showCloseButton</code> - close button visibility</li>
* </ul>
*
* <h4>Note</h4>
* There are several properties, that are inherited from <code>ListItemBase</code> and have no
* visual representation in the Notifications - <code>counter</code>, <code>highlight</code>, <code>highlightText</code>, <code>navigated</code>, <code>selected</code>, <code>type</code>
* @extends sap.m.ListItemBase
*
* @author SAP SE
* @version 1.117.4
*
* @constructor
* @public
* @abstract
* @since 1.38
* @alias sap.m.NotificationListBase
*/
var NotificationListBase = ListItemBase.extend('sap.m.NotificationListBase', /** @lends sap.m.NotificationListBase.prototype */ {
metadata: {
library: 'sap.m',
"abstract": true,
properties: {
// unread is inherit from the ListItemBase.
/**
* Determines the priority of the Notification.
*/
priority: {type: 'sap.ui.core.Priority', group: 'Appearance', defaultValue: Priority.None},
/**
* Determines the title of the NotificationListBase item.
*/
title: {type: 'string', group: 'Appearance', defaultValue: ''},
/**
* The time stamp of the Notification.
*/
datetime: {type: 'string', group: 'Appearance', defaultValue: ''},
/**
* Determines the action buttons visibility.
*
* <b>Note:</b> Action buttons are not shown when Notification List Groups are collapsed.
*/
showButtons: {type: 'boolean', group: 'Behavior', defaultValue: true},
/**
* Determines the visibility of the close button.
*/
showCloseButton: {type: 'boolean', group: 'Behavior', defaultValue: true},
/**
* Determines the notification author name.
*/
authorName: {type: 'string', group: 'Appearance', defaultValue: ''},
/**
* Determines the URL of the notification author picture.
*/
authorPicture: {type: 'sap.ui.core.URI'}
},
aggregations: {
/**
* Action buttons.
*/
buttons: {type: 'sap.m.Button', multiple: true},
/**
* Close button.
* @private
*/
_closeButton: {type: 'sap.m.Button', multiple: false, visibility: "hidden"},
/**
* The overflow toolbar.
* @private
*/
_overflowToolbar: {type: 'sap.m.OverflowToolbar', multiple: false, visibility: "hidden"},
/**
* The priority icon.
* @private
*/
_priorityIcon: {type: 'sap.ui.core.Icon', multiple: false, visibility: "hidden"}
},
events: {
/**
* Fired when the close button of the notification is pressed.<br><b>Note:</b> Pressing the close button doesn't destroy the notification automatically.
*/
close: {}
// 'tap' and 'press' events are inherited from ListItemBase.
}
},
renderer: null // this class has no renderer (it is abstract)
});
// overrides ListItemBase method
NotificationListBase.prototype._activeHandling = function () {
};
// overrides ListItemBase method
NotificationListBase.prototype.updateSelectedDOM = function () {
};
NotificationListBase.prototype.getAccessibilityText = function () {
return '';
};
/**
* @override
*/
NotificationListBase.prototype.setProperty = function () {
this._resetButtonsOverflow();
return ListItemBase.prototype.setProperty.apply(this, arguments);
};
NotificationListBase.prototype.getButtons = function () {
var closeButton = this._getCloseButton(),
toolbarSeparator = this._getToolbarSeparator();
return this._getOverflowToolbar().getContent().filter(function (item) {
return item !== closeButton && item !== toolbarSeparator;
}, this);
};
NotificationListBase.prototype.addButton = function (oButton) {
var overflowToolbar = this._getOverflowToolbar(),
index = overflowToolbar.getContent().length;
if (this._getToolbarSeparator()) {
index -= 2;
}
overflowToolbar.insertContent(oButton, index);
this._resetButtonsOverflow();
this.invalidate();
return this;
};
NotificationListBase.prototype.insertButton = function (oButton, index) {
this._getOverflowToolbar().insertContent(oButton, index);
this._resetButtonsOverflow();
this.invalidate();
return this;
};
NotificationListBase.prototype.removeButton = function (oButton) {
var result = this._getOverflowToolbar().removeContent(oButton.getId());
this._resetButtonsOverflow();
this.invalidate();
return result;
};
NotificationListBase.prototype.removeAllButtons = function () {
var overflowToolbar = this._getOverflowToolbar(),
buttons = this.getButtons();
buttons.forEach(function (button) {
overflowToolbar.removeContent(button);
});
this._resetButtonsOverflow();
this.invalidate();
return this;
};
NotificationListBase.prototype.destroyButtons = function () {
var buttons = this.getButtons();
buttons.forEach(function (button) {
button.destroy();
});
this._resetButtonsOverflow();
this.invalidate();
return this;
};
/* Clones the NotificationListBase.
*
* @public
* @returns {this} The cloned NotificationListBase.
*/
NotificationListBase.prototype.clone = function () {
var clonedObject = ListItemBase.prototype.clone.apply(this, arguments);
// overflow toolbar has been created but the clone of this item does no longer have bindings for the “buttons” aggregation; workaround: destroy and create anew as clone
clonedObject.destroyAggregation('_overflowToolbar');
var overflowToolbar = this.getAggregation('_overflowToolbar');
if (overflowToolbar) {
clonedObject.setAggregation("_overflowToolbar", overflowToolbar.clone(), true);
}
return clonedObject;
};
NotificationListBase.prototype._getOverflowToolbar = function () {
var overflowToolbar = this.getAggregation('_overflowToolbar');
if (!overflowToolbar) {
overflowToolbar = new OverflowToolbar(this.getId() + '-overflowToolbar', {
style: ToolbarStyle.Clear
});
this.setAggregation("_overflowToolbar", overflowToolbar, true);
}
return overflowToolbar;
};
NotificationListBase.prototype._getCloseButton = function () {
var closeButton,
overflowToolbar,
overflowToolbarContent,
closeButtonIndex;
overflowToolbar = this._getOverflowToolbar();
overflowToolbarContent = overflowToolbar.getContent();
if (overflowToolbarContent.length) {
closeButtonIndex = overflowToolbarContent.length - 1;
closeButton = overflowToolbarContent[closeButtonIndex];
if (closeButton.getId() !== this.getId() + "-closeButtonX") {
closeButton = null;
}
}
if (!closeButton) {
closeButton = this.getAggregation("_closeButton");
}
return closeButton;
};
NotificationListBase.prototype._createCloseButton = function () {
var closeButton,
isNotificationListGroup = this.isA("sap.m.NotificationListGroup"),
isCollapsed = isNotificationListGroup && this.getCollapsed();
if (this._isSmallSize() && !isCollapsed) {
closeButton = new Button(this.getId() + '-closeButtonX', {
text: this.isA("sap.m.NotificationListItem") ? closeText : closeAllText,
type: ButtonType.Default,
press: function () {
this.close();
}.bind(this)
});
} else {
closeButton = new Button(this.getId() + '-closeButtonX', {
icon: IconPool.getIconURI('decline'),
type: ButtonType.Transparent,
tooltip: this.isA("sap.m.NotificationListItem") ? closeText : closeAllText,
press: function () {
this.close();
}.bind(this)
});
}
this.setAggregation("_closeButton", closeButton);
return closeButton;
};
NotificationListBase.prototype._getToolbarSeparator = function () {
var toolbarSeparator,
overflowToolbar = this._getOverflowToolbar(),
overflowToolbarContent = overflowToolbar.getContent(),
toolbarSeparatorIndex;
if (overflowToolbarContent.length) {
toolbarSeparatorIndex = overflowToolbarContent.length - 2;
toolbarSeparator = overflowToolbarContent[toolbarSeparatorIndex];
}
if (toolbarSeparator && toolbarSeparator.isA("sap.m.ToolbarSeparator")) {
return toolbarSeparator;
}
return null;
};
NotificationListBase.prototype._hasToolbarOverflowButton = function () {
var iMinLength = this._isSmallSize() ? 0 : 1;
return this.getShowButtons() && this.getButtons().length > iMinLength;
};
NotificationListBase.prototype._hasActionButtons = function () {
return this.getShowButtons() && this.getButtons().length;
};
NotificationListBase.prototype._shouldRenderCloseButton = function () {
return !this._isSmallSize() && this.getShowCloseButton();
};
NotificationListBase.prototype._shouldRenderOverflowToolbar = function () {
var hasActionButtons = this._hasActionButtons();
if (this._isSmallSize()) {
return hasActionButtons || this.getShowCloseButton();
}
return hasActionButtons;
};
NotificationListBase.prototype.onBeforeRendering = function () {
if (this._resizeListenerId) {
ResizeHandler.deregister(this._resizeListenerId);
this._resizeListenerId = null;
}
if (!this._sCurrentLayoutClassName) {
this._destroyCloseBtnAndSeparator();
}
};
NotificationListBase.prototype.onAfterRendering = function() {
if (this.getDomRef()) {
this._resizeListenerId = ResizeHandler.register(this.getDomRef(), this._onResize.bind(this));
}
this._onResize();
};
NotificationListBase.prototype.exit = function () {
if (this._resizeListenerId) {
ResizeHandler.deregister(this._resizeListenerId);
this._resizeListenerId = null;
}
this._sCurrentLayoutClassName = null;
};
NotificationListBase.prototype.onkeydown = function(event) {
var target = event.target;
switch (event.which) {
// Minus keys
// KeyCodes.MINUS is not returning 189
case 189:
case KeyCodes.NUMPAD_MINUS:
case KeyCodes.ARROW_LEFT:
if (target.classList.contains("sapMNLGroup")) {
this._collapse(event);
return;
}
break;
case KeyCodes.PLUS:
case KeyCodes.NUMPAD_PLUS:
case KeyCodes.ARROW_RIGHT:
if (target.classList.contains("sapMNLGroup")) {
this._expand(event);
return;
}
break;
case KeyCodes.F10:
if (target.classList.contains("sapMNLIB") && event.shiftKey && this._hasToolbarOverflowButton()) {
this._getOverflowToolbar()._getOverflowButton().firePress();
event.stopImmediatePropagation();
event.preventDefault();
return;
}
break;
}
this._focusSameItemOnNextRow(event);
};
NotificationListBase.prototype._focusSameItemOnNextRow = function (event) {
var list = this._getParentList(),
itemNavigation,
focusedIndex ,
itemDomRefs,
sourceControl,
listItemDomRef,
nextListItemControl,
nextFocusedDomRef;
if (!list) {
return;
}
if (event.which !== KeyCodes.ARROW_UP &&
event.which !== KeyCodes.ARROW_DOWN) {
return;
}
event.stopPropagation();
event.preventDefault();
itemNavigation = list.getItemNavigation();
if (!itemNavigation) {
return;
}
focusedIndex = itemNavigation.getFocusedIndex();
itemDomRefs = itemNavigation.getItemDomRefs();
switch (event.which) {
case KeyCodes.ARROW_UP:
do {
focusedIndex--;
} while (itemDomRefs[focusedIndex] && isHidden(itemDomRefs[focusedIndex]));
break;
case KeyCodes.ARROW_DOWN:
do {
focusedIndex++;
} while (itemDomRefs[focusedIndex] && isHidden(itemDomRefs[focusedIndex]));
break;
}
listItemDomRef = itemDomRefs[focusedIndex];
if (!listItemDomRef) {
return;
}
// focus the entire row first
listItemDomRef.focus();
if (this.getDomRef() === event.target) {
return;
}
sourceControl = Element.closestTo(event.target);
// collapse/expand button
if (sourceControl.getId() === this.getId() + "-collapseButton") {
nextFocusedDomRef = listItemDomRef.querySelector(":scope > .sapMNLGroupHeader .sapMNLGroupCollapseButton .sapMBtn");
if (nextFocusedDomRef) {
nextFocusedDomRef.focus();
}
return;
}
// "show more" link
if (sourceControl.isA("sap.m.Link")) {
nextFocusedDomRef = listItemDomRef.querySelector(":scope > .sapMNLIMain .sapMNLIShowMore a");
if (nextFocusedDomRef) {
nextFocusedDomRef.focus();
}
return;
}
nextListItemControl = Element.closestTo(listItemDomRef);
// close button
if (!sourceControl.getParent().isA("sap.m.OverflowToolbar")) {
if (!nextListItemControl._focusCloseButton()) {
nextListItemControl._focusToolbarButton();
}
return;
}
// toolbar button
if (!nextListItemControl._focusToolbarButton()) {
nextListItemControl._focusCloseButton();
}
};
NotificationListBase.prototype._focusCloseButton = function () {
if (this.getShowCloseButton() && this.getAggregation("_closeButton")) {
this.getAggregation("_closeButton").focus();
return true;
}
return false;
};
NotificationListBase.prototype._focusToolbarButton = function () {
var button,
overflowToolbar,
visibleContent;
if (this._shouldRenderOverflowToolbar()) {
overflowToolbar = this._getOverflowToolbar();
if (overflowToolbar._getOverflowButtonNeeded()) {
button = overflowToolbar._getOverflowButton();
} else {
visibleContent = overflowToolbar._getVisibleContent();
button = this._isSmallSize() ? visibleContent[visibleContent.length - 1] : visibleContent[0];
}
button.focus();
return true;
}
return false;
};
NotificationListBase.prototype._getParentList = function () {
var parent = this.getParent();
if (parent) {
if (parent.isA("sap.m.NotificationList")) {
return parent;
}
parent = parent.getParent();
if (parent && parent.isA("sap.m.NotificationList")) {
return parent;
}
}
return null;
};
NotificationListBase.prototype._collapse = function () { };
NotificationListBase.prototype._expand = function () { };
NotificationListBase.prototype._onResize = function () {
var oDomRef = this.getDomRef(),
oMediaRange,
sClassName;
if (!oDomRef) {
return;
}
oMediaRange = Device.media.getCurrentRange(NLI_RANGE_SET, oDomRef.offsetWidth);
sClassName = "sapMNLIB-Layout" + oMediaRange.name;
if (this._sCurrentLayoutClassName === sClassName) {
return;
}
if (this._sCurrentLayoutClassName) {
this.removeStyleClass(this._sCurrentLayoutClassName);
}
this.addStyleClass(sClassName);
this._sCurrentLayoutClassName = sClassName;
this._arrangeButtons();
};
NotificationListBase.prototype._destroyCloseBtnAndSeparator = function () {
var closeButton = this._getCloseButton(),
toolbarSeparator = this._getToolbarSeparator();
if (closeButton) {
closeButton.destroy();
}
if (toolbarSeparator) {
toolbarSeparator.destroy();
}
};
NotificationListBase.prototype._arrangeButtons = function () {
this._destroyCloseBtnAndSeparator();
this._createCloseButton();
if (this._isSmallSize()) {
this._arrangeSSizeButtons();
} else {
this._arrangeMSizeButtons();
}
};
NotificationListBase.prototype._arrangeMSizeButtons = function () {
var button,
buttons = this.getButtons(),
buttonOverflowPriorityType = buttons.length > 1 ? OverflowToolbarPriority.AlwaysOverflow : OverflowToolbarPriority.NeverOverflow;
for (var i = 0; i < buttons.length; i++) {
button = buttons[i];
button.setLayoutData(new OverflowToolbarLayoutData({
priority: buttonOverflowPriorityType
}));
}
};
NotificationListBase.prototype._arrangeSSizeButtons = function () {
var overflowToolbar = this._getOverflowToolbar(),
closeButton = this._getCloseButton(),
isNotificationListGroup = this.isA("sap.m.NotificationListGroup"),
buttonText = isNotificationListGroup ? closeAllText : closeText,
isCollapsed = isNotificationListGroup && this.getCollapsed(),
hasActionButtons = !isCollapsed && this._hasActionButtons(),
showCloseButton = this.getShowCloseButton(),
toolbarSeparator = new ToolbarSeparator(),
priority;
this.getButtons().forEach(function (button) {
if (hasActionButtons) {
priority = OverflowToolbarPriority.AlwaysOverflow;
button.removeStyleClass('sapMNLIBHiddenButton');
} else {
priority = OverflowToolbarPriority.NeverOverflow;
button.addStyleClass('sapMNLIBHiddenButton');
}
button.setLayoutData(new OverflowToolbarLayoutData({
priority: priority
}));
});
closeButton.setLayoutData(new OverflowToolbarLayoutData({
priority: OverflowToolbarPriority.AlwaysOverflow
}));
toolbarSeparator.setLayoutData(new OverflowToolbarLayoutData({
priority: OverflowToolbarPriority.AlwaysOverflow
}));
overflowToolbar.addContent(toolbarSeparator);
overflowToolbar.addContent(closeButton);
if (!showCloseButton) {
closeButton.setVisible(false);
toolbarSeparator.setVisible(false);
return;
}
closeButton.setVisible(true);
if (hasActionButtons) {
closeButton.setText(buttonText);
closeButton.setTooltip('');
closeButton.setType(ButtonType.Default);
closeButton.setIcon('');
closeButton.setLayoutData(new OverflowToolbarLayoutData({
priority: OverflowToolbarPriority.AlwaysOverflow
}));
toolbarSeparator.setVisible(true);
} else {
closeButton.setText('');
closeButton.setTooltip(buttonText);
closeButton.setType(ButtonType.Transparent);
closeButton.setIcon(IconPool.getIconURI('decline'));
closeButton.setLayoutData(new OverflowToolbarLayoutData({
priority: OverflowToolbarPriority.NeverOverflow
}));
toolbarSeparator.setVisible(false);
}
};
/**
* Closes the NotificationListBase.
*
* @public
*/
NotificationListBase.prototype.close = function () {
var parent = this.getParent();
this.fireClose();
var bHasParentAfterClose = !!this.getParent(); // no parent after close means the notification is removed or destroyed - in such case move the focus
if (!bHasParentAfterClose && parent && parent instanceof Element) {
var delegate = {
onAfterRendering: function () {
parent.focus();
parent.removeEventDelegate(delegate);
}
};
parent.addEventDelegate(delegate);
}
};
NotificationListBase.prototype._getPriorityIcon = function () {
var priorityIcon = this.getAggregation('_priorityIcon');
if (!priorityIcon) {
priorityIcon = new Icon({
src: 'sap-icon://message-error',
useIconTooltip: false
});
this.setAggregation("_priorityIcon", priorityIcon, true);
}
return priorityIcon;
};
NotificationListBase.prototype._isSmallSize = function () {
return this._sCurrentLayoutClassName === "sapMNLIB-LayoutS";
};
NotificationListBase.prototype._resetButtonsOverflow = function () {
// with this line, the actions buttons will be re-arranged
// next time when the "_onResize" is called
this._sCurrentLayoutClassName = null;
};
return NotificationListBase;
});