├── .bowerrc
├── .editorconfig
├── .gitignore
├── .jshintrc
├── .travis.yml
├── LICENSE
├── README.md
├── bower.json
├── dist
├── angular-consent.js
└── angular-consent.min.js
├── gulpfile.js
├── karma-dist-concatenated.conf.js
├── karma-dist-minified.conf.js
├── karma-src.conf.js
├── package.json
├── src
└── angular-consent
│ ├── consent.module.js
│ ├── controllers
│ └── consent.js
│ └── directives
│ └── consent.js
└── test
└── unit
└── angular-consent
├── consent.js
├── controllers
└── consent.js
└── directives
└── consent.js
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "bower"
3 | }
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | indent_style = space
6 | indent_size = 2
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
11 | [*.md]
12 | trim_trailing_whitespace = false
13 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ._*
2 | .~lock.*
3 | .buildpath
4 | .DS_Store
5 | .idea
6 | .project
7 | .settings
8 |
9 | # Ignore node stuff
10 | node_modules/
11 | npm-debug.log
12 | libpeerconnection.log
13 |
14 | # OS-specific
15 | .DS_Store
16 |
17 | # Bower components
18 | bower
19 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "bitwise": true,
3 | "camelcase": true,
4 | "curly": true,
5 | "eqeqeq": true,
6 | "es3": false,
7 | "forin": true,
8 | "freeze": true,
9 | "immed": true,
10 | "indent": 2,
11 | "latedef": "nofunc",
12 | "newcap": true,
13 | "noarg": true,
14 | "noempty": true,
15 | "nonbsp": true,
16 | "nonew": true,
17 | "plusplus": false,
18 | "quotmark": "single",
19 | "undef": true,
20 | "unused": false,
21 | "strict": false,
22 | "maxparams": 10,
23 | "maxdepth": 5,
24 | "maxstatements": 40,
25 | "maxcomplexity": 8,
26 | "maxlen": 120,
27 |
28 | "asi": false,
29 | "boss": false,
30 | "debug": false,
31 | "eqnull": true,
32 | "esnext": false,
33 | "evil": false,
34 | "expr": false,
35 | "funcscope": false,
36 | "globalstrict": false,
37 | "iterator": false,
38 | "lastsemic": false,
39 | "laxbreak": false,
40 | "laxcomma": false,
41 | "loopfunc": true,
42 | "maxerr": false,
43 | "moz": false,
44 | "multistr": false,
45 | "notypeof": false,
46 | "proto": false,
47 | "scripturl": false,
48 | "shadow": false,
49 | "sub": true,
50 | "supernew": false,
51 | "validthis": false,
52 | "noyield": false,
53 |
54 | "browser": true,
55 | "node": true,
56 |
57 | "globals": {
58 | "angular": false,
59 | "$": false
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js: ["0.10"]
3 | before_script:
4 | - npm install -g bower
5 | - bower install
6 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | Copyright (c) 2015 Jurgen Van de Moere
2 |
3 | Permission is hereby granted, free of charge, to any person obtaining
4 | a copy of this software and associated documentation files (the
5 | "Software"), to deal in the Software without restriction, including
6 | without limitation the rights to use, copy, modify, merge, publish,
7 | distribute, sublicense, and/or sell copies of the Software, and to
8 | permit persons to whom the Software is furnished to do so, subject to
9 | the following conditions:
10 |
11 | The above copyright notice and this permission notice shall be
12 | included in all copies or substantial portions of the Software.
13 |
14 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Angular Consent
2 | [](https://travis-ci.org/jvandemo/angular-consent)
3 |
4 | Easily show consent messages that keep appearing until the user clicks them away.
5 |
6 | Useful if you need to show legal disclaimers (e.g. to conform to the EU Cookie Consent law).
7 |
8 | - very lightweight (~1KB)
9 | - use your own markup and CSS to make the messages fit perfectly in your application
10 | - supports multiple consent messages on the same page
11 |
12 | [Try online demo](http://angular-consent-demo.surge.sh/).
13 |
14 | Requirements:
15 |
16 | - [ngCookies](https://docs.angularjs.org/api/ngCookies/service/$cookies)
17 |
18 | [](http://angular-consent-demo.surge.sh/)
19 |
20 | ## Quick example
21 |
22 | ```xml
23 |
24 |
25 |
26 |
27 |
28 |
29 | This web application uses cookies to store private data.
30 |
31 |
32 |
33 |
34 | ```
35 |
36 | ## Usage
37 |
38 | First install the module using bower:
39 |
40 | ```bash
41 | $ bower install angular-cookies
42 | $ bower install angular-consent
43 | ```
44 |
45 | and add the library to your application:
46 |
47 | ```xml
48 |
49 |
50 | ```
51 |
52 | Then add the `ngCookies` and `angularConsent` modules to the dependencies of your AngularJS application module:
53 |
54 | ```javascript
55 | angular.module('yourApp', ['ngCookies', 'angularConsent']);
56 | ```
57 |
58 | Now you can use the `consent` directive anywhere in your markup:
59 |
60 | ```xml
61 |
62 |
63 |
64 |
65 |
66 |
67 | This web application uses cookies to store private data.
68 |
69 |
70 |
71 |
72 | ```
73 |
74 | To create multiple consents in a single application, pass a unique key to the `consent` attribute:
75 |
76 | ```xml
77 |
78 |
79 |
80 | This website uses cookies.
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | This website stores private data.
89 |
90 |
91 |
92 | ```
93 |
94 | You can also re-use a consent across your page or application:
95 |
96 |
97 | ```xml
98 |
99 |
104 |
105 |
106 |
109 | ```
110 |
111 | By default cookies are stored for 360 days, but you can customize cookie options on a consent level:
112 |
113 | ```xml
114 |
115 |
120 | ```
121 |
122 | ## The $consent API
123 |
124 | The following methods are available on the `$consent` object:
125 |
126 | ### $consent.hasAlreadyAgreed()
127 |
128 | Whether or not the user has already agreed.
129 |
130 | ##### Arguments
131 |
132 | None.
133 |
134 | ##### Returns
135 |
136 | Boolean.
137 |
138 | ### $consent.hasNotAgreedYet()
139 |
140 | Whether or not the user still has to agree.
141 |
142 | ##### Arguments
143 |
144 | None.
145 |
146 | ##### Returns
147 |
148 | Boolean.
149 |
150 | ### $consent.agree()
151 |
152 | Marks the consent as agreed.
153 |
154 | ##### Arguments
155 |
156 | None.
157 |
158 | ##### Returns
159 |
160 | Void.
161 |
162 | ### $consent.reset()
163 |
164 | Resets a previous agreement.
165 |
166 | ##### Arguments
167 |
168 | None.
169 |
170 | ##### Returns
171 |
172 | Void.
173 |
174 | ### Example with all available methods
175 |
176 | ```xml
177 |
178 |
179 |
180 | This message will keep appearing until you agree
181 |
182 |
183 |
184 |
185 | This message will appear when user has already agreed
186 |
188 |
189 |
190 | ```
191 |
192 |
193 | ## Contribute
194 |
195 | To update the build in the `dist` directory:
196 |
197 | ```bash
198 | $ gulp
199 | ```
200 |
201 | To run the unit tests using the src files:
202 |
203 | ```bash
204 | $ gulp test-src
205 | ```
206 |
207 | To run the unit tests using the unminified library:
208 |
209 | ```bash
210 | $ gulp test-dist-concatenated
211 | ```
212 |
213 | To run the unit tests using the minified library:
214 |
215 | ```bash
216 | $ gulp test-dist-minified
217 | ```
218 |
219 | ## Change log
220 |
221 | ### v2.2.0
222 |
223 | - Added main property to package.json (#5)
224 |
225 | ### v2.1.1
226 |
227 | - Added check to make sure expires is always set correctly to fix #4
228 |
229 | ### v2.1.0
230 |
231 | - Added support for AngularJS versions older than AngularJS 1.4
232 |
233 | ### v2.0.0
234 |
235 | - Cookies are now stored for 360 days by default (instead of session)
236 | - Added support for cookie options via `consent-cookie-options` attribute
237 |
238 | ### v1.0.0
239 |
240 | - Added support for multiple consent messages simultaneously
241 | - Updated documentation
242 | - Added demo
243 |
244 | ### v0.1.0
245 |
246 | - Added consent directive
247 | - Added unit tests
248 | - Added initial documentation
249 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-consent",
3 | "version": "2.1.0",
4 | "authors": [
5 | {
6 | "name": "Jurgen Van de Moere",
7 | "email": "jurgen.van.de.moere@gmail.com"
8 | }
9 | ],
10 | "main": ["dist/angular-consent.js"],
11 | "ignore": [
12 | "src",
13 | "test",
14 | "gulpfile.js",
15 | "**/.*"
16 | ],
17 | "dependencies": {},
18 | "devDependencies": {
19 | "angular-mocks": ">=1.2.0",
20 | "angular-scenario": ">=1.2.0",
21 | "angular": ">=1.2.0",
22 | "angular-cookies": ">=1.2.0"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/dist/angular-consent.js:
--------------------------------------------------------------------------------
1 | (function (angular) {
2 |
3 | // Create all modules and define dependencies to make sure they exist
4 | // and are loaded in the correct order to satisfy dependency injection
5 | // before all nested files are concatenated by Gulp
6 |
7 | // Config
8 | angular.module('angularConsent.config', [])
9 | .value('angularConsent.config', {
10 | debug: true
11 | });
12 |
13 | // Modules
14 | angular.module('angularConsent.directives', []);
15 | angular.module('angularConsent.controllers', []);
16 | angular.module('angularConsent',
17 | [
18 | 'angularConsent.config',
19 | 'angularConsent.directives',
20 | 'angularConsent.controllers',
21 | 'ngCookies'
22 | ]);
23 |
24 | })(angular);
25 |
26 | (function (angular) {
27 |
28 | angular
29 | .module('angularConsent.controllers')
30 | .controller('angularConsent.ConsentController', ConsentController);
31 |
32 | function ConsentController($cookies, $attrs, $scope){
33 |
34 | this.getCookieKey = function(){
35 | return 'angular-consent.' + ($attrs.consent || 'global');
36 | };
37 |
38 | this.getCookieOptions = function(){
39 | var options = {};
40 | if($attrs.consentCookieOptions){
41 | options = $scope.$eval($attrs.consentCookieOptions);
42 | }
43 | if(!options.hasOwnProperty('expires')){
44 | var now = new Date();
45 | var expirationDate = new Date();
46 | expirationDate.setTime(+ now + (360 * 24 * 60 * 60 * 1000)); // 360 days
47 | options.expires = expirationDate.toGMTString();
48 | }
49 | return options;
50 | };
51 |
52 | this.getCookieValue = function(){
53 | try {
54 | return $cookies.get(this.getCookieKey());
55 | } catch (e) {
56 | if (e instanceof TypeError){
57 | return $cookies[this.getCookieKey()];
58 | }
59 | }
60 | };
61 |
62 | this.setCookieValue = function(value){
63 | try {
64 | return $cookies.put(this.getCookieKey(), value, this.getCookieOptions());
65 | } catch (e) {
66 | if (e instanceof TypeError){
67 | $cookies[this.getCookieKey()] = value ;
68 | }
69 | }
70 | };
71 |
72 | this.hasAlreadyAgreed = function(){
73 | if(this.getCookieValue()){
74 | return true;
75 | }
76 | return false;
77 | };
78 |
79 | this.hasNotAgreedYet = function(){
80 | return !this.hasAlreadyAgreed();
81 | };
82 |
83 | this.reset = function(){
84 | try {
85 | $cookies.remove(this.getCookieKey());
86 | } catch (e) {
87 | if (e instanceof TypeError){
88 | delete $cookies[this.getCookieKey()];
89 | }
90 | }
91 | };
92 |
93 | this.agree = function(){
94 | this.setCookieValue(Date.now());
95 | };
96 | }
97 |
98 | ConsentController.$inject = ['$cookies', '$attrs', '$scope'];
99 |
100 | })(angular);
101 |
102 | (function (angular) {
103 |
104 | angular
105 | .module('angularConsent.directives')
106 | .directive('consent', createDirectiveDDO);
107 |
108 | function createDirectiveDDO(){
109 | return {
110 | restrict: 'A',
111 | scope: true,
112 | controller: 'angularConsent.ConsentController',
113 | controllerAs: '$consent'
114 | };
115 | }
116 |
117 | })(angular);
118 |
--------------------------------------------------------------------------------
/dist/angular-consent.min.js:
--------------------------------------------------------------------------------
1 | !function(e){e.module("angularConsent.config",[]).value("angularConsent.config",{debug:!0}),e.module("angularConsent.directives",[]),e.module("angularConsent.controllers",[]),e.module("angularConsent",["angularConsent.config","angularConsent.directives","angularConsent.controllers","ngCookies"])}(angular),function(e){function n(e,n,t){this.getCookieKey=function(){return"angular-consent."+(n.consent||"global")},this.getCookieOptions=function(){var e={};if(n.consentCookieOptions&&(e=t.$eval(n.consentCookieOptions)),!e.hasOwnProperty("expires")){var o=new Date,r=new Date;r.setTime(+o+31104e6),e.expires=r.toGMTString()}return e},this.getCookieValue=function(){try{return e.get(this.getCookieKey())}catch(n){if(n instanceof TypeError)return e[this.getCookieKey()]}},this.setCookieValue=function(n){try{return e.put(this.getCookieKey(),n,this.getCookieOptions())}catch(t){t instanceof TypeError&&(e[this.getCookieKey()]=n)}},this.hasAlreadyAgreed=function(){return this.getCookieValue()?!0:!1},this.hasNotAgreedYet=function(){return!this.hasAlreadyAgreed()},this.reset=function(){try{e.remove(this.getCookieKey())}catch(n){n instanceof TypeError&&delete e[this.getCookieKey()]}},this.agree=function(){this.setCookieValue(Date.now())}}e.module("angularConsent.controllers").controller("angularConsent.ConsentController",n),n.$inject=["$cookies","$attrs","$scope"]}(angular),function(e){function n(){return{restrict:"A",scope:!0,controller:"angularConsent.ConsentController",controllerAs:"$consent"}}e.module("angularConsent.directives").directive("consent",n)}(angular);
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp');
2 | var karma = require('karma').server;
3 | var concat = require('gulp-concat');
4 | var uglify = require('gulp-uglify');
5 | var rename = require('gulp-rename');
6 | var path = require('path');
7 | var plumber = require('gulp-plumber');
8 | var runSequence = require('run-sequence');
9 | var jshint = require('gulp-jshint');
10 |
11 | /**
12 | * File patterns
13 | **/
14 |
15 | // Root directory
16 | var rootDirectory = path.resolve('./');
17 |
18 | // Source directory for build process
19 | var sourceDirectory = path.join(rootDirectory, './src');
20 |
21 | var sourceFiles = [
22 |
23 | // Make sure module files are handled first
24 | path.join(sourceDirectory, '/**/*.module.js'),
25 |
26 | // Then add all JavaScript files
27 | path.join(sourceDirectory, '/**/*.js')
28 | ];
29 |
30 | var lintFiles = [
31 | 'gulpfile.js',
32 | // Karma configuration
33 | 'karma-*.conf.js'
34 | ].concat(sourceFiles);
35 |
36 | gulp.task('build', function() {
37 | gulp.src(sourceFiles)
38 | .pipe(plumber())
39 | .pipe(concat('angular-consent.js'))
40 | .pipe(gulp.dest('./dist/'))
41 | .pipe(uglify())
42 | .pipe(rename('angular-consent.min.js'))
43 | .pipe(gulp.dest('./dist'));
44 | });
45 |
46 | /**
47 | * Process
48 | */
49 | gulp.task('process-all', function (done) {
50 | runSequence('jshint', 'test-src', 'build', done);
51 | });
52 |
53 | /**
54 | * Watch task
55 | */
56 | gulp.task('watch', function () {
57 |
58 | // Watch JavaScript files
59 | gulp.watch(sourceFiles, ['process-all']);
60 | });
61 |
62 | /**
63 | * Validate source JavaScript
64 | */
65 | gulp.task('jshint', function () {
66 | return gulp.src(lintFiles)
67 | .pipe(plumber())
68 | .pipe(jshint())
69 | .pipe(jshint.reporter('jshint-stylish'))
70 | .pipe(jshint.reporter('fail'));
71 | });
72 |
73 | /**
74 | * Run test once and exit
75 | */
76 | gulp.task('test-src', function (done) {
77 | karma.start({
78 | configFile: __dirname + '/karma-src.conf.js',
79 | singleRun: true
80 | }, done);
81 | });
82 |
83 | /**
84 | * Run test once and exit
85 | */
86 | gulp.task('test-dist-concatenated', function (done) {
87 | karma.start({
88 | configFile: __dirname + '/karma-dist-concatenated.conf.js',
89 | singleRun: true
90 | }, done);
91 | });
92 |
93 | /**
94 | * Run test once and exit
95 | */
96 | gulp.task('test-dist-minified', function (done) {
97 | karma.start({
98 | configFile: __dirname + '/karma-dist-minified.conf.js',
99 | singleRun: true
100 | }, done);
101 | });
102 |
103 | gulp.task('default', function () {
104 | runSequence('process-all', 'watch');
105 | });
106 |
--------------------------------------------------------------------------------
/karma-dist-concatenated.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | // Generated on Thu Aug 21 2014 10:24:39 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: ['mocha', 'chai-jquery', 'jquery-1.8.3', 'sinon-chai'],
14 |
15 | plugins: [
16 | 'karma-mocha',
17 | 'karma-chai',
18 | 'karma-sinon-chai',
19 | 'karma-chrome-launcher',
20 | 'karma-phantomjs2-launcher',
21 | 'karma-jquery',
22 | 'karma-chai-jquery'
23 | ],
24 |
25 | // list of files / patterns to load in the browser
26 | files: [
27 | 'bower/angular/angular.js',
28 | 'bower/angular-cookies/angular-cookies.js',
29 | 'bower/angular-mocks/angular-mocks.js',
30 | 'dist/angular-consent.js',
31 | 'test/unit/**/*.js'
32 | ],
33 |
34 |
35 | // list of files to exclude
36 | exclude: [
37 | ],
38 |
39 |
40 | // preprocess matching files before serving them to the browser
41 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
42 | preprocessors: {
43 | },
44 |
45 |
46 | // test results reporter to use
47 | // possible values: 'dots', 'progress'
48 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter
49 | reporters: ['progress'],
50 |
51 |
52 | // web server port
53 | port: 9876,
54 |
55 |
56 | // enable / disable colors in the output (reporters and logs)
57 | colors: true,
58 |
59 |
60 | // level of logging
61 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
62 | logLevel: config.LOG_INFO,
63 |
64 |
65 | // enable / disable watching file and executing tests whenever any file changes
66 | autoWatch: true,
67 |
68 |
69 | // start these browsers
70 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
71 | browsers: ['PhantomJS2'],
72 |
73 |
74 | // Continuous Integration mode
75 | // if true, Karma captures browsers, runs the tests and exits
76 | singleRun: false
77 | });
78 | };
79 |
--------------------------------------------------------------------------------
/karma-dist-minified.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | // Generated on Thu Aug 21 2014 10:24:39 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: ['mocha', 'chai-jquery', 'jquery-1.8.3', 'sinon-chai'],
14 |
15 | plugins: [
16 | 'karma-mocha',
17 | 'karma-chai',
18 | 'karma-sinon-chai',
19 | 'karma-chrome-launcher',
20 | 'karma-phantomjs2-launcher',
21 | 'karma-jquery',
22 | 'karma-chai-jquery'
23 | ],
24 |
25 | // list of files / patterns to load in the browser
26 | files: [
27 | 'bower/angular/angular.js',
28 | 'bower/angular-cookies/angular-cookies.js',
29 | 'bower/angular-mocks/angular-mocks.js',
30 | 'dist/angular-consent.min.js',
31 | 'test/unit/**/*.js'
32 | ],
33 |
34 |
35 | // list of files to exclude
36 | exclude: [
37 | ],
38 |
39 |
40 | // preprocess matching files before serving them to the browser
41 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
42 | preprocessors: {
43 | },
44 |
45 |
46 | // test results reporter to use
47 | // possible values: 'dots', 'progress'
48 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter
49 | reporters: ['progress'],
50 |
51 |
52 | // web server port
53 | port: 9876,
54 |
55 |
56 | // enable / disable colors in the output (reporters and logs)
57 | colors: true,
58 |
59 |
60 | // level of logging
61 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
62 | logLevel: config.LOG_INFO,
63 |
64 |
65 | // enable / disable watching file and executing tests whenever any file changes
66 | autoWatch: true,
67 |
68 |
69 | // start these browsers
70 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
71 | browsers: ['PhantomJS2'],
72 |
73 |
74 | // Continuous Integration mode
75 | // if true, Karma captures browsers, runs the tests and exits
76 | singleRun: false
77 | });
78 | };
79 |
--------------------------------------------------------------------------------
/karma-src.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration
2 | // Generated on Thu Aug 21 2014 10:24:39 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: ['mocha', 'chai-jquery', 'jquery-1.8.3', 'sinon-chai'],
14 |
15 | plugins: [
16 | 'karma-mocha',
17 | 'karma-chai',
18 | 'karma-sinon-chai',
19 | 'karma-chrome-launcher',
20 | 'karma-phantomjs2-launcher',
21 | 'karma-jquery',
22 | 'karma-chai-jquery'
23 | ],
24 |
25 | // list of files / patterns to load in the browser
26 | files: [
27 | 'bower/angular/angular.js',
28 | 'bower/angular-cookies/angular-cookies.js',
29 | 'bower/angular-mocks/angular-mocks.js',
30 | 'src/**/*.module.js',
31 | 'src/**/*.js',
32 | 'test/unit/**/*.js'
33 | ],
34 |
35 |
36 | // list of files to exclude
37 | exclude: [
38 | ],
39 |
40 |
41 | // preprocess matching files before serving them to the browser
42 | // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
43 | preprocessors: {
44 | },
45 |
46 |
47 | // test results reporter to use
48 | // possible values: 'dots', 'progress'
49 | // available reporters: https://npmjs.org/browse/keyword/karma-reporter
50 | reporters: ['progress'],
51 |
52 |
53 | // web server port
54 | port: 9876,
55 |
56 |
57 | // enable / disable colors in the output (reporters and logs)
58 | colors: true,
59 |
60 |
61 | // level of logging
62 | // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
63 | logLevel: config.LOG_INFO,
64 |
65 |
66 | // enable / disable watching file and executing tests whenever any file changes
67 | autoWatch: true,
68 |
69 |
70 | // start these browsers
71 | // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
72 | browsers: ['PhantomJS2'],
73 |
74 |
75 | // Continuous Integration mode
76 | // if true, Karma captures browsers, runs the tests and exits
77 | singleRun: false
78 | });
79 | };
80 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-consent",
3 | "main": "dist/angular-consent.js",
4 | "version": "2.2.0",
5 | "author": {
6 | "name": "Jurgen Van de Moere",
7 | "email": "jurgen.van.de.moere@gmail.com"
8 | },
9 | "scripts": {
10 | "test": "gulp test-dist-minified"
11 | },
12 | "dependencies": {},
13 | "devDependencies": {
14 | "chai": "^1.9.1",
15 | "chai-jquery": "^1.2.3",
16 | "gulp": "^3.8.7",
17 | "gulp-concat": "^2.3.4",
18 | "gulp-jshint": "^1.8.4",
19 | "gulp-plumber": "^0.6.6",
20 | "gulp-rename": "^1.2.0",
21 | "gulp-uglify": "^0.3.1",
22 | "jshint-stylish": "^0.4.0",
23 | "karma": "^0.12.22",
24 | "karma-chai": "^0.1.0",
25 | "karma-chai-jquery": "^1.0.0",
26 | "karma-chrome-launcher": "^0.1.4",
27 | "karma-jasmine": "^0.1.5",
28 | "karma-jquery": "^0.1.0",
29 | "karma-mocha": "^0.1.8",
30 | "karma-phantomjs2-launcher": "^0.5.0",
31 | "karma-sinon-chai": "^0.2.0",
32 | "mocha": "^1.21.4",
33 | "run-sequence": "^1.0.2",
34 | "sinon": "^1.10.3",
35 | "sinon-chai": "^2.5.0"
36 | },
37 | "engines": {
38 | "node": ">=0.8.0"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/src/angular-consent/consent.module.js:
--------------------------------------------------------------------------------
1 | (function (angular) {
2 |
3 | // Create all modules and define dependencies to make sure they exist
4 | // and are loaded in the correct order to satisfy dependency injection
5 | // before all nested files are concatenated by Gulp
6 |
7 | // Config
8 | angular.module('angularConsent.config', [])
9 | .value('angularConsent.config', {
10 | debug: true
11 | });
12 |
13 | // Modules
14 | angular.module('angularConsent.directives', []);
15 | angular.module('angularConsent.controllers', []);
16 | angular.module('angularConsent',
17 | [
18 | 'angularConsent.config',
19 | 'angularConsent.directives',
20 | 'angularConsent.controllers',
21 | 'ngCookies'
22 | ]);
23 |
24 | })(angular);
25 |
--------------------------------------------------------------------------------
/src/angular-consent/controllers/consent.js:
--------------------------------------------------------------------------------
1 | (function (angular) {
2 |
3 | angular
4 | .module('angularConsent.controllers')
5 | .controller('angularConsent.ConsentController', ConsentController);
6 |
7 | function ConsentController($cookies, $attrs, $scope){
8 |
9 | this.getCookieKey = function(){
10 | return 'angular-consent.' + ($attrs.consent || 'global');
11 | };
12 |
13 | this.getCookieOptions = function(){
14 | var options = {};
15 | if($attrs.consentCookieOptions){
16 | options = $scope.$eval($attrs.consentCookieOptions);
17 | }
18 | if(!options.hasOwnProperty('expires')){
19 | var now = new Date();
20 | var expirationDate = new Date();
21 | expirationDate.setTime(+ now + (360 * 24 * 60 * 60 * 1000)); // 360 days
22 | options.expires = expirationDate.toGMTString();
23 | }
24 | return options;
25 | };
26 |
27 | this.getCookieValue = function(){
28 | try {
29 | return $cookies.get(this.getCookieKey());
30 | } catch (e) {
31 | if (e instanceof TypeError){
32 | return $cookies[this.getCookieKey()];
33 | }
34 | }
35 | };
36 |
37 | this.setCookieValue = function(value){
38 | try {
39 | return $cookies.put(this.getCookieKey(), value, this.getCookieOptions());
40 | } catch (e) {
41 | if (e instanceof TypeError){
42 | $cookies[this.getCookieKey()] = value ;
43 | }
44 | }
45 | };
46 |
47 | this.hasAlreadyAgreed = function(){
48 | if(this.getCookieValue()){
49 | return true;
50 | }
51 | return false;
52 | };
53 |
54 | this.hasNotAgreedYet = function(){
55 | return !this.hasAlreadyAgreed();
56 | };
57 |
58 | this.reset = function(){
59 | try {
60 | $cookies.remove(this.getCookieKey());
61 | } catch (e) {
62 | if (e instanceof TypeError){
63 | delete $cookies[this.getCookieKey()];
64 | }
65 | }
66 | };
67 |
68 | this.agree = function(){
69 | this.setCookieValue(Date.now());
70 | };
71 | }
72 |
73 | ConsentController.$inject = ['$cookies', '$attrs', '$scope'];
74 |
75 | })(angular);
76 |
--------------------------------------------------------------------------------
/src/angular-consent/directives/consent.js:
--------------------------------------------------------------------------------
1 | (function (angular) {
2 |
3 | angular
4 | .module('angularConsent.directives')
5 | .directive('consent', createDirectiveDDO);
6 |
7 | function createDirectiveDDO(){
8 | return {
9 | restrict: 'A',
10 | scope: true,
11 | controller: 'angularConsent.ConsentController',
12 | controllerAs: '$consent'
13 | };
14 | }
15 |
16 | })(angular);
17 |
--------------------------------------------------------------------------------
/test/unit/angular-consent/consent.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('', function() {
4 |
5 | var module;
6 | var dependencies;
7 | dependencies = [];
8 |
9 | var hasModule = function(module) {
10 | return dependencies.indexOf(module) >= 0;
11 | };
12 |
13 | beforeEach(function() {
14 |
15 | // Get module
16 | module = angular.module('angularConsent');
17 | dependencies = module.requires;
18 | });
19 |
20 | it('should load config module', function() {
21 | expect(hasModule('angularConsent.config')).to.be.ok;
22 | });
23 |
24 | it('should load directives module', function() {
25 | expect(hasModule('angularConsent.directives')).to.be.ok;
26 | });
27 |
28 | it('should load controllers module', function() {
29 | expect(hasModule('angularConsent.controllers')).to.be.ok;
30 | });
31 |
32 |
33 | });
34 |
--------------------------------------------------------------------------------
/test/unit/angular-consent/controllers/consent.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('angular-consent controller', function() {
4 |
5 | var $controller;
6 | var $cookies;
7 | var $scope;
8 | var $rootScope;
9 | var ctrl;
10 |
11 | beforeEach(module('angularConsent'));
12 |
13 | beforeEach(inject(function(_$controller_, _$cookies_, _$rootScope_){
14 | $controller = _$controller_;
15 | $cookies = _$cookies_;
16 | $rootScope = _$rootScope_;
17 | $scope = $rootScope.$new();
18 | ctrl = $controller('angularConsent.ConsentController', {
19 | $attrs: {},
20 | $scope: $scope
21 | });
22 | }));
23 |
24 | it('should exist', function() {
25 | expect(ctrl).to.be.an('object');
26 | });
27 |
28 | describe('#agree()', function(){
29 |
30 | it('should update cookie correctly', function() {
31 | ctrl.reset();
32 | expect(ctrl.getCookieValue()).to.not.exist;
33 | ctrl.agree();
34 | expect(ctrl.getCookieValue()).to.exist;
35 | });
36 |
37 | });
38 |
39 | describe('#reset()', function(){
40 |
41 | it('should update cookie correctly', function() {
42 | ctrl.reset();
43 | expect(ctrl.getCookieValue()).to.not.exist;
44 | ctrl.agree();
45 | expect(ctrl.getCookieValue()).to.exist;
46 | ctrl.reset();
47 | expect(ctrl.getCookieValue()).to.not.exist;
48 | });
49 |
50 | });
51 |
52 |
53 | });
54 |
--------------------------------------------------------------------------------
/test/unit/angular-consent/directives/consent.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | describe('angular-consent directive', function() {
4 |
5 | var $compile;
6 | var $rootScope;
7 | var $cookies;
8 |
9 | beforeEach(module('angularConsent'));
10 |
11 | beforeEach(inject(function(_$rootScope_, _$compile_, _$cookies_){
12 | $rootScope = _$rootScope_;
13 | $compile = _$compile_;
14 | $cookies = _$cookies_;
15 | }));
16 |
17 | it('should handle non-existing cookie correctly', function() {
18 | var markup = '';
19 | markup += 'Not agreed yet
';
20 | markup += 'Already agreed
';
21 | markup += '';
22 | var $scope = $rootScope.$new();
23 | var element = $compile(markup)($scope);
24 | $rootScope.$digest();
25 | expect(element.html()).to.contain('Not agreed yet');
26 | expect(element.html()).to.not.contain('Already agreed');
27 | });
28 |
29 | it('should handle truthy value correctly', function() {
30 | $cookies.put('angular-consent.test', Date.now());
31 | var markup = '';
32 | markup += 'Not agreed yet
';
33 | markup += 'Already agreed
';
34 | markup += '';
35 | var $scope = $rootScope.$new();
36 | var element = $compile(markup)($scope);
37 | $rootScope.$digest();
38 | expect(element.html()).to.not.contain('Not agreed yet');
39 | expect(element.html()).to.contain('Already agreed');
40 | });
41 |
42 | it('should handle empty value correctly', function() {
43 | $cookies.put('angular-consent.test', '');
44 | var markup = '';
45 | markup += 'Not agreed yet
';
46 | markup += 'Already agreed
';
47 | markup += '';
48 | var $scope = $rootScope.$new();
49 | var element = $compile(markup)($scope);
50 | $rootScope.$digest();
51 | expect(element.html()).to.contain('Not agreed yet');
52 | expect(element.html()).to.not.contain('Already agreed');
53 | });
54 |
55 | });
56 |
--------------------------------------------------------------------------------