jquery.noty.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520
  1. /**
  2. * noty - jQuery Notification Plugin v2.0.3
  3. * Contributors: https://github.com/needim/noty/graphs/contributors
  4. *
  5. * Examples and Documentation - http://needim.github.com/noty/
  6. *
  7. * Licensed under the MIT licenses:
  8. * http://www.opensource.org/licenses/mit-license.php
  9. *
  10. **/
  11. if (typeof Object.create !== 'function') {
  12. Object.create = function (o) {
  13. function F() {
  14. }
  15. F.prototype = o;
  16. return new F();
  17. };
  18. }
  19. (function ($) {
  20. var NotyObject = {
  21. init:function (options) {
  22. // Mix in the passed in options with the default options
  23. this.options = $.extend({}, $.noty.defaults, options);
  24. this.options.layout = (this.options.custom) ? $.noty.layouts['inline'] : $.noty.layouts[this.options.layout];
  25. this.options.theme = $.noty.themes[this.options.theme];
  26. delete options.layout;
  27. delete options.theme;
  28. this.options = $.extend({}, this.options, this.options.layout.options);
  29. this.options.id = 'noty_' + (new Date().getTime() * Math.floor(Math.random() * 1000000));
  30. this.options = $.extend({}, this.options, options);
  31. // Build the noty dom initial structure
  32. this._build();
  33. // return this so we can chain/use the bridge with less code.
  34. return this;
  35. }, // end init
  36. _build:function () {
  37. // Generating noty bar
  38. var $bar = $('<div class="noty_bar"></div>').attr('id', this.options.id);
  39. $bar.append(this.options.template).find('.noty_text').html(this.options.text);
  40. this.$bar = (this.options.layout.parent.object !== null) ? $(this.options.layout.parent.object).css(this.options.layout.parent.css).append($bar) : $bar;
  41. // Set buttons if available
  42. if (this.options.buttons) {
  43. // If we have button disable closeWith & timeout options
  44. this.options.closeWith = [];
  45. this.options.timeout = false;
  46. var $buttons = $('<div/>').addClass('noty_buttons');
  47. (this.options.layout.parent.object !== null) ? this.$bar.find('.noty_bar').append($buttons) : this.$bar.append($buttons);
  48. var self = this;
  49. $.each(this.options.buttons, function (i, button) {
  50. var $button = $('<button/>').addClass((button.addClass) ? button.addClass : 'gray').html(button.text)
  51. .appendTo(self.$bar.find('.noty_buttons'))
  52. .bind('click', function () {
  53. if ($.isFunction(button.onClick)) {
  54. button.onClick.call($button, self);
  55. }
  56. });
  57. });
  58. }
  59. // For easy access
  60. this.$message = this.$bar.find('.noty_message');
  61. this.$closeButton = this.$bar.find('.noty_close');
  62. this.$buttons = this.$bar.find('.noty_buttons');
  63. $.noty.store[this.options.id] = this; // store noty for api
  64. }, // end _build
  65. show:function () {
  66. var self = this;
  67. $(self.options.layout.container.selector).append(self.$bar);
  68. self.options.theme.style.apply(self);
  69. ($.type(self.options.layout.css) === 'function') ? this.options.layout.css.apply(self.$bar) : self.$bar.css(this.options.layout.css || {});
  70. self.$bar.addClass(self.options.layout.addClass);
  71. self.options.layout.container.style.apply($(self.options.layout.container.selector));
  72. self.options.theme.callback.onShow.apply(this);
  73. if ($.inArray('click', self.options.closeWith) > -1)
  74. self.$bar.css('cursor', 'pointer').one('click', function () {
  75. if (self.options.callback.onCloseClick) {
  76. self.options.callback.onCloseClick.apply(self);
  77. }
  78. self.close();
  79. });
  80. if ($.inArray('hover', self.options.closeWith) > -1)
  81. self.$bar.one('mouseenter', function () {
  82. self.close();
  83. });
  84. if ($.inArray('button', self.options.closeWith) > -1)
  85. self.$closeButton.one('click', function () {
  86. self.close();
  87. });
  88. if ($.inArray('button', self.options.closeWith) == -1)
  89. self.$closeButton.remove();
  90. if (self.options.callback.onShow)
  91. self.options.callback.onShow.apply(self);
  92. self.$bar.animate(
  93. self.options.animation.open,
  94. self.options.animation.speed,
  95. self.options.animation.easing,
  96. function () {
  97. if (self.options.callback.afterShow) self.options.callback.afterShow.apply(self);
  98. self.shown = true;
  99. });
  100. // If noty is have a timeout option
  101. if (self.options.timeout)
  102. self.$bar.delay(self.options.timeout).promise().done(function () {
  103. self.close();
  104. });
  105. return this;
  106. }, // end show
  107. close:function () {
  108. if (this.closed) return;
  109. if (this.$bar && this.$bar.hasClass('i-am-closing-now')) return;
  110. var self = this;
  111. if (!this.shown) { // If we are still waiting in the queue just delete from queue
  112. var queue = [];
  113. $.each($.noty.queue, function (i, n) {
  114. if (n.options.id != self.options.id) {
  115. queue.push(n);
  116. }
  117. });
  118. $.noty.queue = queue;
  119. return;
  120. }
  121. self.$bar.addClass('i-am-closing-now');
  122. if (self.options.callback.onClose) {
  123. self.options.callback.onClose.apply(self);
  124. }
  125. self.$bar.clearQueue().stop().animate(
  126. self.options.animation.close,
  127. self.options.animation.speed,
  128. self.options.animation.easing,
  129. function () {
  130. if (self.options.callback.afterClose) self.options.callback.afterClose.apply(self);
  131. })
  132. .promise().done(function () {
  133. // Modal Cleaning
  134. if (self.options.modal) {
  135. $.notyRenderer.setModalCount(-1);
  136. if ($.notyRenderer.getModalCount() == 0) $('.noty_modal').fadeOut('fast', function () {
  137. $(this).remove();
  138. });
  139. }
  140. // Layout Cleaning
  141. $.notyRenderer.setLayoutCountFor(self, -1);
  142. if ($.notyRenderer.getLayoutCountFor(self) == 0) $(self.options.layout.container.selector).remove();
  143. // Make sure self.$bar has not been removed before attempting to remove it
  144. if (typeof self.$bar !== 'undefined' && self.$bar !== null ) {
  145. self.$bar.remove();
  146. self.$bar = null;
  147. self.closed = true;
  148. }
  149. delete $.noty.store[self.options.id]; // deleting noty from store
  150. self.options.theme.callback.onClose.apply(self);
  151. if (!self.options.dismissQueue) {
  152. // Queue render
  153. $.noty.ontap = true;
  154. $.notyRenderer.render();
  155. }
  156. });
  157. }, // end close
  158. setText:function (text) {
  159. if (!this.closed) {
  160. this.options.text = text;
  161. this.$bar.find('.noty_text').html(text);
  162. }
  163. return this;
  164. },
  165. setType:function (type) {
  166. if (!this.closed) {
  167. this.options.type = type;
  168. this.options.theme.style.apply(this);
  169. this.options.theme.callback.onShow.apply(this);
  170. }
  171. return this;
  172. },
  173. setTimeout:function (time) {
  174. if (!this.closed) {
  175. var self = this;
  176. this.options.timeout = time;
  177. self.$bar.delay(self.options.timeout).promise().done(function () {
  178. self.close();
  179. });
  180. }
  181. return this;
  182. },
  183. closed:false,
  184. shown:false
  185. }; // end NotyObject
  186. $.notyRenderer = {};
  187. $.notyRenderer.init = function (options) {
  188. // Renderer creates a new noty
  189. var notification = Object.create(NotyObject).init(options);
  190. (notification.options.force) ? $.noty.queue.unshift(notification) : $.noty.queue.push(notification);
  191. $.notyRenderer.render();
  192. return ($.noty.returns == 'object') ? notification : notification.options.id;
  193. };
  194. $.notyRenderer.render = function () {
  195. var instance = $.noty.queue[0];
  196. if ($.type(instance) === 'object') {
  197. if (instance.options.dismissQueue) {
  198. $.notyRenderer.show($.noty.queue.shift());
  199. } else {
  200. if ($.noty.ontap) {
  201. $.notyRenderer.show($.noty.queue.shift());
  202. $.noty.ontap = false;
  203. }
  204. }
  205. } else {
  206. $.noty.ontap = true; // Queue is over
  207. }
  208. };
  209. $.notyRenderer.show = function (notification) {
  210. if (notification.options.modal) {
  211. $.notyRenderer.createModalFor(notification);
  212. $.notyRenderer.setModalCount(+1);
  213. }
  214. // Where is the container?
  215. if ($(notification.options.layout.container.selector).length == 0) {
  216. if (notification.options.custom) {
  217. notification.options.custom.append($(notification.options.layout.container.object).addClass('i-am-new'));
  218. } else {
  219. $('body').append($(notification.options.layout.container.object).addClass('i-am-new'));
  220. }
  221. } else {
  222. $(notification.options.layout.container.selector).removeClass('i-am-new');
  223. }
  224. $.notyRenderer.setLayoutCountFor(notification, +1);
  225. notification.show();
  226. };
  227. $.notyRenderer.createModalFor = function (notification) {
  228. if ($('.noty_modal').length == 0)
  229. $('<div/>').addClass('noty_modal').data('noty_modal_count', 0).css(notification.options.theme.modal.css).prependTo($('body')).fadeIn('fast');
  230. };
  231. $.notyRenderer.getLayoutCountFor = function (notification) {
  232. return $(notification.options.layout.container.selector).data('noty_layout_count') || 0;
  233. };
  234. $.notyRenderer.setLayoutCountFor = function (notification, arg) {
  235. return $(notification.options.layout.container.selector).data('noty_layout_count', $.notyRenderer.getLayoutCountFor(notification) + arg);
  236. };
  237. $.notyRenderer.getModalCount = function () {
  238. return $('.noty_modal').data('noty_modal_count') || 0;
  239. };
  240. $.notyRenderer.setModalCount = function (arg) {
  241. return $('.noty_modal').data('noty_modal_count', $.notyRenderer.getModalCount() + arg);
  242. };
  243. // This is for custom container
  244. $.fn.noty = function (options) {
  245. options.custom = $(this);
  246. return $.notyRenderer.init(options);
  247. };
  248. $.noty = {};
  249. $.noty.queue = [];
  250. $.noty.ontap = true;
  251. $.noty.layouts = {};
  252. $.noty.themes = {};
  253. $.noty.returns = 'object';
  254. $.noty.store = {};
  255. $.noty.get = function (id) {
  256. return $.noty.store.hasOwnProperty(id) ? $.noty.store[id] : false;
  257. };
  258. $.noty.close = function (id) {
  259. return $.noty.get(id) ? $.noty.get(id).close() : false;
  260. };
  261. $.noty.setText = function (id, text) {
  262. return $.noty.get(id) ? $.noty.get(id).setText(text) : false;
  263. };
  264. $.noty.setType = function (id, type) {
  265. return $.noty.get(id) ? $.noty.get(id).setType(type) : false;
  266. };
  267. $.noty.clearQueue = function () {
  268. $.noty.queue = [];
  269. };
  270. $.noty.closeAll = function () {
  271. $.noty.clearQueue();
  272. $.each($.noty.store, function (id, noty) {
  273. noty.close();
  274. });
  275. };
  276. var windowAlert = window.alert;
  277. $.noty.consumeAlert = function (options) {
  278. window.alert = function (text) {
  279. if (options)
  280. options.text = text;
  281. else
  282. options = {text:text};
  283. $.notyRenderer.init(options);
  284. };
  285. };
  286. $.noty.stopConsumeAlert = function () {
  287. window.alert = windowAlert;
  288. };
  289. $.noty.defaults = {
  290. layout:'topRight',
  291. theme:'defaultTheme',
  292. type:'alert',
  293. text:'',
  294. dismissQueue:true,
  295. template:'<div class="noty_message"><span class="noty_text"></span><div class="noty_close"></div></div>',
  296. animation:{
  297. open:{opacity:'toggle'},
  298. close:{opacity:'toggle'},
  299. easing:'linear',
  300. speed: 200
  301. },
  302. timeout:false,
  303. force:false,
  304. modal:false,
  305. closeWith:['click'],
  306. callback:{
  307. onShow:function () {
  308. },
  309. afterShow:function () {
  310. },
  311. onClose:function () {
  312. },
  313. afterClose:function () {
  314. },
  315. onCloseClick:function () {
  316. }
  317. },
  318. buttons:false
  319. };
  320. $(window).resize(function () {
  321. $.each($.noty.layouts, function (index, layout) {
  322. layout.container.style.apply($(layout.container.selector));
  323. });
  324. });
  325. })(jQuery);
  326. // Helpers
  327. function noty(options) {
  328. // This is for BC - Will be deleted on v2.2.0
  329. var using_old = 0
  330. , old_to_new = {
  331. 'animateOpen':'animation.open',
  332. 'animateClose':'animation.close',
  333. 'easing':'animation.easing',
  334. 'speed':'animation.speed',
  335. 'onShow':'callback.onShow',
  336. 'onShown':'callback.afterShow',
  337. 'onClose':'callback.onClose',
  338. 'onCloseClick':'callback.onCloseClick',
  339. 'onClosed':'callback.afterClose'
  340. };
  341. jQuery.each(options, function (key, value) {
  342. if (old_to_new[key]) {
  343. using_old++;
  344. var _new = old_to_new[key].split('.');
  345. if (!options[_new[0]]) options[_new[0]] = {};
  346. options[_new[0]][_new[1]] = (value) ? value : function () {
  347. };
  348. delete options[key];
  349. }
  350. });
  351. if (!options.closeWith) {
  352. options.closeWith = jQuery.noty.defaults.closeWith;
  353. }
  354. if (options.hasOwnProperty('closeButton')) {
  355. using_old++;
  356. if (options.closeButton) options.closeWith.push('button');
  357. delete options.closeButton;
  358. }
  359. if (options.hasOwnProperty('closeOnSelfClick')) {
  360. using_old++;
  361. if (options.closeOnSelfClick) options.closeWith.push('click');
  362. delete options.closeOnSelfClick;
  363. }
  364. if (options.hasOwnProperty('closeOnSelfOver')) {
  365. using_old++;
  366. if (options.closeOnSelfOver) options.closeWith.push('hover');
  367. delete options.closeOnSelfOver;
  368. }
  369. if (options.hasOwnProperty('custom')) {
  370. using_old++;
  371. if (options.custom.container != 'null') options.custom = options.custom.container;
  372. }
  373. if (options.hasOwnProperty('cssPrefix')) {
  374. using_old++;
  375. delete options.cssPrefix;
  376. }
  377. if (options.theme == 'noty_theme_default') {
  378. using_old++;
  379. options.theme = 'defaultTheme';
  380. }
  381. if (!options.hasOwnProperty('dismissQueue')) {
  382. options.dismissQueue = jQuery.noty.defaults.dismissQueue;
  383. }
  384. if (options.buttons) {
  385. jQuery.each(options.buttons, function (i, button) {
  386. if (button.click) {
  387. using_old++;
  388. button.onClick = button.click;
  389. delete button.click;
  390. }
  391. if (button.type) {
  392. using_old++;
  393. button.addClass = button.type;
  394. delete button.type;
  395. }
  396. });
  397. }
  398. if (using_old) {
  399. if (typeof console !== "undefined" && console.warn) {
  400. console.warn('You are using noty v2 with v1.x.x options. @deprecated until v2.2.0 - Please update your options.');
  401. }
  402. }
  403. // console.log(options);
  404. // End of the BC
  405. return jQuery.notyRenderer.init(options);
  406. }