UNPKG

8.84 kBJavaScriptView Raw
1/*!
2 * @wcjiang/notify v2.0.12
3 * JS achieve the browser title flashing , scrolling, voice prompts , chrome notice.
4 *
5 * Copyright (c) 2018 kenny wang
6 * http://jaywcjlove.github.io/iNotify
7 *
8 * Licensed under the MIT license.
9 */
10
11'use strict';
12
13// 提醒是否添加chrome通知
14if (window.Notification && window.Notification.permission !== 'granted') {
15 window.Notification.requestPermission();
16}
17
18var iconURL = '';
19var repeatableEffects = ['flash', 'scroll'];
20var defaultNotification = {
21 title: 'iNotify !',
22 body: 'You have a new message.',
23 openurl: ''
24};
25
26function jsonArguments(news, olds) {
27 for (var a in olds) {
28 if (news[a]) {
29 olds[a] = news[a];
30 }
31 }
32
33 return olds;
34}
35
36function isArray(value) {
37 return Object.prototype.toString.call(value) === '[object Array]';
38}
39
40function createAudio(url) {
41 var audioElm = document.createElement('audio');
42 var source;
43
44 if (isArray(url) && url.length > 0) {
45 for (var i = 0; i < url.length; i++) {
46 source = document.createElement('source');
47 source.src = url[i];
48 source.type = "audio/".concat(getExtension(url[i]));
49 audioElm.appendChild(source);
50 }
51 } else {
52 audioElm.src = url;
53 }
54
55 return audioElm;
56}
57
58function getFavicon(setting) {
59 var ic = document.querySelectorAll('link[rel~=shortcut]')[0];
60
61 if (!ic) {
62 ic = changeFavicon('O', setting);
63 }
64
65 return ic;
66}
67
68function getExtension(fileName) {
69 return fileName.match(/\.([^\\.]+)$/)[1];
70}
71
72function changeFavicon(num, settings) {
73 var canvas = document.createElement('canvas');
74 var head = document.getElementsByTagName('head')[0];
75 var linkTag = document.createElement('link');
76 var ctx = null;
77 canvas.height = 32;
78 canvas.width = 32;
79 ctx = canvas.getContext('2d');
80 ctx.fillStyle = settings.backgroundColor;
81 ctx.fillRect(0, 0, 32, 32);
82 ctx.textAlign = 'center';
83 ctx.font = '22px "helvetica", sans-serif';
84 ctx.fillStyle = settings.textColor;
85 num && ctx.fillText(num, 16, 24); // 生成到
86
87 linkTag.setAttribute('rel', 'shortcut icon');
88 linkTag.setAttribute('type', 'image/x-icon');
89 linkTag.setAttribute('id', "new".concat(settings.id));
90 linkTag.setAttribute('href', canvas.toDataURL('image/png'));
91 iconURL = canvas.toDataURL('image/png');
92 return head.appendChild(linkTag);
93}
94
95function Notify(config) {
96 if (config) {
97 this.init(config);
98 }
99}
100
101Notify.prototype = {
102 init: function init(config) {
103 if (!config) {
104 config = {};
105 }
106
107 this.interval = config.interval || 100; // 响应时长
108
109 this.effect = config.effect || 'flash'; // 效果
110
111 this.title = config.title || document.title; // 标题
112
113 this.message = config.message || this.title; // 原来的标题
114
115 this.onclick = config.onclick || this.onclick; // 点击事件
116
117 this.openurl = config.openurl || this.openurl; // 点击事件
118
119 this.updateFavicon = config.updateFavicon || {
120 id: 'favicon',
121 textColor: '#fff',
122 backgroundColor: '#2F9A00'
123 };
124 this.audio = config.audio || '';
125 this.favicon = getFavicon(this.updateFavicon);
126 this.cloneFavicon = this.favicon.cloneNode(true);
127 iconURL = config.notification && config.notification.icon ? config.notification.icon : config.icon ? config.icon : this.favicon.href;
128 defaultNotification.icon = iconURL;
129 this.notification = config.notification || defaultNotification; // 初始化生成声音文件节点
130
131 if (this.audio && this.audio.file) {
132 this.setURL(this.audio.file);
133 }
134
135 return this;
136 },
137 render: function render() {
138 if (this.effect === 'flash') {
139 document.title = this.title === document.title ? this.message : this.title;
140 } else if (this.effect === 'scroll') {
141 var title = this.message || document.title;
142
143 if (!this.scrollTitle || !this.scrollTitle.slice(1)) {
144 document.title = title;
145 this.scrollTitle = title;
146 } else {
147 this.scrollTitle = this.scrollTitle.slice(1);
148 document.title = this.scrollTitle;
149 }
150 }
151
152 return this;
153 },
154 // 设置标题
155 setTitle: function setTitle(str) {
156 if (str === true) {
157 if (repeatableEffects.indexOf(this.effect) >= 0) {
158 return this.addTimer();
159 }
160 } else if (str) {
161 this.message = str;
162 this.scrollTitle = '';
163 this.addTimer();
164 } else {
165 this.clearTimer();
166 }
167
168 return this;
169 },
170 setURL: function setURL(url) {
171 if (url) {
172 if (this.audioElm) {
173 this.audioElm.remove();
174 }
175
176 this.audioElm = createAudio(url);
177 document.body.appendChild(this.audioElm);
178 }
179
180 return this;
181 },
182 loopPlay: function loopPlay() {
183 this.setURL();
184 this.audioElm.loop = true;
185 this.player();
186 return this;
187 },
188 stopPlay: function stopPlay() {
189 this.audioElm && (this.audioElm.loop = false, this.audioElm.pause());
190 return this;
191 },
192 // 播放声音
193 player: function player() {
194 if (!this.audio || !this.audio.file) {
195 return;
196 }
197
198 if (!this.audioElm) {
199 this.audioElm = createAudio(this.audio.file);
200 document.body.appendChild(this.audioElm);
201 }
202
203 this.audioElm.play();
204 return this;
205 },
206 notify: function notify(json) {
207 var nt = this.notification;
208 var url = json.openurl ? json.openurl : this.openurl;
209 var onclick = json.onclick ? json.onclick : this.onclick;
210
211 if (window.Notification) {
212 if (json) {
213 nt = jsonArguments(json, nt);
214 } else {
215 nt = defaultNotification;
216 }
217
218 var option = {};
219 option.icon = json.icon ? json.icon : iconURL;
220 option.body = nt.body;
221 if (json.dir) option.dir = json.dir;
222 var n = new Notification(nt.title, option);
223
224 n.onclick = function () {
225 onclick && typeof onclick === 'function' && onclick(n);
226 url && window.open(url);
227 };
228
229 n.onshow = function () {
230 json.onshow && typeof json.onshow === 'function' && json.onshow(n);
231 };
232
233 n.onclose = function () {
234 json.onclose && typeof json.onclose === 'function' && json.onclose(n);
235 };
236
237 n.onerror = function () {
238 json.onerror && typeof json.onerror === 'function' && json.onerror(n);
239 };
240
241 this.Notifiy = n;
242 }
243
244 return this;
245 },
246 // 是否许可弹框通知
247 isPermission: function isPermission() {
248 return window.Notification && Notification.permission === 'granted';
249 },
250 // 设置时间间隔
251 setInterval: function setInterval(num) {
252 if (num) {
253 this.interval = num;
254 this.addTimer();
255 }
256
257 return this;
258 },
259 // 设置网页Icon
260 setFavicon: function setFavicon(num) {
261 if (!num && num !== 0) {
262 return this.faviconClear();
263 }
264
265 var oldicon = document.getElementById("new".concat(this.updateFavicon.id));
266
267 if (this.favicon) {
268 this.favicon.remove();
269 }
270
271 if (oldicon) {
272 oldicon.remove();
273 }
274
275 this.updateFavicon.num = num;
276 changeFavicon(num, this.updateFavicon);
277 return this;
278 },
279 // 设置 Favicon 文字颜色
280 setFaviconColor: function setFaviconColor(color) {
281 if (color) {
282 this.faviconRemove();
283 this.updateFavicon.textColor = color;
284 changeFavicon(this.updateFavicon.num, this.updateFavicon);
285 }
286
287 return this;
288 },
289 // 设置 Favicon 背景颜色
290 setFaviconBackgroundColor: function setFaviconBackgroundColor(color) {
291 if (color) {
292 this.faviconRemove();
293 this.updateFavicon.backgroundColor = color;
294 changeFavicon(this.updateFavicon.num, this.updateFavicon);
295 }
296
297 return this;
298 },
299 faviconRemove: function faviconRemove() {
300 this.faviconClear();
301 var oldicon = document.getElementById("new".concat(this.updateFavicon.id));
302
303 if (this.favicon) {
304 this.favicon.remove();
305 }
306
307 if (oldicon) {
308 oldicon.remove();
309 }
310 },
311 // 添加计数器
312 addTimer: function addTimer() {
313 this.clearTimer();
314
315 if (repeatableEffects.indexOf(this.effect) >= 0) {
316 this.timer = setInterval(this.render.bind(this), this.interval);
317 }
318
319 return this;
320 },
321 close: function close() {
322 if (this.Notifiy) this.Notifiy.close();
323 },
324 // 清除Icon
325 faviconClear: function faviconClear() {
326 var newicon = document.getElementById("new".concat(this.updateFavicon.id));
327 var head = document.getElementsByTagName('head')[0];
328 var ficon = document.querySelectorAll('link[rel~=shortcut]');
329 newicon && newicon.remove();
330
331 if (ficon.length > 0) {
332 for (var i = 0; i < ficon.length; i++) {
333 ficon[i].remove();
334 }
335 }
336
337 head.appendChild(this.cloneFavicon);
338 iconURL = this.cloneFavicon.href;
339 this.favicon = this.cloneFavicon;
340 return this;
341 },
342 // 清除计数器
343 clearTimer: function clearTimer() {
344 this.timer && clearInterval(this.timer);
345 document.title = this.title;
346 return this;
347 }
348};
349
350module.exports = Notify;