/*! * 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. */ sap.ui.define([ './library', './NotificationListBase', 'sap/ui/core/InvisibleText', './ListItemBase', 'sap/ui/core/IconPool', 'sap/ui/core/library', 'sap/ui/Device', 'sap/m/Button', './NotificationListGroupRenderer', "sap/ui/events/KeyCodes" ], function( library, NotificationListBase, InvisibleText, ListItemBase, IconPool, coreLibrary, Device, Button, NotificationListGroupRenderer, KeyCodes ) { 'use strict'; // shortcut for sap.ui.core.Priority var Priority = coreLibrary.Priority; // shortcut for sap.m.ButtonType var ButtonType = library.ButtonType; /** * Constructor for a new NotificationListGroup. * * @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 NotificationListItemGroup control is used for grouping {@link sap.m.NotificationListItem notification items} of the same type. *

Behavior

* The group handles specific behavior for different usecases: * * @extends sap.m.NotificationListBase * * @author SAP SE * @version 1.60.23 * * @constructor * @public * @since 1.34 * @alias sap.m.NotificationListGroup * @ui5-metamodel This control/element also will be described in the UI5 (legacy) designtime metamodel */ var NotificationListGroup = NotificationListBase.extend('sap.m.NotificationListGroup', /** @lends sap.m.NotificationListGroup.prototype */ { metadata: { library: 'sap.m', properties: { /** * Determines if the group is collapsed or expanded. */ collapsed: {type: 'boolean', group: 'Behavior', defaultValue: false}, /** * Determines if the group will automatically set the priority based on the highest priority of its notifications or get its priority from the developer. */ autoPriority: {type: 'boolean', group: 'Behavior', defaultValue: true}, /** * Determines if the group header/footer of the empty group will be always shown. By default groups with 0 notifications are not shown. */ showEmptyGroup: {type: 'boolean', group: 'Behavior', defaultValue: false}, /** * Determines if the collapse/expand button should be enabled for an empty group. */ enableCollapseButtonWhenEmpty: {type: 'boolean', group: 'Behavior', defaultValue: false} }, defaultAggregation : 'items', aggregations: { /** * The NotificationListItems inside the group. */ items: {type: 'sap.m.NotificationListItem', multiple: true, singularName: 'item'}, /** * The details of the NotificationListGroup that will be used to implement the ARIA specification */ _ariaDetailsText: {type: 'sap.ui.core.InvisibleText', multiple: false, visibility: 'hidden'} }, events: { /** * This event is called when collapse property value is changed * @since 1.44 */ onCollapse: { parameters: { /** * Indicates exact collapse direction */ collapsed: {type: 'boolean'} } } } } }); /** * Sets up the initial values of the control. * * @protected */ NotificationListGroup.prototype.init = function () { NotificationListBase.prototype.init.call(this); var resourceBundle = sap.ui.getCore().getLibraryResourceBundle('sap.m'); this._closeText = resourceBundle.getText('NOTIFICATION_LIST_BASE_CLOSE'); /** * @type {sap.m.Button} * @private */ var _closeButton = new Button(this.getId() + '-closeButton', { type: ButtonType.Transparent, icon: IconPool.getIconURI('decline'), tooltip: this._closeText, press: function () { this.close(); }.bind(this) }); this.setAggregation('_closeButton', _closeButton, true); /** * @type {sap.m.Button} * @private */ var _collapseButton = new Button({ type: ButtonType.Transparent, press: function () { this.setCollapsed(!this.getCollapsed()); }.bind(this) }); this.setAggregation('_collapseButton', _collapseButton, true); this._maxNumberReached = false; this._ariaLabbeledByIds = ''; this.setAggregation('_ariaDetailsText', new InvisibleText()); /** * Resource bundle used for translation * @private */ this._resourceBundle = sap.ui.getCore().getLibraryResourceBundle('sap.m'); }; //================================================================================ // Overwritten setters and getters //================================================================================ /** * Overwrites the setter for collapsed property. * * @override * @public * @param {boolean} Collapsed Collapsed indicator. * @returns {sap.m.NotificationListGroup} this NotificationListGroup reference for chaining. */ NotificationListGroup.prototype.setCollapsed = function (collapsed) { this._toggleCollapsed(); //Setter overwritten to suppress invalidation this.setProperty('collapsed', collapsed, true); this.fireOnCollapse({collapsed: collapsed}); return this; }; /** * Overrides the getter for priority property. * * @override * @public * @returns {sap.ui.core.Priority} Items by priority. */ NotificationListGroup.prototype.getPriority = function () { //If the autoPriority flag is off then return what has been set by the developer if (!this.getAutoPriority()) { return this.getProperty('priority'); } /** @type {sap.m.NotificationListItem[]} */ var notifications = this.getAggregation('items'); /** @type {sap.ui.core.Priority|string} */ var priority = Priority.None; if (notifications) { notifications.forEach(function (item) { priority = comparePriority(priority, item.getPriority()); }); } else { priority = this.getProperty('priority'); } return priority; }; /** * Overwrites the getter for unread property. * * @override * @public * @returns {boolean} Unread items. */ NotificationListGroup.prototype.getUnread = function () { /** @type {sap.m.NotificationListItem[]} */ var notifications = this.getItems(); if (notifications.length) { return notifications.some(function (item) { return item.getUnread(); }); } return this.getProperty('unread'); }; //================================================================================ // Control methods //================================================================================ /** * Overwrites the onBeforeRendering. * * @overwrites * @public */ NotificationListGroup.prototype.onBeforeRendering = function() { /** @type {sap.m.NotificationListItem[]} */ var notifications = this.getItems(); var notificationsCount = notifications.length; var collapseButton = this.getAggregation('_collapseButton'); this._maxNumberOfNotifications = Device.system.desktop ? 400 : 100; collapseButton.setEnabled(this._getCollapseButtonEnabled(), true); this._maxNumberReached = notificationsCount > this._maxNumberOfNotifications; notifications.forEach(function (item) { item.addEventDelegate({onfocusin: this._notificationFocusHandler}, this); item.addEventDelegate({onkeydown: this._notificationNavigationHandler}, this); }.bind(this)); this._updateAccessibilityInfo(); this._updateCollapseButtonText(this.getCollapsed()); this._maxNumberOfNotificationsTitle = this._resourceBundle.getText('NOTIFICATION_LIST_GROUP_MAX_NOTIFICATIONS_TITLE', notificationsCount - this._maxNumberOfNotifications); this._maxNumberOfNotificationsBody = this._resourceBundle.getText('NOTIFICATION_LIST_GROUP_MAX_NOTIFICATIONS_BODY'); }; //================================================================================ // Private and protected getters and setters //================================================================================ /** * Returns the sap.m.Title control used in the NotificationListGroup's title. * * @private * @returns {sap.m.Text} The hidden title control aggregation used in the group title. */ NotificationListGroup.prototype._getHeaderTitle = function () { /** @type {sap.m.Text} */ var title = NotificationListBase.prototype._getHeaderTitle.call(this); title.addStyleClass('sapMNLG-Title'); if (this.getUnread()) { title.addStyleClass('sapMNLGTitleUnread'); } return title; }; /** * Returns the sap.m.Text control used in the NotificationListGroup's datetime. * * @private * @returns {sap.m.Text} The hidden text control aggregation used in the group's timestamp. */ NotificationListGroup.prototype._getDateTimeText = function () { /** @type {sap.m.Text} */ var dateTime = NotificationListBase.prototype._getDateTimeText.call(this); dateTime.setTextAlign('End'); return dateTime; }; //================================================================================ // Private and protected internal methods //================================================================================ /** * Toggles the NotificationListGroup state between collapsed/expanded. * * @private */ NotificationListGroup.prototype._toggleCollapsed = function () { /** @type {boolean} */ var newCollapsedState = !this.getCollapsed(); this._updateCollapseButtonText(newCollapsedState); this.$().toggleClass('sapMNLG-Collapsed', newCollapsedState); this.$().toggleClass('sapMNLG-NoNotifications', this._getVisibleItemsCount() <= 0); }; /** * Gets the number of visible NotificationListItems inside the group. * * @private * @returns {number} The number of visible notifications. */ NotificationListGroup.prototype._getVisibleItemsCount = function () { /** @type {sap.m.NotificationListItem[]} */ var items = this.getItems(); var result = 0; items.forEach(function (item) { if (item.getVisible()) { result += 1; } }); return result; }; /** * Gets what the state (enabled/disabled) of the collapse button should be. * * @private * @returns {boolean} Should the collapse button be enabled. */ NotificationListGroup.prototype._getCollapseButtonEnabled = function () { if (this._getVisibleItemsCount() > 0) { return true; } return this.getEnableCollapseButtonWhenEmpty(); }; /** * Focus handler for the NotificationListGroup's items. * * @private * @param {jQuery.Event} event The passed event object. */ NotificationListGroup.prototype._notificationFocusHandler = function (event) { ListItemBase.prototype.onfocusin.call(this, event); var targetControl = event.srcControl; if (targetControl.getMetadata().getName() != 'sap.m.NotificationListItem') { return; } var notificationGroup = targetControl.getParent(); var groupIndex = notificationGroup.indexOfItem(targetControl); var targetDomRef = targetControl.getDomRef(); targetDomRef.setAttribute('aria-posinset', groupIndex + 1); targetDomRef.setAttribute('aria-setsize', notificationGroup.getItems().length); }; /** * Event handler for keypressed. * * @private * @param {jQuery.Event} event The passed event object. */ NotificationListGroup.prototype._notificationNavigationHandler = function (event) { ListItemBase.prototype.onkeydown.call(this, event); var targetControl = event.srcControl; if (targetControl.getMetadata().getName() != 'sap.m.NotificationListItem') { return; } var notificationGroup = targetControl.getParent(); var groupIndex = notificationGroup.indexOfItem(targetControl); switch (event.which) { case KeyCodes.ARROW_UP: if (groupIndex == 0) { return; } var previousIndex = groupIndex - 1; notificationGroup.getItems()[previousIndex].focus(); break; case KeyCodes.ARROW_DOWN: var nextIndex = groupIndex + 1; if (nextIndex == notificationGroup.getItems().length) { return; } notificationGroup.getItems()[nextIndex].focus(); break; default: return; } }; /** * Updates all the text needed for accessibility. * * @private */ NotificationListGroup.prototype._updateAccessibilityInfo = function() { var authorName = this.getAuthorName(); var infoText = this._resourceBundle.getText('NOTIFICATION_LIST_ITEM_DATETIME_PRIORITY', [this.getDatetime(), this.getPriority()]); var unreadText = this.getUnread() ? this._resourceBundle.getText('NOTIFICATION_LIST_GROUP_UNREAD') : this._resourceBundle.getText('NOTIFICATION_LIST_GROUP_READ'); var ariaText = ''; var ariaDetailsText = this.getAggregation('_ariaDetailsText'); if (authorName) { ariaText += this._resourceBundle.getText('NOTIFICATION_LIST_ITEM_CREATED_BY') + ' ' + authorName + ' '; } ariaText += infoText + ' ' + unreadText; ariaDetailsText.setText(ariaText); this._ariaLabbeledByIds = this._getHeaderTitle().getId() + ' ' + ariaDetailsText.getId(); }; /** * Updates the collapse/expand text according to the new passed state. * * @private * @param {boolean} collapsed The new collapsed state. */ NotificationListGroup.prototype._updateCollapseButtonText = function(collapsed) { var collapseButtonText = collapsed ? this._resourceBundle.getText('NOTIFICATION_LIST_GROUP_EXPAND') : this._resourceBundle.getText('NOTIFICATION_LIST_GROUP_COLLAPSE'); this.getAggregation('_collapseButton').setText(collapseButtonText, true); }; /** * Compares two priorities and returns the higher one. * * @private * @param {sap.ui.core.Priority} firstPriority First priority string to be compared. * @param {sap.ui.core.Priority} secondPriority Second priority string to be compared. * @returns {sap.ui.core.Priority} The highest priority. */ function comparePriority(firstPriority, secondPriority) { if (firstPriority == secondPriority) { return firstPriority; } if ((firstPriority == 'None')) { return secondPriority; } if ((firstPriority == 'Low') && (secondPriority != 'None')) { return secondPriority; } if ((firstPriority == 'Medium') && (secondPriority != 'None' && secondPriority != 'Low')) { return secondPriority; } return firstPriority; } return NotificationListGroup; });