diff --git a/README.md b/README.md index 097d939..55228e9 100755 --- a/README.md +++ b/README.md @@ -63,6 +63,9 @@ Call `config` to set the default configuration options for angular-notify. The * `position` - The default position of each message. `center`, `left` and `right` are the supported values. * `container` - The default element that contains each notification. Defaults to `document.body`. * `maximumOpen` - The maximum number of total notifications that can be visible at one time. Older notifications will be closed when the maximum is reached. +* `cleanupTimeout` - A timeout that cleans up the DOM after the message has faded out. This does not normally need to be set, but if you change the opacity transition duration +in `.cg-notify-message` you may want to adjust this so that the message isn't suddenly +removed before the fade-out transition is completed. ### notify.closeAll() diff --git a/angular-notify.js b/angular-notify.js index 7fbdf6e..ede245a 100755 --- a/angular-notify.js +++ b/angular-notify.js @@ -8,6 +8,7 @@ angular.module('cgNotify', []).factory('notify',['$timeout','$http','$compile',' var position = 'center'; var container = document.body; var maximumOpen = 0; + var cleanupTimeout = 500; var messageElements = []; var openNotificationsScope = []; @@ -77,6 +78,11 @@ angular.module('cgNotify', []).factory('notify',['$timeout','$http','$compile',' scope.$close = function(){ templateElement.css('opacity',0).attr('data-closing','true'); layoutMessages(); + // add a cleanup handler for the templateElement in case the transitionend event is not fired (e.g. the transition is + // interrupted by the browser). + $timeout(function() { + templateElement.remove(); + }, cleanupTimeout); }; var layoutMessages = function(){ @@ -142,6 +148,7 @@ angular.module('cgNotify', []).factory('notify',['$timeout','$http','$compile',' position = !angular.isUndefined(args.position) ? args.position : position; container = args.container ? args.container : container; maximumOpen = args.maximumOpen ? args.maximumOpen : maximumOpen; + cleanupTimeout = args.cleanupTimeout ? args.cleanupTimeout : cleanupTimeout; }; notify.closeAll = function(){ diff --git a/dist/angular-notify.js b/dist/angular-notify.js index b23e7bb..3d42e4a 100644 --- a/dist/angular-notify.js +++ b/dist/angular-notify.js @@ -8,6 +8,7 @@ angular.module('cgNotify', []).factory('notify',['$timeout','$http','$compile',' var position = 'center'; var container = document.body; var maximumOpen = 0; + var opacityAnimationTimeout = 500; var messageElements = []; var openNotificationsScope = []; @@ -77,6 +78,11 @@ angular.module('cgNotify', []).factory('notify',['$timeout','$http','$compile',' scope.$close = function(){ templateElement.css('opacity',0).attr('data-closing','true'); layoutMessages(); + // add a cleanup handler for the templateElement in case the transitionend event is not fired (e.g. the transition is + // interrupted by the browser). + $timeout(function() { + templateElement.remove(); + }, opacityAnimationTimeout); }; var layoutMessages = function(){ @@ -142,6 +148,7 @@ angular.module('cgNotify', []).factory('notify',['$timeout','$http','$compile',' position = !angular.isUndefined(args.position) ? args.position : position; container = args.container ? args.container : container; maximumOpen = args.maximumOpen ? args.maximumOpen : maximumOpen; + opacityAnimationTimeout = args.opacityAnimationTimeout ? args.opacityAnimationTimeout : opacityAnimationTimeout; }; notify.closeAll = function(){ diff --git a/dist/angular-notify.min.js b/dist/angular-notify.min.js index 8607d9f..d10b097 100644 --- a/dist/angular-notify.min.js +++ b/dist/angular-notify.min.js @@ -1 +1 @@ -angular.module("cgNotify",[]).factory("notify",["$timeout","$http","$compile","$templateCache","$rootScope",function(a,b,c,d,e){var f=10,g=15,h=1e4,i="angular-notify.html",j="center",k=document.body,l=0,m=[],n=[],o=function(o){"object"!=typeof o&&(o={message:o}),o.duration=o.duration?o.duration:h,o.templateUrl=o.templateUrl?o.templateUrl:i,o.container=o.container?o.container:k,o.classes=o.classes?o.classes:"";var p=o.scope?o.scope.$new():e.$new();if(p.$position=o.position?o.position:j,p.$message=o.message,p.$classes=o.classes,p.$messageTemplate=o.messageTemplate,l>0)for(var q=n.length+1-l,r=0;q>r;r++)n[r].$close();b.get(o.templateUrl,{cache:d}).success(function(b){var d=c(b)(p);if(d.bind("webkitTransitionEnd oTransitionEnd otransitionend transitionend msTransitionEnd",function(a){("opacity"===a.propertyName||0===a.currentTarget.style.opacity||a.originalEvent&&"opacity"===a.originalEvent.propertyName)&&(d.remove(),m.splice(m.indexOf(d),1),n.splice(n.indexOf(p),1),i())}),o.messageTemplate){for(var e,h=0;h=0;c--){var d=10,e=m[c],h=e[0].offsetHeight,i=b+h+d;e.attr("data-closing")?i+=20:b+=h+g,e.css("top",i+"px").css("margin-top","-"+(h+d)+"px").css("visibility","visible"),a++}};a(function(){i()}),o.duration>0&&a(function(){p.$close()},o.duration)}).error(function(a){throw new Error("Template specified for cgNotify ("+o.templateUrl+") could not be loaded. "+a)});var s={};return s.close=function(){p.$close&&p.$close()},Object.defineProperty(s,"message",{get:function(){return p.$message},set:function(a){p.$message=a}}),n.push(p),s};return o.config=function(a){f=angular.isUndefined(a.startTop)?f:a.startTop,g=angular.isUndefined(a.verticalSpacing)?g:a.verticalSpacing,h=angular.isUndefined(a.duration)?h:a.duration,i=a.templateUrl?a.templateUrl:i,j=angular.isUndefined(a.position)?j:a.position,k=a.container?a.container:k,l=a.maximumOpen?a.maximumOpen:l},o.closeAll=function(){for(var a=m.length-1;a>=0;a--){var b=m[a];b.css("opacity",0)}},o}]),angular.module("cgNotify").run(["$templateCache",function(a){"use strict";a.put("angular-notify.html","
\n\n
\n {{$message}}\n
\n\n"+'
\n \n
\n\n \n\n
')}]); \ No newline at end of file +angular.module("cgNotify",[]).factory("notify",["$timeout","$http","$compile","$templateCache","$rootScope",function(a,b,c,d,e){var f=10,g=15,h=1e4,i="angular-notify.html",j="center",k=document.body,l=0,m=500,n=[],o=[],p=function(p){"object"!=typeof p&&(p={message:p}),p.duration=p.duration?p.duration:h,p.templateUrl=p.templateUrl?p.templateUrl:i,p.container=p.container?p.container:k,p.classes=p.classes?p.classes:"";var q=p.scope?p.scope.$new():e.$new();if(q.$position=p.position?p.position:j,q.$message=p.message,q.$classes=p.classes,q.$messageTemplate=p.messageTemplate,l>0)for(var r=o.length+1-l,s=0;r>s;s++)o[s].$close();b.get(p.templateUrl,{cache:d}).success(function(b){var d=c(b)(q);if(d.bind("webkitTransitionEnd oTransitionEnd otransitionend transitionend msTransitionEnd",function(a){("opacity"===a.propertyName||0===a.currentTarget.style.opacity||a.originalEvent&&"opacity"===a.originalEvent.propertyName)&&(d.remove(),n.splice(n.indexOf(d),1),o.splice(o.indexOf(q),1),i())}),p.messageTemplate){for(var e,h=0;h=0;c--){var d=10,e=n[c],h=e[0].offsetHeight,i=b+h+d;e.attr("data-closing")?i+=20:b+=h+g,e.css("top",i+"px").css("margin-top","-"+(h+d)+"px").css("visibility","visible"),a++}};a(function(){i()}),p.duration>0&&a(function(){q.$close()},p.duration)}).error(function(a){throw new Error("Template specified for cgNotify ("+p.templateUrl+") could not be loaded. "+a)});var t={};return t.close=function(){q.$close&&q.$close()},Object.defineProperty(t,"message",{get:function(){return q.$message},set:function(a){q.$message=a}}),o.push(q),t};return p.config=function(a){f=angular.isUndefined(a.startTop)?f:a.startTop,g=angular.isUndefined(a.verticalSpacing)?g:a.verticalSpacing,h=angular.isUndefined(a.duration)?h:a.duration,i=a.templateUrl?a.templateUrl:i,j=angular.isUndefined(a.position)?j:a.position,k=a.container?a.container:k,l=a.maximumOpen?a.maximumOpen:l,m=a.opacityAnimationTimeout?a.opacityAnimationTimeout:m},p.closeAll=function(){for(var a=n.length-1;a>=0;a--){var b=n[a];b.css("opacity",0)}},p}]),angular.module("cgNotify").run(["$templateCache",function(a){"use strict";a.put("angular-notify.html","
\n\n
\n {{$message}}\n
\n\n"+'
\n \n
\n\n \n\n
')}]); \ No newline at end of file