| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467 |
- (function() {
- 'use strict';
- angular.module('toastr', [])
- .factory('toastr', toastr);
- toastr.$inject = ['$animate', '$injector', '$document', '$rootScope', '$sce', 'toastrConfig', '$q'];
- function toastr($animate, $injector, $document, $rootScope, $sce, toastrConfig, $q) {
- var container;
- var index = 0;
- var toasts = [];
- var previousToastMessage = '';
- var openToasts = {};
- var containerDefer = $q.defer();
- var toast = {
- clear: clear,
- error: error,
- info: info,
- remove: remove,
- success: success,
- warning: warning
- };
- return toast;
- /* Public API */
- function clear(toast) {
- if (toast) {
- remove(toast.toastId);
- } else {
- for (var i = 0; i < toasts.length; i++) {
- remove(toasts[i].toastId);
- }
- }
- }
- function error(message, title, optionsOverride) {
- var type = _getOptions().iconClasses.error;
- return _buildNotification(type, message, title, optionsOverride);
- }
- function info(message, title, optionsOverride) {
- var type = _getOptions().iconClasses.info;
- return _buildNotification(type, message, title, optionsOverride);
- }
- function success(message, title, optionsOverride) {
- var type = _getOptions().iconClasses.success;
- return _buildNotification(type, message, title, optionsOverride);
- }
- function warning(message, title, optionsOverride) {
- var type = _getOptions().iconClasses.warning;
- return _buildNotification(type, message, title, optionsOverride);
- }
- function remove(toastId, wasClicked) {
- var toast = findToast(toastId);
- if (toast && ! toast.deleting) { // Avoid clicking when fading out
- toast.deleting = true;
- toast.isOpened = false;
- $animate.leave(toast.el).then(function() {
- if (toast.scope.options.onHidden) {
- toast.scope.options.onHidden(wasClicked);
- }
- toast.scope.$destroy();
- var index = toasts.indexOf(toast);
- delete openToasts[toast.scope.message];
- toasts.splice(index, 1);
- var maxOpened = toastrConfig.maxOpened;
- if (maxOpened && toasts.length >= maxOpened) {
- toasts[maxOpened - 1].open.resolve();
- }
- if (lastToast()) {
- container.remove();
- container = null;
- containerDefer = $q.defer();
- }
- });
- }
- function findToast(toastId) {
- for (var i = 0; i < toasts.length; i++) {
- if (toasts[i].toastId === toastId) {
- return toasts[i];
- }
- }
- }
- function lastToast() {
- return !toasts.length;
- }
- }
- /* Internal functions */
- function _buildNotification(type, message, title, optionsOverride)
- {
- if (angular.isObject(title)) {
- optionsOverride = title;
- title = null;
- }
- return _notify({
- iconClass: type,
- message: message,
- optionsOverride: optionsOverride,
- title: title
- });
- }
- function _getOptions() {
- return angular.extend({}, toastrConfig);
- }
- function _createOrGetContainer(options) {
- if(container) { return containerDefer.promise; }
- container = angular.element('<div></div>');
- container.attr('id', options.containerId);
- container.addClass(options.positionClass);
- container.css({'pointer-events': 'auto'});
- var target = angular.element(document.querySelector(options.target));
- if ( ! target || ! target.length) {
- throw 'Target for toasts doesn\'t exist';
- }
- $animate.enter(container, target).then(function() {
- containerDefer.resolve();
- });
- return containerDefer.promise;
- }
- function _notify(map) {
- var options = _getOptions();
- if (shouldExit()) { return; }
- var newToast = createToast();
- toasts.push(newToast);
- if (options.autoDismiss && options.maxOpened > 0) {
- var oldToasts = toasts.slice(0, (toasts.length - options.maxOpened));
- for (var i = 0, len = oldToasts.length; i < len; i++) {
- remove(oldToasts[i].toastId);
- }
- }
- if (maxOpenedNotReached()) {
- newToast.open.resolve();
- }
- newToast.open.promise.then(function() {
- _createOrGetContainer(options).then(function() {
- newToast.isOpened = true;
- if (options.newestOnTop) {
- $animate.enter(newToast.el, container).then(function() {
- newToast.scope.init();
- });
- } else {
- var sibling = container[0].lastChild ? angular.element(container[0].lastChild) : null;
- $animate.enter(newToast.el, container, sibling).then(function() {
- newToast.scope.init();
- });
- }
- });
- });
- return newToast;
- function createScope(toast, map, options) {
- if (options.allowHtml) {
- toast.scope.allowHtml = true;
- toast.scope.title = $sce.trustAsHtml(map.title);
- toast.scope.message = $sce.trustAsHtml(map.message);
- } else {
- toast.scope.title = map.title;
- toast.scope.message = map.message;
- }
- toast.scope.toastType = toast.iconClass;
- toast.scope.toastId = toast.toastId;
- toast.scope.options = {
- extendedTimeOut: options.extendedTimeOut,
- messageClass: options.messageClass,
- onHidden: options.onHidden,
- onShown: options.onShown,
- progressBar: options.progressBar,
- tapToDismiss: options.tapToDismiss,
- timeOut: options.timeOut,
- titleClass: options.titleClass,
- toastClass: options.toastClass
- };
- if (options.closeButton) {
- toast.scope.options.closeHtml = options.closeHtml;
- }
- }
- function createToast() {
- var newToast = {
- toastId: index++,
- isOpened: false,
- scope: $rootScope.$new(),
- open: $q.defer()
- };
- newToast.iconClass = map.iconClass;
- if (map.optionsOverride) {
- options = angular.extend(options, cleanOptionsOverride(map.optionsOverride));
- newToast.iconClass = map.optionsOverride.iconClass || newToast.iconClass;
- }
- createScope(newToast, map, options);
- newToast.el = createToastEl(newToast.scope);
- return newToast;
- function cleanOptionsOverride(options) {
- var badOptions = ['containerId', 'iconClasses', 'maxOpened', 'newestOnTop',
- 'positionClass', 'preventDuplicates', 'preventOpenDuplicates', 'templates'];
- for (var i = 0, l = badOptions.length; i < l; i++) {
- delete options[badOptions[i]];
- }
- return options;
- }
- }
- function createToastEl(scope) {
- var angularDomEl = angular.element('<div toast></div>'),
- $compile = $injector.get('$compile');
- return $compile(angularDomEl)(scope);
- }
- function maxOpenedNotReached() {
- return options.maxOpened && toasts.length <= options.maxOpened || !options.maxOpened;
- }
- function shouldExit() {
- var isDuplicateOfLast = options.preventDuplicates && map.message === previousToastMessage;
- var isDuplicateOpen = options.preventOpenDuplicates && openToasts[map.message];
- if (isDuplicateOfLast || isDuplicateOpen) {
- return true;
- }
- previousToastMessage = map.message;
- openToasts[map.message] = true;
- return false;
- }
- }
- }
- }());
- (function() {
- 'use strict';
- angular.module('toastr')
- .constant('toastrConfig', {
- allowHtml: false,
- autoDismiss: false,
- closeButton: false,
- closeHtml: '<button>×</button>',
- containerId: 'toast-container',
- extendedTimeOut: 1000,
- iconClasses: {
- error: 'toast-error',
- info: 'toast-info',
- success: 'toast-success',
- warning: 'toast-warning'
- },
- maxOpened: 0,
- messageClass: 'toast-message',
- newestOnTop: true,
- onHidden: null,
- onShown: null,
- positionClass: 'toast-top-right',
- preventDuplicates: false,
- preventOpenDuplicates: false,
- progressBar: false,
- tapToDismiss: true,
- target: 'body',
- templates: {
- toast: 'directives/toast/toast.html',
- progressbar: 'directives/progressbar/progressbar.html'
- },
- timeOut: 5000,
- titleClass: 'toast-title',
- toastClass: 'toast'
- });
- }());
- (function() {
- 'use strict';
- angular.module('toastr')
- .directive('progressBar', progressBar);
- progressBar.$inject = ['toastrConfig'];
- function progressBar(toastrConfig) {
- return {
- replace: true,
- require: '^toast',
- templateUrl: function() {
- return toastrConfig.templates.progressbar;
- },
- link: linkFunction
- };
- function linkFunction(scope, element, attrs, toastCtrl) {
- var intervalId, currentTimeOut, hideTime;
- toastCtrl.progressBar = scope;
- scope.start = function(duration) {
- if (intervalId) {
- clearInterval(intervalId);
- }
- currentTimeOut = parseFloat(duration);
- hideTime = new Date().getTime() + currentTimeOut;
- intervalId = setInterval(updateProgress, 10);
- };
- scope.stop = function() {
- if (intervalId) {
- clearInterval(intervalId);
- }
- };
- function updateProgress() {
- var percentage = ((hideTime - (new Date().getTime())) / currentTimeOut) * 100;
- element.css('width', percentage + '%');
- }
- scope.$on('$destroy', function() {
- // Failsafe stop
- clearInterval(intervalId);
- });
- }
- }
- }());
- (function() {
- 'use strict';
- angular.module('toastr')
- .controller('ToastController', ToastController);
- function ToastController() {
- this.progressBar = null;
- this.startProgressBar = function(duration) {
- if (this.progressBar) {
- this.progressBar.start(duration);
- }
- };
- this.stopProgressBar = function() {
- if (this.progressBar) {
- this.progressBar.stop();
- }
- };
- }
- }());
- (function() {
- 'use strict';
- angular.module('toastr')
- .directive('toast', toast);
- toast.$inject = ['$injector', '$interval', 'toastrConfig', 'toastr'];
- function toast($injector, $interval, toastrConfig, toastr) {
- return {
- replace: true,
- templateUrl: function() {
- return toastrConfig.templates.toast;
- },
- controller: 'ToastController',
- link: toastLinkFunction
- };
- function toastLinkFunction(scope, element, attrs, toastCtrl) {
- var timeout;
- scope.toastClass = scope.options.toastClass;
- scope.titleClass = scope.options.titleClass;
- scope.messageClass = scope.options.messageClass;
- scope.progressBar = scope.options.progressBar;
- if (wantsCloseButton()) {
- var button = angular.element(scope.options.closeHtml),
- $compile = $injector.get('$compile');
- button.addClass('toast-close-button');
- button.attr('ng-click', 'close()');
- $compile(button)(scope);
- element.prepend(button);
- }
- scope.init = function() {
- if (scope.options.timeOut) {
- timeout = createTimeout(scope.options.timeOut);
- }
- if (scope.options.onShown) {
- scope.options.onShown();
- }
- };
- element.on('mouseenter', function() {
- hideAndStopProgressBar();
- if (timeout) {
- $interval.cancel(timeout);
- }
- });
- scope.tapToast = function () {
- if (scope.options.tapToDismiss) {
- scope.close(true);
- }
- };
- scope.close = function (wasClicked) {
- toastr.remove(scope.toastId, wasClicked);
- };
- element.on('mouseleave', function() {
- if (scope.options.timeOut === 0 && scope.options.extendedTimeOut === 0) { return; }
- scope.$apply(function() {
- scope.progressBar = scope.options.progressBar;
- });
- timeout = createTimeout(scope.options.extendedTimeOut);
- });
- function createTimeout(time) {
- toastCtrl.startProgressBar(time);
- return $interval(function() {
- toastCtrl.stopProgressBar();
- toastr.remove(scope.toastId);
- }, time, 1);
- }
- function hideAndStopProgressBar() {
- scope.progressBar = false;
- toastCtrl.stopProgressBar();
- }
- function wantsCloseButton() {
- return scope.options.closeHtml;
- }
- }
- }
- }());
|