AutorÃa | Ultima modificación | Ver Log |
{"version":3,"file":"notification_area_control_area.min.js","sources":["../src/notification_area_control_area.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Controls the notification area on the notification page.\n *\n * @module message_popup/notification_area_control_area\n * @copyright 2016 Ryan Wyllie <ryan@moodle.com>\n * @lice
nse http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine(['jquery', 'core/templates', 'core/notification', 'core/custom_interaction_events',\n 'message_popup/notification_repository', 'message_popup/notification_area_events'],\n function($, Templates, DebugNotification, CustomEvents, NotificationRepo, NotificationAreaEvents) {\n\n var SELECTORS = {\n CONTAINER: '[data-region=\"notification-area\"]',\n CONTENT: '[data-region=\"content\"]',\n NOTIFICATION: '[data-region=\"notification-content-item-container\"]',\n CAN_RECEIVE_FOCUS: 'input:not([type=\"hidden\"]), a[href], button, textarea, select, [tabindex]',\n };\n\n var TEMPLATES = {\n NOTIFICATION: 'message_popup/notification_content_item',\n };\n\n /**\n * Constructor for ControlArea\n *\n * @class\n * @param {object} root The root element for the content area\n * @param {int} userId The user id of the current user\n */\n var ControlArea = function(r
oot, userId) {\n this.root = $(root);\n this.container = this.root.closest(SELECTORS.CONTAINER);\n this.userId = userId;\n this.content = this.root.find(SELECTORS.CONTENT);\n this.offset = 0;\n this.limit = 20;\n this.initialLoad = false;\n this.isLoading = false;\n this.loadedAll = false;\n this.notifications = {};\n\n this.registerEventListeners();\n };\n\n /**\n * Get the root element.\n *\n * @method getRoot\n * @return {object} jQuery element\n */\n ControlArea.prototype.getRoot = function() {\n return this.root;\n };\n\n /**\n * Get the container element (which the control area is within).\n *\n * @method getContainer\n * @return {object} jQuery element\n */\n ControlArea.prototype.getContainer = function() {\n return this.container;\n };\n\n /**\n * Get the user id.\n *\n * @method getUserId\n * @return {int}\n */\n ControlAre
a.prototype.getUserId = function() {\n return this.userId;\n };\n\n /**\n * Get the control area content element.\n *\n * @method getContent\n * @return {object} jQuery element\n */\n ControlArea.prototype.getContent = function() {\n return this.content;\n };\n\n /**\n * Get the offset value for paginated loading of the\n * notifications.\n *\n * @method getOffset\n * @return {int}\n */\n ControlArea.prototype.getOffset = function() {\n return this.offset;\n };\n\n /**\n * Get the limit value for the paginated loading of the\n * notifications.\n *\n * @method getLimit\n * @return {int}\n */\n ControlArea.prototype.getLimit = function() {\n return this.limit;\n };\n\n /**\n * Set the offset value for the paginated loading of the\n * notifications.\n *\n * @method setOffset\n * @param {int} value The new offset value\n */\n ControlArea.prototype.setOffset =
function(value) {\n this.offset = value;\n };\n\n /**\n * Set the limit value for the paginated loading of the\n * notifications.\n *\n * @method setLimit\n * @param {int} value The new limit value\n */\n ControlArea.prototype.setLimit = function(value) {\n this.limit = value;\n };\n\n /**\n * Increment the offset by the limit amount.\n *\n * @method incrementOffset\n */\n ControlArea.prototype.incrementOffset = function() {\n this.offset += this.limit;\n };\n\n /**\n * Flag the control area as loading.\n *\n * @method startLoading\n */\n ControlArea.prototype.startLoading = function() {\n this.isLoading = true;\n this.getRoot().addClass('loading');\n };\n\n /**\n * Remove the loading flag from the control area.\n *\n * @method stopLoading\n */\n ControlArea.prototype.stopLoading = function() {\n this.isLoading = false;\n this.getRoot().removeClass('loa
ding');\n };\n\n /**\n * Check if the first load of notifications has been triggered.\n *\n * @method hasDoneInitialLoad\n * @return {bool} true if first notification loaded, false otherwise\n */\n ControlArea.prototype.hasDoneInitialLoad = function() {\n return this.initialLoad;\n };\n\n /**\n * Check if all of the notifications have been loaded.\n *\n * @method hasLoadedAllContent\n * @return {bool}\n */\n ControlArea.prototype.hasLoadedAllContent = function() {\n return this.loadedAll;\n };\n\n /**\n * Set the state of the loaded all content property.\n *\n * @method setLoadedAllContent\n * @param {bool} val True if all content is loaded, false otherwise\n */\n ControlArea.prototype.setLoadedAllContent = function(val) {\n this.loadedAll = val;\n };\n\n /**\n * Save a notification in the cache.\n *\n * @method setCacheNotification\n * @param {object} notification A notification
returned by a webservice\n */\n ControlArea.prototype.setCacheNotification = function(notification) {\n this.notifications[notification.id] = notification;\n };\n\n /**\n * Retrieve a notification from the cache.\n *\n * @method getCacheNotification\n * @param {int} id The id for the notification you wish to retrieve\n * @return {object} A notification (as returned by a webservice)\n */\n ControlArea.prototype.getCacheNotification = function(id) {\n return this.notifications[id];\n };\n\n /**\n * Find the notification element in the control area for the given id.\n *\n * @method getNotificationElement\n * @param {int} id The notification id\n * @return {(object|null)} jQuery element or null\n */\n ControlArea.prototype.getNotificationElement = function(id) {\n var element = this.getRoot().find(SELECTORS.NOTIFICATION + '[data-id=\"' + id + '\"]');\n return element.length == 1 ? element : null;\n };\n\n /
**\n * Scroll the notification element into view within the control area, if it\n * isn't already visible.\n *\n * @method scrollNotificationIntoView\n * @param {object} notificationElement The jQuery notification element\n */\n ControlArea.prototype.scrollNotificationIntoView = function(notificationElement) {\n var position = notificationElement.position();\n var container = this.getRoot();\n var relativeTop = position.top - container.scrollTop();\n\n // If the element isn't in the view window.\n if (relativeTop > container.innerHeight()) {\n var height = notificationElement.outerHeight();\n // Offset enough to make sure the notification will be in view.\n height = height * 4;\n var scrollTo = position.top - height;\n container.scrollTop(scrollTo);\n }\n };\n\n /**\n * Show the full notification for the given notification element. The notification\n * context is retrieved
from the cache and send as data with an event to be\n * rendered in the content area.\n *\n * @method showNotification\n * @param {(int|object)} notificationElement The notification id or jQuery notification element\n */\n ControlArea.prototype.showNotification = function(notificationElement) {\n if (typeof notificationElement !== 'object') {\n // Assume it's an ID if it's not an object.\n notificationElement = this.getNotificationElement(notificationElement);\n }\n\n if (notificationElement && notificationElement.length) {\n this.getRoot().find(SELECTORS.NOTIFICATION).removeClass('selected');\n notificationElement.addClass('selected').find(SELECTORS.CAN_RECEIVE_FOCUS).focus();\n var notificationId = notificationElement.attr('data-id');\n var notification = this.getCacheNotification(notificationId);\n this.scrollNotificationIntoView(notificationElement);\n // Create a new versi
on of the notification to send with the notification so\n // this copy isn't modified.\n this.getContainer().trigger(NotificationAreaEvents.showNotification, [$.extend({}, notification)]);\n }\n };\n\n /**\n * Send a request to mark the notification as read in the server and remove the unread\n * status from the element.\n *\n * @method markNotificationAsRead\n * @param {object} notificationElement The jQuery notification element\n * @return {object} jQuery promise\n */\n ControlArea.prototype.markNotificationAsRead = function(notificationElement) {\n return NotificationRepo.markAsRead(notificationElement.attr('data-id')).done(function() {\n notificationElement.removeClass('unread');\n });\n };\n\n\n /**\n * Render the notification data with the appropriate template and add it to the DOM.\n *\n * @method renderNotifications\n * @param {array} notifications Array of notification data\n * @retur
n {object} jQuery promise that is resolved when all notifications have been\n * rendered and added to the DOM\n */\n ControlArea.prototype.renderNotifications = function(notifications) {\n var promises = [];\n var container = this.getContent();\n\n $.each(notifications, function(index, notification) {\n // Need to remove the contexturl so the item isn't rendered\n // as a link.\n var contextUrl = notification.contexturl;\n delete notification.contexturl;\n\n var promise = Templates.render(TEMPLATES.NOTIFICATION, notification)\n .then(function(html, js) {\n // Restore it for the cache.\n notification.contexturl = contextUrl;\n this.setCacheNotification(notification);\n // Pass the Rendered content out.\n return {html: html, js: js};\n }.bind(this));\n promises.push(promise);\n }.bind(this));\n\
n return $.when.apply($, promises).then(function() {\n // Each of the promises in the when will pass its results as an argument to the function.\n // The order of the arguments will be the order that the promises are passed to when()\n // i.e. the first promise's results will be in the first argument.\n $.each(arguments, function(index, argument) {\n container.append(argument.html);\n Templates.runTemplateJS(argument.js);\n });\n return;\n });\n };\n\n /**\n * Load notifications from the server and render them.\n *\n * @method loadMoreNotifications\n * @return {object} jQuery promise\n */\n ControlArea.prototype.loadMoreNotifications = function() {\n if (this.isLoading || this.hasLoadedAllContent()) {\n return $.Deferred().resolve();\n }\n\n this.startLoading();\n var request = {\n limit: this.getLimit(),\n offs
et: this.getOffset(),\n useridto: this.getUserId(),\n };\n\n if (!this.initialLoad) {\n // If this is the first load we may have been given a non-zero offset,\n // in which case we need to load all notifications preceeding that offset\n // to make sure the full list is rendered.\n request.limit = this.getOffset() + this.getLimit();\n request.offset = 0;\n }\n\n var promise = NotificationRepo.query(request).then(function(result) {\n var notifications = result.notifications;\n this.unreadCount = result.unreadcount;\n this.setLoadedAllContent(!notifications.length || notifications.length < this.getLimit());\n this.initialLoad = true;\n\n if (notifications.length) {\n this.incrementOffset();\n return this.renderNotifications(notifications);\n }\n\n return false;\n }.bind(this))\n .always(function() {\
n this.stopLoading();\n }.bind(this));\n\n return promise;\n };\n\n /**\n * Create the event listeners for the control area.\n *\n * @method registerEventListeners\n */\n ControlArea.prototype.registerEventListeners = function() {\n CustomEvents.define(this.getRoot(), [\n CustomEvents.events.activate,\n CustomEvents.events.scrollBottom,\n CustomEvents.events.scrollLock,\n CustomEvents.events.up,\n CustomEvents.events.down,\n ]);\n\n this.getRoot().on(CustomEvents.events.scrollBottom, function() {\n this.loadMoreNotifications();\n }.bind(this));\n\n this.getRoot().on(CustomEvents.events.activate, SELECTORS.NOTIFICATION, function(e) {\n var notificationElement = $(e.target).closest(SELECTORS.NOTIFICATION);\n this.showNotification(notificationElement);\n }.bind(this));\n\n // Show the previous notification in the list.\n
this.getRoot().on(CustomEvents.events.up, SELECTORS.NOTIFICATION, function(e, data) {\n var notificationElement = $(e.target).closest(SELECTORS.NOTIFICATION);\n this.showNotification(notificationElement.prev());\n\n data.originalEvent.preventDefault();\n }.bind(this));\n\n // Show the next notification in the list.\n this.getRoot().on(CustomEvents.events.down, SELECTORS.NOTIFICATION, function(e, data) {\n var notificationElement = $(e.target).closest(SELECTORS.NOTIFICATION);\n this.showNotification(notificationElement.next());\n\n data.originalEvent.preventDefault();\n }.bind(this));\n\n this.getContainer().on(NotificationAreaEvents.notificationShown, function(e, notification) {\n if (!notification.read) {\n var element = this.getNotificationElement(notification.id);\n\n if (element) {\n this.markNotificationAsRead(element);\n }\n\n
var cachedNotification = this.getCacheNotification(notification.id);\n\n if (cachedNotification) {\n cachedNotification.read = true;\n }\n }\n }.bind(this));\n };\n\n return ControlArea;\n});\n"],"names":["define","$","Templates","DebugNotification","CustomEvents","NotificationRepo","NotificationAreaEvents","SELECTORS","TEMPLATES","ControlArea","root","userId","container","this","closest","content","find","offset","limit","initialLoad","isLoading","loadedAll","notifications","registerEventListeners","prototype","getRoot","getContainer","getUserId","getContent","getOffset","getLimit","setOffset","value","setLimit","incrementOffset","startLoading","addClass","stopLoading","removeClass","hasDoneInitialLoad","hasLoadedAllContent","setLoadedAllContent","val","setCacheNotification","notification","id","getCacheNotification","getNotificationElement","element","length","scrollNotificationIntoView","notificationElement","position",
"top","scrollTop","innerHeight","height","outerHeight","scrollTo","showNotification","focus","notificationId","attr","trigger","extend","markNotificationAsRead","markAsRead","done","renderNotifications","promises","each","index","contextUrl","contexturl","promise","render","then","html","js","bind","push","when","apply","arguments","argument","append","runTemplateJS","loadMoreNotifications","Deferred","resolve","request","useridto","query","result","unreadCount","unreadcount","always","events","activate","scrollBottom","scrollLock","up","down","on","e","target","data","prev","originalEvent","preventDefault","next","notificationShown","read","cachedNotification"],"mappings":"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"}