angular.module('cgNotify', []).factory('notify',['$timeout','$http','$compile','$templateCache','$rootScope', function($timeout,$http,$compile,$templateCache,$rootScope){ var startTop = 10; var verticalSpacing = 15; var defaultDuration = 10000; var defaultTemplateUrl = 'angular-notify.html'; var position = 'center'; var container = document.body; var maximumOpen = 0; var messageElements = []; var openNotificationsScope = []; var notify = function(args){ if (typeof args !== 'object'){ args = {message:args}; } args.duration = args.duration ? args.duration : defaultDuration; args.templateUrl = args.templateUrl ? args.templateUrl : defaultTemplateUrl; args.container = args.container ? args.container : container; args.classes = args.classes ? args.classes : ''; var scope = args.scope ? args.scope.$new() : $rootScope.$new(); scope.$position = args.position ? args.position : position; scope.$message = args.message; scope.$classes = args.classes; scope.$messageTemplate = args.messageTemplate; if (maximumOpen > 0) { var numToClose = (openNotificationsScope.length + 1) - maximumOpen; for (var i = 0; i < numToClose; i++) { openNotificationsScope[i].$close(); } } $http.get(args.templateUrl,{cache: $templateCache}).then(function(template){ var templateElement = $compile(template.data)(scope); templateElement.bind('webkitTransitionEnd oTransitionEnd otransitionend transitionend msTransitionEnd', function(e){ if (e.propertyName === 'opacity' || e.currentTarget.style.opacity === 0 || (e.originalEvent && e.originalEvent.propertyName === 'opacity')){ templateElement.remove(); messageElements.splice(messageElements.indexOf(templateElement),1); openNotificationsScope.splice(openNotificationsScope.indexOf(scope),1); layoutMessages(); } }); if (args.messageTemplate){ var messageTemplateElement; for (var i = 0; i < templateElement.children().length; i ++){ if (angular.element(templateElement.children()[i]).hasClass('cg-notify-message-template')){ messageTemplateElement = angular.element(templateElement.children()[i]); break; } } if (messageTemplateElement){ messageTemplateElement.append($compile(args.messageTemplate)(scope)); } else { throw new Error('cgNotify could not find the .cg-notify-message-template element in '+args.templateUrl+'.'); } } angular.element(args.container).append(templateElement); messageElements.push(templateElement); if (scope.$position === 'center'){ $timeout(function(){ scope.$centerMargin = '-' + (templateElement[0].offsetWidth /2) + 'px'; }); } scope.$close = function(){ templateElement.css('opacity',0).attr('data-closing','true'); layoutMessages(); }; var layoutMessages = function(){ var j = 0; var currentY = startTop; for(var i = messageElements.length - 1; i >= 0; i --){ var shadowHeight = 10; var element = messageElements[i]; var height = element[0].offsetHeight; var top = currentY + height + shadowHeight; if (element.attr('data-closing')){ top += 20; } else { currentY += height + verticalSpacing; } element.css('top',top + 'px').css('margin-top','-' + (height+shadowHeight) + 'px').css('visibility','visible'); j ++; } }; $timeout(function(){ layoutMessages(); }); if (args.duration > 0){ $timeout(function(){ scope.$close(); },args.duration); } }, function(data) { throw new Error('Template specified for cgNotify ('+args.templateUrl+') could not be loaded. ' + data); }); var retVal = {}; retVal.close = function(){ if (scope.$close){ scope.$close(); } }; Object.defineProperty(retVal,'message',{ get: function(){ return scope.$message; }, set: function(val){ scope.$message = val; } }); openNotificationsScope.push(scope); return retVal; }; notify.config = function(args){ startTop = !angular.isUndefined(args.startTop) ? args.startTop : startTop; verticalSpacing = !angular.isUndefined(args.verticalSpacing) ? args.verticalSpacing : verticalSpacing; defaultDuration = !angular.isUndefined(args.duration) ? args.duration : defaultDuration; defaultTemplateUrl = args.templateUrl ? args.templateUrl : defaultTemplateUrl; position = !angular.isUndefined(args.position) ? args.position : position; container = args.container ? args.container : container; maximumOpen = args.maximumOpen ? args.maximumOpen : maximumOpen; }; notify.closeAll = function(){ for(var i = messageElements.length - 1; i >= 0; i --){ var element = messageElements[i]; element.css('opacity',0); } }; return notify; } ]); angular.module('cgNotify').run(['$templateCache', function($templateCache) { 'use strict'; $templateCache.put('angular-notify.html', "<div class=\"cg-notify-message\" ng-class=\"[$classes, \n" + " $position === 'center' ? 'cg-notify-message-center' : '',\n" + " $position === 'left' ? 'cg-notify-message-left' : '',\n" + " $position === 'right' ? 'cg-notify-message-right' : '']\"\n" + " ng-style=\"{'margin-left': $centerMargin}\">\n" + "\n" + " <div ng-show=\"!$messageTemplate\">\n" + " {{$message}}\n" + " </div>\n" + "\n" + " <div ng-show=\"$messageTemplate\" class=\"cg-notify-message-template\">\n" + " \n" + " </div>\n" + "\n" + " <button type=\"button\" class=\"cg-notify-close\" ng-click=\"$close()\">\n" + " <span aria-hidden=\"true\">×</span>\n" + " <span class=\"cg-notify-sr-only\">Close</span>\n" + " </button>\n" + "\n" + "</div>" ); }]);