From 3126a533e0ab12ec3ff374e155a37fd38bd23bb6 Mon Sep 17 00:00:00 2001 From: John Papa Date: Tue, 29 Apr 2014 07:53:08 -0400 Subject: [PATCH] Clear all toasts followed by a new toast now shows the new toast. Fixes #149 #118 --- demo.html | 275 ++++++++++++++++ tests/unit/toastr-tests.js | 21 +- toastr.js | 630 +++++++++++++++++++------------------ 3 files changed, 609 insertions(+), 317 deletions(-) create mode 100644 demo.html diff --git a/demo.html b/demo.html new file mode 100644 index 00000000..8bf1dc95 --- /dev/null +++ b/demo.html @@ -0,0 +1,275 @@ + + + + + toastr examples + + + + + + + +
+

toastr

+ +
+
+
+
+
+ + + + +
+
+
+
+ +
+
+ +
+
+ +
+
+
+ +
+
+
+ + + + + +
+
+
+
+ + + + + + + +
+
+
+ +
+
+
+ + + + + + + + + + + +
+
+
+ +
+
+
+ + + + + + + + + + + +
+
+
+
+ +
+ + + +
+ +
+

+        
+
+
+ + + + + + + + + + + diff --git a/tests/unit/toastr-tests.js b/tests/unit/toastr-tests.js index f1d3b73a..47d617dd 100644 --- a/tests/unit/toastr-tests.js +++ b/tests/unit/toastr-tests.js @@ -123,6 +123,17 @@ start(); }, delay); }); + test('clear and show - after clear all toasts new toast still appears', 1, function () { + //Arrange + var $toast = []; + //Act + $toast[0] = toastr.info(sampleMsg, sampleTitle + '-1'); + $toast[1] = toastr.info(sampleMsg, sampleTitle + '-2'); + toastr.clear(); + $toast[2] = toastr.info(sampleMsg, sampleTitle + '-3-Visible'); + //Assert + equal($(selectors.container).find('div.toast-title').html(), sampleTitle + '-3-Visible', 'Finds toast after a clear'); //Teardown + }); module('info'); test('info - pass title and message', 3, function () { //Arrange @@ -289,7 +300,7 @@ //Arrange toastr.options.closeButton = true; //Act - var $toast = toastr.success(''); + var $toast = toastr.success(''); //Assert equal($toast.find('button.toast-close-button').length, 1, 'close button should exist with closeButton=true'); //Teardown @@ -364,7 +375,7 @@ $toast.remove(); clearContainerChildren(); }); - + module('order of appearance'); test('Newest toast on top', 1, function () { //Arrange @@ -406,7 +417,7 @@ toastr.options.positionClass = positionClasses.topRight; //Act var $toast = toastr.success(sampleMsg); - var $container = toastr.getContainer(); + var $container = toastr.getContainer(); //Assert ok($container.hasClass(positionClasses.topRight), 'Has position top right'); //Teardown @@ -419,7 +430,7 @@ toastr.options.positionClass = positionClasses.bottomRight; //Act var $toast = toastr.success(sampleMsg); - var $container = toastr.getContainer(); + var $container = toastr.getContainer(); //Assert ok($container.hasClass(positionClasses.bottomRight), 'Has position bottom right'); //Teardown @@ -446,7 +457,7 @@ toastr.options.positionClass = positionClasses.topLeft; //Act var $toast = toastr.success(sampleMsg); - var $container = toastr.getContainer(); + var $container = toastr.getContainer(); //Assert ok($container.hasClass(positionClasses.topLeft), 'Has position top left'); //Teardown diff --git a/toastr.js b/toastr.js index 89b0f40b..c6060ff9 100644 --- a/toastr.js +++ b/toastr.js @@ -11,317 +11,323 @@ * Project: https://github.com/CodeSeven/toastr */ ; (function (define) { - define(['jquery'], function ($) { - return (function () { - var version = '2.0.1'; - var $container; - var listener; - var toastId = 0; - var toastType = { - error: 'error', - info: 'info', - success: 'success', - warning: 'warning' - }; - - var toastr = { - clear: clear, - remove: remove, - error: error, - getContainer: getContainer, - info: info, - options: {}, - subscribe: subscribe, - success: success, - version: version, - warning: warning - }; - - return toastr; - - //#region Accessible Methods - function error(message, title, optionsOverride) { - return notify({ - type: toastType.error, - iconClass: getOptions().iconClasses.error, - message: message, - optionsOverride: optionsOverride, - title: title - }); - } - - function info(message, title, optionsOverride) { - return notify({ - type: toastType.info, - iconClass: getOptions().iconClasses.info, - message: message, - optionsOverride: optionsOverride, - title: title - }); - } - - function subscribe(callback) { - listener = callback; - } - - function success(message, title, optionsOverride) { - return notify({ - type: toastType.success, - iconClass: getOptions().iconClasses.success, - message: message, - optionsOverride: optionsOverride, - title: title - }); - } - - function warning(message, title, optionsOverride) { - return notify({ - type: toastType.warning, - iconClass: getOptions().iconClasses.warning, - message: message, - optionsOverride: optionsOverride, - title: title - }); - } - - function clear($toastElement) { - var options = getOptions(); - if (!$container) { getContainer(options); } - if ($toastElement && $(':focus', $toastElement).length === 0) { - $toastElement[options.hideMethod]({ - duration: options.hideDuration, - easing: options.hideEasing, - complete: function () { removeToast($toastElement); } - }); - return; - } - if ($container.children().length) { - $container[options.hideMethod]({ - duration: options.hideDuration, - easing: options.hideEasing, - complete: function () { $container.remove(); } - }); - } - } - - function remove($toastElement) { - var options = getOptions(); - if (!$container) { getContainer(options); } - if ($toastElement && $(':focus', $toastElement).length === 0) { - removeToast($toastElement); - return; - } - if ($container.children().length) { - $container.remove(); - } - } - //#endregion - - //#region Internal Methods - - function getDefaults() { - return { - tapToDismiss: true, - toastClass: 'toast', - containerId: 'toast-container', - debug: false, - - showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery - showDuration: 300, - showEasing: 'swing', //swing and linear are built into jQuery - onShown: undefined, - hideMethod: 'fadeOut', - hideDuration: 1000, - hideEasing: 'swing', - onHidden: undefined, - - extendedTimeOut: 1000, - iconClasses: { - error: 'toast-error', - info: 'toast-info', - success: 'toast-success', - warning: 'toast-warning' - }, - iconClass: 'toast-info', - positionClass: 'toast-top-right', - timeOut: 5000, // Set timeOut and extendedTimeout to 0 to make it sticky - titleClass: 'toast-title', - messageClass: 'toast-message', - target: 'body', - closeHtml: '', - newestOnTop: true - }; - } - - function publish(args) { - if (!listener) { - return; - } - listener(args); - } - - function notify(map) { - var - options = getOptions(), - iconClass = map.iconClass || options.iconClass; - - if (typeof (map.optionsOverride) !== 'undefined') { - options = $.extend(options, map.optionsOverride); - iconClass = map.optionsOverride.iconClass || iconClass; - } - - toastId++; - - $container = getContainer(options); - var - intervalId = null, - $toastElement = $('
'), - $titleElement = $('
'), - $messageElement = $('
'), - $closeElement = $(options.closeHtml), - response = { - toastId: toastId, - state: 'visible', - startTime: new Date(), - options: options, - map: map - }; - - if (map.iconClass) { - $toastElement.addClass(options.toastClass).addClass(iconClass); - } - - if (map.title) { - $titleElement.append(map.title).addClass(options.titleClass); - $toastElement.append($titleElement); - } - - if (map.message) { - $messageElement.append(map.message).addClass(options.messageClass); - $toastElement.append($messageElement); - } - - if (options.closeButton) { - $closeElement.addClass('toast-close-button').attr("role", "button"); - $toastElement.prepend($closeElement); - } - - $toastElement.hide(); - if (options.newestOnTop) { - $container.prepend($toastElement); - } else { - $container.append($toastElement); - } - - - $toastElement[options.showMethod]( - { duration: options.showDuration, easing: options.showEasing, complete: options.onShown } - ); - if (options.timeOut > 0) { - intervalId = setTimeout(hideToast, options.timeOut); - } - - $toastElement.hover(stickAround, delayedhideToast); - if (!options.onclick && options.tapToDismiss) { - $toastElement.click(hideToast); - } - if (options.closeButton && $closeElement) { - $closeElement.click(function (event) { - if( event.stopPropagation ) { - event.stopPropagation(); - } else if( event.cancelBubble !== undefined && event.cancelBubble !== true ) { - event.cancelBubble = true; - } - hideToast(true); - }); - } - - if (options.onclick) { - $toastElement.click(function () { - options.onclick(); - hideToast(); - }); - } - - publish(response); - - if (options.debug && console) { - console.log(response); - } - - return $toastElement; - - function hideToast(override) { - if ($(':focus', $toastElement).length && !override) { - return; - } - return $toastElement[options.hideMethod]({ - duration: options.hideDuration, - easing: options.hideEasing, - complete: function () { - removeToast($toastElement); - if (options.onHidden && response.state !== 'hidden') { - options.onHidden(); - } - response.state = 'hidden'; - response.endTime = new Date(); - publish(response); - } - }); - } - - function delayedhideToast() { - if (options.timeOut > 0 || options.extendedTimeOut > 0) { - intervalId = setTimeout(hideToast, options.extendedTimeOut); - } - } - - function stickAround() { - clearTimeout(intervalId); - $toastElement.stop(true, true)[options.showMethod]( - { duration: options.showDuration, easing: options.showEasing } - ); - } - } - function getContainer(options) { - if (!options) { options = getOptions(); } - $container = $('#' + options.containerId); - if ($container.length) { - return $container; - } - $container = $('
') - .attr('id', options.containerId) - .addClass(options.positionClass) - .attr('aria-live', 'polite') - .attr('role', 'alert'); - - $container.appendTo($(options.target)); - return $container; - } - - function getOptions() { - return $.extend({}, getDefaults(), toastr.options); - } - - function removeToast($toastElement) { - if (!$container) { $container = getContainer(); } - if ($toastElement.is(':visible')) { - return; - } - $toastElement.remove(); - $toastElement = null; - if ($container.children().length === 0) { - $container.remove(); - } - } - //#endregion - - })(); - }); + define(['jquery'], function ($) { + return (function () { + var $container; + var listener; + var toastId = 0; + var toastType = { + error: 'error', + info: 'info', + success: 'success', + warning: 'warning' + }; + + var toastr = { + clear: clear, + remove: remove, + error: error, + getContainer: getContainer, + info: info, + options: {}, + subscribe: subscribe, + success: success, + version: '2.0.1', + warning: warning + }; + + return toastr; + + //#region Accessible Methods + function error(message, title, optionsOverride) { + return notify({ + type: toastType.error, + iconClass: getOptions().iconClasses.error, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function info(message, title, optionsOverride) { + return notify({ + type: toastType.info, + iconClass: getOptions().iconClasses.info, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function subscribe(callback) { + listener = callback; + } + + function success(message, title, optionsOverride) { + return notify({ + type: toastType.success, + iconClass: getOptions().iconClasses.success, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function warning(message, title, optionsOverride) { + return notify({ + type: toastType.warning, + iconClass: getOptions().iconClasses.warning, + message: message, + optionsOverride: optionsOverride, + title: title + }); + } + + function clear($toastElement) { + var options = getOptions(); + if (!$container) { getContainer(options); } + if (!clearToast($toastElement, options)) { + clearContainer(options); + } + } + + function remove($toastElement) { + var options = getOptions(); + if (!$container) { getContainer(options); } + if ($toastElement && $(':focus', $toastElement).length === 0) { + removeToast($toastElement); + return; + } + if ($container.children().length) { + $container.remove(); + } + } + //#endregion + + //#region Internal Methods + + function clearContainer(options){ + var toastsToClear = $container.children(); + for (var i = toastsToClear.length - 1; i >= 0; i--) { + clearToast($(toastsToClear[i]), options); + }; + } + + function clearToast($toastElement, options){ + if ($toastElement && $(':focus', $toastElement).length === 0) { + $toastElement[options.hideMethod]({ + duration: options.hideDuration, + easing: options.hideEasing, + complete: function () { removeToast($toastElement); } + }); + return true; + } + return false; + } + + function getDefaults() { + return { + tapToDismiss: true, + toastClass: 'toast', + containerId: 'toast-container', + debug: false, + + showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery + showDuration: 300, + showEasing: 'swing', //swing and linear are built into jQuery + onShown: undefined, + hideMethod: 'fadeOut', + hideDuration: 1000, + hideEasing: 'swing', + onHidden: undefined, + + extendedTimeOut: 1000, + iconClasses: { + error: 'toast-error', + info: 'toast-info', + success: 'toast-success', + warning: 'toast-warning' + }, + iconClass: 'toast-info', + positionClass: 'toast-top-right', + timeOut: 5000, // Set timeOut and extendedTimeout to 0 to make it sticky + titleClass: 'toast-title', + messageClass: 'toast-message', + target: 'body', + closeHtml: '', + newestOnTop: true + }; + } + + function publish(args) { + if (!listener) { + return; + } + listener(args); + } + + function notify(map) { + var + options = getOptions(), + iconClass = map.iconClass || options.iconClass; + + if (typeof (map.optionsOverride) !== 'undefined') { + options = $.extend(options, map.optionsOverride); + iconClass = map.optionsOverride.iconClass || iconClass; + } + + toastId++; + + $container = getContainer(options); + var + intervalId = null, + $toastElement = $('
'), + $titleElement = $('
'), + $messageElement = $('
'), + $closeElement = $(options.closeHtml), + response = { + toastId: toastId, + state: 'visible', + startTime: new Date(), + options: options, + map: map + }; + + if (map.iconClass) { + $toastElement.addClass(options.toastClass).addClass(iconClass); + } + + if (map.title) { + $titleElement.append(map.title).addClass(options.titleClass); + $toastElement.append($titleElement); + } + + if (map.message) { + $messageElement.append(map.message).addClass(options.messageClass); + $toastElement.append($messageElement); + } + + if (options.closeButton) { + $closeElement.addClass('toast-close-button').attr("role", "button"); + $toastElement.prepend($closeElement); + } + + $toastElement.hide(); + if (options.newestOnTop) { + $container.prepend($toastElement); + } else { + $container.append($toastElement); + } + + + $toastElement[options.showMethod]( + { duration: options.showDuration, easing: options.showEasing, complete: options.onShown } + ); + if (options.timeOut > 0) { + intervalId = setTimeout(hideToast, options.timeOut); + } + + $toastElement.hover(stickAround, delayedhideToast); + if (!options.onclick && options.tapToDismiss) { + $toastElement.click(hideToast); + } + if (options.closeButton && $closeElement) { + $closeElement.click(function (event) { + if( event.stopPropagation ) { + event.stopPropagation(); + } else if( event.cancelBubble !== undefined && event.cancelBubble !== true ) { + event.cancelBubble = true; + } + hideToast(true); + }); + } + + if (options.onclick) { + $toastElement.click(function () { + options.onclick(); + hideToast(); + }); + } + + publish(response); + + if (options.debug && console) { + console.log(response); + } + + return $toastElement; + + function hideToast(override) { + if ($(':focus', $toastElement).length && !override) { + return; + } + return $toastElement[options.hideMethod]({ + duration: options.hideDuration, + easing: options.hideEasing, + complete: function () { + removeToast($toastElement); + if (options.onHidden && response.state !== 'hidden') { + options.onHidden(); + } + response.state = 'hidden'; + response.endTime = new Date(); + publish(response); + } + }); + } + + function delayedhideToast() { + if (options.timeOut > 0 || options.extendedTimeOut > 0) { + intervalId = setTimeout(hideToast, options.extendedTimeOut); + } + } + + function stickAround() { + clearTimeout(intervalId); + $toastElement.stop(true, true)[options.showMethod]( + { duration: options.showDuration, easing: options.showEasing } + ); + } + } + function getContainer(options) { + if (!options) { options = getOptions(); } + $container = $('#' + options.containerId); + if ($container.length) { + return $container; + } + $container = $('
') + .attr('id', options.containerId) + .addClass(options.positionClass) + .attr('aria-live', 'polite') + .attr('role', 'alert'); + + $container.appendTo($(options.target)); + return $container; + } + + function getOptions() { + return $.extend({}, getDefaults(), toastr.options); + } + + function removeToast($toastElement) { + if (!$container) { $container = getContainer(); } + if ($toastElement.is(':visible')) { + return; + } + $toastElement.remove(); + $toastElement = null; + if ($container.children().length === 0) { + $container.remove(); + } + } + //#endregion + + })(); + }); }(typeof define === 'function' && define.amd ? define : function (deps, factory) { - if (typeof module !== 'undefined' && module.exports) { //Node - module.exports = factory(require('jquery')); - } else { - window['toastr'] = factory(window['jQuery']); - } + if (typeof module !== 'undefined' && module.exports) { //Node + module.exports = factory(require('jquery')); + } else { + window['toastr'] = factory(window['jQuery']); + } })); \ No newline at end of file