text: (function() {
    'use strict';
  
    angular.module('toastr', [])
      .factory('toastr', toastr);
  
    toastr.$inject = ['$animate', '$injector', '$rootScope', '$sce', 'toastrConfig', '$q'];
  
    function toastr($animate, $injector, $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) {
          var domClassList = container[0].classList;
          var isSamePosition = domClassList.contains(options.positionClass);
          
          if (!isSamePosition) {
            //remove old position class
            domClassList.remove(domClassList[0]);
            //insert new class
            domClassList.add(options.positionClass);
          }
          
          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();
  
        // rewrite global config
        if (map.optionsOverride && map.optionsOverride.positionClass)
          options.positionClass = map.optionsOverride.positionClass;
  
        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;
        }
      }
    }
  }());
  
  (function() {
    'use strict';
  
    angular.module('toastr')
      .constant('toastrConfig', {
        allowHtml: false,
        autoDismiss: false,
        closeButton: false,
        closeHtml: '<button>&times;</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,
        onTap: 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')
      .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 {
        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(true, $event)');
          $compile(button)(scope);
          element.children().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 (angular.isFunction(scope.options.onTap)) {
            scope.options.onTap();
          }
          if (scope.options.tapToDismiss) {
            scope.close(true);
          }
        };
  
        scope.close = function (wasClicked, $event) {
          if ($event && angular.isFunction($event.stopPropagation)) {
            $event.stopPropagation();
          }
          toastr.remove(scope.toastId, wasClicked);
        };
        
        scope.refreshTimer = function(newTime) {
          if (timeout) {
            $interval.cancel(timeout);
            timeout = createTimeout(newTime || scope.options.timeOut);
          }
        };
  
        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;
        }
      }
    }
  }());
  
  (function() {
    'use strict';
  
    angular.module('toastr')
      .directive('progressBar', progressBar);
  
    progressBar.$inject = ['toastrConfig'];
  
    function progressBar(toastrConfig) {
      return {
        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);
        });
      }
    }
  }());
  
  angular.module("toastr").run(["$templateCache", function($templateCache) {$templateCache.put("directives/progressbar/progressbar.html","<div class=\"toast-progress\"></div>\n");
  $templateCache.put("directives/toast/toast.html","<div class=\"{{toastClass}} {{toastType}}\" ng-click=\"tapToast()\">\n  <div ng-switch on=\"allowHtml\">\n    <div ng-switch-default ng-if=\"title\" class=\"{{titleClass}}\" aria-label=\"{{title}}\">{{title}}</div>\n    <div ng-switch-default class=\"{{messageClass}}\" aria-label=\"{{message}}\">{{message}}</div>\n    <div ng-switch-when=\"true\" ng-if=\"title\" class=\"{{titleClass}}\" ng-bind-html=\"title\"></div>\n    <div ng-switch-when=\"true\" class=\"{{messageClass}}\" ng-bind-html=\"message\"></div>\n  </div>\n  <progress-bar ng-if=\"progressBar\"></progress-bar>\n</div>\n");}]);