├── README.md ├── bower.json ├── notification.css ├── notification.js ├── notification.min.css └── notification.scss /README.md: -------------------------------------------------------------------------------- 1 | ## Angular-Notifications 2 | 3 | **This Repository is not maintained** 4 | 5 | ### v0.1 6 | 7 | This particular component provides a service for creating notifications, and an 8 | easy to use directive for displaying those notifications. Also provides the ability 9 | to use Chrome Notifications instead. 10 | 11 | This is an early release, and I'm going to be changing a lot of stuff soon. 12 | 13 | ### Demo 14 | You can check out a really simple [Demo right here](http://derekries.github.io/angular-notifications). Documentation beyond this README coming soon. 15 | 16 | ### Dependencies 17 | This component is an angularjs component so it should be obvious it depends on angular. 18 | Also for the default notifications **font-awesome 3.1.1** is required to display the icons. 19 | 20 | ### Installation 21 | After you've downloaded this repository, include both the css and javascript file 22 | and then declare the notifications module as a dependency of your app module. 23 | 24 | e.g `angular.module('ngcomponentsApp', ['notifications'])` 25 | 26 | Once you've finished that business you should be able to use the notifications service. 27 | If you want those notifications to show up on the screen however (optional), you 28 | will need to add a div to your body tag somewhere and give it a notifications directive 29 | specifying its position like so: 30 | 31 | `
` 32 | 33 | You should now magically get notifications 34 | 35 | ### Usage 36 | 37 | In order to use the API you need to inject the `$notification` service into 38 | your controllers. From there you can use one of the many different notifications 39 | like: 40 | 41 | * info 42 | * warning 43 | * error 44 | * success 45 | 46 | You can use these methods with the following line of code 47 | 48 | `$notification.info(title, content, userData);` 49 | `$notification.warning(title, content, userData);` 50 | `$notification.error(title, content, userData);` 51 | `$notification.success(title, content, userData);` 52 | 53 | **Title** is of course the title displayed in a large, bold text on the notification. 54 | **Content** is the additional detail text for that notification. The **userData** parameter 55 | is optional but allows you to store some data with a particular notification. 56 | 57 | You can also use a generic notify method more inline with the standard chrome desktop 58 | notifications by specifying an image to display in the notification. 59 | `$notification.notify('image.jpg', 'My Title', 'My notification description text');` 60 | 61 | ### HTML5 Notifications 62 | If you want to use HTML5 notifications with the same API then you can call 63 | `$notification.enableHtml5Mode()`. **Note:** You will need permissions in 64 | order to use HTML5 notifications so for this reason you should call enableHtml5Mode 65 | in a click event listener or something. 66 | 67 | 68 | ### Coming Soon 69 | 70 | * Animations - Using ng-animate, will require a minimum of angular 1.1.4 for these 71 | * Better Looking, More Easily Styleable Notifications 72 | -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "author": { 3 | "name": "https://github.com/Derekries" 4 | }, 5 | "name": "angular-notifications", 6 | "version": "0.1.0", 7 | "main": "notification.js", 8 | "ignore": [ 9 | "**/.*", 10 | "node_modules", 11 | "components" 12 | ], 13 | "dependencies": { 14 | "angular": "~1.0.7" 15 | } 16 | } -------------------------------------------------------------------------------- /notification.css: -------------------------------------------------------------------------------- 1 | .dr-notification-container { 2 | position: absolute; 3 | z-index: 10000; 4 | } 5 | 6 | .dr-notification-container.bottom { 7 | bottom: 20px; 8 | } 9 | 10 | .dr-notification-container.right { 11 | right: 20px; 12 | } 13 | 14 | .dr-notification-container.left { 15 | left: 20px; 16 | } 17 | 18 | .dr-notification-container.top { 19 | top: 20px; 20 | } 21 | 22 | .dr-notification-container.center { 23 | left: 50%; 24 | margin-left: -190px; 25 | } 26 | 27 | .dr-notification-wrapper { 28 | width: 380px; 29 | position: relative; 30 | margin: 10px 0; 31 | } 32 | 33 | .dr-notification { 34 | width: 380px; 35 | background-color: rgba(2, 45, 59, 0.85); 36 | clear: both; 37 | min-height: 80px; 38 | max-height: 90px; 39 | -webkit-border-radius: 5px; 40 | -moz-border-radius: 5px; 41 | -ms-border-radius: 5px; 42 | border-radius: 5px; 43 | color: #bfe2de; 44 | border: 1px solid rgba(4, 94, 123, 0.85); 45 | overflow: hidden; 46 | } 47 | 48 | .dr-notification-close-btn { 49 | -webkit-border-radius: 20px; 50 | -moz-border-radius: 20px; 51 | -ms-border-radius: 20px; 52 | border-radius: 20px; 53 | display: inline-block; 54 | padding: 3px; 55 | background-color: rgba(1, 26, 34, 0.85); 56 | font-size: 14px; 57 | color: #adfaff; 58 | border: 1px solid rgba(4, 94, 123, 0.85); 59 | position: absolute; 60 | right: -11px; 61 | top: 5px; 62 | -webkit-transition: all 0.35s cubic-bezier(0.31, 0.39, 0.21, 1.65); 63 | -moz-transition: all 0.35s cubic-bezier(0.31, 0.39, 0.21, 1.65); 64 | transition: all 0.35s cubic-bezier(0.31, 0.39, 0.21, 1.65); 65 | cursor: pointer; 66 | } 67 | .dr-notification-close-btn i { 68 | padding-left: 3px; 69 | } 70 | .dr-notification-close-btn:hover { 71 | -webkit-transform: scale3d(1.25, 1.25, 1); 72 | -moz-transform: scale3d(1.25, 1.25, 1); 73 | -ms-transform: scale3d(1.25, 1.25, 1); 74 | transform: scale3d(1.25, 1.25, 1); 75 | } 76 | 77 | .dr-notification-image { 78 | width: 80px; 79 | height: 80px; 80 | border-right: 1px solid rgba(4, 94, 123, 0.85); 81 | float: left; 82 | display: block; 83 | font-size: 40px; 84 | color: white; 85 | text-align: center; 86 | } 87 | .dr-notification-image i { 88 | display: block; 89 | width: 100%; 90 | padding-top: 25px; 91 | } 92 | .dr-notification-image img { 93 | margin: 15px; 94 | max-width: 70px; 95 | min-width: 48px; 96 | } 97 | 98 | .dr-notification-image.dr-notification-type-info { 99 | color: #FFF; 100 | } 101 | 102 | .dr-notification-image.dr-notification-type-warning { 103 | color: #FFA226; 104 | } 105 | 106 | .dr-notification-image.dr-notification-type-error { 107 | color: #FF4B4F; 108 | } 109 | 110 | .dr-notification-image.dr-notification-type-success { 111 | color: #B4D455; 112 | } 113 | 114 | .dr-notification-image.success { 115 | color: #B4D455; 116 | } 117 | 118 | .dr-notification-content { 119 | padding-left: 100px; 120 | padding-right: 15px; 121 | padding-top: 10px; 122 | } 123 | 124 | .dr-notification-title { 125 | color: white; 126 | margin: 0px; 127 | padding: 0px; 128 | font-size: 20px; 129 | } 130 | 131 | p.dr-notification-text { 132 | margin-top: -5px; 133 | font-size: 12px; 134 | } 135 | -------------------------------------------------------------------------------- /notification.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | angular.module('notifications', []). 4 | factory('$notification', ['$timeout',function($timeout){ 5 | 6 | console.log('notification service online'); 7 | var notifications = JSON.parse(localStorage.getItem('$notifications')) || [], 8 | queue = []; 9 | 10 | var settings = { 11 | info: { duration: 5000, enabled: true }, 12 | warning: { duration: 5000, enabled: true }, 13 | error: { duration: 5000, enabled: true }, 14 | success: { duration: 5000, enabled: true }, 15 | progress: { duration: 0, enabled: true }, 16 | custom: { duration: 35000, enabled: true }, 17 | details: true, 18 | localStorage: false, 19 | html5Mode: false, 20 | html5DefaultIcon: 'icon.png' 21 | }; 22 | 23 | function html5Notify(icon, title, content, ondisplay, onclose){ 24 | if(window.webkitNotifications.checkPermission() === 0){ 25 | if(!icon){ 26 | icon = 'favicon.ico'; 27 | } 28 | var noti = window.webkitNotifications.createNotification(icon, title, content); 29 | if(typeof ondisplay === 'function'){ 30 | noti.ondisplay = ondisplay; 31 | } 32 | if(typeof onclose === 'function'){ 33 | noti.onclose = onclose; 34 | } 35 | noti.show(); 36 | } 37 | else { 38 | settings.html5Mode = false; 39 | } 40 | } 41 | 42 | 43 | return { 44 | 45 | /* ========== SETTINGS RELATED METHODS =============*/ 46 | 47 | disableHtml5Mode: function(){ 48 | settings.html5Mode = false; 49 | }, 50 | 51 | disableType: function(notificationType){ 52 | settings[notificationType].enabled = false; 53 | }, 54 | 55 | enableHtml5Mode: function(){ 56 | // settings.html5Mode = true; 57 | settings.html5Mode = this.requestHtml5ModePermissions(); 58 | }, 59 | 60 | enableType: function(notificationType){ 61 | settings[notificationType].enabled = true; 62 | }, 63 | 64 | getSettings: function(){ 65 | return settings; 66 | }, 67 | 68 | toggleType: function(notificationType){ 69 | settings[notificationType].enabled = !settings[notificationType].enabled; 70 | }, 71 | 72 | toggleHtml5Mode: function(){ 73 | settings.html5Mode = !settings.html5Mode; 74 | }, 75 | 76 | requestHtml5ModePermissions: function(){ 77 | if (window.webkitNotifications){ 78 | console.log('notifications are available'); 79 | if (window.webkitNotifications.checkPermission() === 0) { 80 | return true; 81 | } 82 | else{ 83 | window.webkitNotifications.requestPermission(function(){ 84 | if(window.webkitNotifications.checkPermission() === 0){ 85 | settings.html5Mode = true; 86 | } 87 | else{ 88 | settings.html5Mode = false; 89 | } 90 | }); 91 | return false; 92 | } 93 | } 94 | else{ 95 | console.log('notifications are not supported'); 96 | return false; 97 | } 98 | }, 99 | 100 | 101 | /* ============ QUERYING RELATED METHODS ============*/ 102 | 103 | getAll: function(){ 104 | // Returns all notifications that are currently stored 105 | return notifications; 106 | }, 107 | 108 | getQueue: function(){ 109 | return queue; 110 | }, 111 | 112 | /* ============== NOTIFICATION METHODS ==============*/ 113 | 114 | info: function(title, content, userData){ 115 | console.log(title, content); 116 | return this.awesomeNotify('info','info', title, content, userData); 117 | }, 118 | 119 | error: function(title, content, userData){ 120 | return this.awesomeNotify('error', 'remove', title, content, userData); 121 | }, 122 | 123 | success: function(title, content, userData){ 124 | return this.awesomeNotify('success', 'ok', title, content, userData); 125 | }, 126 | 127 | warning: function(title, content, userData){ 128 | return this.awesomeNotify('warning', 'exclamation', title, content, userData); 129 | }, 130 | 131 | awesomeNotify: function(type, icon, title, content, userData){ 132 | /** 133 | * Supposed to wrap the makeNotification method for drawing icons using font-awesome 134 | * rather than an image. 135 | * 136 | * Need to find out how I'm going to make the API take either an image 137 | * resource, or a font-awesome icon and then display either of them. 138 | * Also should probably provide some bits of color, could do the coloring 139 | * through classes. 140 | */ 141 | // image = ''; 142 | return this.makeNotification(type, false, icon, title, content, userData); 143 | }, 144 | 145 | notify: function(image, title, content, userData){ 146 | // Wraps the makeNotification method for displaying notifications with images 147 | // rather than icons 148 | return this.makeNotification('custom', image, true, title, content, userData); 149 | }, 150 | 151 | makeNotification: function(type, image, icon, title, content, userData){ 152 | var notification = { 153 | 'type': type, 154 | 'image': image, 155 | 'icon': icon, 156 | 'title': title, 157 | 'content': content, 158 | 'timestamp': +new Date(), 159 | 'userData': userData 160 | }; 161 | notifications.push(notification); 162 | 163 | if(settings.html5Mode){ 164 | html5Notify(image, title, content, function(){ 165 | console.log("inner on display function"); 166 | }, function(){ 167 | console.log("inner on close function"); 168 | }); 169 | } 170 | else{ 171 | queue.push(notification); 172 | $timeout(function removeFromQueueTimeout(){ 173 | queue.splice(queue.indexOf(notification), 1); 174 | }, settings[type].duration); 175 | 176 | } 177 | 178 | this.save(); 179 | return notification; 180 | }, 181 | 182 | 183 | /* ============ PERSISTENCE METHODS ============ */ 184 | 185 | save: function(){ 186 | // Save all the notifications into localStorage 187 | // console.log(JSON); 188 | if(settings.localStorage){ 189 | localStorage.setItem('$notifications', JSON.stringify(notifications)); 190 | } 191 | // console.log(localStorage.getItem('$notifications')); 192 | }, 193 | 194 | restore: function(){ 195 | // Load all notifications from localStorage 196 | }, 197 | 198 | clear: function(){ 199 | notifications = []; 200 | this.save(); 201 | } 202 | 203 | }; 204 | }]). 205 | directive('notifications', ['$notification', '$compile', function($notification, $compile){ 206 | /** 207 | * 208 | * It should also parse the arguments passed to it that specify 209 | * its position on the screen like "bottom right" and apply those 210 | * positions as a class to the container element 211 | * 212 | * Finally, the directive should have its own controller for 213 | * handling all of the notifications from the notification service 214 | */ 215 | console.log('this is a new directive'); 216 | var html = 217 | '{{noti.content}}
' + 229 | '