desktop-notify.js 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207
  1. /**
  2. * Copyright 2012 Tsvetan Tsvetkov
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. *
  16. * Author: Tsvetan Tsvetkov (tsekach@gmail.com)
  17. */
  18. (function (win) {
  19. /*
  20. Safari native methods required for Notifications do NOT run in strict mode.
  21. */
  22. //"use strict";
  23. var PERMISSION_DEFAULT = "default",
  24. PERMISSION_GRANTED = "granted",
  25. PERMISSION_DENIED = "denied",
  26. PERMISSION = [PERMISSION_GRANTED, PERMISSION_DEFAULT, PERMISSION_DENIED],
  27. defaultSetting = {
  28. pageVisibility: false,
  29. autoClose: 0
  30. },
  31. empty = {},
  32. emptyString = "",
  33. isSupported = (function () {
  34. var isSupported = false;
  35. /*
  36. * Use try {} catch() {} because the check for IE may throws an exception
  37. * if the code is run on browser that is not Safar/Chrome/IE or
  38. * Firefox with html5notifications plugin.
  39. *
  40. * Also, we canNOT detect if msIsSiteMode method exists, as it is
  41. * a method of host object. In IE check for existing method of host
  42. * object returns undefined. So, we try to run it - if it runs
  43. * successfully - then it is IE9+, if not - an exceptions is thrown.
  44. */
  45. try {
  46. isSupported = !!(/* Safari, Chrome */win.Notification || /* Chrome & ff-html5notifications plugin */win.webkitNotifications || /* Firefox Mobile */navigator.mozNotification || /* IE9+ */(win.external && win.external.msIsSiteMode() !== undefined));
  47. } catch (e) {}
  48. return isSupported;
  49. }()),
  50. ieVerification = Math.floor((Math.random() * 10) + 1),
  51. isFunction = function (value) { return (value && (value).constructor === Function); },
  52. isString = function (value) {return (value && (value).constructor === String); },
  53. isObject = function (value) {return (value && (value).constructor === Object); },
  54. /**
  55. * Dojo Mixin
  56. */
  57. mixin = function (target, source) {
  58. var name, s;
  59. for (name in source) {
  60. s = source[name];
  61. if (!(name in target) || (target[name] !== s && (!(name in empty) || empty[name] !== s))) {
  62. target[name] = s;
  63. }
  64. }
  65. return target; // Object
  66. },
  67. noop = function () {},
  68. settings = defaultSetting;
  69. function getNotification(title, options) {
  70. var notification;
  71. if (win.Notification) { /* Safari 6, Chrome (23+) */
  72. notification = new win.Notification(title, {
  73. /* The notification's icon - For Chrome in Windows, Linux & Chrome OS */
  74. icon: isString(options.icon) ? options.icon : options.icon.x32,
  75. /* The notification’s subtitle. */
  76. body: options.body || emptyString,
  77. /*
  78. The notification’s unique identifier.
  79. This prevents duplicate entries from appearing if the user has multiple instances of your website open at once.
  80. */
  81. tag: options.tag || emptyString
  82. });
  83. } else if (win.webkitNotifications) { /* FF with html5Notifications plugin installed */
  84. notification = win.webkitNotifications.createNotification(options.icon, title, options.body);
  85. notification.show();
  86. } else if (navigator.mozNotification) { /* Firefox Mobile */
  87. notification = navigator.mozNotification.createNotification(title, options.body, options.icon);
  88. notification.show();
  89. } else if (win.external && win.external.msIsSiteMode()) { /* IE9+ */
  90. //Clear any previous notifications
  91. win.external.msSiteModeClearIconOverlay();
  92. win.external.msSiteModeSetIconOverlay((isString(options.icon) ? options.icon : options.icon.x16), title);
  93. win.external.msSiteModeActivate();
  94. notification = {
  95. "ieVerification": ieVerification + 1
  96. };
  97. }
  98. return notification;
  99. }
  100. function getWrapper(notification) {
  101. return {
  102. webNotification: notification,
  103. close: function () {
  104. if (notification) {
  105. if (notification.close) {
  106. //http://code.google.com/p/ff-html5notifications/issues/detail?id=58
  107. notification.close();
  108. }
  109. else if (notification.cancel) {
  110. notification.cancel();
  111. } else if (win.external && win.external.msIsSiteMode()) {
  112. if (notification.ieVerification === ieVerification) {
  113. win.external.msSiteModeClearIconOverlay();
  114. }
  115. }
  116. }
  117. }
  118. };
  119. }
  120. function requestPermission(callback) {
  121. if (!isSupported) { return; }
  122. var callbackFunction = isFunction(callback) ? callback : noop;
  123. if (win.webkitNotifications && win.webkitNotifications.checkPermission) {
  124. /*
  125. * Chrome 23 supports win.Notification.requestPermission, but it
  126. * breaks the browsers, so use the old-webkit-prefixed
  127. * win.webkitNotifications.checkPermission instead.
  128. *
  129. * Firefox with html5notifications plugin supports this method
  130. * for requesting permissions.
  131. */
  132. win.webkitNotifications.requestPermission(callbackFunction);
  133. } else if (win.Notification && win.Notification.requestPermission) {
  134. win.Notification.requestPermission(callbackFunction);
  135. }
  136. }
  137. function permissionLevel() {
  138. var permission;
  139. if (!isSupported) { return; }
  140. if (win.Notification && win.Notification.permissionLevel) {
  141. //Safari 6
  142. permission = win.Notification.permissionLevel();
  143. } else if (win.webkitNotifications && win.webkitNotifications.checkPermission) {
  144. //Chrome & Firefox with html5-notifications plugin installed
  145. permission = PERMISSION[win.webkitNotifications.checkPermission()];
  146. } else if (win.Notification && win.Notification.permission) {
  147. // Firefox 23+
  148. permission = win.Notification.permission;
  149. } else if (navigator.mozNotification) {
  150. //Firefox Mobile
  151. permission = PERMISSION_GRANTED;
  152. } else if (win.external && (win.external.msIsSiteMode() !== undefined)) { /* keep last */
  153. //IE9+
  154. permission = win.external.msIsSiteMode() ? PERMISSION_GRANTED : PERMISSION_DEFAULT;
  155. }
  156. return permission;
  157. }
  158. /**
  159. *
  160. */
  161. function config(params) {
  162. if (params && isObject(params)) {
  163. mixin(settings, params);
  164. }
  165. return settings;
  166. }
  167. function createNotification(title, options) {
  168. var notification,
  169. notificationWrapper;
  170. /*
  171. Return undefined if notifications are not supported.
  172. Return undefined if no permissions for displaying notifications.
  173. Title and icons are required. Return undefined if not set.
  174. */
  175. if (isSupported && isString(title) && (options && (isString(options.icon) || isObject(options.icon))) && (permissionLevel() === PERMISSION_GRANTED)) {
  176. notification = getNotification(title, options);
  177. }
  178. notificationWrapper = getWrapper(notification);
  179. //Auto-close notification
  180. if (settings.autoClose && notification && !notification.ieVerification && notification.addEventListener) {
  181. notification.addEventListener("show", function () {
  182. var notification = notificationWrapper;
  183. win.setTimeout(function () {
  184. notification.close();
  185. }, settings.autoClose);
  186. });
  187. }
  188. return notificationWrapper;
  189. }
  190. win.notify = {
  191. PERMISSION_DEFAULT: PERMISSION_DEFAULT,
  192. PERMISSION_GRANTED: PERMISSION_GRANTED,
  193. PERMISSION_DENIED: PERMISSION_DENIED,
  194. isSupported: isSupported,
  195. config: config,
  196. createNotification: createNotification,
  197. permissionLevel: permissionLevel,
  198. requestPermission: requestPermission
  199. };
  200. if (isFunction(Object.seal)) {
  201. Object.seal(win.notify);
  202. }
  203. }(window));