181 lines
6.1 KiB
JavaScript
181 lines
6.1 KiB
JavaScript
/**
|
|
* @defgroup js_classes_notification
|
|
*/
|
|
/**
|
|
* @file js/classes/notification/NotificationHelper.js
|
|
*
|
|
* Copyright (c) 2014-2021 Simon Fraser University
|
|
* Copyright (c) 2000-2021 John Willinsky
|
|
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
|
|
*
|
|
* @class NotificationHelper
|
|
* @ingroup js_classes_notification
|
|
*
|
|
* @brief Class that perform notification helper actions.
|
|
*/
|
|
(function($) {
|
|
|
|
/** @type {Object} */
|
|
$.pkp.classes.notification = $.pkp.classes.notification || {};
|
|
|
|
|
|
|
|
/**
|
|
* @constructor
|
|
*/
|
|
$.pkp.classes.notification.NotificationHelper = function() {
|
|
};
|
|
|
|
|
|
//
|
|
// Public static helper methods
|
|
//
|
|
/**
|
|
* Decides which notification will be used: in place or general.
|
|
* This method finds all notification widgets that are inside of the
|
|
* handled element of the controller that is handling the current
|
|
* notify user event (page or modal). We need to make sure that all
|
|
* notifications will be shown inside the same widget where the notify
|
|
* user was triggered. Beyond that, we also need to make sure that,
|
|
* inside some widgets (tabs and accordions, for example) we use the
|
|
* right notification controller.
|
|
* To do this, the notification element must follow these rules:
|
|
*
|
|
* 1 - the notification element must not have a hidden parent, although
|
|
* it can be hidden itself.
|
|
*
|
|
* 2 - the notification element first widget parent also needs to contain
|
|
* the element that triggered the notify user event.
|
|
*
|
|
* 3 - if the notification element is inside an accordion container, it
|
|
* will only notify user from events that have the trigger element also
|
|
* inside the accordion container.
|
|
*
|
|
* At the final, if this method find and select more than one
|
|
* notification element, we get the closest comparing to the element
|
|
* that triggered the event. If it don't find any visible element, it
|
|
* bubbles up the event so the site handler can show general
|
|
* notifications.
|
|
*
|
|
* @param {$.pkp.classes.Handler} handler The widget handler that is
|
|
* handling the notify user event.
|
|
* @param {HTMLElement|Object} triggerElement The element that triggered the
|
|
* notify user event.
|
|
*/
|
|
$.pkp.classes.notification.NotificationHelper.redirectNotifyUserEvent =
|
|
function(handler, triggerElement) {
|
|
|
|
// Get the selector for a notification element.
|
|
var $notificationSelector = '.pkp_notification',
|
|
$handledElement,
|
|
trivialAlreadyHandled,
|
|
$pageNotificationElements,
|
|
possibleNotificationWidgets,
|
|
i, length,
|
|
notificationsData,
|
|
$accordionContainer,
|
|
$element,
|
|
$elementParents, parentHandler,
|
|
j, parentsLength, $elementParentWidget;
|
|
|
|
|
|
// Sometimes the notification handler will bubble up
|
|
// the notifyUser event when in place notifications are
|
|
// not visible because of scrolling. When this happens, the
|
|
// trigger element will not be an element, but the notifications
|
|
// data that were shown by the in place but no visible. In those
|
|
// cases, just bubble up again the event until it gets the right
|
|
// handler (the site handler).
|
|
if (triggerElement !== undefined && triggerElement.content !== undefined) {
|
|
notificationsData = triggerElement;
|
|
handler.getHtmlElement().parent().trigger(
|
|
'notifyUser', [notificationsData]);
|
|
return; // no need to do any other event redirection.
|
|
}
|
|
|
|
// Get the html element of the handler.
|
|
$handledElement = handler.getHtmlElement();
|
|
|
|
// If the trigger element is inside a grid, let the site
|
|
// handler show TRIVIAL notifications.
|
|
trivialAlreadyHandled = false;
|
|
if (!(handler instanceof $.pkp.controllers.SiteHandler)) {
|
|
if (triggerElement !== undefined &&
|
|
$(triggerElement).parents('.pkp_controllers_grid').length > 0) {
|
|
$handledElement.parent().trigger('notifyUser');
|
|
trivialAlreadyHandled = true;
|
|
}
|
|
}
|
|
|
|
// Find all notification elements inside the handled element.
|
|
$pageNotificationElements = $($notificationSelector, $handledElement);
|
|
|
|
// Create a variable to store all possible notification widgets
|
|
// that can notify this event.
|
|
possibleNotificationWidgets = [];
|
|
|
|
for (i = 0, length = $pageNotificationElements.length; i < length; i++) {
|
|
$element = $($pageNotificationElements[i]);
|
|
|
|
// If it is inside a hidden parent, get next element.
|
|
if ($element.parents(':hidden').length > 0) {
|
|
continue;
|
|
}
|
|
|
|
// Find its parent widget.
|
|
// FIXME If we use a class to identify pkp widgets, we can avoid
|
|
// this code duplication from the get handler method in Handler class,
|
|
// unnecessary access to the element data and unnecessary loop.
|
|
$elementParents = $element.parents();
|
|
for (j = 0, parentsLength = $elementParents.length;
|
|
j < parentsLength; j++) {
|
|
parentHandler = $($elementParents[j]).data('pkp.handler');
|
|
if ((parentHandler instanceof $.pkp.classes.Handler)) {
|
|
$elementParentWidget = $($elementParents[j]);
|
|
break;
|
|
}
|
|
}
|
|
|
|
// If the element that triggered the event is inside of
|
|
// this widget or is the widget...
|
|
if (triggerElement !== undefined &&
|
|
($elementParentWidget.has(triggerElement[0]).length ||
|
|
$elementParentWidget[0] === triggerElement[0])) {
|
|
|
|
// If it is inside an accordion container, and this accordion container
|
|
// doesn't also contain the element that triggered the event, get other
|
|
// element.
|
|
if ($element.parents('.ui-accordion:first').length > 0) {
|
|
$accordionContainer = $element.parents('.ui-accordion:first');
|
|
|
|
if (!$accordionContainer.has(triggerElement[0])) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
// This notification element is able to notify this event.
|
|
possibleNotificationWidgets.push($element);
|
|
}
|
|
}
|
|
|
|
// Check if we found a notification element.
|
|
if (possibleNotificationWidgets.length) {
|
|
|
|
// Trigger all in place notification widgets found, from the
|
|
// closest to the element that triggered the action to the top.
|
|
for (i = possibleNotificationWidgets.length - 1; i > -1; i--) {
|
|
// Show in place notification to user.
|
|
possibleNotificationWidgets[i].triggerHandler('notifyUser');
|
|
}
|
|
} else {
|
|
if (!trivialAlreadyHandled) {
|
|
// Bubble up the notify user event so the site can handle the
|
|
// general notification.
|
|
handler.getHtmlElement().parent().trigger('notifyUser');
|
|
}
|
|
}
|
|
};
|
|
|
|
|
|
}(jQuery));
|