├── .gitignore
├── .idea
├── .name
├── angular-inform.iml
├── encodings.xml
├── inspectionProfiles
│ ├── Project_Default.xml
│ └── profiles_settings.xml
├── jsLibraryMappings.xml
├── libraries
│ └── angular_inform_node_modules.xml
├── misc.xml
├── modules.xml
├── runConfigurations
│ ├── gulp_dist.xml
│ ├── gulp_kitchensink.xml
│ └── gulp_test_watch.xml
├── scopes
│ └── scope_settings.xml
├── vcs.xml
└── webResources.xml
├── .npmignore
├── LICENSE
├── README.md
├── bower.json
├── build-config.js
├── dist
├── README.md
├── angular-inform.css
├── angular-inform.css.map
├── angular-inform.js
├── angular-inform.js.map
├── angular-inform.min.css
├── angular-inform.min.js
└── angular-inform.min.js.map
├── gulp-tasks
├── bower-task.js
├── index-task.js
├── lib
│ ├── gulp-autoprefixer-map.js
│ ├── gulp-bower-power.js
│ ├── gulp-csswring.js
│ ├── gulp-mini-filter.js
│ ├── gulp-modify-content.js
│ ├── gulp-rename-filename.js
│ ├── gulp-wrap-src.js
│ └── ng-xml.js
├── module-tasks
│ ├── clean-task.js
│ ├── copy-task.js
│ ├── scripts-task.js
│ ├── styles-task.js
│ ├── svg-task.js
│ └── templates-task.js
├── modules-task.js
└── visual-studio.targets
├── gulpfile.js
├── karma.conf.js
├── package.json
└── src
├── angular-inform
├── angular-inform.css
├── angular-inform.js
├── controller.js
├── directive.js
├── directive.ng.html
├── exception
│ ├── exception.js
│ ├── exception.test.js
│ ├── http.js
│ └── http.test.js
├── provider.js
└── provider.test.js
├── angular-showdown
└── angular-showdown.js
├── app
├── app.css
├── app.js
├── assets
│ └── favicon.ico
├── demo
│ ├── demo.css
│ ├── demo.html
│ └── demo.js
└── readme
│ └── readme.html
└── index.html
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/workspace.xml
2 | .idea/tasks.xml
3 | .DS_Store
4 | node_modules/*
5 | bower_components/*
6 | dest/*
7 |
8 | projectFilesBackup
--------------------------------------------------------------------------------
/.idea/.name:
--------------------------------------------------------------------------------
1 | angular-inform
--------------------------------------------------------------------------------
/.idea/angular-inform.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.idea/encodings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/Project_Default.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/.idea/inspectionProfiles/profiles_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/jsLibraryMappings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/libraries/angular_inform_node_modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/.idea/misc.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/.idea/modules.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/gulp_dist.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/gulp_kitchensink.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/.idea/runConfigurations/gulp_test_watch.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
--------------------------------------------------------------------------------
/.idea/scopes/scope_settings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/.idea/vcs.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/.idea/webResources.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .idea/workspace.xml
2 | .idea/tasks.xml
3 | .DS_Store
4 | node_modules/*
5 | bower_components/*
6 | dest/*
7 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 McNull
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # [angular-inform](https://github.com/McNull/angular-inform)
2 | A small growl-like easy-to-use message toaster for angular.
3 |
4 | #### Dependencies
5 | Besides AngularJS (~1.2.4), none.
6 |
7 | #### Browser Support
8 |
9 | Tested under _Internet Explorer 8+_, _Chrome 34+_, _FireFox 28+_ and _Safari 7+_. The styling should work on any _decent_ mobile device.
10 |
11 | #### Demo
12 |
13 | Either visit [this Plunker](http://plnkr.co/edit/x0sJj8) page or clone this repository locally and run a http-server from the `public` folder.
14 |
15 | Installation
16 | ============
17 |
18 | The latest version can be installed via _bower_ from the command line.
19 |
20 | $ bower --save install angular-inform
21 |
22 | Include both the _JavaScript_ and _CSS_ in your _HTML_.
23 |
24 | ```
25 |
26 |
27 |
28 | ```
29 |
30 | Make your main angular module dependent of the `inform` module.
31 |
32 | angular.module('myApp', ['inform']);
33 |
34 | Insert the `inform` directive somewhere in your _HTML_.
35 |
36 | ```
37 |
38 | ```
39 |
40 | ### Optional Installation Steps
41 |
42 | Provide the element the `inform-fixed` class if you want the messages to float at the upper left position.
43 |
44 | ```
45 |
46 | ```
47 |
48 | Provide the element the `inform-fixes` and `inform-center` to display the messages in the center of the screen.
49 |
50 | ```
51 |
52 | ```
53 |
54 | Provide the element the `inform-shadow` to give the messages a light box-shadow.
55 |
56 | ```
57 |
58 | ```
59 |
60 | #### Unhandled Exceptions
61 |
62 | Make your main angular module dependent of the `inform-exception` module if you want _unhandled exceptions_ to be displayed in the notification list.
63 |
64 | angular.module('myApp', ['inform', 'inform-exception']);
65 |
66 | Make your main angular module dependent of the `inform-http-exception` module if you want _http exceptions_ to be displayed in the notification list.
67 |
68 | angular.module('myApp', ['inform', 'inform-http-exception']);
69 |
70 | #### Animations
71 |
72 | Install `angular-animate` and provide the element the `inform-animate` class if you want to have CSS3 animations.
73 |
74 | ```
75 | # Install angular-animate
76 | $ bower install angular-animate
77 |
78 | // Enable ngAnimate in your module
79 | angular.module('myApp', ['inform', 'ngAnimate']);
80 |
81 |
82 |
83 | ```
84 |
85 | Usage
86 | =====
87 |
88 | The module exposes an injectable service by the name `inform`, which allows you to add notifications.
89 |
90 | ```
91 | angular.module('myApp')
92 | .controller('MyController', function($scope, inform) {
93 | inform.add('Hello!');
94 | });
95 | ```
96 |
97 | Service Methods
98 | ===============
99 |
100 | #### Add
101 | The `add` methods appends new messages to the list of notifications. The first argument is the message to display and the _optional_ second argument is an object containing some options.
102 |
103 | inform.add('The content of the message', {
104 | ttl: 2000, type: 'warning'
105 | });
106 |
107 | **Option properties**
108 |
109 | The default property values are used if no options are provided. See _configuration_ how to change these default values.
110 |
111 | {
112 | /*
113 | The time to live for the message in milliseconds.
114 | Default value is 5000. Specify <0 to make the message sticky.
115 | */
116 | ttl: 5000,
117 |
118 | /*
119 | The type of message to enable styling.
120 | Values can be any of the following:
121 |
122 | - 'default'
123 | - 'primary'
124 | - 'success'
125 | - 'info'
126 | - 'warning'
127 | - 'danger'
128 | - or any other custom type.
129 |
130 | Default value is 'default'
131 | */
132 | type: 'danger'
133 | }
134 |
135 | **Flood protection**
136 |
137 | To prevent the list from flooding, the method will search the current notification list for a match on content and type. If an earlier message is found, than the _TTL_ of that message will be reset and a track count is increased.
138 |
139 | **Return value**
140 |
141 | The method will either return a newly created message object or any match found.
142 |
143 | #### Remove
144 |
145 | Any earlier returned message object can be manually removed from the notification list if needed. This will also cancel any pending TTL timeouts.
146 |
147 | var myMsg = inform.add('My Message');
148 | inform.remove(myMsg);
149 |
150 | #### Clear
151 |
152 | This method (no arguments) will simply clear the list of messages.
153 |
154 | #### Messages
155 |
156 | Returns the array of messages maintained by the service.
157 |
158 | Service Configuration
159 | =====================
160 |
161 | The defaults of the service can be manipulated in the config phase of your module by injecting the `informProvider`.
162 |
163 | angular.module('myApp')
164 | .config(function(informProvider) {
165 |
166 | var myDefaults = {
167 | /* default time to live for each notification */
168 | ttl: 1234,
169 | /* default type of notification */
170 | type: 'danger'
171 | };
172 |
173 | informProvider.defaults(myDefaults);
174 |
175 | });
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-inform",
3 | "description": "A small growl-like easy-to-use message toaster for angular.",
4 | "keywords": [ "angular", "growl", "message", "message-list", "notification", "notification-list", "toaster", "toastr", "popup", "alert", "alert-list" ],
5 | "version": "0.0.18",
6 | "authors": [
7 | "Null McNull "
8 | ],
9 | "license": "MIT",
10 | "ignore": [
11 | "**/.*",
12 | "node_modules",
13 | "bower_components",
14 | "gulp-tasks",
15 | "src",
16 | "dest",
17 | "/build-config.js",
18 | "/gulpfile.js",
19 | "/package.json",
20 | "/README.md",
21 | "/karma.conf.js"
22 | ],
23 | "dependencies": {
24 | "angular": "~1.2.16"
25 | },
26 | "main": [
27 | "dist/angular-inform.css",
28 | "dist/angular-inform.js"
29 | ],
30 | "devDependencies": {
31 | "angular-mocks": "~1.2.26",
32 | "angular-route": "~1.2.26",
33 | "angular-animate": "~1.2.26",
34 | "bootstrap-css": "~3.1.1",
35 | "jquery": "1.*",
36 | "modernizr": "~2.8.3",
37 | "respondJS": "~1.4.2",
38 | "showdown": "~0.3.1"
39 | },
40 | "overrides": {
41 | "respond": {
42 | "main": "dest/respond.min.js"
43 | },
44 | "showdown": {
45 | "main": "compressed/showdown.js"
46 | },
47 | "angular-mocks": {
48 | "ignore": true
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/build-config.js:
--------------------------------------------------------------------------------
1 | // - - - - - 8-< - - - - - - - - - - - - - -
2 |
3 | var _ = require('lodash');
4 |
5 | // - - - - - 8-< - - - - - - - - - - - - - -
6 |
7 | var pkg = require('./package.json');
8 | pkg.year = pkg.year || new Date().getFullYear();
9 |
10 | // - - - - - 8-< - - - - - - - - - - - - - -
11 |
12 | var config = {
13 |
14 | /* 'production' || 'development' */
15 | env: process.env.NODE_ENV,
16 |
17 | folders: {
18 | dest: 'dest/',
19 | src: 'src/'
20 | },
21 |
22 | modules: [
23 | {
24 | name: 'angular-inform',
25 | alias: 'inform'
26 | },
27 | {
28 | name: 'angular-showdown',
29 | alias: 'showdown'
30 | },
31 | {
32 | name: 'app'
33 | }
34 | ],
35 |
36 | bower: {
37 | includeDev: true
38 | },
39 |
40 | header: _.template([
41 | '/*!',
42 | ' <%= pkg.name %> v<%= pkg.version %>',
43 | ' (c) <%= pkg.year %> <%= pkg.author %> <%= pkg.homepage %>',
44 | ' License: <%= pkg.license %>',
45 | '*/\n'
46 | ].join('\n'), { pkg: pkg })
47 |
48 | };
49 |
50 | // - - - - - 8-< - - - - - - - - - - - - - -
51 |
52 | module.exports = config;
--------------------------------------------------------------------------------
/dist/README.md:
--------------------------------------------------------------------------------
1 | # [angular-inform](https://github.com/McNull/angular-inform)
2 | A small growl-like easy-to-use message toaster for angular.
3 |
4 | #### Dependencies
5 | Besides AngularJS (~1.2.4), none.
6 |
7 | #### Browser Support
8 |
9 | Tested under _Internet Explorer 8+_, _Chrome 34+_, _FireFox 28+_ and _Safari 7+_. The styling should work on any _decent_ mobile device.
10 |
11 | #### Demo
12 |
13 | Either visit [this Plunker](http://plnkr.co/edit/x0sJj8) page or clone this repository locally and run a http-server from the `public` folder.
14 |
15 | Installation
16 | ============
17 |
18 | The latest version can be installed via _bower_ from the command line.
19 |
20 | $ bower --save install angular-inform
21 |
22 | Include both the _JavaScript_ and _CSS_ in your _HTML_.
23 |
24 | ```
25 |
26 |
27 |
28 | ```
29 |
30 | Make your main angular module dependent of the `inform` module.
31 |
32 | angular.module('myApp', ['inform']);
33 |
34 | Insert the `inform` directive somewhere in your _HTML_.
35 |
36 | ```
37 |
38 | ```
39 |
40 | ### Optional Installation Steps
41 |
42 | Provide the element the `inform-fixed` class if you want the messages to float at the upper left position.
43 |
44 | ```
45 |
46 | ```
47 |
48 | Provide the element the `inform-fixes` and `inform-center` to display the messages in the center of the screen.
49 |
50 | ```
51 |
52 | ```
53 |
54 | Provide the element the `inform-shadow` to give the messages a light box-shadow.
55 |
56 | ```
57 |
58 | ```
59 |
60 | #### Unhandled Exceptions
61 |
62 | Make your main angular module dependent of the `inform-exception` module if you want _unhandled exceptions_ to be displayed in the notification list.
63 |
64 | angular.module('myApp', ['inform', 'inform-exception']);
65 |
66 | Make your main angular module dependent of the `inform-http-exception` module if you want _http exceptions_ to be displayed in the notification list.
67 |
68 | angular.module('myApp', ['inform', 'inform-http-exception']);
69 |
70 | #### Animations
71 |
72 | Install `angular-animate` and provide the element the `inform-animate` class if you want to have CSS3 animations.
73 |
74 | ```
75 | # Install angular-animate
76 | $ bower install angular-animate
77 |
78 | // Enable ngAnimate in your module
79 | angular.module('myApp', ['inform', 'ngAnimate']);
80 |
81 |
82 |
83 | ```
84 |
85 | Usage
86 | =====
87 |
88 | The module exposes an injectable service by the name `inform`, which allows you to add notifications.
89 |
90 | ```
91 | angular.module('myApp')
92 | .controller('MyController', function($scope, inform) {
93 | inform.add('Hello!');
94 | });
95 | ```
96 |
97 | Service Methods
98 | ===============
99 |
100 | #### Add
101 | The `add` methods appends new messages to the list of notifications. The first argument is the message to display and the _optional_ second argument is an object containing some options.
102 |
103 | inform.add('The content of the message', {
104 | ttl: 2000, type: 'warning'
105 | });
106 |
107 | **Option properties**
108 |
109 | The default property values are used if no options are provided. See _configuration_ how to change these default values.
110 |
111 | {
112 | /*
113 | The time to live for the message in milliseconds.
114 | Default value is 5000. Specify <0 to make the message sticky.
115 | */
116 | ttl: 5000,
117 |
118 | /*
119 | The type of message to enable styling.
120 | Values can be any of the following:
121 |
122 | - 'default'
123 | - 'primary'
124 | - 'success'
125 | - 'info'
126 | - 'warning'
127 | - 'danger'
128 | - or any other custom type.
129 |
130 | Default value is 'default'
131 | */
132 | type: 'danger'
133 | }
134 |
135 | **Flood protection**
136 |
137 | To prevent the list from flooding, the method will search the current notification list for a match on content and type. If an earlier message is found, than the _TTL_ of that message will be reset and a track count is increased.
138 |
139 | **Return value**
140 |
141 | The method will either return a newly created message object or any match found.
142 |
143 | #### Remove
144 |
145 | Any earlier returned message object can be manually removed from the notification list if needed. This will also cancel any pending TTL timeouts.
146 |
147 | var myMsg = inform.add('My Message');
148 | inform.remove(myMsg);
149 |
150 | #### Clear
151 |
152 | This method (no arguments) will simply clear the list of messages.
153 |
154 | #### Messages
155 |
156 | Returns the array of messages maintained by the service.
157 |
158 | Service Configuration
159 | =====================
160 |
161 | The defaults of the service can be manipulated in the config phase of your module by injecting the `informProvider`.
162 |
163 | angular.module('myApp')
164 | .config(function(informProvider) {
165 |
166 | var myDefaults = {
167 | /* default time to live for each notification */
168 | ttl: 1234,
169 | /* default type of notification */
170 | type: 'danger'
171 | };
172 |
173 | informProvider.defaults(myDefaults);
174 |
175 | });
--------------------------------------------------------------------------------
/dist/angular-inform.css:
--------------------------------------------------------------------------------
1 | /*!
2 | angular-inform v0.0.18
3 | (c) 2014 (null) McNull https://github.com/McNull/angular-inform
4 | License: MIT
5 | */
6 |
7 |
8 |
9 | .inform-fixed {
10 | position: fixed;
11 | top: 20px;
12 | left: 20px;
13 | right: 20px;
14 | z-index: 1002;
15 | }
16 |
17 | .inform-fixed .inform-message {
18 | width: auto;
19 | }
20 |
21 | @media screen and (min-width: 480px) {
22 | .inform-fixed {
23 | left: auto;
24 | width: 440px;
25 | }
26 |
27 | .inform-fixed.inform-center {
28 | right: 0;
29 | left: 0;
30 | margin-left: auto;
31 | margin-right: auto;
32 | }
33 | }
34 |
35 | .inform-message {
36 | overflow: hidden;
37 | }
38 |
39 | .inform-message > button.close {
40 | margin-left: 15px;
41 | }
42 |
43 | .inform-shadow .inform-message {
44 | box-shadow: 0px 5px 20px 0px rgba(0, 0, 0, 0.25);
45 | }
46 |
47 | .inform-message.alert-primary {
48 | color: #FFF;
49 | background-color: #428BCA;
50 | }
51 |
52 | .inform-message.alert-default {
53 | background-color: #F5F5F5;
54 | border: 1px solid #CCC;
55 | color: #333;
56 | }
57 |
58 |
59 | .inform-message-wrap {
60 | /*overflow: hidden;*/
61 | }
62 | .inform-animate .inform-message-wrap.ng-enter {
63 | -webkit-animation: 1.0s inform-message-slide-in;
64 | animation: 1.0s inform-message-slide-in;
65 | }
66 |
67 | .inform-animate .inform-message-wrap.ng-leave {
68 | -webkit-animation: 1.0s inform-message-fade-out;
69 | animation: 1.0s inform-message-fade-out;
70 | }
71 |
72 | .inform-animate .inform-badge.ng-enter {
73 | -webkit-animation: inform-badge-scale 0.5s;
74 | animation: inform-badge-scale 0.5s;
75 | }
76 |
77 | @-webkit-keyframes inform-badge-scale {
78 | 0% {
79 | opacity: 0;
80 | -webkit-transform: scale(0);
81 | transform: scale(0);
82 | }
83 | 25% {
84 | opacity: 1;
85 | -webkit-transform: scale(1.5);
86 | transform: scale(1.5);
87 | }
88 | 100% {
89 | opacity: 1;
90 | -webkit-transform: scale(1);
91 | transform: scale(1);
92 | }
93 | }
94 |
95 | @keyframes inform-badge-scale {
96 | 0% {
97 | opacity: 0;
98 | -webkit-transform: scale(0);
99 | transform: scale(0);
100 | }
101 | 25% {
102 | opacity: 1;
103 | -webkit-transform: scale(1.5);
104 | transform: scale(1.5);
105 | }
106 | 100% {
107 | opacity: 1;
108 | -webkit-transform: scale(1);
109 | transform: scale(1);
110 | }
111 | }
112 |
113 | @-webkit-keyframes inform-message-slide-in {
114 | 0% {
115 | opacity: 0;
116 | -webkit-transform: translateX(100%);
117 | transform: translateX(100%);
118 | max-height: 0px;
119 | }
120 | 50% {
121 | opacity: 0;
122 | -webkit-transform: translateX(100%);
123 | transform: translateX(100%);
124 | max-height: 1000px;
125 | }
126 | 100% {
127 | opacity: 1;
128 | -webkit-transform: translateX(0%);
129 | transform: translateX(0%);
130 | max-height: 1000px;
131 | }
132 | }
133 |
134 | @keyframes inform-message-slide-in {
135 | 0% {
136 | opacity: 0;
137 | -webkit-transform: translateX(100%);
138 | transform: translateX(100%);
139 | max-height: 0px;
140 | }
141 | 50% {
142 | opacity: 0;
143 | -webkit-transform: translateX(100%);
144 | transform: translateX(100%);
145 | max-height: 1000px;
146 | }
147 | 100% {
148 | opacity: 1;
149 | -webkit-transform: translateX(0%);
150 | transform: translateX(0%);
151 | max-height: 1000px;
152 | }
153 | }
154 |
155 | @-webkit-keyframes inform-message-fade-out {
156 | 0% {
157 | opacity: 1;
158 | max-height: 1000px;
159 | }
160 | 50% {
161 | opacity: 0;
162 | max-height: 1000px;
163 | }
164 | 100% {
165 | opacity: 0;
166 | max-height: 0px;
167 | }
168 | }
169 |
170 | @keyframes inform-message-fade-out {
171 | 0% {
172 | opacity: 1;
173 | max-height: 1000px;
174 | }
175 | 50% {
176 | opacity: 0;
177 | max-height: 1000px;
178 | }
179 | 100% {
180 | opacity: 0;
181 | max-height: 0px;
182 | }
183 | }
184 | /*# sourceMappingURL=angular-inform.css.map */
--------------------------------------------------------------------------------
/dist/angular-inform.css.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["angular-inform-header.css","angular-inform.css"],"names":[],"mappings":"AAAA;;;;GAIA;;;;ACFA;EACA,iBAAA;EACA,WAAA;EACA,YAAA;EACA,aAAA;EACA,eAAA;EACA;;AAEA;EACA,aAAA;EACA;;AAEA;EACA;IACA,YAAA;IACA,cAAA;IACA;;EAEA;IACA,UAAA;IACA,SAAA;IACA,mBAAA;IACA,oBAAA;IACA;EACA;;AAEA;EACA,kBAAA;EACA;;AAEA;EACA,mBAAA;EACA;;AAEA;EACA,kDAAA;EACA;;AAEA;EACA,aAAA;EACA,2BAAA;EACA;;AAEA;EACA,2BAAA;EACA,wBAAA;EACA,aAAA;EACA;;;AAGA;EACA,sBAAA;EACA;AACA;EACA,iDAAA;UAAA,yCAAA;EACA;;AAEA;EACA,iDAAA;UAAA,yCAAA;EACA;;AAEA;EACA,4CAAA;UAAA,oCAAA;EACA;;AAEA;EACA;IACA,YAAA;IACA,6BAAA;YAAA,qBAAA;IACA;EACA;IACA,YAAA;IACA,+BAAA;YAAA,uBAAA;IACA;EACA;IACA,YAAA;IACA,6BAAA;YAAA,qBAAA;IACA;EACA;;AAbA;EACA;IACA,YAAA;IACA,6BAAA;YAAA,qBAAA;IACA;EACA;IACA,YAAA;IACA,+BAAA;YAAA,uBAAA;IACA;EACA;IACA,YAAA;IACA,6BAAA;YAAA,qBAAA;IACA;EACA;;AAEA;EACA;IACA,YAAA;IACA,qCAAA;YAAA,6BAAA;IACA,iBAAA;IACA;EACA;IACA,YAAA;IACA,qCAAA;YAAA,6BAAA;IACA,oBAAA;IACA;EACA;IACA,YAAA;IACA,mCAAA;YAAA,2BAAA;IACA,oBAAA;IACA;EACA;;AAhBA;EACA;IACA,YAAA;IACA,qCAAA;YAAA,6BAAA;IACA,iBAAA;IACA;EACA;IACA,YAAA;IACA,qCAAA;YAAA,6BAAA;IACA,oBAAA;IACA;EACA;IACA,YAAA;IACA,mCAAA;YAAA,2BAAA;IACA,oBAAA;IACA;EACA;;AAEA;EACA;IACA,YAAA;IACA,oBAAA;IACA;EACA;IACA,YAAA;IACA,oBAAA;IACA;EACA;IACA,YAAA;IACA,iBAAA;IACA;EACA;;AAbA;EACA;IACA,YAAA;IACA,oBAAA;IACA;EACA;IACA,YAAA;IACA,oBAAA;IACA;EACA;IACA,YAAA;IACA,iBAAA;IACA;EACA","file":"angular-inform.css","sourcesContent":["/*!\n angular-inform v0.0.18\n (c) 2014 (null) McNull https://github.com/McNull/angular-inform\n License: MIT\n*/\n","\n\n.inform-fixed {\n position: fixed;\n top: 20px;\n left: 20px;\n right: 20px;\n z-index: 1002;\n}\n\n.inform-fixed .inform-message {\n width: auto;\n}\n\n@media screen and (min-width: 480px) {\n .inform-fixed {\n left: auto;\n width: 440px;\n }\n\n .inform-fixed.inform-center {\n right: 0;\n left: 0;\n margin-left: auto;\n margin-right: auto;\n }\n}\n\n.inform-message {\n overflow: hidden;\n}\n\n.inform-message > button.close {\n margin-left: 15px;\n}\n\n.inform-shadow .inform-message {\n box-shadow: 0px 5px 20px 0px rgba(0, 0, 0, 0.25);\n}\n\n.inform-message.alert-primary {\n color: #FFF;\n background-color: #428BCA;\n}\n\n.inform-message.alert-default {\n background-color: #F5F5F5;\n border: 1px solid #CCC;\n color: #333;\n}\n\n\n.inform-message-wrap {\n /*overflow: hidden;*/\n}\n.inform-animate .inform-message-wrap.ng-enter {\n animation: 1.0s inform-message-slide-in;\n}\n\n.inform-animate .inform-message-wrap.ng-leave {\n animation: 1.0s inform-message-fade-out;\n}\n\n.inform-animate .inform-badge.ng-enter {\n animation: inform-badge-scale 0.5s;\n}\n\n@keyframes inform-badge-scale {\n 0% {\n opacity: 0;\n transform: scale(0);\n }\n 25% {\n opacity: 1;\n transform: scale(1.5);\n }\n 100% {\n opacity: 1;\n transform: scale(1);\n }\n}\n\n@keyframes inform-message-slide-in {\n 0% {\n opacity: 0;\n transform: translateX(100%);\n max-height: 0px;\n }\n 50% {\n opacity: 0;\n transform: translateX(100%);\n max-height: 1000px;\n }\n 100% {\n opacity: 1;\n transform: translateX(0%);\n max-height: 1000px;\n }\n}\n\n@keyframes inform-message-fade-out {\n 0% {\n opacity: 1;\n max-height: 1000px;\n }\n 50% {\n opacity: 0;\n max-height: 1000px;\n }\n 100% {\n opacity: 0;\n max-height: 0px;\n }\n}"],"sourceRoot":"../src/angular-inform"}
--------------------------------------------------------------------------------
/dist/angular-inform.js:
--------------------------------------------------------------------------------
1 | /*!
2 | angular-inform v0.0.18
3 | (c) 2014 (null) McNull https://github.com/McNull/angular-inform
4 | License: MIT
5 | */
6 | (function(angular) {
7 |
8 | var inform = angular.module('inform', []);
9 |
10 |
11 | inform.controller('InformCtrl', ["$scope", "inform", function($scope, inform) {
12 |
13 | $scope.messages = inform.messages();
14 | $scope.remove = inform.remove;
15 | $scope.cancelTimeout = inform.cancelTimeout;
16 | $scope.setTimeout = inform.setTimeout;
17 |
18 | }]);
19 |
20 | inform.directive('inform', function () {
21 | return {
22 | restrict: 'AE',
23 | templateUrl: 'angular-inform/directive.ng.html',
24 | controller: 'InformCtrl'
25 | };
26 | });
27 | inform.provider('inform', function () {
28 |
29 | var provider = this;
30 |
31 | this._defaults = {
32 | type: 'default',
33 | ttl: 5000
34 | };
35 |
36 | this.defaults = function (options) {
37 | provider._defaults = angular.extend(provider._defaults, options || {});
38 | return provider._defaults;
39 | };
40 |
41 |
42 | this.$get = ['$timeout', '$sce', function ($timeout, $sce) {
43 |
44 | var _messages = [];
45 |
46 | function _indexOf(predicate) {
47 | var i = _messages.length;
48 |
49 | while (i--) {
50 | if (predicate(_messages[i])) {
51 | return i;
52 | }
53 | }
54 |
55 | return -1;
56 | }
57 |
58 | function cancelTimeout(msg) {
59 | if (msg.timeout) {
60 | $timeout.cancel(msg.timeout);
61 | delete msg.timeout;
62 | }
63 | }
64 |
65 | function setTimeout(msg) {
66 |
67 | cancelTimeout(msg);
68 |
69 | if (msg.ttl > 0) {
70 | msg.timeout = $timeout(function () {
71 | remove(msg);
72 | }, msg.ttl);
73 | }
74 | }
75 |
76 | function add(content, options) {
77 |
78 | var msg = angular.extend({}, provider._defaults, options);
79 |
80 | if(!angular.isString(content)) {
81 | content = '' + JSON.stringify(content, null, ' ') + '
';
82 | msg.html = true;
83 | }
84 |
85 | var idx = _indexOf(function (x) {
86 | return x.content.toString() === content && x.type == msg.type;
87 | });
88 |
89 | if (idx >= 0) {
90 |
91 | msg = _messages[idx];
92 | msg.count += 1;
93 |
94 | } else {
95 |
96 | msg.content = content;
97 |
98 | if(msg.html) {
99 | msg.content = $sce.trustAsHtml(content);
100 | }
101 |
102 | msg.tickCount = +new Date();
103 | msg.count = 1;
104 |
105 | _messages.push(msg);
106 | }
107 |
108 | setTimeout(msg);
109 |
110 | return msg;
111 | }
112 |
113 | function remove(msg) {
114 |
115 | var idx = _indexOf(function (x) {
116 | return x === msg;
117 | });
118 |
119 | if (idx >= 0) {
120 | _messages.splice(idx, 1);
121 | cancelTimeout(msg);
122 | }
123 | }
124 |
125 | function clear() {
126 | _messages.length = 0;
127 | }
128 |
129 | return {
130 | messages: function () {
131 | return _messages;
132 | },
133 | add: add,
134 | remove: remove,
135 | clear: clear,
136 | cancelTimeout: cancelTimeout,
137 | setTimeout: setTimeout
138 | };
139 | }];
140 |
141 | });
142 |
143 | angular.module('inform-exception', ['inform'])
144 | .config(["$provide", function($provide) {
145 | $provide.decorator('$exceptionHandler', ['$delegate', '$injector',function($delegate, $injector) {
146 |
147 | var inform;
148 |
149 | return function(exception, cause) {
150 | try {
151 | inform = inform || $injector.get('inform');
152 | inform.add(exception.toString(), { type: 'danger', ttl: 0 });
153 | } catch(ex) {
154 | console.log('$exceptionHandler', ex);
155 | }
156 | $delegate(exception, cause);
157 | };
158 | }]);
159 | }]);
160 |
161 | angular.module('inform-http-exception', ['inform'])
162 |
163 | .factory('informHttpInterceptor', ["$q", "inform", function ($q, inform) {
164 |
165 | function interceptor(rejection) {
166 | try {
167 | var msg = 'Network error (' + rejection.status + '): ' + rejection.statusText;
168 | inform.add(msg, { type: 'danger', ttl: 0});
169 | } catch(ex) {
170 | console.log('$httpProvider', ex);
171 | }
172 |
173 | return $q.reject(rejection);
174 | }
175 |
176 | return {
177 | requestError: interceptor,
178 | responseError: interceptor
179 | };
180 |
181 | }])
182 |
183 | .config(["$httpProvider", function ($httpProvider) {
184 | $httpProvider.interceptors.push('informHttpInterceptor');
185 | }]);
186 |
187 | // Automatically generated.
188 | // This file is already embedded in your main javascript output, there's no need to include this file
189 | // manually in the index.html. This file is only here for your debugging pleasures.
190 | angular.module('inform').run(['$templateCache', function($templateCache){
191 | $templateCache.put('angular-inform/directive.ng.html', '');
192 | }]);
193 | })(angular);
194 | //# sourceMappingURL=angular-inform.js.map
--------------------------------------------------------------------------------
/dist/angular-inform.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["angular-inform-header.js","angular-inform.js","controller.js","directive.js","provider.js","exception/exception.js","exception/http.js","angular-inform-templates.js","angular-inform-footer.js"],"names":[],"mappings":"AAAA;GACA;GACA;GACA;AACA;AACA;;ACLA;;;ACAA,mBAAA,UAAA,GAAA,qBAAA;;EAEA;EACA;EACA;EACA;;AAEA,CAAA,CAAA;;ACPA,kBAAA,MAAA;EACA;IACA;IACA;IACA,aAAA,UAAA;EACA;AACA;ACNA,iBAAA,MAAA;;EAEA;;EAEA;IACA;IACA;EACA;;EAEA;IACA;IACA;EACA;;;EAGA;;IAEA;;IAEA;MACA;;MAEA;QACA;UACA;QACA;MACA;;MAEA;IACA;;IAEA;MACA;QACA;QACA;MACA;IACA;;IAEA;;MAEA;;MAEA;QACA;UACA;QACA;MACA;IACA;;IAEA;;MAEA;;MAEA;QACA;QACA;MACA;;MAEA;QACA;MACA;;MAEA;;QAEA;QACA;;MAEA;;QAEA;;QAEA;UACA;QACA;;QAEA;QACA;;QAEA;MACA;;MAEA;;MAEA;IACA;;IAEA;;MAEA;QACA;MACA;;MAEA;QACA;QACA;MACA;IACA;;IAEA;MACA;IACA;;IAEA;MACA;QACA;MACA;MACA;MACA;MACA;MACA;MACA;IACA;EACA;;AAEA;;ACjHA;EACA,QAAA,aAAA;IACA,oBAAA,iBAAA;;MAEA;;MAEA;QACA;UACA;UACA;QACA;UACA;QACA;QACA;MACA;IACA;EACA,CAAA,CAAA;;ACjBA;;EAEA,UAAA,qBAAA,GAAA,iBAAA;;IAEA;MACA;QACA;QACA;MACA;QACA;MACA;;MAEA;IACA;;IAEA;MACA;MACA;IACA;;EAEA,CAAA,CAAA;;EAEA,QAAA,kBAAA;IACA,iCAAA,qBAAA;EACA,CAAA,CAAA;;ACxBA;AACA;AACA;AACA;EACA;AACA;ACLA","file":"angular-inform.js","sourcesContent":["/*!\n angular-inform v0.0.18\n (c) 2014 (null) McNull https://github.com/McNull/angular-inform\n License: MIT\n*/\n(function(angular) {\n","var inform = angular.module('inform', []);\n\n","inform.controller('InformCtrl', function($scope, inform) {\n\n $scope.messages = inform.messages();\n $scope.remove = inform.remove;\n $scope.cancelTimeout = inform.cancelTimeout;\n $scope.setTimeout = inform.setTimeout;\n\n});\n","inform.directive('inform', function () {\n return {\n restrict: 'AE',\n templateUrl: 'angular-inform/directive.ng.html',\n controller: 'InformCtrl'\n };\n});","inform.provider('inform', function () {\n\n var provider = this;\n\n this._defaults = {\n type: 'default',\n ttl: 5000\n };\n\n this.defaults = function (options) {\n provider._defaults = angular.extend(provider._defaults, options || {});\n return provider._defaults;\n };\n\n\n this.$get = ['$timeout', '$sce', function ($timeout, $sce) {\n\n var _messages = [];\n\n function _indexOf(predicate) {\n var i = _messages.length;\n\n while (i--) {\n if (predicate(_messages[i])) {\n return i;\n }\n }\n\n return -1;\n }\n\n function cancelTimeout(msg) {\n if (msg.timeout) {\n $timeout.cancel(msg.timeout);\n delete msg.timeout;\n }\n }\n\n function setTimeout(msg) {\n\n cancelTimeout(msg);\n\n if (msg.ttl > 0) {\n msg.timeout = $timeout(function () {\n remove(msg);\n }, msg.ttl);\n }\n }\n\n function add(content, options) {\n\n var msg = angular.extend({}, provider._defaults, options);\n\n if(!angular.isString(content)) {\n content = '' + JSON.stringify(content, null, ' ') + '
';\n msg.html = true;\n }\n\n var idx = _indexOf(function (x) {\n return x.content.toString() === content && x.type == msg.type;\n });\n\n if (idx >= 0) {\n\n msg = _messages[idx];\n msg.count += 1;\n\n } else {\n\n msg.content = content;\n\n if(msg.html) {\n msg.content = $sce.trustAsHtml(content);\n }\n\n msg.tickCount = +new Date();\n msg.count = 1;\n\n _messages.push(msg);\n }\n\n setTimeout(msg);\n\n return msg;\n }\n\n function remove(msg) {\n\n var idx = _indexOf(function (x) {\n return x === msg;\n });\n\n if (idx >= 0) {\n _messages.splice(idx, 1);\n cancelTimeout(msg);\n }\n }\n\n function clear() {\n _messages.length = 0;\n }\n\n return {\n messages: function () {\n return _messages;\n },\n add: add,\n remove: remove,\n clear: clear,\n cancelTimeout: cancelTimeout,\n setTimeout: setTimeout\n };\n }];\n\n});","\nangular.module('inform-exception', ['inform'])\n .config(function($provide) {\n $provide.decorator('$exceptionHandler', ['$delegate', '$injector',function($delegate, $injector) {\n\n var inform;\n\n return function(exception, cause) {\n try {\n inform = inform || $injector.get('inform');\n inform.add(exception.toString(), { type: 'danger', ttl: 0 });\n } catch(ex) {\n console.log('$exceptionHandler', ex);\n }\n $delegate(exception, cause);\n };\n }]);\n });\n","angular.module('inform-http-exception', ['inform'])\n\n .factory('informHttpInterceptor', function ($q, inform) {\n\n function interceptor(rejection) {\n try {\n var msg = 'Network error (' + rejection.status + '): ' + rejection.statusText;\n inform.add(msg, { type: 'danger', ttl: 0});\n } catch(ex) {\n console.log('$httpProvider', ex);\n }\n\n return $q.reject(rejection);\n }\n\n return {\n requestError: interceptor,\n responseError: interceptor\n };\n\n })\n\n .config(function ($httpProvider) {\n $httpProvider.interceptors.push('informHttpInterceptor');\n });\n","// Automatically generated.\n// This file is already embedded in your main javascript output, there's no need to include this file\n// manually in the index.html. This file is only here for your debugging pleasures.\nangular.module('inform').run(['$templateCache', function($templateCache){\n $templateCache.put('angular-inform/directive.ng.html', '');\n}]);","})(angular);"],"sourceRoot":"../src/angular-inform"}
--------------------------------------------------------------------------------
/dist/angular-inform.min.css:
--------------------------------------------------------------------------------
1 | /*!
2 | angular-inform v0.0.18
3 | (c) 2014 (null) McNull https://github.com/McNull/angular-inform
4 | License: MIT
5 | */.inform-fixed{position:fixed;top:20px;left:20px;right:20px;z-index:1002}.inform-fixed .inform-message{width:auto}@media screen and (min-width:480px){.inform-fixed{left:auto;width:440px}.inform-fixed.inform-center{right:0;left:0;margin-left:auto;margin-right:auto}}.inform-message{overflow:hidden}.inform-message>button.close{margin-left:15px}.inform-shadow .inform-message{box-shadow:0 5px 20px 0 rgba(0,0,0,.25)}.inform-message.alert-primary{color:#FFF;background-color:#428BCA}.inform-message.alert-default{background-color:#F5F5F5;border:1px solid #CCC;color:#333}.inform-animate .inform-message-wrap.ng-enter{-webkit-animation:1s inform-message-slide-in;animation:1s inform-message-slide-in}.inform-animate .inform-message-wrap.ng-leave{-webkit-animation:1s inform-message-fade-out;animation:1s inform-message-fade-out}.inform-animate .inform-badge.ng-enter{-webkit-animation:inform-badge-scale .5s;animation:inform-badge-scale .5s}@-webkit-keyframes inform-badge-scale{0%{opacity:0;-webkit-transform:scale(0);transform:scale(0)}25%{opacity:1;-webkit-transform:scale(1.5);transform:scale(1.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@keyframes inform-badge-scale{0%{opacity:0;-webkit-transform:scale(0);transform:scale(0)}25%{opacity:1;-webkit-transform:scale(1.5);transform:scale(1.5)}100%{opacity:1;-webkit-transform:scale(1);transform:scale(1)}}@-webkit-keyframes inform-message-slide-in{0%{opacity:0;-webkit-transform:translateX(100%);transform:translateX(100%);max-height:0}50%{opacity:0;-webkit-transform:translateX(100%);transform:translateX(100%);max-height:1000px}100%{opacity:1;-webkit-transform:translateX(0%);transform:translateX(0%);max-height:1000px}}@keyframes inform-message-slide-in{0%{opacity:0;-webkit-transform:translateX(100%);transform:translateX(100%);max-height:0}50%{opacity:0;-webkit-transform:translateX(100%);transform:translateX(100%);max-height:1000px}100%{opacity:1;-webkit-transform:translateX(0%);transform:translateX(0%);max-height:1000px}}@-webkit-keyframes inform-message-fade-out{0%{opacity:1;max-height:1000px}50%{opacity:0;max-height:1000px}100%{opacity:0;max-height:0}}@keyframes inform-message-fade-out{0%{opacity:1;max-height:1000px}50%{opacity:0;max-height:1000px}100%{opacity:0;max-height:0}}
--------------------------------------------------------------------------------
/dist/angular-inform.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | angular-inform v0.0.18
3 | (c) 2014 (null) McNull https://github.com/McNull/angular-inform
4 | License: MIT
5 | */
6 | !function(t){var e=t.module("inform",[]);e.controller("InformCtrl",["$scope","inform",function(t,e){t.messages=e.messages(),t.remove=e.remove,t.cancelTimeout=e.cancelTimeout,t.setTimeout=e.setTimeout}]),e.directive("inform",function(){return{restrict:"AE",templateUrl:"angular-inform/directive.ng.html",controller:"InformCtrl"}}),e.provider("inform",function(){var e=this;this._defaults={type:"default",ttl:5e3},this.defaults=function(n){return e._defaults=t.extend(e._defaults,n||{}),e._defaults},this.$get=["$timeout","$sce",function(n,r){function o(t){for(var e=m.length;e--;)if(t(m[e]))return e;return-1}function i(t){t.timeout&&(n.cancel(t.timeout),delete t.timeout)}function s(t){i(t),t.ttl>0&&(t.timeout=n(function(){u(t)},t.ttl))}function c(n,i){var c=t.extend({},e._defaults,i);t.isString(n)||(n=""+JSON.stringify(n,null," ")+"
",c.html=!0);var u=o(function(t){return t.content.toString()===n&&t.type==c.type});return u>=0?(c=m[u],c.count+=1):(c.content=n,c.html&&(c.content=r.trustAsHtml(n)),c.tickCount=+new Date,c.count=1,m.push(c)),s(c),c}function u(t){var e=o(function(e){return e===t});e>=0&&(m.splice(e,1),i(t))}function a(){m.length=0}var m=[];return{messages:function(){return m},add:c,remove:u,clear:a,cancelTimeout:i,setTimeout:s}}]}),t.module("inform-exception",["inform"]).config(["$provide",function(t){t.decorator("$exceptionHandler",["$delegate","$injector",function(t,e){var n;return function(r,o){try{n=n||e.get("inform"),n.add(r.toString(),{type:"danger",ttl:0})}catch(i){console.log("$exceptionHandler",i)}t(r,o)}}])}]),t.module("inform-http-exception",["inform"]).factory("informHttpInterceptor",["$q","inform",function(t,e){function n(n){try{var r="Network error ("+n.status+"): "+n.statusText;e.add(r,{type:"danger",ttl:0})}catch(o){console.log("$httpProvider",o)}return t.reject(n)}return{requestError:n,responseError:n}}]).config(["$httpProvider",function(t){t.interceptors.push("informHttpInterceptor")}]),t.module("inform").run(["$templateCache",function(t){t.put("angular-inform/directive.ng.html",'')}])}(angular);
7 | //# sourceMappingURL=angular-inform.min.js.map
--------------------------------------------------------------------------------
/dist/angular-inform.min.js.map:
--------------------------------------------------------------------------------
1 | {"version":3,"sources":["angular-inform.js"],"names":["angular","inform","module","controller","$scope","messages","remove","cancelTimeout","setTimeout","directive","restrict","templateUrl","provider","this","_defaults","type","ttl","defaults","options","extend","$get","$timeout","$sce","_indexOf","predicate","i","_messages","length","msg","timeout","cancel","add","content","isString","JSON","stringify","html","idx","x","toString","count","trustAsHtml","tickCount","Date","push","splice","clear","config","$provide","decorator","$delegate","$injector","exception","cause","get","ex","console","log","factory","$q","interceptor","rejection","status","statusText","reject","requestError","responseError","$httpProvider","interceptors","run","$templateCache","put"],"mappings":";;;;;CAKA,SAAUA,GAEV,GAAIC,GAASD,EAAQE,OAAO,YAG5BD,GAAOE,WAAW,cAAe,SAAU,SAAU,SAASC,EAAQH,GAEpEG,EAAOC,SAAWJ,EAAOI,WACzBD,EAAOE,OAASL,EAAOK,OACvBF,EAAOG,cAAgBN,EAAOM,cAC9BH,EAAOI,WAAaP,EAAOO,cAI7BP,EAAOQ,UAAU,SAAU,WACzB,OACEC,SAAU,KACVC,YAAa,mCACbR,WAAY,gBAGhBF,EAAOW,SAAS,SAAU,WAExB,GAAIA,GAAWC,IAEfA,MAAKC,WACHC,KAAM,UACNC,IAAK,KAGPH,KAAKI,SAAW,SAAUC,GAExB,MADAN,GAASE,UAAYd,EAAQmB,OAAOP,EAASE,UAAWI,OACjDN,EAASE,WAIlBD,KAAKO,MAAQ,WAAY,OAAQ,SAAUC,EAAUC,GAInD,QAASC,GAASC,GAGhB,IAFA,GAAIC,GAAIC,EAAUC,OAEXF,KACL,GAAID,EAAUE,EAAUD,IACtB,MAAOA,EAIX,OAAO,GAGT,QAASlB,GAAcqB,GACjBA,EAAIC,UACNR,EAASS,OAAOF,EAAIC,eACbD,GAAIC,SAIf,QAASrB,GAAWoB,GAElBrB,EAAcqB,GAEVA,EAAIZ,IAAM,IACZY,EAAIC,QAAUR,EAAS,WACrBf,EAAOsB,IACNA,EAAIZ,MAIX,QAASe,GAAIC,EAASd,GAEpB,GAAIU,GAAM5B,EAAQmB,UAAWP,EAASE,UAAWI,EAE7ClB,GAAQiC,SAASD,KACnBA,EAAU,cAAgBE,KAAKC,UAAUH,EAAS,KAAM,MAAQ,gBAChEJ,EAAIQ,MAAO,EAGb,IAAIC,GAAMd,EAAS,SAAUe,GAC3B,MAAOA,GAAEN,QAAQO,aAAeP,GAAWM,EAAEvB,MAAQa,EAAIb,MAwB3D,OArBIsB,IAAO,GAETT,EAAMF,EAAUW,GAChBT,EAAIY,OAAS,IAIbZ,EAAII,QAAUA,EAEXJ,EAAIQ,OACLR,EAAII,QAAUV,EAAKmB,YAAYT,IAGjCJ,EAAIc,WAAa,GAAIC,MACrBf,EAAIY,MAAQ,EAEZd,EAAUkB,KAAKhB,IAGjBpB,EAAWoB,GAEJA,EAGT,QAAStB,GAAOsB,GAEd,GAAIS,GAAMd,EAAS,SAAUe,GAC3B,MAAOA,KAAMV,GAGXS,IAAO,IACTX,EAAUmB,OAAOR,EAAK,GACtB9B,EAAcqB,IAIlB,QAASkB,KACPpB,EAAUC,OAAS,EAlFrB,GAAID,KAqFJ,QACErB,SAAU,WACR,MAAOqB,IAETK,IAAKA,EACLzB,OAAQA,EACRwC,MAAOA,EACPvC,cAAeA,EACfC,WAAYA,OAMlBR,EAAQE,OAAO,oBAAqB,WACjC6C,QAAQ,WAAY,SAASC,GAC5BA,EAASC,UAAU,qBAAsB,YAAa,YAAY,SAASC,EAAWC,GAEpF,GAAIlD,EAEJ,OAAO,UAASmD,EAAWC,GACzB,IACEpD,EAASA,GAAUkD,EAAUG,IAAI,UACjCrD,EAAO8B,IAAIqB,EAAUb,YAAcxB,KAAM,SAAUC,IAAK,IACxD,MAAMuC,GACNC,QAAQC,IAAI,oBAAqBF,GAEnCL,EAAUE,EAAWC,UAK7BrD,EAAQE,OAAO,yBAA0B,WAEtCwD,QAAQ,yBAA0B,KAAM,SAAU,SAAUC,EAAI1D,GAE/D,QAAS2D,GAAYC,GACnB,IACE,GAAIjC,GAAM,kBAAoBiC,EAAUC,OAAS,MAAQD,EAAUE,UACnE9D,GAAO8B,IAAIH,GAAOb,KAAM,SAAUC,IAAK,IACvC,MAAMuC,GACNC,QAAQC,IAAI,gBAAiBF,GAG/B,MAAOI,GAAGK,OAAOH,GAGnB,OACEI,aAAcL,EACdM,cAAeN,MAKlBb,QAAQ,gBAAiB,SAAUoB,GAClCA,EAAcC,aAAaxB,KAAK,4BAMpC5C,EAAQE,OAAO,UAAUmE,KAAK,iBAAkB,SAASC,GACvDA,EAAeC,IAAI,mCAAoC,+lBAEtDvE","file":"angular-inform.min.js","sourceRoot":"./"}
--------------------------------------------------------------------------------
/gulp-tasks/bower-task.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | // - - - - 8-< - - - - - - - - - - - - - - - - - - -
4 |
5 | var path = require('path');
6 | var clean = require('gulp-clean');
7 |
8 | // - - - - 8-< - - - - - - - - - - - - - - - - - - -
9 |
10 | var bower = require('./lib/gulp-bower-power.js');
11 | var config = require('../build-config.js');
12 |
13 | // - - - - 8-< - - - - - - - - - - - - - - - - - - -
14 |
15 | module.exports = function(gulp) {
16 | gulp.task('bower-clean', function () {
17 |
18 | return gulp.src(path.join(config.folders.dest, 'vendor'), { read: false })
19 | .pipe(clean({ force: true }));
20 |
21 | });
22 |
23 | gulp.task('bower', ['bower-clean'], function () {
24 |
25 | return bower.src(gulp, { env: config.env, includeDev: config.bower && config.bower.includeDev })
26 | .pipe(gulp.dest(path.join(config.folders.dest, 'vendor')));
27 |
28 | });
29 | };
30 |
31 | // - - - - 8-< - - - - - - - - - - - - - - - - - - -
32 |
--------------------------------------------------------------------------------
/gulp-tasks/index-task.js:
--------------------------------------------------------------------------------
1 | // - - - - 8-< - - - - - - - - - - - - - - - - - - -
2 |
3 | var config = require('../build-config.js');
4 | var modify = require('./lib/gulp-modify-content.js');
5 | var pkg = require('../package.json');
6 | var _ = require('lodash');
7 | var path = require('path');
8 | var fs = require('fs');
9 |
10 | // - - - - 8-< - - - - - - - - - - - - - - - - - - -
11 |
12 | module.exports = function (gulp) {
13 |
14 | gulp.task('index', ['modules'], function () {
15 |
16 | return gulp.src('index.html', {
17 | cwd: config.folders.src
18 | }).pipe(modify(function (content) {
19 |
20 | var css = [], js = [];
21 |
22 | var ext = config.env === 'production' ? '.min' : '';
23 |
24 | _.forEach(config.modules, function (module) {
25 |
26 | var moduleBase = module.name + '/' + module.name + ext;
27 | var moduleCss = moduleBase + '.css';
28 | var moduleJs = moduleBase + '.js';
29 |
30 | if(fs.existsSync(path.join(config.folders.dest, moduleCss))) {
31 | css.push(module.name + '/' + module.name + ext + '.css');
32 | }
33 |
34 | if(fs.existsSync(path.join(config.folders.dest, moduleJs))) {
35 | js.push(module.name + '/' + module.name + ext + '.js');
36 | }
37 | });
38 |
39 | return _.template(content, {
40 | pkg: pkg, css: css, js: js
41 | });
42 |
43 | })).pipe(gulp.dest(config.folders.dest));
44 |
45 | });
46 | };
47 |
48 | // - - - - 8-< - - - - - - - - - - - - - - - - - - -
49 |
--------------------------------------------------------------------------------
/gulp-tasks/lib/gulp-autoprefixer-map.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | /*
4 | Hack to enable source maps in with gulp-sourcemaps and autoprefixer.
5 |
6 | Created by null on 12/08/14.
7 |
8 | npm --save-dev install through2
9 | npm --save-dev install autoprefixer
10 | npm --save-dev install vinyl-sourcemaps-apply
11 |
12 | var prefixer = require('./gulp-autoprefixer-map.js');
13 |
14 | gulp.task('css', [], function() {
15 | .pipe(sourcemaps.init())
16 | .pipe(prefixer())
17 | .pipe(sourcemaps.write('.'))
18 | });
19 |
20 | */
21 |
22 | var through = require('through2');
23 | var prefix = require('autoprefixer');
24 | //var applySourceMap = require('vinyl-sourcemaps-apply');
25 |
26 | module.exports = function(browsers, options) {
27 |
28 | options = options || {};
29 |
30 | return through.obj(function(file, enc, cb) {
31 |
32 | if(file.isStream()) {
33 | throw new Error('Streams not supported');
34 | }
35 |
36 | if(!file.isNull()) {
37 |
38 | if(file.sourceMap) {
39 | options.map = {
40 | prev: file.sourceMap.mappings ? file.sourceMap : undefined,
41 | annotation: false,
42 | sourcesContent: true
43 | };
44 | options.to = options.from = file.relative;
45 | }
46 |
47 | var contents = file.contents.toString();
48 |
49 | var result = prefix.apply(this, browsers).process(contents, options);
50 | contents = result.css;
51 |
52 | file.contents = new Buffer(contents);
53 |
54 | if(file.sourceMap) {
55 | var map = JSON.parse(result.map.toString());
56 |
57 | map.sources = file.sourceMap.sources;
58 | map.file = file.sourceMap.file;
59 |
60 | file.sourceMap = map;
61 |
62 | //applySourceMap(file, map);
63 | }
64 | }
65 |
66 | this.push(file);
67 | cb();
68 |
69 | });
70 |
71 | };
72 |
--------------------------------------------------------------------------------
/gulp-tasks/lib/gulp-bower-power.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var path = require('path');
4 | var fs = require('fs');
5 |
6 | var mainBowerFiles = require('main-bower-files');
7 |
8 | module.exports = {
9 | src: src
10 | };
11 |
12 | function src(gulp, options) {
13 |
14 | options = options || {};
15 |
16 | // Grab globs from main-bower-files module.
17 | // This sorts out the dependencies.
18 |
19 | var globs = mainBowerFiles(options);
20 |
21 | for(var i = 0; i < globs.length; i++) {
22 |
23 | var glob = globs[i];
24 |
25 | var ext = path.extname(glob);
26 |
27 | // Check if the extension is JS or css
28 | if(ext === '.js' || ext === '.css') {
29 |
30 | if(glob.indexOf('.min') == -1) {
31 | // Add the minified version file name to the list
32 | var dirname = path.dirname(glob);
33 | var basename = path.basename(glob);
34 |
35 | var minified = basename.split('.');
36 | minified.splice(minified.length - 1, 0, 'min');
37 | minified = minified.join('.');
38 | minified = path.join(dirname, minified);
39 |
40 | i += 1;
41 | globs.splice(i, 0, minified);
42 |
43 | // Add the source map file name for the minified version
44 |
45 | i += 1;
46 | globs.splice(i, 0, minified + '.map');
47 | }
48 |
49 | // Add the source map file name for the unminified version
50 |
51 | i += 1;
52 | globs.splice(i, 0, glob + '.map');
53 |
54 | }
55 | }
56 |
57 | return gulp.src(globs, options);
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/gulp-tasks/lib/gulp-csswring.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var through = require('through2');
4 | var csswring = require('csswring');
5 | var applySourceMap = require('vinyl-sourcemaps-apply');
6 |
7 | module.exports = function(options) {
8 |
9 | options = options || {};
10 |
11 | return through.obj(function(file, enc, cb) {
12 |
13 | if(file.isStream()) {
14 | throw new Error('Streams are not supported.');
15 | }
16 |
17 | if (!file.isNull()) {
18 |
19 | if(file.sourceMap) {
20 | options.map = {
21 | prev: file.sourceMap.mappings ? file.sourceMap : undefined,
22 | annotation: false,
23 | sourcesContent: true
24 | };
25 | options.from =
26 | options.to = file.relative;
27 | }
28 |
29 | var contents = file.contents.toString();
30 |
31 | var result = csswring().wring(contents, options);
32 |
33 | file.contents = new Buffer(result.css);
34 |
35 | if(file.sourceMap) {
36 | var map = JSON.parse(result.map.toString());
37 |
38 | map.sources = file.sourceMap.sources;
39 | map.file = file.sourceMap.file;
40 |
41 | // applySourceMap(file, map);
42 | file.sourceMap = map;
43 | }
44 | }
45 |
46 | this.push(file);
47 | cb();
48 |
49 | });
50 | };
--------------------------------------------------------------------------------
/gulp-tasks/lib/gulp-mini-filter.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var through = require('through2');
4 |
5 | module.exports = function filter(fn) {
6 | return through.obj(function(file, enc, cb) {
7 |
8 | if(fn(file)) {
9 | this.push(file);
10 | }
11 |
12 | cb();
13 | });
14 | };
--------------------------------------------------------------------------------
/gulp-tasks/lib/gulp-modify-content.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | var through = require('through2');
4 |
5 | module.exports = function modify(modifiers) {
6 |
7 | return through.obj(function(file, encoding, done) {
8 |
9 | var stream = this;
10 |
11 | function applyModifiers(content) {
12 | (typeof modifiers === 'function' ? [modifiers] : modifiers).forEach(function(modifier) {
13 | content = modifier(content, file);
14 | });
15 | return content;
16 | }
17 |
18 | function write(data) {
19 | file.contents = new Buffer(data);
20 | stream.push(file);
21 | return done();
22 | }
23 |
24 | if (file.isBuffer()) {
25 | return write(applyModifiers(String(file.contents)));
26 | } else if (file.isStream()) {
27 | var buffer = '';
28 | file.contents.on('data', function(chunk) {
29 | buffer += chunk;
30 | });
31 | file.contents.on('end', function() {
32 | write(applyModifiers(String(buffer)));
33 | });
34 | }
35 | });
36 | };
--------------------------------------------------------------------------------
/gulp-tasks/lib/gulp-rename-filename.js:
--------------------------------------------------------------------------------
1 |
2 | var path = require('path');
3 | var through = require('through2');
4 |
5 | function rename(filename) {
6 | return through.obj(function(file, enc, cb) {
7 |
8 | file.path = path.join(file.base, filename);
9 |
10 | if(file.sourceMap) {
11 | file.sourceMap.file = file.relative;
12 | }
13 |
14 | this.push(file);
15 | cb();
16 | });
17 | }
18 |
19 | module.exports = rename;
--------------------------------------------------------------------------------
/gulp-tasks/lib/gulp-wrap-src.js:
--------------------------------------------------------------------------------
1 | var File = require('vinyl');
2 | var through = require('through2');
3 |
4 | // options = {
5 | // header: {
6 | // contents: '/* my header */',
7 | // path: 'my-virtual-header.js'
8 | // } || '/* my header */,
9 | // footer: {
10 | // contents: '/* my footer */',
11 | // path: 'my-virtual-footer.js'
12 | // } || '/* my footer */
13 | // };
14 |
15 | module.exports = function (options) {
16 |
17 | var pushedHeader = false;
18 |
19 | function pushHeader(file, enc, cb) {
20 |
21 | if (!pushedHeader) {
22 | pushedHeader = true;
23 |
24 | if (typeof(options.header) == 'string') {
25 | options.header = {
26 | contents: options.header
27 | };
28 | }
29 |
30 | if (options.header.contents === undefined) {
31 | throw new Error('No header content provided.');
32 | }
33 |
34 | var headerFile = new File({
35 | path: options.header.path || 'header',
36 | contents: new Buffer(options.header.contents)
37 | });
38 |
39 | this.push(headerFile);
40 | }
41 |
42 | this.push(file);
43 | cb();
44 |
45 | }
46 |
47 | function pass(file, enc, cb) {
48 | this.push(file);
49 | cb();
50 | }
51 |
52 | function pushFooter(cb) {
53 |
54 | if (typeof(options.footer) == 'string') {
55 | options.footer = {
56 | contents: options.footer
57 | };
58 | }
59 |
60 | if (options.header.contents === undefined) {
61 | throw new Error('No header content provided.');
62 | }
63 |
64 | var footerFile = new File({
65 | path: options.footer.path || 'footer',
66 | contents: new Buffer(options.footer.contents)
67 | });
68 |
69 | this.push(footerFile);
70 |
71 | cb();
72 | }
73 |
74 | return through.obj(
75 | options.header ? pushHeader : pass,
76 | options.footer ? pushFooter : undefined
77 | );
78 | };
--------------------------------------------------------------------------------
/gulp-tasks/lib/ng-xml.js:
--------------------------------------------------------------------------------
1 | // Optimised version of https://github.com/fraserxu/gulp-html2js
2 |
3 | var path = require('path');
4 | var through = require('through2');
5 | var File = require('vinyl');
6 |
7 | var bsRegexp = new RegExp('\\\\', 'g');
8 | var quoteRegexp = new RegExp('\\\"', 'g');
9 | var nlReplace = '\\n\'' + ' +\n \'';
10 |
11 | function escape(content) {
12 | return content
13 | .replace(bsRegexp, '\\\\')
14 | .replace(quoteRegexp, '\\\"')
15 | .replace(/'/g, '\\\'')
16 | .replace(/\r?\n/g, nlReplace);
17 | }
18 |
19 | function templateCache(content, key) {
20 | return '$templateCache.put(\'' + key + '\', \'' + escape(content) + '\');'
21 | }
22 |
23 | function ensureSlashPath(p) {
24 | if (path.sep !== '/') {
25 | p = p.replace(/\\/g, '/')
26 | }
27 | return p;
28 | }
29 |
30 | /*
31 | options.base: base filepath of the template. This value is used as cache key.
32 | options.moduleName: the name of the module where to inject the templates.
33 | options.filename: [optional] target filename of the result.
34 | */
35 |
36 | module.exports = function (options) {
37 |
38 | var buffer = [];
39 |
40 | function transform(file, encoding, callback) {
41 |
42 | var key = ensureSlashPath(path.relative(options.base, file.path));
43 | var contents = templateCache(file.contents.toString(), key);
44 |
45 | buffer.push(' ' + contents);
46 | callback();
47 |
48 | }
49 |
50 | function flush(callback) {
51 |
52 | var contents = 'angular.module(\'' + options.moduleName + '\').run([\'$templateCache\', function($templateCache){\n' +
53 | buffer.join('\n') + '\n}]);';
54 |
55 |
56 | var file = new File({
57 | path: options.filename || options.moduleName + '-templates.js',
58 | contents: new Buffer(contents)
59 | });
60 |
61 | this.push(file);
62 |
63 | return callback();
64 | }
65 |
66 | return through.obj(transform, flush);
67 | };
68 |
69 |
--------------------------------------------------------------------------------
/gulp-tasks/module-tasks/clean-task.js:
--------------------------------------------------------------------------------
1 |
2 | var clean = require('gulp-clean');
3 |
4 | module.exports = function(gulp, module) {
5 |
6 | module.task('clean', function () {
7 |
8 | return gulp.src(module.folders.dest, { read: false })
9 | .pipe(clean({ force: true }));
10 |
11 | });
12 |
13 |
14 | };
--------------------------------------------------------------------------------
/gulp-tasks/module-tasks/copy-task.js:
--------------------------------------------------------------------------------
1 |
2 | var path = require('path');
3 | var filter = require('../lib/gulp-mini-filter.js');
4 |
5 | module.exports = function(gulp, module) {
6 |
7 | module.task('copy', ['scripts', 'styles', 'svg'], function () {
8 |
9 | var glob = [
10 | path.join(module.folders.src, '/**/*'),
11 | '!**/*.test.js',
12 | '!**/*.ignore.*'
13 | ];
14 |
15 | module.touched.forEach(function (filename) {
16 | glob.push('!' + filename);
17 | });
18 |
19 | return gulp.src(glob)
20 | .pipe(filter(function(file) {
21 | // Only copy files -- don't copy empty directories
22 | return file.stat.isFile();
23 | }))
24 | .pipe(gulp.dest(module.folders.dest));
25 |
26 | });
27 |
28 | };
29 |
30 |
--------------------------------------------------------------------------------
/gulp-tasks/module-tasks/scripts-task.js:
--------------------------------------------------------------------------------
1 | var sourcemaps = require('gulp-sourcemaps');
2 | var concat = require('gulp-concat');
3 | var ngAnnotate = require('gulp-ng-annotate');
4 | var uglify = require('gulp-uglify');
5 | var path = require('path');
6 |
7 | var wrap = require('../lib/gulp-wrap-src.js');
8 | var config = require('../../build-config.js');
9 | var rename = require('../lib/gulp-rename-filename.js');
10 | var filter = require('../lib/gulp-mini-filter.js');
11 |
12 | module.exports = function (gulp, module) {
13 |
14 | module.task('scripts', ['clean', 'templates'], function () {
15 |
16 | // At the moment of writing, generating and consuming source maps isn't optimal. Compile tools merge previous
17 | // maps incorrectly, browsers aren't 100% certain about breakpoint locations and are unable to unmangle
18 | // argument names. The most stable seems to be to uglify and map in two stages:
19 |
20 | // 1. concat all js in one file and persist to the filesystem
21 | // 2. uglify the previous file and point point the content of the source map to the original file.
22 |
23 | var jsGlob = [
24 | path.join(module.folders.src, module.name + '.js'),
25 | path.join(module.folders.src, '**/*.js'),
26 | path.join(module.folders.dest, module.name + '-templates.js'),
27 | '!**/*.test.js',
28 | '!**/*.ignore.js'
29 | ];
30 |
31 | return gulp.src(jsGlob)
32 | .pipe(module.touch())
33 | .pipe(wrap({
34 | header: {
35 | path: module.name + '-header.js',
36 | contents: config.header + '(function(angular) {\n'
37 | },
38 | footer: {
39 | path: module.name + '-footer.js',
40 | contents: '})(angular);'
41 | }
42 | }))
43 | .pipe(sourcemaps.init())
44 | .pipe(concat(module.name + '.js'))
45 | .pipe(ngAnnotate())
46 | .pipe(sourcemaps.write('.', { sourceRoot: '../src/' + module.name }))
47 | .pipe(gulp.dest(module.folders.dest))
48 |
49 | // Create the minified version
50 |
51 | .pipe(sourcemaps.init())
52 | .pipe(filter(function(file) {
53 |
54 | // Filter out the previous map file.
55 | return path.extname(file.path) != '.map';
56 |
57 | }))
58 | .pipe(rename(module.name + '.min.js'))
59 | .pipe(uglify({ preserveComments: 'some' }))
60 | .pipe(sourcemaps.write('.', { includeContent: false, sourceRoot: './' }))
61 | .pipe(gulp.dest(module.folders.dest));
62 | }
63 | );
64 | };
65 |
66 |
--------------------------------------------------------------------------------
/gulp-tasks/module-tasks/styles-task.js:
--------------------------------------------------------------------------------
1 | var sourcemaps = require('gulp-sourcemaps');
2 | var concat = require('gulp-concat');
3 | var minifyCss = require('gulp-minify-css');
4 | var path = require('path');
5 |
6 | var config = require('../../build-config.js');
7 |
8 | var prefixer = require('../lib/gulp-autoprefixer-map.js');
9 | var rename = require('../lib/gulp-rename-filename.js');
10 | var filter = require('../lib/gulp-mini-filter.js');
11 | var wrapper = require('../lib/gulp-wrap-src');
12 |
13 | module.exports = function (gulp, module) {
14 |
15 | module.task('styles', 'clean', function () {
16 |
17 | var cssGlob = [
18 | path.join(module.folders.src, module.name + '.css'),
19 | path.join(module.folders.src, '**/*.css'),
20 | '!**/*.ignore.css'
21 | ];
22 |
23 | // Gulp plugins with support for sourcemaps with css are minimal and buggy.
24 | // I couldn't get any minifier to output a valid sourcemap in all situations.
25 | // The task here generates two stylesheets.
26 | //
27 | // 1. unminified + concat + autoprefixed + sourcemaps
28 | // 2. minified
29 | //
30 | // The minified version is based on the output generated by the 1st but does
31 | // not have a sourcemap associated with it.
32 |
33 | return gulp.src(cssGlob)
34 |
35 | .pipe(wrapper({
36 | header: {
37 | path: module.name + '-header.css',
38 | contents: config.header
39 | }
40 | }))
41 |
42 | // Generate the unminified stylesheet
43 |
44 | .pipe(module.touch())
45 | .pipe(sourcemaps.init())
46 | .pipe(concat(module.name + '.css'))
47 | .pipe(prefixer(['last 2 versions', '> 1%', 'ie 8']))
48 | .pipe(sourcemaps.write('.', { sourceRoot: '../src/' + module.name }))
49 | .pipe(gulp.dest(module.folders.dest))
50 |
51 | // Generate the minified stylesheet
52 |
53 | .pipe(filter(function (file) {
54 |
55 | // delete the previous generated sourcemap so we don't trigger
56 | // sourcemap merging in csswring.
57 |
58 | delete file.sourceMap;
59 |
60 | // Filter out the previous map file.
61 |
62 | return path.extname(file.path) != '.map';
63 |
64 | }))
65 | .pipe(minifyCss({ keepSpecialComments: 1 }))
66 | .pipe(rename(module.name + '.min.css'))
67 | .pipe(gulp.dest(module.folders.dest));
68 |
69 | });
70 |
71 | };
72 |
--------------------------------------------------------------------------------
/gulp-tasks/module-tasks/svg-task.js:
--------------------------------------------------------------------------------
1 |
2 | var svgmin = require('gulp-svgmin');
3 | var path = require('path');
4 |
5 | module.exports = function(gulp, module) {
6 | module.task('svg', 'clean', function () {
7 |
8 | var glob = [
9 | path.join(module.folders.src, '/**/*.svg'),
10 | '!**/*.ng.svg',
11 | '!**/*.ignore.svg'
12 | ];
13 |
14 | return gulp.src(glob)
15 | .pipe(module.touch())
16 | .pipe(svgmin())
17 | .pipe(gulp.dest(module.folders.dest));
18 |
19 | });
20 |
21 | };
22 |
23 |
--------------------------------------------------------------------------------
/gulp-tasks/module-tasks/templates-task.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 | /**
3 | * Created by null on 11/08/14.
4 | */
5 |
6 | var minifyHtml = require('gulp-minify-html');
7 | var svgmin = require('gulp-svgmin');
8 | var merge = require('merge-stream');
9 |
10 | var path = require('path');
11 |
12 | var ngXml = require('../lib/ng-xml.js');
13 | var modify = require('../lib/gulp-modify-content.js');
14 | var config = require('../../build-config.js');
15 |
16 | module.exports = function(gulp, module) {
17 |
18 | module.task('templates', 'clean', function () {
19 |
20 | var ngHtmlGlob = [
21 | path.join(module.folders.src, '**/*.ng.html'),
22 | '!**/*.ignore.ng.html'
23 | ];
24 |
25 | var ngHtmlStream = gulp.src(ngHtmlGlob)
26 | .pipe(module.touch())
27 | .pipe(minifyHtml({
28 | empty: true,
29 | spare: true,
30 | quotes: true
31 | }));
32 |
33 | var ngSvgGlob = [
34 | path.join(module.folders.src, '/**/*.ng.svg'),
35 | '!**/*.ignore.ng.svg'
36 | ];
37 |
38 | var ngSvgStream = gulp.src(ngSvgGlob)
39 | .pipe(module.touch())
40 | .pipe(svgmin());
41 |
42 | return merge(ngHtmlStream, ngSvgStream)
43 | .pipe(ngXml({
44 | moduleName: module.alias || module.name,
45 | base: config.folders.src,
46 | filename: module.name + '-templates.js'
47 | }))
48 | .pipe(modify(function(contents) {
49 | return [
50 | '// Automatically generated.',
51 | '// This file is already embedded in your main javascript output, there\'s no need to include this file',
52 | '// manually in the index.html. This file is only here for your debugging pleasures.',
53 | ''
54 | ].join('\n') + contents;
55 | }))
56 | .pipe(gulp.dest(module.folders.dest));
57 |
58 | });
59 |
60 | };
61 |
62 |
--------------------------------------------------------------------------------
/gulp-tasks/modules-task.js:
--------------------------------------------------------------------------------
1 | var path = require('path');
2 | var through = require('through2');
3 | var config = require('../build-config.js');
4 |
5 | module.exports = function (gulp) {
6 |
7 | var moduleTasks = [];
8 |
9 | for (var i = 0; i < config.modules.length; i++) (function (module) {
10 |
11 | moduleTasks.push(module.name);
12 |
13 | module.folders = {
14 | src: path.join(config.folders.src, module.name),
15 | dest: path.join(config.folders.dest, module.name)
16 | };
17 |
18 | // We'll track the tasks that are created for this module so that we can one gulp task that is dependent on this list.
19 |
20 | module.tasks = [];
21 | module.task = moduleTask;
22 |
23 | // Filenames of every file we'll process in some way is kept in this array. Everything not touched is copied to the
24 | // destination directory at the end (copy-task).
25 |
26 | module.touched = [];
27 | module.touch = moduleTouchFile;
28 |
29 | // Register all tasks for the current module.
30 |
31 | require('./module-tasks/clean-task.js')(gulp, module);
32 | require('./module-tasks/styles-task.js')(gulp, module);
33 | require('./module-tasks/templates-task.js')(gulp, module);
34 | require('./module-tasks/scripts-task.js')(gulp, module);
35 | require('./module-tasks/svg-task.js')(gulp, module);
36 | require('./module-tasks/copy-task.js')(gulp, module);
37 |
38 | // Register a task for this module that is dependent on all sub tasks.
39 |
40 | gulp.task(module.name, module.tasks);
41 |
42 | })(config.modules[i]);
43 |
44 | // Register the main task that is dependent on all module tasks
45 |
46 | gulp.task('modules', moduleTasks);
47 |
48 | // - - - - - - - 8-< - - - - - - - - - - - - - - - - - - - -
49 |
50 | function moduleTask(taskname, depsOrFn, fn) {
51 |
52 | var module = this;
53 |
54 | if (typeof(depsOrFn) == 'string') {
55 | depsOrFn = [depsOrFn];
56 | }
57 |
58 | if (Array.isArray(depsOrFn)) {
59 |
60 | var map = [];
61 |
62 | depsOrFn.forEach(function (dep) {
63 | map.push(module.name + '-' + dep);
64 | });
65 |
66 | depsOrFn = map;
67 |
68 | }
69 |
70 | var fulltaskname = module.name + '-' + taskname;
71 | gulp.task(fulltaskname, depsOrFn, fn);
72 | module.tasks.push(fulltaskname);
73 |
74 | }
75 |
76 | // - - - - - - - 8-< - - - - - - - - - - - - - - - - - - - -
77 |
78 | function moduleTouchFile() {
79 |
80 | var module = this;
81 |
82 | return through.obj(function (file, enc, callback) {
83 | module.touched.push(file.path);
84 | this.push(file);
85 | return callback();
86 | });
87 |
88 | }
89 |
90 | // - - - - - - - 8-< - - - - - - - - - - - - - - - - - - - -
91 | };
92 |
93 |
--------------------------------------------------------------------------------
/gulp-tasks/visual-studio.targets:
--------------------------------------------------------------------------------
1 |
6 |
7 |
8 | release
9 | debug
10 | c:\program files (x86)\nodejs\node.exe
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env node
2 |
3 | // - - - - 8-< - - - - - - - - - - - - - - - - - - -
4 |
5 | var config = require('./build-config.js');
6 |
7 | // - - - - 8-< - - - - - - - - - - - - - - - - - - -
8 |
9 | var path = require('path');
10 | var gulp = require('gulp');
11 | var clean = require('gulp-clean');
12 | var karma = require('gulp-karma');
13 |
14 | // - - - - 8-< - - - - - - - - - - - - - - - - - - -
15 |
16 | require('./gulp-tasks/bower-task.js')(gulp);
17 | require('./gulp-tasks/modules-task.js')(gulp);
18 | require('./gulp-tasks/index-task.js')(gulp);
19 |
20 | // - - - - 8-< - - - - - - - - - - - - - - - - - - -
21 | // Builds the whole kitchensink including example website
22 |
23 | gulp.task('kitchensink', [ 'modules', 'bower', 'index', 'sandbox' ], function () {
24 |
25 | var path = require('path');
26 |
27 | return gulp.src('README.md')
28 | .pipe(gulp.dest(path.join(config.folders.dest, 'app')));
29 |
30 | });
31 |
32 | // - - - - 8-< - - - - - - - - - - - - - - - - - - -
33 |
34 | gulp.task('sandbox-clean', [ 'modules', 'bower' ], function () {
35 | return gulp.src(path.join(config.folders.dest, 'sandbox'))
36 | .pipe(clean());
37 | });
38 |
39 | gulp.task('sandbox', [ 'sandbox-clean', 'modules', 'bower' ], function () {
40 | return gulp.src(path.join(config.folders.src, 'sandbox/**/*'))
41 | .pipe(gulp.dest(path.join(config.folders.dest, 'sandbox')));
42 | });
43 | //
44 | // - - - - 8-< - - - - - - - - - - - - - - - - - - -
45 |
46 | gulp.task('test-run', ['angular-inform'], function () {
47 |
48 | return gulp.src([
49 | 'bower_components/angular/angular.js',
50 | 'bower_components/angular-mocks/angular-mocks.js',
51 | path.join(config.folders.dest, 'angular-inform/angular-inform.min.js'),
52 | path.join(config.folders.src, 'angular-inform/**/*.test.js')
53 | ])
54 | .pipe(karma({
55 | configFile: 'karma.conf.js',
56 | action: 'run'
57 | })).on('error', function (err) {
58 | throw err;
59 | });
60 |
61 | });
62 |
63 | gulp.task('test-watch', ['angular-inform'], function () {
64 |
65 | gulp.src([
66 | 'bower_components/angular/angular.js',
67 | 'bower_components/angular-mocks/angular-mocks.js',
68 | path.join(config.folders.src, 'angular-inform/angular-inform.js'),
69 | path.join(config.folders.dest, 'angular-inform/angular-inform-templates.js'),
70 | path.join(config.folders.src, 'angular-inform/**/*.js')
71 | ])
72 | .pipe(karma({
73 | configFile: 'karma.conf.js',
74 | action: 'watch'
75 | }));
76 |
77 | });
78 |
79 | // - - - - 8-< - - - - - - - - - - - - - - - - - - -
80 |
81 | gulp.task('dist-clean', ['angular-inform-clean'], function () {
82 |
83 | return gulp.src('dist/**/*', { read: false }).pipe(clean());
84 |
85 | });
86 |
87 | gulp.task('dist', ['dist-clean', 'angular-inform', 'test-run'], function () {
88 |
89 | var destGlob = path.join(config.folders.dest, 'angular-inform/**/*');
90 | return gulp.src([ destGlob, 'README.md', '!**/angular-inform-templates.js' ])
91 | .pipe(gulp.dest('dist'));
92 |
93 | });
94 |
95 | // - - - - 8-< - - - - - - - - - - - - - - - - - - -
96 |
97 | gulp.task('default', [ 'dist' ]);
98 |
99 | // - - - - 8-< - - - - - - - - - - - - - - - - - - -
--------------------------------------------------------------------------------
/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | // Generated on Thu Aug 14 2014 11:05:59 GMT+0200 (CEST)
3 |
4 | module.exports = function(config) {
5 | config.set({
6 |
7 | // base path that will be used to resolve all patterns (eg. files, exclude)
8 | basePath: '',
9 |
10 |
11 | // frameworks to use
12 | // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
13 | frameworks: ['jasmine'],
14 |
15 |
16 | // list of files / patterns to load in the browser
17 | files: [
18 | ],
19 |
20 |
21 | // list of files to exclude
22 | exclude: [
23 | ],
24 |
25 |
26 | // preprocess matching files before serving them to the browser
27 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
28 | preprocessors: {
29 | },
30 |
31 |
32 | // test results reporter to use
33 | // possible values: 'dots', 'progress'
34 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter
35 | reporters: ['dots', 'growl'],
36 |
37 |
38 | // web server port
39 | port: 9876,
40 |
41 |
42 | // enable / disable colors in the output (reporters and logs)
43 | colors: true,
44 |
45 |
46 | // level of logging
47 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
48 | logLevel: config.LOG_INFO,
49 |
50 |
51 | // enable / disable watching file and executing tests whenever any file changes
52 | autoWatch: false,
53 |
54 |
55 | // start these browsers
56 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
57 | browsers: ['PhantomJS'],
58 |
59 |
60 | // Continuous Integration mode
61 | // if true, Karma captures browsers, runs the tests and exits
62 | singleRun: false
63 | });
64 | };
65 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-inform",
3 | "version": "0.0.18",
4 | "description": "A growl-like easy-to-use message toaster for angular.",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "homepage": "https://github.com/McNull/angular-inform",
10 | "author": "(null) McNull",
11 | "license": "MIT",
12 | "dependencies": {},
13 | "devDependencies": {
14 | "gulp-clean": "~0.3.1",
15 | "main-bower-files": "~1.0.2",
16 | "gulp": "~3.8.7",
17 | "through2": "~0.5.1",
18 | "gulp-concat": "~2.3.4",
19 | "gulp-minify-css": "~0.3.7",
20 | "gulp-sourcemaps": "~1.1.1",
21 | "lodash": "~2.4.1",
22 | "gulp-uglify": "~0.3.1",
23 | "gulp-minify-html": "~0.1.4",
24 | "vinyl": "~0.3.2",
25 | "merge-stream": "~0.1.5",
26 | "gulp-svgmin": "~0.4.6",
27 | "gulp-ng-annotate": "~0.3.0",
28 | "autoprefixer": "~2.2.0",
29 | "karma": "~0.12.23",
30 | "gulp-karma": "0.0.4",
31 | "karma-growl-reporter": "~0.1.1",
32 | "karma-jasmine": "~0.1.5",
33 | "karma-phantomjs-launcher": "~0.1.4"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/src/angular-inform/angular-inform.css:
--------------------------------------------------------------------------------
1 |
2 |
3 | .inform-fixed {
4 | position: fixed;
5 | top: 20px;
6 | left: 20px;
7 | right: 20px;
8 | z-index: 1002;
9 | }
10 |
11 | .inform-fixed .inform-message {
12 | width: auto;
13 | }
14 |
15 | @media screen and (min-width: 480px) {
16 | .inform-fixed {
17 | left: auto;
18 | width: 440px;
19 | }
20 |
21 | .inform-fixed.inform-center {
22 | right: 0;
23 | left: 0;
24 | margin-left: auto;
25 | margin-right: auto;
26 | }
27 | }
28 |
29 | .inform-message {
30 | overflow: hidden;
31 | }
32 |
33 | .inform-message > button.close {
34 | margin-left: 15px;
35 | }
36 |
37 | .inform-shadow .inform-message {
38 | box-shadow: 0px 5px 20px 0px rgba(0, 0, 0, 0.25);
39 | }
40 |
41 | .inform-message.alert-primary {
42 | color: #FFF;
43 | background-color: #428BCA;
44 | }
45 |
46 | .inform-message.alert-default {
47 | background-color: #F5F5F5;
48 | border: 1px solid #CCC;
49 | color: #333;
50 | }
51 |
52 |
53 | .inform-message-wrap {
54 | /*overflow: hidden;*/
55 | }
56 | .inform-animate .inform-message-wrap.ng-enter {
57 | animation: 1.0s inform-message-slide-in;
58 | }
59 |
60 | .inform-animate .inform-message-wrap.ng-leave {
61 | animation: 1.0s inform-message-fade-out;
62 | }
63 |
64 | .inform-animate .inform-badge.ng-enter {
65 | animation: inform-badge-scale 0.5s;
66 | }
67 |
68 | @keyframes inform-badge-scale {
69 | 0% {
70 | opacity: 0;
71 | transform: scale(0);
72 | }
73 | 25% {
74 | opacity: 1;
75 | transform: scale(1.5);
76 | }
77 | 100% {
78 | opacity: 1;
79 | transform: scale(1);
80 | }
81 | }
82 |
83 | @keyframes inform-message-slide-in {
84 | 0% {
85 | opacity: 0;
86 | transform: translateX(100%);
87 | max-height: 0px;
88 | }
89 | 50% {
90 | opacity: 0;
91 | transform: translateX(100%);
92 | max-height: 1000px;
93 | }
94 | 100% {
95 | opacity: 1;
96 | transform: translateX(0%);
97 | max-height: 1000px;
98 | }
99 | }
100 |
101 | @keyframes inform-message-fade-out {
102 | 0% {
103 | opacity: 1;
104 | max-height: 1000px;
105 | }
106 | 50% {
107 | opacity: 0;
108 | max-height: 1000px;
109 | }
110 | 100% {
111 | opacity: 0;
112 | max-height: 0px;
113 | }
114 | }
--------------------------------------------------------------------------------
/src/angular-inform/angular-inform.js:
--------------------------------------------------------------------------------
1 | var inform = angular.module('inform', []);
2 |
3 |
--------------------------------------------------------------------------------
/src/angular-inform/controller.js:
--------------------------------------------------------------------------------
1 | inform.controller('InformCtrl', function($scope, inform) {
2 |
3 | $scope.messages = inform.messages();
4 | $scope.remove = inform.remove;
5 | $scope.cancelTimeout = inform.cancelTimeout;
6 | $scope.setTimeout = inform.setTimeout;
7 |
8 | });
9 |
--------------------------------------------------------------------------------
/src/angular-inform/directive.js:
--------------------------------------------------------------------------------
1 | inform.directive('inform', function () {
2 | return {
3 | restrict: 'AE',
4 | templateUrl: 'angular-inform/directive.ng.html',
5 | controller: 'InformCtrl'
6 | };
7 | });
--------------------------------------------------------------------------------
/src/angular-inform/directive.ng.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/angular-inform/exception/exception.js:
--------------------------------------------------------------------------------
1 |
2 | angular.module('inform-exception', ['inform'])
3 | .config(function($provide) {
4 | $provide.decorator('$exceptionHandler', ['$delegate', '$injector',function($delegate, $injector) {
5 |
6 | var inform;
7 |
8 | return function(exception, cause) {
9 | try {
10 | inform = inform || $injector.get('inform');
11 | inform.add(exception.toString(), { type: 'danger', ttl: 0 });
12 | } catch(ex) {
13 | console.log('$exceptionHandler', ex);
14 | }
15 | $delegate(exception, cause);
16 | };
17 | }]);
18 | });
19 |
--------------------------------------------------------------------------------
/src/angular-inform/exception/exception.test.js:
--------------------------------------------------------------------------------
1 | describe('angular-inform', function () {
2 |
3 | describe('exception', function() {
4 |
5 | var inform, $exceptionHandler;
6 |
7 | beforeEach(function() {
8 |
9 | module('inform-exception');
10 |
11 | inject(function(_inform_, _$exceptionHandler_) {
12 |
13 | inform = _inform_;
14 | $exceptionHandler = _$exceptionHandler_;
15 |
16 | });
17 |
18 | });
19 |
20 | it('should add an error message if a unhandled exception has occured', function() {
21 |
22 | expect(inform.messages().length).toBe(0);
23 |
24 | var error = new Error('This is a baddass error!');
25 |
26 | try {
27 | $exceptionHandler(error);
28 | }
29 | catch(e) {
30 | if(e !== error) {
31 | throw e;
32 | }
33 | }
34 | finally {
35 | expect(inform.messages().length).toBe(1);
36 | expect(inform.messages()[0].content).toBe(error.toString());
37 | }
38 | });
39 | });
40 |
41 | });
42 |
--------------------------------------------------------------------------------
/src/angular-inform/exception/http.js:
--------------------------------------------------------------------------------
1 | angular.module('inform-http-exception', ['inform'])
2 |
3 | .factory('informHttpInterceptor', function ($q, inform) {
4 |
5 | function interceptor(rejection) {
6 | try {
7 | var msg = 'Network error (' + rejection.status + '): ' + rejection.statusText;
8 | inform.add(msg, { type: 'danger', ttl: 0});
9 | } catch(ex) {
10 | console.log('$httpProvider', ex);
11 | }
12 |
13 | return $q.reject(rejection);
14 | }
15 |
16 | return {
17 | requestError: interceptor,
18 | responseError: interceptor
19 | };
20 |
21 | })
22 |
23 | .config(function ($httpProvider) {
24 | $httpProvider.interceptors.push('informHttpInterceptor');
25 | });
26 |
--------------------------------------------------------------------------------
/src/angular-inform/exception/http.test.js:
--------------------------------------------------------------------------------
1 | describe('angular-inform', function () {
2 |
3 | describe('informHttpInterceptor', function() {
4 |
5 | var inform, informHttpInterceptor;
6 |
7 | beforeEach(function() {
8 |
9 | module('inform-http-exception');
10 |
11 | inject(function(_inform_, _informHttpInterceptor_) {
12 |
13 | inform = _inform_;
14 | informHttpInterceptor = _informHttpInterceptor_;
15 |
16 | });
17 |
18 | });
19 |
20 | it('should have the same methods for response and request', function() {
21 | // Just to safeguard the tests ... if this fails we'll need to test both functions.
22 | expect(informHttpInterceptor.responseError).toBe(informHttpInterceptor.requestError);
23 | });
24 |
25 | it('should add an error message if a http exception has occured', function() {
26 |
27 | expect(inform.messages().length).toBe(0);
28 |
29 | var rejection = {
30 | status: 123,
31 | statusText: 'This is bad!'
32 | };
33 |
34 | try {
35 | informHttpInterceptor.responseError(rejection);
36 | }
37 | catch(e) {
38 | if(e !== error) {
39 | throw e;
40 | }
41 | }
42 | finally {
43 | expect(inform.messages().length).toBe(1);
44 | var content = inform.messages()[0].content;
45 | expect(content.indexOf(rejection.status.toString())).not.toBe(-1);
46 | expect(content.indexOf(rejection.statusText.toString())).not.toBe(-1);
47 | }
48 | });
49 | });
50 |
51 | });
52 |
--------------------------------------------------------------------------------
/src/angular-inform/provider.js:
--------------------------------------------------------------------------------
1 | inform.provider('inform', function () {
2 |
3 | var provider = this;
4 |
5 | this._defaults = {
6 | type: 'default',
7 | ttl: 5000
8 | };
9 |
10 | this.defaults = function (options) {
11 | provider._defaults = angular.extend(provider._defaults, options || {});
12 | return provider._defaults;
13 | };
14 |
15 |
16 | this.$get = ['$timeout', '$sce', function ($timeout, $sce) {
17 |
18 | var _messages = [];
19 |
20 | function _indexOf(predicate) {
21 | var i = _messages.length;
22 |
23 | while (i--) {
24 | if (predicate(_messages[i])) {
25 | return i;
26 | }
27 | }
28 |
29 | return -1;
30 | }
31 |
32 | function cancelTimeout(msg) {
33 | if (msg.timeout) {
34 | $timeout.cancel(msg.timeout);
35 | delete msg.timeout;
36 | }
37 | }
38 |
39 | function setTimeout(msg) {
40 |
41 | cancelTimeout(msg);
42 |
43 | if (msg.ttl > 0) {
44 | msg.timeout = $timeout(function () {
45 | remove(msg);
46 | }, msg.ttl);
47 | }
48 | }
49 |
50 | function add(content, options) {
51 |
52 | var msg = angular.extend({}, provider._defaults, options);
53 |
54 | if(!angular.isString(content)) {
55 | content = '' + JSON.stringify(content, null, ' ') + '
';
56 | msg.html = true;
57 | }
58 |
59 | var idx = _indexOf(function (x) {
60 | return x.content.toString() === content && x.type == msg.type;
61 | });
62 |
63 | if (idx >= 0) {
64 |
65 | msg = _messages[idx];
66 | msg.count += 1;
67 |
68 | } else {
69 |
70 | msg.content = content;
71 |
72 | if(msg.html) {
73 | msg.content = $sce.trustAsHtml(content);
74 | }
75 |
76 | msg.tickCount = +new Date();
77 | msg.count = 1;
78 |
79 | _messages.push(msg);
80 | }
81 |
82 | setTimeout(msg);
83 |
84 | return msg;
85 | }
86 |
87 | function remove(msg) {
88 |
89 | var idx = _indexOf(function (x) {
90 | return x === msg;
91 | });
92 |
93 | if (idx >= 0) {
94 | _messages.splice(idx, 1);
95 | cancelTimeout(msg);
96 | }
97 | }
98 |
99 | function clear() {
100 | _messages.length = 0;
101 | }
102 |
103 | return {
104 | messages: function () {
105 | return _messages;
106 | },
107 | add: add,
108 | remove: remove,
109 | clear: clear,
110 | cancelTimeout: cancelTimeout,
111 | setTimeout: setTimeout
112 | };
113 | }];
114 |
115 | });
--------------------------------------------------------------------------------
/src/angular-inform/provider.test.js:
--------------------------------------------------------------------------------
1 | describe('angular-inform', function () {
2 |
3 |
4 | describe('informProvider', function () {
5 |
6 | // http://stackoverflow.com/questions/14771810/how-to-test-angularjs-custom-provider
7 |
8 | var provider;
9 |
10 | beforeEach(function () {
11 |
12 | angular.module('i.am.so.fake', []).config(function (informProvider) {
13 | provider = informProvider;
14 | });
15 |
16 | module('inform', 'i.am.so.fake');
17 |
18 | inject(function () {
19 | });
20 |
21 | });
22 |
23 | it('should resolve the informProvider', function () {
24 | expect(provider).not.toBeUndefined();
25 | });
26 |
27 | it('should return the default options', function () {
28 |
29 | var defaults = provider.defaults();
30 |
31 | expect(defaults).not.toBeUndefined();
32 |
33 | });
34 |
35 | it('should extend the default options', function () {
36 |
37 | expect(provider.defaults().type).not.toBe('pannekoek'); // u nvr knw
38 |
39 | var defaults = provider.defaults({
40 | type: 'pannekoek'
41 | });
42 |
43 | expect(defaults.type).toBe('pannekoek');
44 | });
45 |
46 | });
47 |
48 | describe('informService', function () {
49 |
50 | var service, $timeout;
51 |
52 | beforeEach(function () {
53 | module('inform');
54 |
55 | //angular.copy(origDefaultOptions, defaultOptions);
56 |
57 | inject(function (inform, _$timeout_) {
58 | service = inform;
59 | $timeout = _$timeout_;
60 | });
61 | });
62 |
63 | it('should resolve the inform service', function () {
64 | expect(service).not.toBeUndefined();
65 | });
66 |
67 | it('should add a message', function () {
68 |
69 | expect(service.messages().length).toBe(0);
70 |
71 | service.add('simple message');
72 |
73 | expect(service.messages().length).toBe(1);
74 | expect(service.messages()[0].content).toBe('simple message');
75 | });
76 |
77 | it('should add a message using the provided type', function () {
78 | service.add('simple message', { type: 'pannekoek' });
79 | expect(service.messages()[0].type).toBe('pannekoek');
80 | });
81 |
82 | it('should remove the specified message', function () {
83 | expect(service.messages().length).toBe(0);
84 | var msg = service.add('kill me');
85 | expect(service.messages().length).toBe(1);
86 | service.remove(msg);
87 | expect(service.messages().length).toBe(0);
88 | });
89 |
90 | it('should remove the message after a timeout', function () {
91 |
92 | expect(service.messages().length).toBe(0);
93 | service.add('timeout me');
94 | expect(service.messages().length).toBe(1);
95 |
96 | $timeout.flush();
97 |
98 | expect(service.messages().length).toBe(0);
99 |
100 | });
101 |
102 | it('should cancel a pending timeout when removing a msg', function () {
103 |
104 | var msg = service.add('timeout me');
105 | expect(msg.timeout).toBeDefined();
106 |
107 | service.remove(msg);
108 |
109 | expect(msg.timeout).toBeFalsy();
110 |
111 | });
112 |
113 | it('should clear all messages', function () {
114 |
115 | var c = 5;
116 |
117 | while (c--) {
118 | service.add('message ' + c);
119 | }
120 |
121 | service.clear();
122 |
123 | expect(service.messages().length).toBe(0);
124 |
125 | });
126 |
127 | it('should not display duplicate messages', function () {
128 |
129 | var c = 5;
130 |
131 | while (c--) {
132 | service.add('duplicate message');
133 | }
134 |
135 | expect(service.messages().length).toBe(1);
136 | });
137 |
138 | it('should allow duplicate messages of different kinds', function () {
139 |
140 | service.add('duplicate message', { type: 'success' });
141 | service.add('duplicate message', { type: 'info' });
142 |
143 | expect(service.messages().length).toBe(2);
144 | });
145 |
146 | it('should return the same msg object for duplicates', function () {
147 |
148 | var msg1 = service.add('duplicate message');
149 | var msg2 = service.add('duplicate message');
150 |
151 | expect(msg1).toBe(msg2);
152 |
153 | });
154 |
155 | it('should increase occurence count for duplicates', function () {
156 |
157 | var duplicate = service.add('duplicate message');
158 | service.add('duplicate message');
159 | service.add('duplicate message');
160 |
161 | expect(duplicate.count).toBe(3);
162 |
163 | });
164 |
165 | });
166 |
167 |
168 | });
169 |
--------------------------------------------------------------------------------
/src/angular-showdown/angular-showdown.js:
--------------------------------------------------------------------------------
1 | angular.module('showdown', []);
2 |
3 | angular.module('showdown').directive('showdown', function(showdown, showdownConfig) {
4 |
5 | return {
6 | restrict: 'EA',
7 | link: function($scope, $element, $attrs) {
8 |
9 | var options = angular.copy(showdownConfig);
10 |
11 | options.outline = $attrs.showdownSrc ? $attrs.showdownSrc == 'true' : options.outline;
12 | options.src = $attrs.showdownSrc;
13 |
14 | $scope.$watch($attrs.showdownModel, function(value) {
15 | options.markdown = value;
16 | showdown.updateElement($element, options);
17 | });
18 | }
19 | };
20 | });
21 |
22 | angular.module('showdown').provider('showdownConfig', function() {
23 | var config = {
24 | extensions: [],
25 | css: {
26 | loading: 'showdown-loading',
27 | error: 'showdown-error'
28 | },
29 | outline: true
30 | };
31 | this.$get = function() {
32 | return config;
33 | };
34 | });
35 |
36 | angular.module('showdown').factory('showdown', function($http) {
37 |
38 | var _converter;
39 |
40 | function getConverter(options) {
41 |
42 | // options: { extensions: ['twitter', mine] }
43 | // TODO: Locate (and create) converter based on extensions
44 |
45 | _converter = _converter || new Showdown.converter(options);
46 |
47 | return _converter;
48 | }
49 |
50 | function makeHtml(options) {
51 |
52 | var converter = getConverter(options);
53 |
54 | return converter.makeHtml(options.markdown || options.defaultMarkdown);
55 | }
56 |
57 | function outline(text) {
58 | if (text) {
59 |
60 | // trim leading empty lines
61 |
62 | text = text.replace(/^\s*\n/, '');
63 |
64 | // grab the first ident on the first line
65 |
66 | var m = text.match(/^[ \t]+/);
67 | if (m && m.length) {
68 |
69 | // build a pattern to strip out the located ident from all lines
70 |
71 | var p = '^[ \t]{' + m[0].length + '}';
72 | var r = new RegExp(p, 'gm');
73 | text = text.replace(r, '');
74 | }
75 | }
76 |
77 | return text;
78 | }
79 |
80 | function updateElement($element, options) {
81 |
82 | if (options.defaultMarkdown === undefined) {
83 |
84 | var t = $element.text();
85 |
86 | if (options.outline) {
87 | t = outline(t);
88 | }
89 |
90 | options.defaultMarkdown = t;
91 | }
92 |
93 | if (options.src) {
94 |
95 | $element.addClass(options.css.loading);
96 | $element.removeClass(options.css.error);
97 | options.markdown = '';
98 |
99 | $http.get(options.src).then(function(response) {
100 | options.markdown = response.data;
101 | $element.removeClass(options.css.error);
102 | })['catch'](function() {
103 | $element.addClass(options.css.error);
104 | })['finally'](function() {
105 | $element.removeClass(options.css.loading);
106 | options.src = undefined;
107 | updateElement($element, options);
108 | });
109 | } else {
110 | var html = makeHtml(options);
111 | $element.html(html);
112 | }
113 |
114 | }
115 |
116 | return {
117 | makeHtml: makeHtml,
118 | updateElement: updateElement,
119 | outline: outline
120 | };
121 | });
122 |
--------------------------------------------------------------------------------
/src/app/app.css:
--------------------------------------------------------------------------------
1 | body {
2 | /*padding-top: 59px;*/
3 | padding-bottom: 100px;
4 | overflow: hidden;
5 | }
6 |
7 | .container {
8 | max-width: 900px;
9 | min-width: 320px;
10 | }
11 |
12 | html {
13 | overflow-y: scroll;
14 | }
--------------------------------------------------------------------------------
/src/app/app.js:
--------------------------------------------------------------------------------
1 |
2 | var app = angular.module('app', ['ngRoute', 'inform', 'inform-exception', 'inform-http-exception', 'showdown', 'ngAnimate']);
3 |
4 | app.config(function($routeProvider) {
5 |
6 | $routeProvider.when('/readme', {
7 | templateUrl: 'app/readme/readme.html'
8 | });
9 |
10 | $routeProvider.when('/demo', {
11 | templateUrl: 'app/demo/demo.html'
12 | });
13 |
14 | $routeProvider.otherwise({
15 | redirectTo: '/demo'
16 | });
17 |
18 | });
19 |
20 | app.controller('MainCtrl', function($scope, $location) {
21 |
22 | // Keep track of the active url to highlite the nav-pill
23 |
24 | $scope.$watch(function() {
25 | return $location.path();
26 | }, function(value) {
27 | $scope.activeUrl = value;
28 | });
29 |
30 | });
--------------------------------------------------------------------------------
/src/app/assets/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/McNull/angular-inform/68e839ad6f9eef3be438cc7b864f4e4346fb00a0/src/app/assets/favicon.ico
--------------------------------------------------------------------------------
/src/app/demo/demo.css:
--------------------------------------------------------------------------------
1 | .messages-form {
2 | margin-bottom: 15px;
3 | }
--------------------------------------------------------------------------------
/src/app/demo/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
Javascript
6 |
7 |
56 |
57 |
{{ jsStatement() }}
58 |
59 |
Element
60 |
61 |
62 |
63 |
64 | Display messages at fixed position
65 |
66 |
67 |
68 |
69 |
70 | Enable animations
71 |
72 |
73 |
74 |
75 |
76 | Enable shadows
77 |
78 |
79 |
80 |
81 |
82 | Center messages
83 |
84 |
85 |
86 |
87 |
88 |
{{ htmlMarkup() }}
89 |
angular.module('myModule', ['inform', 'ngAnimate']);
90 |
91 |
Messages
92 |
93 |
95 |
96 |
Unhandled Exceptions
97 |
angular.module('myModule', ['inform', 'inform-exception']);
98 |
Throw unhandled exception
99 |
100 |
HTTP Exceptions
101 |
angular.module('myModule', ['inform', 'inform-http-exception']);
102 |
Request invalid url
103 |
104 |
105 |
106 |
--------------------------------------------------------------------------------
/src/app/demo/demo.js:
--------------------------------------------------------------------------------
1 | app.controller('DemoController', function($scope, inform, $http) {
2 |
3 | if(inform.messages().length === 0) {
4 |
5 | //inform.add('{{ msg | json }}
', { ttl: -1, type: 'success', html: true });
6 | //
7 | //
8 | //inform.add('Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ab amet, blanditiis debitis dolorem doloremque et facilis harum in iusto laborum minima molestiae nemo nisi non possimus, quisquam rerum tempore voluptates.', { ttl: -1, type: 'info' });
9 | //inform.add('Lorem ipsum dolor sit amet, consectetur adipisicing elit. Assumenda atque, earum est id illum laboriosam maxime praesentium quisquam! Blanditiis cum deleniti eum impedit quasi. Eius eligendi eveniet ipsum natus quis.', { ttl: -1, type: 'warning' });
10 | //inform.add('Lorem ipsum dolor sit amet, consectetur adipisicing elit. Assumenda deserunt dicta esse, ipsam molestiae nobis provident qui quidem quis repudiandae totam veniam voluptas voluptatum? A adipisci aut cumque earum pariatur?', { ttl: -1, type: 'danger' });
11 | //
12 | //inform.add('HTML content Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
', { ttl: -1, html: true });
13 | //inform.add('HTML content Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer posuere erat a ante.
', { ttl: -1, html: true });
14 | }
15 |
16 | $scope.inform = inform;
17 |
18 | $scope.msg = {
19 | content: 'The message content',
20 | options: {
21 | ttl: 5000,
22 | type: 'default'
23 | }
24 | };
25 |
26 | $scope.htmlMarkup = function() {
27 |
28 | var classes = [];
29 |
30 | if($scope.element.animations) {
31 | classes.push('inform-animate');
32 | }
33 |
34 | if($scope.element.fixed) {
35 | classes.push('inform-fixed');
36 | }
37 |
38 | if($scope.element.shadows) {
39 | classes.push('inform-shadow');
40 | }
41 |
42 | if($scope.element.center) {
43 | classes.push('inform-center');
44 | }
45 |
46 | var markup = '
';
55 |
56 | return markup;
57 | };
58 |
59 | $scope.jsStatement = function() {
60 |
61 | var ret = "inform.add(" + JSON.stringify($scope.msg.content);
62 | var options;
63 |
64 | if($scope.msg.options.ttl !== 5000) {
65 | var ttl = $scope.msg.options.ttl === null ? 0 : $scope.msg.options.ttl;
66 | options = { ttl: ttl };
67 | }
68 |
69 | if($scope.msg.options.type !== 'default') {
70 | options = options || {};
71 | options.type = $scope.msg.options.type;
72 | }
73 |
74 | if($scope.msg.options.html) {
75 | options = options || {};
76 | options.html = true;
77 | }
78 |
79 | if(options) {
80 | ret += ", " + JSON.stringify(options, null, ' ');
81 | }
82 |
83 | ret += ");";
84 |
85 | return ret;
86 |
87 | };
88 |
89 | $scope.element = {
90 | fixed: true,
91 | animations: true,
92 | shadows: true,
93 | center: false
94 | };
95 |
96 | $scope.add = function(msg) {
97 | inform.add(msg.content, msg.options);
98 | };
99 |
100 | $scope.throwException = function() {
101 | throw new Error('Oh dear! Something bad has occured!');
102 | };
103 |
104 | $scope.throwHttpException = function() {
105 | $http.get('/this/does/not/exist', function() {});
106 | };
107 |
108 | $scope.clear = inform.clear;
109 |
110 | });
111 |
--------------------------------------------------------------------------------
/src/app/readme/readme.html:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | <% _.forEach(css, function(include) { %>
13 |
14 | <%
15 | }); %>
16 |
17 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
Angular Inform
30 |
A small growl-like easy-to-use message toaster for angular.
31 |
32 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 | <% _.forEach(js, function(include) { %>
56 |
57 | <%
58 | }); %>
59 |
60 |
61 |
--------------------------------------------------------------------------------