MDL-30811 javascript: Lazily load core dependencies
[moodle.git] / lib / amd / src / notification.js
1 // This file is part of Moodle - http://moodle.org/
2 //
3 // Moodle is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // Moodle is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16 /**
17  * A system for displaying notifications to users from the session.
18  *
19  * Wrapper for the YUI M.core.notification class. Allows us to
20  * use the YUI version in AMD code until it is replaced.
21  *
22  * @module     core/notification
23  * @class      notification
24  * @package    core
25  * @copyright  2015 Damyon Wiese <damyon@moodle.com>
26  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27  * @since      2.9
28  */
29 define(['core/yui', 'jquery', 'theme_bootstrapbase/bootstrap', 'core/log'],
30 function(Y, $, bootstrap, log) {
31     var notificationModule = {
32         types: {
33             'success':  'core/notification_success',
34             'info':     'core/notification_info',
35             'warning':  'core/notification_warning',
36             'error':    'core/notification_error',
37         },
39         fieldName: 'user-notifications',
41         fetchNotifications: function() {
42             require(['core/ajax'], function(ajax) {
43                 var promises = ajax.call([{
44                     methodname: 'core_fetch_notifications',
45                     args: {
46                         contextid: notificationModule.contextid
47                     }
48                 }]);
50                 promises[0]
51                     .done(notificationModule.addNotifications)
52                     ;
53             });
54         },
56         addNotifications: function(notifications) {
57             if (!notifications) {
58                 notifications = [];
59             }
61             $.each(notifications, function(i, notification) {
62                 notificationModule.renderNotification(notification.template, notification.variables);
63             });
64         },
66         setupTargetRegion: function() {
67             var targetRegion = $('#' + notificationModule.fieldName);
68             if (targetRegion.length) {
69                 return;
70             }
72             var newRegion = $('<span>').attr('id', notificationModule.fieldName);
74             targetRegion = $('#region-main');
75             if (targetRegion.length) {
76                 return targetRegion.prepend(newRegion);
77             }
79             targetRegion = $('[role="main"]');
80             if (targetRegion.length) {
81                 return targetRegion.prepend(newRegion);
82             }
84             targetRegion = $('body');
85             return targetRegion.prepend(newRegion);
86         },
88         addNotification: function(notification) {
89             var template = notificationModule.types.error;
91             notification = $.extend({
92                     closebutton:    true,
93                     announce:       true,
94                     type:           'error'
95                 }, notification);
97             if (notification.template) {
98                 template = notification.template;
99                 delete notification.template;
100             } else if (notification.type){
101                 if (typeof notificationModule.types[notification.type] !== 'undefined') {
102                     template = notificationModule.types[notification.type];
103                 }
104                 delete notification.type;
105             }
107             return notificationModule.renderNotification(template, notification);
108         },
110         renderNotification: function(template, variables) {
111             if (typeof variables.message === 'undefined' || !variables.message) {
112                 log.debug('Notification received without content. Skipping.');
113                 return;
114             }
115             require(['core/templates'], function(templates) {
116                 templates.render(template, variables)
117                     .done(function(html) {
118                         $('#' + notificationModule.fieldName).prepend(html);
119                     })
120                     .fail(notificationModule.exception)
121                     ;
122             });
123         },
125         alert: function(title, message, yesLabel) {
126             // Here we are wrapping YUI. This allows us to start transitioning, but
127             // wait for a good alternative without having inconsistent dialogues.
128             Y.use('moodle-core-notification-alert', function () {
129                 var alert = new M.core.alert({
130                     title : title,
131                     message : message,
132                     yesLabel: yesLabel
133                 });
135                 alert.show();
136             });
137         },
139         confirm: function(title, question, yesLabel, noLabel, callback) {
140             // Here we are wrapping YUI. This allows us to start transitioning, but
141             // wait for a good alternative without having inconsistent dialogues.
142             Y.use('moodle-core-notification-confirm', function () {
143                 var modal = new M.core.confirm({
144                     title : title,
145                     question : question,
146                     yesLabel: yesLabel,
147                     noLabel: noLabel
148                 });
150                 modal.on('complete-yes', function() {
151                     callback();
152                 });
153                 modal.show();
154             });
155         },
157         exception: function(ex) {
158             // Fudge some parameters.
159             if (ex.backtrace) {
160                 ex.lineNumber = ex.backtrace[0].line;
161                 ex.fileName = ex.backtrace[0].file;
162                 ex.fileName = '...' + ex.fileName.substr(ex.fileName.length - 20);
163                 ex.stack = ex.debuginfo;
164                 ex.name = ex.errorcode;
165             }
166             Y.use('moodle-core-notification-exception', function () {
167                 var modal = new M.core.exception(ex);
169                 modal.show();
170             });
171         }
172     };
174     return /** @alias module:core/notification */{
175         init: function(contextid, notifications) {
176             notificationModule.contextid = contextid;
178             // Setup the message target region if it isn't setup already
179             notificationModule.setupTargetRegion();
181             // Setup closing of bootstrap alerts.
182             $().alert();
184             // Add provided notifications.
185             notificationModule.addNotifications(notifications);
187             // Poll for any new notifications.
188             notificationModule.fetchNotifications();
189         },
191         /**
192          * Poll the server for any new notifications.
193          *
194          * @method fetchNotifications
195          */
196         fetchNotifications: notificationModule.fetchNotifications,
198         /**
199          * Add a notification to the page.
200          *
201          * Note: This does not cause the notification to be added to the session.
202          *
203          * @method addNotification
204          * @param {Object}  notification                The notification to add.
205          * @param {string}  notification.message        The body of the notification
206          * @param {string}  notification.type           The type of notification to add (error, warning, info, success).
207          * @param {Boolean} notification.closebutton    Whether to show the close button.
208          * @param {Boolean} notification.announce       Whether to announce to screen readers.
209          */
210         addNotification: notificationModule.addNotification,
212         /**
213          * Wrap M.core.alert.
214          *
215          * @method alert
216          * @param {string} title
217          * @param {string} message
218          * @param {string} yesLabel
219          */
220         alert: notificationModule.alert,
222         /**
223          * Wrap M.core.confirm.
224          *
225          * @method confirm
226          * @param {string} title
227          * @param {string} question
228          * @param {string} yesLabel
229          * @param {string} noLabel
230          * @param {function} callback
231          */
232         confirm: notificationModule.confirm,
234         /**
235          * Wrap M.core.exception.
236          *
237          * @method exception
238          * @param {Error} ex
239          */
240         exception: notificationModule.exception
241     };
242 });