Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/phabricator
Path: blob/master/webroot/rsrc/js/core/Notification.js
12241 views
1
/**
2
* @requires javelin-install
3
* javelin-dom
4
* javelin-stratcom
5
* javelin-util
6
* phabricator-notification-css
7
* @provides phabricator-notification
8
* @javelin
9
*/
10
11
/**
12
* Show a notification popup on screen. Usage:
13
*
14
* var n = new JX.Notification()
15
* .setContent('click me!');
16
* n.listen('activate', function(e) { alert('you clicked!'); });
17
* n.show();
18
*
19
*/
20
JX.install('Notification', {
21
22
events : ['activate', 'close'],
23
24
members : {
25
_container : null,
26
_visible : false,
27
_hideTimer : null,
28
_duration : 12000,
29
_asDesktop : false,
30
_asWeb : true,
31
_key : null,
32
_title : null,
33
_body : null,
34
_href : null,
35
_icon : null,
36
37
show : function() {
38
var self = JX.Notification;
39
40
if (!this._visible) {
41
this._visible = true;
42
43
self._show(this);
44
this._updateTimer();
45
}
46
47
if (self.supportsDesktopNotifications() &&
48
self.desktopNotificationsEnabled() &&
49
this._asDesktop) {
50
// Note: specifying "tag" means that notifications with matching
51
// keys will aggregate.
52
var n = new window.Notification(this._title, {
53
icon: this._icon,
54
body: this._body,
55
tag: this._key,
56
});
57
n.onclick = JX.bind(n, function (href) {
58
this.close();
59
window.focus();
60
if (href) {
61
JX.$U(href).go();
62
}
63
}, this._href);
64
// Note: some OS / browsers do this automagically; make the behavior
65
// happen everywhere.
66
setTimeout(n.close.bind(n), this._duration);
67
}
68
return this;
69
},
70
71
hide : function() {
72
if (this._visible) {
73
this._visible = false;
74
75
var self = JX.Notification;
76
self._hide(this);
77
this._updateTimer();
78
}
79
return this;
80
},
81
82
alterClassName : function(name, enable) {
83
JX.DOM.alterClass(this._getContainer(), name, enable);
84
return this;
85
},
86
87
setContent : function(content) {
88
JX.DOM.setContent(this._getContainer(), content);
89
return this;
90
},
91
92
setShowAsWebNotification: function(mode) {
93
this._asWeb = mode;
94
return this;
95
},
96
97
setShowAsDesktopNotification : function(mode) {
98
this._asDesktop = mode;
99
return this;
100
},
101
102
setTitle : function(title) {
103
this._title = title;
104
return this;
105
},
106
107
setBody : function(body) {
108
this._body = body;
109
return this;
110
},
111
112
setHref : function(href) {
113
this._href = href;
114
return this;
115
},
116
117
setKey : function(key) {
118
this._key = key;
119
return this;
120
},
121
122
setIcon : function(icon) {
123
this._icon = icon;
124
return this;
125
},
126
127
/**
128
* Set duration before the notification fades away, in milliseconds. If set
129
* to 0, the notification persists until dismissed.
130
*
131
* @param int Notification duration, in milliseconds.
132
* @return this
133
*/
134
setDuration : function(milliseconds) {
135
this._duration = milliseconds;
136
this._updateTimer(false);
137
return this;
138
},
139
140
_updateTimer : function() {
141
if (this._hideTimer) {
142
clearTimeout(this._hideTimer);
143
this._hideTimer = null;
144
}
145
146
if (this._visible && this._duration) {
147
this._hideTimer = setTimeout(JX.bind(this, this.hide), this._duration);
148
}
149
},
150
151
_getContainer : function() {
152
if (!this._container) {
153
this._container = JX.$N(
154
'div',
155
{
156
className: 'jx-notification',
157
sigil: 'jx-notification'
158
});
159
}
160
return this._container;
161
}
162
},
163
164
statics : {
165
supportsDesktopNotifications : function () {
166
return 'Notification' in window;
167
},
168
desktopNotificationsEnabled : function () {
169
return window.Notification.permission === 'granted';
170
},
171
_container : null,
172
_listening : false,
173
_active : [],
174
_show : function(notification) {
175
var self = JX.Notification;
176
177
self._installListener();
178
self._active.push(notification);
179
self._redraw();
180
},
181
_hide : function(notification) {
182
var self = JX.Notification;
183
184
for (var ii = 0; ii < self._active.length; ii++) {
185
if (self._active[ii] === notification) {
186
notification.invoke('close');
187
self._active.splice(ii, 1);
188
break;
189
}
190
}
191
192
self._redraw();
193
},
194
_installListener : function() {
195
var self = JX.Notification;
196
197
if (self._listening) {
198
return;
199
} else {
200
self._listening = true;
201
}
202
203
JX.Stratcom.listen(
204
'click',
205
'jx-notification',
206
function(e) {
207
// NOTE: Don't kill the event since the user might have clicked a
208
// link, and we want to follow the link if they did. Instead, invoke
209
// the activate event for the active notification and dismiss it if it
210
// isn't handled.
211
212
var target = e.getNode('jx-notification');
213
for (var ii = 0; ii < self._active.length; ii++) {
214
var n = self._active[ii];
215
if (n._getContainer() === target) {
216
var activation = n.invoke('activate');
217
if (!activation.getPrevented()) {
218
n.hide();
219
}
220
return;
221
}
222
}
223
224
});
225
},
226
_redraw : function() {
227
var self = JX.Notification;
228
229
if (!self._active.length) {
230
if (self._container) {
231
JX.DOM.remove(self._container);
232
self._container = null;
233
}
234
return;
235
}
236
237
if (!self._container) {
238
self._container = JX.$N(
239
'div',
240
{
241
className: 'jx-notification-container'
242
});
243
document.body.appendChild(self._container);
244
}
245
246
// Show only a limited number of notifications at once.
247
var limit = 5;
248
249
var notifications = [];
250
for (var ii = 0; ii < self._active.length; ii++) {
251
252
// Don't render this notification if it's not configured to show as
253
// a web notification.
254
if (!self._active[ii]._asWeb) {
255
continue;
256
}
257
258
notifications.push(self._active[ii]._getContainer());
259
if (!(--limit)) {
260
break;
261
}
262
}
263
264
JX.DOM.setContent(self._container, notifications);
265
}
266
}
267
268
});
269
270