Commit | Line | Data |
---|---|---|
5fb6968e | 1 | _kiwi.utils.notifications = (function () { |
99d8d2bf NF |
2 | if (!window.Notification) { |
3 | return { | |
4 | allowed: _.constant(false), | |
5 | requestPermission: _.constant($.Deferred().reject()) | |
6 | }; | |
7 | } | |
8 | ||
9 | var notifications = { | |
10 | /** | |
11 | * Check if desktop notifications have been allowed by the user. | |
12 | * | |
13 | * @returns {?Boolean} `true` - they have been allowed. | |
14 | * `false` - they have been blocked. | |
15 | * `null` - the user hasn't answered yet. | |
16 | */ | |
17 | allowed: function () { | |
18 | return Notification.permission === 'granted' ? true | |
19 | : Notification.permission === 'denied' ? false | |
20 | : null; | |
21 | }, | |
22 | ||
23 | /** | |
24 | * Ask the user their permission to display desktop notifications. | |
25 | * This will return a promise which will be resolved if the user allows notifications, or rejected if they blocked | |
26 | * notifictions or simply closed the dialog. If the user had previously given their preference, the promise will be | |
27 | * immediately resolved or rejected with their previous answer. | |
28 | * | |
29 | * @example | |
30 | * notifications.requestPermission().then(function () { 'allowed' }, function () { 'not allowed' }); | |
31 | * | |
32 | * @returns {Promise} | |
33 | */ | |
34 | requestPermission: function () { | |
35 | var deferred = $.Deferred(); | |
36 | Notification.requestPermission(function (permission) { | |
37 | deferred[(permission === 'granted') ? 'resolve' : 'reject'](); | |
38 | }); | |
39 | return deferred.promise(); | |
40 | }, | |
41 | ||
42 | /** | |
43 | * Create a new notification. If the user has not yet given permission to display notifications, they will be asked | |
44 | * to confirm first. The notification will show afterwards if they allow it. | |
45 | * | |
46 | * Notifications implement Backbone.Events (so you can use `on` and `off`). They trigger four different events: | |
47 | * - 'click' | |
48 | * - 'close' | |
49 | * - 'error' | |
50 | * - 'show' | |
51 | * | |
52 | * @example | |
53 | * notifications | |
54 | * .create('Cool notification', { icon: 'logo.png' }) | |
55 | * .on('click', function () { | |
56 | * window.focus(); | |
57 | * }) | |
58 | * .closeAfter(5000); | |
59 | * | |
60 | * @param {String} title | |
61 | * @param {Object} options | |
62 | * @param {String=} options.body A string representing an extra content to display within the notification | |
63 | * @param {String=} options.dir The direction of the notification; it can be auto, ltr, or rtl | |
64 | * @param {String=} options.lang Specify the lang used within the notification. This string must be a valid BCP | |
65 | * 47 language tag. | |
66 | * @param {String=} options.tag An ID for a given notification that allows to retrieve, replace or remove it if necessary | |
67 | * @param {String=} options.icon The URL of an image to be used as an icon by the notification | |
68 | * @returns {Notifier} | |
69 | */ | |
70 | create: function (title, options) { | |
71 | return new Notifier(title, options); | |
72 | } | |
73 | }; | |
74 | ||
75 | function Notifier(title, options) { | |
76 | createNotification.call(this, title, options); | |
77 | } | |
78 | _.extend(Notifier.prototype, Backbone.Events, { | |
79 | closed: false, | |
80 | _closeTimeout: null, | |
81 | ||
82 | /** | |
83 | * Close the notification after a given number of milliseconds. | |
84 | * @param {Number} timeout | |
85 | * @returns {this} | |
86 | */ | |
87 | closeAfter: function (timeout) { | |
88 | if (!this.closed) { | |
89 | if (this.notification) { | |
90 | this._closeTimeout = this._closeTimeout || setTimeout(_.bind(this.close, this), timeout); | |
91 | } else { | |
92 | this.once('show', _.bind(this.closeAfter, this, timeout)); | |
93 | } | |
94 | } | |
95 | return this; | |
96 | }, | |
97 | ||
98 | /** | |
99 | * Close the notification immediately. | |
100 | * @returns {this} | |
101 | */ | |
102 | close: function () { | |
103 | if (this.notification && !this.closed) { | |
104 | this.notification.close(); | |
105 | this.closed = true; | |
106 | } | |
107 | return this; | |
108 | } | |
109 | }); | |
110 | ||
111 | function createNotification(title, options) { | |
112 | switch (notifications.allowed()) { | |
113 | case true: | |
114 | this.notification = new Notification(title, options); | |
115 | _.each(['click', 'close', 'error', 'show'], function (eventName) { | |
116 | this.notification['on' + eventName] = _.bind(this.trigger, this, eventName); | |
117 | }, this); | |
118 | break; | |
119 | case null: | |
120 | notifications.requestPermission().done(_.bind(createNotification, this, title, options)); | |
121 | break; | |
122 | } | |
123 | } | |
124 | ||
125 | return notifications; | |
126 | }()); |