UNPKG

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