/*!
* 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:
*
* autoPriority
- sets the group priority to the highest priority of an item in the group.
* enableCollapseButtonWhenEmpty
- displays a collapse button for an empty group.
* showEmptyGroup
- determines if the header/footer of an empty group is displayed.
*
* @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;
});