UNPKG

angular-toastr

Version:

[![Code Climate](https://codeclimate.com/github/Foxandxss/angular-toastr.png)](https://codeclimate.com/github/Foxandxss/angular-toastr) [![Build Status](https://travis-ci.org/Foxandxss/angular-toastr.svg?branch=master)](https://travis-ci.org/Foxandxss/ang

293 lines (238 loc) 8.47 kB
(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 = { active: active, clear: clear, error: error, info: info, remove: remove, success: success, warning: warning, refreshTimer: refreshTimer }; return toast; /* Public API */ function active() { return toasts.length; } function clear(toast) { // Bit of a hack, I will remove this soon with a BC if (arguments.length === 1 && !toast) { return; } 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 refreshTimer(toast, newTime) { if (toast && toast.isOpened && toasts.indexOf(toast) >= 0) { toast.scope.refreshTimer(newTime); } } 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); } 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 (ifMaxOpenedAndAutoDismiss()) { 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 ifMaxOpenedAndAutoDismiss() { return options.autoDismiss && options.maxOpened && toasts.length > options.maxOpened; } 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.extraData = options.extraData; toast.scope.options = { extendedTimeOut: options.extendedTimeOut, messageClass: options.messageClass, onHidden: options.onHidden, onShown: generateEvent('onShown'), onTap: generateEvent('onTap'), 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 generateEvent(event) { if (options[event]) { return function() { options[event](toast); }; } } } function createToast() { var newToast = { toastId: index++, isOpened: false, scope: $rootScope.$new(), open: $q.defer() }; newToast.iconClass = map.iconClass; if (map.optionsOverride) { 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; } } } }());