diff --git a/README.md b/README.md index 1b63bc1..82ac2f0 100755 --- a/README.md +++ b/README.md @@ -46,8 +46,12 @@ The `notify` function can either be passed a string or an object. When passing * `classes` - Optional. A list of custom CSS classes to apply to the message element. * `messageTemplate` - Optional. A string containing any valid Angular HTML which will be shown instead of the regular `message` text. The string must contain one root element like all valid Angular HTML templates (so wrap everything in a ``). * `scope` - Optional. A valid Angular scope object. The scope of the template will be created by calling `$new()` on this scope. -* `position` - Optional. Currently `center` and `right` are the only acceptable values. +* `position` - Optional. 'left', 'right' and 'center' are the only acceptable values. +* `duration` - Optional. The duration (in milliseconds) of the message. A duration of 0 will prevent the message from closing automatically. * `container` - Optional. Element that contains each notification. Defaults to `document.body`. +* `onOpen` - Optional. Function that is called when the notification is shown to the user. The function receives the message of the notification as its only parameter. +* `onClick` - Optional. Function that is called when the notification is clicked by the user. The function receives the message of the notification as its only parameter. +* `onClose` - Optional. Function that is called when the notification is closed by the user manually. It is not called when `closeAll()` is called and closes the notification programatically. The function receives the message of the notification as its only parameter. This function will return an object with a `close()` method and a `message` property. @@ -59,12 +63,12 @@ Call `config` to set the default configuration options for angular-notify. The * `startTop` - The Y pixel value where messages will be shown. * `verticalSpacing` - The number of pixels that should be reserved between messages vertically. * `templateUrl` - The default message template. -* `position` - The default position of each message. Currently only `center` and `right` are the supported values. +* `position` - The default position of each message. 'left', 'right' and 'center' are the only acceptable values. * `container` - The default element that contains each notification. Defaults to `document.body`. ### notify.closeAll() -Closes all currently open notifications. +Closes all currently open notifications. Notifications that are closed by `closeAll()` will not call their `onClose`-events. ## Providing Custom Templates diff --git a/angular-notify.css b/angular-notify.css index 66e56e8..ec993f9 100755 --- a/angular-notify.css +++ b/angular-notify.css @@ -1,6 +1,5 @@ .cg-notify-message { position:fixed; - left:50%; top:0px; z-index: 9999; max-width:400px; @@ -23,6 +22,18 @@ box-shadow: 0 6px 12px rgba(0,0,0,.175); } +.cg-notify-message-center { + left:50%; +} + +.cg-notify-message-left { + left:15px; +} + +.cg-notify-message-right { + right:15px; +} + .cg-notify-message a { font-weight:bold; color:inherit; diff --git a/angular-notify.html b/angular-notify.html index b8c320c..bc53413 100755 --- a/angular-notify.html +++ b/angular-notify.html @@ -1,4 +1,4 @@ -
+
{{$message}} diff --git a/angular-notify.js b/angular-notify.js index a3328a3..7eba457 100755 --- a/angular-notify.js +++ b/angular-notify.js @@ -16,21 +16,30 @@ angular.module('cgNotify', []).factory('notify',['$timeout','$http','$compile',' args = {message:args}; } - args.templateUrl = args.templateUrl ? args.templateUrl : defaultTemplateUrl; - args.position = args.position ? args.position : position; - args.container = args.container ? args.container : container; - args.classes = args.classes ? args.classes : ''; - - var scope = args.scope ? args.scope.$new() : $rootScope.$new(); + args.templateUrl = angular.isString(args.templateUrl) && args.templateUrl.length > 0 ? args.templateUrl : defaultTemplateUrl; + args.position = angular.isString(args.position) ? args.position : position; + args.container = angular.isObject(args.container) ? args.container : container; + args.classes = angular.isString(args.classes) ? args.classes : ''; + args.duration = angular.isNumber(args.duration) ? args.duration : duration; + args.onOpen = angular.isFunction(args.onOpen) ? args.onOpen : undefined; + args.onClose = angular.isFunction(args.onClose) ? args.onClose : undefined; + + var scope = angular.isDefined(args.scope) ? args.scope.$new() : $rootScope.$new(); scope.$message = args.message; scope.$classes = args.classes; - scope.$messageTemplate = args.messageTemplate; + scope.$messageTemplate = args.messageTemplate; + + if(angular.isFunction(args.onClick)){ + scope.$click = function(){ + args.onClick(scope.$message); + }; + } $http.get(args.templateUrl,{cache: $templateCache}).success(function(template){ var templateElement = $compile(template)(scope); templateElement.bind('webkitTransitionEnd oTransitionEnd otransitionend transitionend msTransitionEnd', function(e){ - if (e.propertyName === 'opacity' || + if (e.propertyName === 'opacity' || e.currentTarget.style.opacity === '0' || (e.originalEvent && e.originalEvent.propertyName === 'opacity')){ templateElement.remove(); @@ -57,19 +66,29 @@ angular.module('cgNotify', []).factory('notify',['$timeout','$http','$compile',' angular.element(args.container).append(templateElement); messageElements.push(templateElement); - if (args.position === 'center'){ - $timeout(function(){ - templateElement.css('margin-left','-' + (templateElement[0].offsetWidth /2) + 'px'); - }); - } + $timeout(function(){ + switch (args.position){ + case 'center': scope.$classes += 'cg-notify-message-center'; + scope.$centerStyle = {'margin-left': '-' + (templateElement[0].offsetWidth /2) + 'px'}; + //templateElement.css('margin-left','-' + (templateElement[0].offsetWidth /2) + 'px'); + break; + case 'left': scope.$classes += ' cg-notify-message-left'; + break; + case 'right': scope.$classes += ' cg-notify-message-right'; + break; + } + }); scope.$close = function(){ templateElement.css('opacity',0).attr('data-closing','true'); layoutMessages(); + + if(angular.isDefined(args.onClose)){ + args.onClose(scope.$message); + } }; var layoutMessages = function(){ - var j = 0; var currentY = startTop; for(var i = messageElements.length - 1; i >= 0; i --){ var shadowHeight = 10; @@ -82,7 +101,6 @@ angular.module('cgNotify', []).factory('notify',['$timeout','$http','$compile',' currentY += height + verticalSpacing; } element.css('top',top + 'px').css('margin-top','-' + (height+shadowHeight) + 'px').css('visibility','visible'); - j ++; } }; @@ -90,10 +108,14 @@ angular.module('cgNotify', []).factory('notify',['$timeout','$http','$compile',' layoutMessages(); }); - if (duration > 0){ + if (args.duration > 0){ $timeout(function(){ scope.$close(); - },duration); + },args.duration); + } + + if(angular.isDefined(args.onOpen)){ + args.onOpen(scope.$message); } }).error(function(data){ @@ -122,12 +144,12 @@ angular.module('cgNotify', []).factory('notify',['$timeout','$http','$compile',' }; notify.config = function(args){ - startTop = !angular.isUndefined(args.startTop) ? args.startTop : startTop; - verticalSpacing = !angular.isUndefined(args.verticalSpacing) ? args.verticalSpacing : verticalSpacing; - duration = !angular.isUndefined(args.duration) ? args.duration : duration; - defaultTemplateUrl = args.templateUrl ? args.templateUrl : defaultTemplateUrl; - position = !angular.isUndefined(args.position) ? args.position : position; - container = args.container ? args.container : container; + startTop = angular.isNumber(args.startTop) ? args.startTop : startTop; + verticalSpacing = angular.isNumber(args.verticalSpacing) ? args.verticalSpacing : verticalSpacing; + duration = angular.isNumber(args.duration) ? args.duration : duration; + defaultTemplateUrl = angular.isString(args.templateUrl) && args.templateUrl.length > 0 ? args.templateUrl : defaultTemplateUrl; + position = angular.isString(args.position) ? args.position : position; + container = angular.isObject(args.container) ? args.container : container; }; notify.closeAll = function(){ diff --git a/demo/demo.js b/demo/demo.js index cbdc439..f8d3560 100755 --- a/demo/demo.js +++ b/demo/demo.js @@ -5,11 +5,18 @@ angular.module('app').controller('DemoCtrl',function($scope,notify){ $scope.msg = 'Hello! This is a sample message!'; $scope.template = ''; + $scope.positions = ['center', 'left', 'right']; + $scope.position = $scope.positions[0]; + + $scope.duration = 10000; + $scope.demo = function(){ notify({ message: $scope.msg, classes: $scope.classes, - templateUrl: $scope.template + templateUrl: $scope.template, + position: $scope.position, + duration: $scope.duration }); }; diff --git a/demo/index.html b/demo/index.html index c363e64..5ff63f9 100755 --- a/demo/index.html +++ b/demo/index.html @@ -39,7 +39,20 @@

angular-notify

-
+
+
+ +
+ +
+
+
+ +
+ +
+
diff --git a/dist/angular-notify.css b/dist/angular-notify.css index 66e56e8..ec993f9 100644 --- a/dist/angular-notify.css +++ b/dist/angular-notify.css @@ -1,6 +1,5 @@ .cg-notify-message { position:fixed; - left:50%; top:0px; z-index: 9999; max-width:400px; @@ -23,6 +22,18 @@ box-shadow: 0 6px 12px rgba(0,0,0,.175); } +.cg-notify-message-center { + left:50%; +} + +.cg-notify-message-left { + left:15px; +} + +.cg-notify-message-right { + right:15px; +} + .cg-notify-message a { font-weight:bold; color:inherit; diff --git a/dist/angular-notify.js b/dist/angular-notify.js index 58242fc..4d89d21 100644 --- a/dist/angular-notify.js +++ b/dist/angular-notify.js @@ -16,21 +16,30 @@ angular.module('cgNotify', []).factory('notify',['$timeout','$http','$compile',' args = {message:args}; } - args.templateUrl = args.templateUrl ? args.templateUrl : defaultTemplateUrl; - args.position = args.position ? args.position : position; - args.container = args.container ? args.container : container; - args.classes = args.classes ? args.classes : ''; - - var scope = args.scope ? args.scope.$new() : $rootScope.$new(); + args.templateUrl = angular.isString(args.templateUrl) && args.templateUrl.length > 0 ? args.templateUrl : defaultTemplateUrl; + args.position = angular.isString(args.position) ? args.position : position; + args.container = angular.isObject(args.container) ? args.container : container; + args.classes = angular.isString(args.classes) ? args.classes : ''; + args.duration = angular.isNumber(args.duration) ? args.duration : duration; + args.onOpen = angular.isFunction(args.onOpen) ? args.onOpen : undefined; + args.onClose = angular.isFunction(args.onClose) ? args.onClose : undefined; + + var scope = angular.isDefined(args.scope) ? args.scope.$new() : $rootScope.$new(); scope.$message = args.message; scope.$classes = args.classes; - scope.$messageTemplate = args.messageTemplate; + scope.$messageTemplate = args.messageTemplate; + + if(angular.isFunction(args.onClick)){ + scope.$click = function(){ + args.onClick(scope.$message); + }; + } $http.get(args.templateUrl,{cache: $templateCache}).success(function(template){ var templateElement = $compile(template)(scope); templateElement.bind('webkitTransitionEnd oTransitionEnd otransitionend transitionend msTransitionEnd', function(e){ - if (e.propertyName === 'opacity' || + if (e.propertyName === 'opacity' || e.currentTarget.style.opacity === '0' || (e.originalEvent && e.originalEvent.propertyName === 'opacity')){ templateElement.remove(); @@ -57,19 +66,29 @@ angular.module('cgNotify', []).factory('notify',['$timeout','$http','$compile',' angular.element(args.container).append(templateElement); messageElements.push(templateElement); - if (args.position === 'center'){ - $timeout(function(){ - templateElement.css('margin-left','-' + (templateElement[0].offsetWidth /2) + 'px'); - }); - } + $timeout(function(){ + switch (args.position){ + case 'center': scope.$classes += 'cg-notify-message-center'; + scope.$centerStyle = {'margin-left': '-' + (templateElement[0].offsetWidth /2) + 'px'}; + //templateElement.css('margin-left','-' + (templateElement[0].offsetWidth /2) + 'px'); + break; + case 'left': scope.$classes += ' cg-notify-message-left'; + break; + case 'right': scope.$classes += ' cg-notify-message-right'; + break; + } + }); scope.$close = function(){ templateElement.css('opacity',0).attr('data-closing','true'); layoutMessages(); + + if(angular.isDefined(args.onClose)){ + args.onClose(scope.$message); + } }; var layoutMessages = function(){ - var j = 0; var currentY = startTop; for(var i = messageElements.length - 1; i >= 0; i --){ var shadowHeight = 10; @@ -82,7 +101,6 @@ angular.module('cgNotify', []).factory('notify',['$timeout','$http','$compile',' currentY += height + verticalSpacing; } element.css('top',top + 'px').css('margin-top','-' + (height+shadowHeight) + 'px').css('visibility','visible'); - j ++; } }; @@ -90,10 +108,14 @@ angular.module('cgNotify', []).factory('notify',['$timeout','$http','$compile',' layoutMessages(); }); - if (duration > 0){ + if (args.duration > 0){ $timeout(function(){ scope.$close(); - },duration); + },args.duration); + } + + if(angular.isDefined(args.onOpen)){ + args.onOpen(scope.$message); } }).error(function(data){ @@ -122,12 +144,12 @@ angular.module('cgNotify', []).factory('notify',['$timeout','$http','$compile',' }; notify.config = function(args){ - startTop = !angular.isUndefined(args.startTop) ? args.startTop : startTop; - verticalSpacing = !angular.isUndefined(args.verticalSpacing) ? args.verticalSpacing : verticalSpacing; - duration = !angular.isUndefined(args.duration) ? args.duration : duration; - defaultTemplateUrl = args.templateUrl ? args.templateUrl : defaultTemplateUrl; - position = !angular.isUndefined(args.position) ? args.position : position; - container = args.container ? args.container : container; + startTop = angular.isNumber(args.startTop) ? args.startTop : startTop; + verticalSpacing = angular.isNumber(args.verticalSpacing) ? args.verticalSpacing : verticalSpacing; + duration = angular.isNumber(args.duration) ? args.duration : duration; + defaultTemplateUrl = angular.isString(args.templateUrl) && args.templateUrl.length > 0 ? args.templateUrl : defaultTemplateUrl; + position = angular.isString(args.position) ? args.position : position; + container = angular.isObject(args.container) ? args.container : container; }; notify.closeAll = function(){ @@ -145,7 +167,7 @@ angular.module('cgNotify').run(['$templateCache', function($templateCache) { 'use strict'; $templateCache.put('angular-notify.html', - "
\n" + + "
\n" + "\n" + "
\n" + " {{$message}}\n" + diff --git a/dist/angular-notify.min.css b/dist/angular-notify.min.css index 530c3c0..f6420d5 100644 --- a/dist/angular-notify.min.css +++ b/dist/angular-notify.min.css @@ -1 +1 @@ -.cg-notify-message{position:fixed;left:50%;top:0;z-index:9999;max-width:400px;text-align:center;background-color:#d9edf7;color:#31708f;padding:15px;border:1px solid #bce8f1;border-radius:4px;-webkit-transition:top .5s ease-out,opacity .2s ease-out;-moz-transition:top .5s ease-out,opacity .2s ease-out;-o-transition:top .5s ease-out,opacity .2s ease-out;transition:top .5s ease-out,opacity .2s ease-out;visibility:hidden;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.cg-notify-message a{font-weight:700;color:inherit}.cg-notify-message a:hover{color:inherit}.cg-notify-close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0;font-size:21px;font-weight:700;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2;position:absolute;top:0;right:3px;line-height:15px}.cg-notify-close:focus,.cg-notify-close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}.cg-notify-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0} \ No newline at end of file +.cg-notify-message{position:fixed;top:0;z-index:9999;max-width:400px;text-align:center;background-color:#d9edf7;color:#31708f;padding:15px;border:1px solid #bce8f1;border-radius:4px;-webkit-transition:top .5s ease-out,opacity .2s ease-out;-moz-transition:top .5s ease-out,opacity .2s ease-out;-o-transition:top .5s ease-out,opacity .2s ease-out;transition:top .5s ease-out,opacity .2s ease-out;visibility:hidden;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.cg-notify-message-center{left:50%}.cg-notify-message-left{left:15px}.cg-notify-message-right{right:15px}.cg-notify-message a{font-weight:700;color:inherit}.cg-notify-message a:hover{color:inherit}.cg-notify-close{-webkit-appearance:none;padding:0;cursor:pointer;background:0 0;border:0;font-size:21px;font-weight:700;color:#000;text-shadow:0 1px 0 #fff;filter:alpha(opacity=20);opacity:.2;position:absolute;top:0;right:3px;line-height:15px}.cg-notify-close:focus,.cg-notify-close:hover{color:#000;text-decoration:none;cursor:pointer;filter:alpha(opacity=50);opacity:.5}.cg-notify-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);border:0} \ No newline at end of file diff --git a/dist/angular-notify.min.js b/dist/angular-notify.min.js index 29bbe45..64d124d 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=[],m=function(m){"object"!=typeof m&&(m={message:m}),m.templateUrl=m.templateUrl?m.templateUrl:i,m.position=m.position?m.position:j,m.container=m.container?m.container:k,m.classes=m.classes?m.classes:"";var n=m.scope?m.scope.$new():e.$new();n.$message=m.message,n.$classes=m.classes,n.$messageTemplate=m.messageTemplate,b.get(m.templateUrl,{cache:d}).success(function(b){var d=c(b)(n);if(d.bind("webkitTransitionEnd oTransitionEnd otransitionend transitionend msTransitionEnd",function(a){("opacity"===a.propertyName||a.originalEvent&&"opacity"===a.originalEvent.propertyName)&&(d.remove(),l.splice(l.indexOf(d),1),j())}),m.messageTemplate){for(var e,i=0;i=0;c--){var d=10,e=l[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(){j()}),h>0&&a(function(){n.$close()},h)}).error(function(a){throw new Error("Template specified for cgNotify ("+m.templateUrl+") could not be loaded. "+a)});var o={};return o.close=function(){n.$close&&n.$close()},Object.defineProperty(o,"message",{get:function(){return n.$message},set:function(a){n.$message=a}}),o};return m.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},m.closeAll=function(){for(var a=l.length-1;a>=0;a--){var b=l[a];b.css("opacity",0)}},m}]),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=[],m=function(m){"object"!=typeof m&&(m={message:m}),m.templateUrl=angular.isString(m.templateUrl)&&m.templateUrl.length>0?m.templateUrl:i,m.position=angular.isString(m.position)?m.position:j,m.container=angular.isObject(m.container)?m.container:k,m.classes=angular.isString(m.classes)?m.classes:"",m.duration=angular.isNumber(m.duration)?m.duration:h,m.onOpen=angular.isFunction(m.onOpen)?m.onOpen:void 0,m.onClose=angular.isFunction(m.onClose)?m.onClose:void 0;var n=angular.isDefined(m.scope)?m.scope.$new():e.$new();n.$message=m.message,n.$classes=m.classes,n.$messageTemplate=m.messageTemplate,angular.isFunction(m.onClick)&&(n.$click=function(){m.onClick(n.$message)}),b.get(m.templateUrl,{cache:d}).success(function(b){var d=c(b)(n);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(),l.splice(l.indexOf(d),1),i())}),m.messageTemplate){for(var e,h=0;h=0;b--){var c=10,d=l[b],e=d[0].offsetHeight,h=a+e+c;d.attr("data-closing")?h+=20:a+=e+g,d.css("top",h+"px").css("margin-top","-"+(e+c)+"px").css("visibility","visible")}};a(function(){i()}),m.duration>0&&a(function(){n.$close()},m.duration),angular.isDefined(m.onOpen)&&m.onOpen(n.$message)}).error(function(a){throw new Error("Template specified for cgNotify ("+m.templateUrl+") could not be loaded. "+a)});var o={};return o.close=function(){n.$close&&n.$close()},Object.defineProperty(o,"message",{get:function(){return n.$message},set:function(a){n.$message=a}}),o};return m.config=function(a){f=angular.isNumber(a.startTop)?a.startTop:f,g=angular.isNumber(a.verticalSpacing)?a.verticalSpacing:g,h=angular.isNumber(a.duration)?a.duration:h,i=angular.isString(a.templateUrl)&&a.templateUrl.length>0?a.templateUrl:i,j=angular.isString(a.position)?a.position:j,k=angular.isObject(a.container)?a.container:k},m.closeAll=function(){for(var a=l.length-1;a>=0;a--){var b=l[a];b.css("opacity",0)}},m}]),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