├── .gitattributes
├── .bowerrc
├── .gitignore
├── .jsbeautifyrc
├── lib
├── selectcomposite.constants.js
├── selectoption.typedef.js
├── constants.js
├── expiryselect.constants.js
├── monthselect.constants.js
├── yearselect.constants.js
├── main.js
├── yearselect.controller.js
├── monthselect.controller.js
├── monthselect.directive.js
├── yearselect.directive.js
├── selectcomposite.directive.js
├── genericselect.controller.js
├── expiryselect.directive.js
└── genericselect.directive.js
├── .editorconfig
├── .jshintrc
├── example
├── expiryselect.html
├── selectcomposite.html
├── year.html
└── month.html
├── LICENSE
├── bower.json
├── package.json
├── README.md
├── gulpfile.js
└── date-elements.min.js
/.gitattributes:
--------------------------------------------------------------------------------
1 | example/* linguist-documentation
2 |
--------------------------------------------------------------------------------
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "bower_components",
3 | "json": "bower.json"
4 | }
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # General
2 | /coverage
3 | *.log
4 |
5 | # Node
6 | /node_modules
7 |
8 | # Bower
9 | /bower_components
10 |
11 | # IDEs
12 | /.idea
13 |
--------------------------------------------------------------------------------
/.jsbeautifyrc:
--------------------------------------------------------------------------------
1 | {
2 | "indent_char": " ",
3 | "indent_size": 2,
4 | "preserve_newlines": false,
5 | "jslint_happy": true,
6 | "wrap_line_length": 110
7 | }
8 |
--------------------------------------------------------------------------------
/lib/selectcomposite.constants.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.provide('leodido.constants.SelectComposite');
4 |
5 | leodido.constants.SelectComposite = {};
6 | /** @const */
7 | leodido.constants.SelectComposite.DIRECTIVE_NAME = 'selectComposite';
8 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 |
5 | indent_style = space
6 | indent_size = 2
7 |
8 | end_of_line = lf
9 | charset = utf-8
10 | trim_trailing_whitespace = true
11 | insert_final_newline = true
12 |
13 | [*.md]
14 | trim_trailing_whitespace = false
15 |
--------------------------------------------------------------------------------
/lib/selectoption.typedef.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.provide('leodido.typedef.SelectOption');
4 |
5 | /**
6 | * A complex type representing each option of the select
7 | *
8 | * @typedef SelectOption
9 | * @property {!number} index
10 | * @property {!string} label
11 | * @property {!string} value
12 | */
13 | var SelectOption;
14 |
--------------------------------------------------------------------------------
/lib/constants.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.provide('leodido.constants');
4 |
5 | goog.require('leodido.constants.MonthSelect');
6 | goog.require('leodido.constants.YearSelect');
7 | goog.require('leodido.constants.SelectComposite');
8 | goog.require('leodido.constants.ExpirySelect');
9 |
10 | leodido.constants.Module = {};
11 | /** @const */
12 | leodido.constants.Module.NAME = 'leodido.dateElements';
13 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "globalstrict": true,
3 | "expr": true,
4 | "globals": {
5 | "document": false,
6 | "console": false,
7 | "angular": false,
8 | "goog": false,
9 | "jasmine": false,
10 | "describe": false,
11 | "it": false,
12 | "beforeEach": false,
13 | "expect": false,
14 | "require": false,
15 | "process": false,
16 | "__dirname": false,
17 | "leodido": false
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/lib/expiryselect.constants.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.provide('leodido.constants.ExpirySelect');
4 |
5 | leodido.constants.ExpirySelect = {};
6 | /** @const */
7 | leodido.constants.ExpirySelect.DIRECTIVE_NAME = 'expirySelect';
8 | /** @const */
9 | leodido.constants.ExpirySelect.DEFAULT_NAME = 'expiry';
10 | /** @const */
11 | leodido.constants.ExpirySelect.DEFAULT_MONTH_NAME = 'month';
12 | /** @const */
13 | leodido.constants.ExpirySelect.DEFAULT_YEAR_NAME = 'year';
14 |
--------------------------------------------------------------------------------
/lib/monthselect.constants.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.provide('leodido.constants.MonthSelect');
4 |
5 | leodido.constants.MonthSelect = {};
6 |
7 | /** @const */
8 | leodido.constants.MonthSelect.DIRECTIVE_NAME = 'monthSelect';
9 | /** @const */
10 | leodido.constants.MonthSelect.CONTROLLER_NAME = 'MonthSelectController';
11 | /** @const */
12 | leodido.constants.MonthSelect.FORMATS = [
13 | 'MMMM', // Month in year (January-December)
14 | 'MMM', // Month in year (Jan-Dec)
15 | 'MM', // Month in year, padded (01-12)
16 | 'M' // Month in year (1-12)
17 | ];
18 | /** @const */
19 | leodido.constants.MonthSelect.DEFAULT_FORMAT = leodido.constants.MonthSelect.FORMATS[2];
20 | /** @const */
21 | leodido.constants.MonthSelect.DEFAULT_FIRST = '0';
22 | /** @const */
23 | leodido.constants.MonthSelect.DEFAULT_LAST = '11';
24 |
--------------------------------------------------------------------------------
/lib/yearselect.constants.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.provide('leodido.constants.YearSelect');
4 |
5 | leodido.constants.YearSelect = {};
6 |
7 | /** @const */
8 | leodido.constants.YearSelect.DIRECTIVE_NAME = 'yearSelect';
9 | /** @const */
10 | leodido.constants.YearSelect.CONTROLLER_NAME = 'YearSelectController';
11 | /** @const */
12 | leodido.constants.YearSelect.FORMATS = [
13 | 'yyyy', // 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010)
14 | 'yy', // 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10)
15 | 'y' // 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199)
16 | ];
17 | /** @const */
18 | leodido.constants.YearSelect.DEFAULT_FORMAT = leodido.constants.YearSelect.FORMATS[0];
19 | /** @const */
20 | leodido.constants.YearSelect.DEFAULT_FIRST = '' + new Date().getFullYear();
21 | /** @const */
22 | leodido.constants.YearSelect.DEFAULT_RANGE = 10;
23 |
--------------------------------------------------------------------------------
/example/expiryselect.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | ExpirySelect Directive
7 |
8 |
9 |
15 |
16 |
17 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/lib/main.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | //goog.provide('leodido.Main');
4 |
5 | goog.require('leodido.constants');
6 | goog.require('leodido.directive.MonthSelectFactory');
7 | goog.require('leodido.controller.MonthSelect');
8 | goog.require('leodido.directive.YearSelectFactory');
9 | goog.require('leodido.controller.YearSelect');
10 | goog.require('leodido.directive.SelectCompositeFactory');
11 | goog.require('leodido.directive.ExpirySelectFactory');
12 |
13 | angular
14 | .module(leodido.constants.Module.NAME, [])
15 | .directive(leodido.constants.ExpirySelect.DIRECTIVE_NAME, leodido.directive.ExpirySelectFactory)
16 | .directive(leodido.constants.SelectComposite.DIRECTIVE_NAME, leodido.directive.SelectCompositeFactory)
17 | .controller(leodido.constants.MonthSelect.CONTROLLER_NAME, leodido.controller.MonthSelect)
18 | .directive(leodido.constants.MonthSelect.DIRECTIVE_NAME, leodido.directive.MonthSelectFactory)
19 | .controller(leodido.constants.YearSelect.CONTROLLER_NAME, leodido.controller.YearSelect)
20 | .directive(leodido.constants.YearSelect.DIRECTIVE_NAME, leodido.directive.YearSelectFactory);
21 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Leonardo Di Donato
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 |
--------------------------------------------------------------------------------
/example/selectcomposite.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | SelectComposite Directive
7 |
8 |
9 |
12 |
13 |
14 |
15 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/lib/yearselect.controller.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.provide('leodido.controller.YearSelect');
4 |
5 | goog.require('leodido.controller.GenericSelect');
6 |
7 | /**
8 | * YearSelect directive controller
9 | *
10 | * @param {!angular.Scope} $scope
11 | * @param {!angular.JQLite} $element
12 | * @param {!angular.Attributes} $attrs
13 | * @constructor
14 | * @extends {leodido.controller.GenericSelect}
15 | * @ngInject
16 | */
17 | leodido.controller.YearSelect = function ($scope, $element, $attrs) {
18 | goog.DEBUG && console.log('YearSelectController::constructor', $scope);
19 | var date = $element.injector().get('dateFilter');
20 | // Privileged methods
21 | /**
22 | * Format a year
23 | * Year have to be expressed as a 4 digit integer.
24 | *
25 | * @param {!number} year
26 | * @return {!string}
27 | */
28 | this.formatYear = function (year) {
29 | /** @type {string} */
30 | $scope.format;
31 | return date(new Date(year.toString()), $scope.format);
32 | };
33 | //
34 | goog.base(this, $scope, $element, $attrs);
35 | };
36 | goog.inherits(leodido.controller.YearSelect, leodido.controller.GenericSelect);
37 |
38 | /**
39 | * @inheritDoc
40 | */
41 | leodido.controller.YearSelect.prototype.getValue = function (index) {
42 | return index.toString();
43 | };
44 |
45 | /**
46 | * @inheritDoc
47 | */
48 | leodido.controller.YearSelect.prototype.getLabel = function (index) {
49 | return this.formatYear(index);
50 | };
51 |
--------------------------------------------------------------------------------
/lib/monthselect.controller.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.provide('leodido.controller.MonthSelect');
4 |
5 | goog.require('leodido.controller.GenericSelect');
6 |
7 | /**
8 | * MonthSelect directive controller
9 | *
10 | * @param {!angular.Scope} $scope
11 | * @param {!angular.JQLite} $element
12 | * @param {!angular.Attributes} $attrs
13 | * @constructor
14 | * @extends {leodido.controller.GenericSelect}
15 | * @ngInject
16 | */
17 | leodido.controller.MonthSelect = function ($scope, $element, $attrs) {
18 | goog.DEBUG && console.log('MonthSelectController::constructor', $scope);
19 | var date = $element.injector().get('dateFilter');
20 | // Privileged methods
21 | /**
22 | * Format a month
23 | * Input have to be expressed as a zero indexed integer.
24 | *
25 | * @param {!number} month
26 | * @return {!string}
27 | */
28 | this.formatMonth = function (month) {
29 | /** @type {string} */
30 | $scope.format;
31 | return date(new Date().setMonth(month), $scope.format);
32 | };
33 | //
34 | goog.base(this, $scope, $element, $attrs);
35 | };
36 | goog.inherits(leodido.controller.MonthSelect, leodido.controller.GenericSelect);
37 |
38 | /**
39 | * @inheritDoc
40 | */
41 | leodido.controller.MonthSelect.prototype.getValue = function (index) {
42 | return (index + 1).toString();
43 | };
44 |
45 | /**
46 | * @inheritDoc
47 | */
48 | leodido.controller.MonthSelect.prototype.getLabel = function (index) {
49 | return this.formatMonth(index);
50 | };
51 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ng-date-elements",
3 | "description": "AngularJS directives for date elements",
4 | "version": "0.4.0",
5 | "authors": [
6 | "Leo Di Donato (http://git.io/leodido)"
7 | ],
8 | "main": "date-elements.min.js",
9 | "license": "MIT",
10 | "ignore": [
11 | "**/.*",
12 | "node_modules",
13 | "bower_components",
14 | "test",
15 | "coverage",
16 | "example",
17 | "gulpfile.js",
18 | "bower.json",
19 | "package.json",
20 | "lib"
21 | ],
22 | "dependencies": {
23 | "angular": "~1.3.0"
24 | },
25 | "devDependencies": {
26 | "angular-mocks": "~1.3.0",
27 | "closure-library": "google/closure-library",
28 | "closure-compiler": "http://dl.google.com/closure-compiler/compiler-latest.zip",
29 | "closure-angularjs-externs": "https://raw.githubusercontent.com/google/closure-compiler/master/contrib/externs/angular-1.3.js",
30 | "closure-angularjs-q_templated-externs": "https://raw.githubusercontent.com/google/closure-compiler/master/contrib/externs/angular-1.3-q_templated.js",
31 | "closure-angularjs-http-promise_templated-externs": "https://raw.githubusercontent.com/google/closure-compiler/master/contrib/externs/angular-1.3-http-promise_templated.js"
32 | },
33 | "keywords": [
34 | "date",
35 | "select",
36 | "input",
37 | "day",
38 | "month",
39 | "year",
40 | "time",
41 | "datetime",
42 | "time",
43 | "angular",
44 | "closure",
45 | "gulp"
46 | ]
47 | }
48 |
--------------------------------------------------------------------------------
/example/year.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | YearSelect Directive
7 |
8 |
9 |
26 |
27 |
28 |
50 |
51 |
52 |
--------------------------------------------------------------------------------
/lib/monthselect.directive.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.provide('leodido.directive.MonthSelectFactory');
4 |
5 | goog.require('leodido.directive.GenericSelect');
6 | goog.require('leodido.constants.MonthSelect');
7 |
8 | /**
9 | * MonthSelect directive
10 | *
11 | * @constructor
12 | * @extends {leodido.directive.GenericSelect}
13 | */
14 | leodido.directive.MonthSelect = function () {
15 | goog.base(this);
16 | goog.DEBUG && console.log('MonthSelectDirective::constructor');
17 | };
18 | goog.inherits(leodido.directive.MonthSelect, leodido.directive.GenericSelect);
19 |
20 | /**
21 | * @inheritDoc
22 | */
23 | leodido.directive.MonthSelect.prototype.prelink = function (scope, iElem, iAttrs) {
24 | /* jshint -W069 */
25 | // Settings (attributes and related scope variables) checking
26 | iAttrs.$set('first', leodido.constants.MonthSelect.DEFAULT_FIRST);
27 | iAttrs.$set('last', leodido.constants.MonthSelect.DEFAULT_LAST);
28 | var filter = iElem.injector().get('filterFilter');
29 | if (filter(leodido.constants.MonthSelect.FORMATS, iAttrs['format'], true).length !== 1) {
30 | iAttrs.$set('format', leodido.constants.MonthSelect.DEFAULT_FORMAT);
31 | }
32 | };
33 |
34 | /**
35 | * MonthSelect directive factory
36 | *
37 | * @returns {!angular.Directive} Directive definition object
38 | * @constructor
39 | */
40 | leodido.directive.MonthSelectFactory = function () {
41 | goog.DEBUG && console.log('MonthSelectFactory::constructor');
42 | return (new leodido.directive.MonthSelect())
43 | .setDirective(leodido.constants.MonthSelect.DIRECTIVE_NAME)
44 | .setController(leodido.constants.MonthSelect.CONTROLLER_NAME)
45 | .getDefinition();
46 | };
47 |
--------------------------------------------------------------------------------
/example/month.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | MonthSelect Directive
7 |
8 |
9 |
26 |
27 |
28 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ng-date-elements",
3 | "version": "0.4.0",
4 | "description": "AngularJS directives for date elements",
5 | "main": "date-elements.min.js",
6 | "author": {
7 | "name": "Leo Di Donato",
8 | "email": "leodidonato@gmail.com",
9 | "url": "http://git.io/leodido"
10 | },
11 | "license": "MIT",
12 | "repository": {
13 | "type": "git",
14 | "url": "http://github.com/leodido/ng-date-elements.git"
15 | },
16 | "homepage": "http://github.com/leodido/ng-date-elements",
17 | "devDependencies": {
18 | "bower": "~1.3.12",
19 | "del": "^1.0.0",
20 | "gulp": "~3.8.10",
21 | "gulp-bump": "^0.1.13",
22 | "gulp-closure-compiler": "~0.2.17",
23 | "gulp-connect": "~2.2.0",
24 | "gulp-debug": "^2.0.0",
25 | "gulp-help": "^1.3.1",
26 | "gulp-jshint": "~1.9.0",
27 | "gulp-util": "~3.0.0",
28 | "jasmine-spec-reporter": "~2.1.0",
29 | "karma": "~0.12.31",
30 | "karma-chrome-launcher": "~0.1.7",
31 | "karma-coverage": "~0.2.7",
32 | "karma-firefox-launcher": "~0.1.4",
33 | "karma-jasmine": "~0.3.5",
34 | "karma-phantomjs-launcher": "~0.1.4",
35 | "karma-spec-reporter": "~0.0.16",
36 | "minimist": "~1.1.0",
37 | "protractor": "^1.7.0",
38 | "run-sequence": "^1.0.2"
39 | },
40 | "scripts": {
41 | "postinstall": "./node_modules/.bin/bower install",
42 | "production": "./node_modules/.bin/gulp build --env production --banner",
43 | "development": "./node_modules/.bin/gulp build --env development --banner",
44 | "unit": "./node_modules/karma/bin/karma start karma.conf.js",
45 | "e2e": "(./node_modules/protractor/bin/webdriver-manager update) && (./node_modules/protractor/bin/protractor protractor.conf.js)"
46 | },
47 | "keywords": [
48 | "date",
49 | "select",
50 | "input",
51 | "day",
52 | "month",
53 | "year",
54 | "time",
55 | "datetime",
56 | "time",
57 | "angular",
58 | "closure",
59 | "gulp"
60 | ],
61 | "directories": {
62 | "lib": "./lib",
63 | "example": "./example"
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/lib/yearselect.directive.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.provide('leodido.directive.YearSelectFactory');
4 |
5 | goog.require('leodido.directive.GenericSelect');
6 | goog.require('leodido.constants.YearSelect');
7 |
8 | /**
9 | * YearSelect directive
10 | *
11 | * @constructor
12 | * @extends {leodido.directive.GenericSelect}
13 | */
14 | leodido.directive.YearSelect = function () {
15 | goog.base(this);
16 | goog.DEBUG && console.log('YearSelectDirective::constructor');
17 | };
18 | goog.inherits(leodido.directive.YearSelect, leodido.directive.GenericSelect);
19 |
20 | /**
21 | * @inheritDoc
22 | */
23 | leodido.directive.YearSelect.prototype.prelink = function (scope, iElem, iAttrs, controllers) {
24 | /* jshint -W069 */
25 | // Settings (attributes and related scope variables) checking
26 | var first,
27 | last,
28 | filter = iElem.injector().get('filterFilter');
29 | if (!/^\d{4}$/.test(iAttrs['first'])) {
30 | first = leodido.constants.YearSelect.DEFAULT_FIRST;
31 | iAttrs.$set('first', first);
32 | } else {
33 | first = iAttrs['first'];
34 | }
35 | first = + first;
36 | if (!/^\d{4}$/.test(iAttrs['last'])) {
37 | last = '' + (first + leodido.constants.YearSelect.DEFAULT_RANGE);
38 | iAttrs.$set('last', last);
39 | } else {
40 | last = iAttrs['last'];
41 | }
42 | last = + last;
43 | if (first > last) {
44 | throw new Error('Last year must be greather than the first year (i.e., ' + first + '); received: ' + last);
45 | }
46 | if (filter(leodido.constants.YearSelect.FORMATS, iAttrs['format'], true).length !== 1) {
47 | iAttrs.$set('format', leodido.constants.YearSelect.DEFAULT_FORMAT);
48 | }
49 | };
50 |
51 | /**
52 | * YearSelect directive factory
53 | *
54 | * @returns {!angular.Directive} Directive definition object
55 | * @constructor
56 | */
57 | leodido.directive.YearSelectFactory = function () {
58 | goog.DEBUG && console.log('YearSelectFactory::constructor');
59 | return (new leodido.directive.YearSelect())
60 | .setDirective(leodido.constants.YearSelect.DIRECTIVE_NAME)
61 | .setController(leodido.constants.YearSelect.CONTROLLER_NAME)
62 | .getDefinition();
63 | };
64 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | Date elements
2 | =============
3 |
4 | **AngularJS select directives for date elements**.
5 |
6 | []()
7 |
8 | ### Directives:
9 |
10 | - MonthSelect
11 | - YearSelect
12 | - SelectComposite
13 | - ExpirySelect
14 |
15 | *WIP*
16 |
17 | Usage
18 | -----
19 |
20 | *WIP*
21 |
22 | Install
23 | -------
24 |
25 | Install it via `bower`.
26 |
27 | ```
28 | bower install ng-date-elements
29 | ```
30 |
31 | Or, you can clone this repo and install it locally (you will need `npm`, of course).
32 |
33 | ```
34 | $ git clone git@github.com:leodido/ng-date-elements.git
35 | $ cd ng-date-elements/
36 | $ npm install
37 | ```
38 |
39 | Otherwise you can simply grab `date-elements.min.js` file in the repository root, and include it together with angular (~1.3) in your HTML page.
40 |
41 | Build
42 | -----
43 |
44 | Build is handled through [Gulp](https://github.com/gulpjs/gulp/) and performed mainly via [Google Closure Compiler](https://github.com/google/closure-compiler).
45 |
46 | Need help? Run `gulp help` !
47 |
48 | ```
49 | # Usage
50 | # gulp [task]
51 | #
52 | # Available tasks
53 | # build Build the library
54 | # --banner Prepend banner to the built file
55 | # --env=production|development Kind of build to perform, defaults to production
56 | # bump Bump version up for a new release
57 | # --level=major|minor|patch|prerelease Version level to bump
58 | # clean Clean build directory
59 | # help Display this help text
60 | # lint Lint JS source files
61 | # version Print the library version
62 | ```
63 |
64 | To build a development version (logging not disabled, sourcemaps file) of JS lib:
65 |
66 | ```
67 | $ gulp build --env dev
68 | ```
69 |
70 | Or, also:
71 |
72 | ```
73 | $ npm run development
74 | ```
75 |
76 | Rather to build a production ready code:
77 |
78 | ```
79 | $ npm run production
80 | ````
81 |
82 | ---
83 |
84 | [](https://github.com/igrigorik/ga-beacon)
85 |
--------------------------------------------------------------------------------
/lib/selectcomposite.directive.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.provide('leodido.directive.SelectCompositeFactory');
4 |
5 | /**
6 | * A directive for composite selects
7 | * It allows the construction of a group of select directives
8 | *
9 | * @constructor
10 | */
11 | leodido.directive.SelectComposite = function () {
12 | goog.DEBUG && console.log('SelectCompositeDirective::constructor');
13 | };
14 |
15 | /**
16 | * Retrieve the DDO
17 | *
18 | * @return {!angular.Directive}
19 | */
20 | leodido.directive.SelectComposite.prototype.getDefinition = function () {
21 | return {
22 | restrict: 'AC',
23 | transclude: true,
24 | replace: false,
25 | template: '
',
26 | controller: this.controller
27 | };
28 | };
29 |
30 | /**
31 | * SelectComposite controller
32 | *
33 | * @param {!angular.Scope} $scope
34 | * @param {!angular.Attributes} $attrs
35 | * @ngInject
36 | */
37 | leodido.directive.SelectComposite.prototype.controller = function ($scope, $attrs) {
38 | goog.DEBUG && console.log('SelectCompositeDirective::controller');
39 | /** @type {string} */
40 | $attrs.options;
41 | /**
42 | * Contains the value of the options attribute's expression
43 | *
44 | * @expose
45 | */
46 | $scope.options = $scope.$eval($attrs.options);
47 | /**
48 | * Keeps track of the selects
49 | *
50 | * @type {!Array}
51 | */
52 | this.selects = [];
53 | /**
54 | * Add a select to the select list
55 | * Use it from the select directive to add itself to the select list.
56 | *
57 | * @param {!angular.Scope} selectScope
58 | * @expose
59 | */
60 | this.addSelect = function (selectScope) {
61 | var that = this;
62 | //
63 | this.selects.push(selectScope);
64 | // Handle destroy
65 | selectScope.$on('$destroy', function (event) {
66 | that.removeSelect(selectScope);
67 | });
68 | };
69 | /**
70 | * Remove a select from the select list
71 | * Called from the select directive when to remove itself (i.e., on destroy).
72 | *
73 | * @param {!angular.Scope} selectScope
74 | * @expose
75 | */
76 | this.removeSelect = function (selectScope) {
77 | var index = this.selects.indexOf(selectScope);
78 | if (index !== -1) {
79 | this.selects.splice(index, 1);
80 | }
81 | };
82 | };
83 |
84 | /**
85 | * SelectComposite directive factory
86 | *
87 | * @returns {!angular.Directive} Directive definition object
88 | * @constructor
89 | */
90 | leodido.directive.SelectCompositeFactory = function () {
91 | goog.DEBUG && console.log('SelectCompositeFactory::constructor');
92 | return (new leodido.directive.SelectComposite()).getDefinition();
93 | };
94 |
--------------------------------------------------------------------------------
/lib/genericselect.controller.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.provide('leodido.controller.GenericSelect');
4 |
5 | goog.require('leodido.typedef.SelectOption');
6 |
7 | /**
8 | * Controller for GenericSelect directives
9 | *
10 | * @param {!angular.Scope=} $scope
11 | * @param {!angular.JQLite=} $element
12 | * @param {!angular.Attributes=} $attrs
13 | * @constructor
14 | * @ngInject
15 | */
16 | leodido.controller.GenericSelect = function ($scope, $element, $attrs) {
17 | goog.DEBUG && console.log('GenericSelectController::constructor');
18 | var self = this,
19 | filter = $element.injector().get('filterFilter');
20 | // Privileged methods
21 | /**
22 | * Setup the initial state of the directive
23 | */
24 | this.setup = function () {
25 | goog.DEBUG && console.log('GenericSelectController::setup', $scope);
26 | $scope.element = $scope.element || {};
27 | /**
28 | * Options array
29 | *
30 | * @expose
31 | * @type {Array.}
32 | */
33 | $scope.element.opts = [];
34 | for (var i = self.getFirst(), ii = self.getLast(); i <= ii; i++) {
35 | $scope.element.opts.push({
36 | index: i,
37 | label: self.getLabel(i),
38 | value: self.getValue(i)
39 | });
40 | }
41 | };
42 | /**
43 | * Validate option
44 | *
45 | * @param {SelectOption} option
46 | * @return {!boolean}
47 | */
48 | this.isValid = function (option) {
49 | return angular.isDefined(option) &&
50 | option.index >= this.getFirst() &&
51 | option.index <= this.getLast() &&
52 | option.value === this.getValue(option.index) &&
53 | option.label === this.getLabel(option.index);
54 | };
55 | /**
56 | * Search options by pair key/value
57 | *
58 | * @param {String} key
59 | * @param {String} value
60 | * @return Array.{SelectOption}
61 | */
62 | this.searchOptions = function (key, value) {
63 | var target = {};
64 | target[key] = value;
65 | return filter($scope.element.opts, target, true);
66 | };
67 | /**
68 | * Retrive the index of the first option
69 | *
70 | * @return {!number}
71 | */
72 | this.getFirst = function () {
73 | /** @type {!string} first */
74 | $scope.first;
75 | return + $scope.first;
76 | };
77 | /**
78 | * Retrieve the index of the last option
79 | *
80 | * @return {!number}
81 | */
82 | this.getLast = function () {
83 | /** @type {!string} last */
84 | $scope.last;
85 | return + $scope.last;
86 | };
87 | };
88 |
89 | /**
90 | * Retrieve the label of an option
91 | *
92 | * @param {!number} index The option index
93 | * @returns {!string}
94 | */
95 | leodido.controller.GenericSelect.prototype.getLabel = goog.abstractMethod;
96 |
97 | /**
98 | * Retrive the value of an option (i.e. the model value)
99 | *
100 | * @param {!number} index The option index
101 | * @returns {!string}
102 | */
103 | leodido.controller.GenericSelect.prototype.getValue = goog.abstractMethod;
104 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var gulp = require('gulp'),
4 | debug = require('gulp-debug'),
5 | comp = require('gulp-closure-compiler'),
6 | jshint = require('gulp-jshint'),
7 | minimist = require('minimist'),
8 | gutil = require('gulp-util'),
9 | bump = require('gulp-bump'),
10 | del = require('del'),
11 | sequence = require('run-sequence'),
12 | connect = require('gulp-connect'),
13 | pack = require('./package.json'),
14 | banner = [
15 | '/*',
16 | ' * Copyright (c) ' + new Date().getFullYear() + ', ' + pack.author.name + ' <' + pack.author.email + '>',
17 | ' * ' + pack.main + ' - ' + pack.description,
18 | ' * @version '+ pack.version,
19 | ' * @link ' + pack.homepage,
20 | ' * @license ' + pack.license,
21 | ' */'
22 | ].join('\n');
23 | gulp = gulp = require('gulp-help')(gulp, {
24 | description: 'Display this help text'
25 | });
26 |
27 | var knownFlags = {
28 | 'boolean': ['banner'],
29 | 'string': ['env', 'level'],
30 | 'default': {
31 | env: 'production',
32 | banner: false,
33 | level: 'patch'
34 | },
35 | 'alias': { e: 'env', b: 'banner', l: 'level' }
36 | },
37 | flags = minimist(process.argv.slice(2), knownFlags),
38 | productionBuild = function(value) {
39 | switch(value) {
40 | case 'prod':
41 | case 'production':
42 | return true;
43 | case 'dev':
44 | case 'development':
45 | return false;
46 | default:
47 | return true;
48 | }
49 | },
50 | getVersionLevel = function() {
51 | if (['major', 'minor', 'patch', 'prerelease'].indexOf(flags.level) === -1) {
52 | flags.level = 'patch';
53 | }
54 | return flags.level;
55 | };
56 |
57 | var build = {
58 | compiler: './bower_components/closure-compiler/compiler.jar',
59 | filename: pack.main,
60 | externs: [
61 | './bower_components/closure-angularjs-externs/index.js',
62 | './bower_components/closure-angularjs-q_templated-externs/index.js',
63 | './bower_components/closure-angularjs-http-promise_templated-externs/index.js'
64 | ],
65 | src: pack.directories.lib + '/*.js',
66 | deps: [
67 | 'bower_components/closure-library/closure/goog/base.js'
68 | ]
69 | };
70 |
71 | gulp.task('version', 'Print the library version', [], function() {
72 | return gutil.log('Library', gutil.colors.magenta(pack.name) + ',', gutil.colors.magenta(pack.version));
73 | });
74 |
75 | gulp.task('lint', 'Lint JS source files', [], function() {
76 | return gulp.src(build.src)
77 | .pipe(jshint('./.jshintrc'))
78 | .pipe(jshint.reporter('default'));
79 | });
80 |
81 | gulp.task('minify', false, [], function() {
82 | var isProduction = productionBuild(flags.env),
83 | sourcemap = build.filename + '.map',
84 | wrapper = (flags.banner ? banner + '\n': '') +
85 | '(function(){%output%})();' +
86 | (isProduction ? '' : '\n//# sourceMappingURL=' + sourcemap);
87 |
88 | var compilerFlags = {
89 | // closure_entry_point: 'leodido.Main',
90 | // only_closure_dependencies: true,
91 | compilation_level: 'ADVANCED_OPTIMIZATIONS',
92 | language_in: 'ECMASCRIPT3',
93 | angular_pass: true,
94 | formatting: 'SINGLE_QUOTES',
95 | externs: build.externs,
96 | generate_exports: true,
97 | define: [
98 | 'goog.DEBUG=' + (isProduction ? 'false' : 'true')
99 | ],
100 | output_wrapper: wrapper,
101 | warning_level: 'VERBOSE'
102 | };
103 | if (!isProduction) {
104 | compilerFlags.create_source_map = sourcemap;
105 | }
106 |
107 | return gulp.src(build.deps.concat(build.src))
108 | .pipe(debug({title: 'File: '}))
109 | .pipe(comp({
110 | compilerPath: build.compiler,
111 | fileName: build.filename,
112 | compilerFlags: compilerFlags
113 | }));
114 | });
115 |
116 | //gulp.task('prova', false, [], function () {
117 | // var isProduction = productionBuild(flags.env);
118 | // var wrapper = (flags.banner ? banner + '\n': '');
119 | // wrapper += '(function(){';
120 | // wrapper += '\n';
121 | // wrapper += '%output%})();'; // +
122 | // // (isProduction ? '' : '\n//# sourceMappingURL=' + sourcemap);
123 | //
124 | // var compilerFlags = {
125 | //// closure_entry_point: 'leodido.Main',
126 | // compilation_level: 'SIMPLE_OPTIMIZATIONS',
127 | // language_in: 'ECMASCRIPT3',
128 | // angular_pass: true,
129 | // formatting: ['SINGLE_QUOTES', 'PRETTY_PRINT'],
130 | // externs: build.externs,
131 | // generate_exports: true,
132 | //// manage_closure_dependencies: true,
133 | //// only_closure_dependencies: true,
134 | // define: [
135 | // 'goog.DEBUG=' + (isProduction ? 'false' : 'true')
136 | // ],
137 | // output_wrapper: wrapper
138 | //// warning_level: 'VERBOSE'
139 | // };
140 | //
141 | // return gulp.src(build.src) // build.deps.concat(build.src))
142 | // .pipe(debug({title: 'File: '}))
143 | // .pipe(comp({
144 | // compilerPath: build.compiler,
145 | // fileName: build.directory + '/' + build.filename,
146 | // compilerFlags: compilerFlags
147 | // }));
148 | //});
149 |
150 | gulp.task('bump', 'Bump version up for a new release', function () {
151 | return gulp.src(['./bower.json', 'package.json'])
152 | .pipe(bump({ type: getVersionLevel() }))
153 | .pipe(gulp.dest('./'));
154 | }, {
155 | options: {
156 | 'level=major|minor|patch|prerelease': 'Version level to bump'
157 | }
158 | });
159 |
160 | gulp.task('clean', 'Clean build directory', function(cb) {
161 | del([build.filename, build.filename + '.map'], cb);
162 | });
163 |
164 | gulp.task('build', 'Build the library', [], function(cb) {
165 | return sequence(
166 | 'clean',
167 | 'lint',
168 | 'minify',
169 | cb);
170 | }, {
171 | options: {
172 | 'env=production|development': 'Kind of build to perform, defaults to production',
173 | 'banner': 'Prepend banner to the built file'
174 | }
175 | });
176 |
177 | gulp.task('connect', 'Create a server', function () {
178 | connect.server({
179 | port: 8000,
180 | livereload: true
181 | });
182 | });
183 |
184 | gulp.task('default', false, ['help']);
185 |
186 | // TODO
187 | // [ ] - beautified release file
188 |
--------------------------------------------------------------------------------
/lib/expiryselect.directive.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.provide('leodido.directive.ExpirySelectFactory');
4 |
5 | goog.require('leodido.constants.ExpirySelect');
6 |
7 | /**
8 | * Select directive for expiration data
9 | *
10 | * @constructor
11 | */
12 | leodido.directive.ExpirySelect = function () {
13 | goog.DEBUG && console.log('ExpirySelectDirective::constructor');
14 | };
15 |
16 | /**
17 | * Retrieve the DDO
18 | *
19 | * @return {!angular.Directive}
20 | */
21 | leodido.directive.ExpirySelect.prototype.getDefinition = function () {
22 | var self = this;
23 | return {
24 | restrict: 'AC',
25 | require: '?ngModel',
26 | replace: false,
27 | scope: {
28 | /**
29 | * @expose
30 | */
31 | getOptions: '&options',
32 | /**
33 | * @expose
34 | */
35 | name: '@'
36 | },
37 | template: [
38 | '',
41 | '
',
49 | '
',
59 | '
'
60 | ].join(''),
61 | controller: this.controller,
62 | compile: goog.bind(self.build, self)
63 | // link: goog.bind(self.postlink, self)
64 | };
65 | };
66 |
67 | /**
68 | * ExpirySelect controller function
69 | *
70 | * @param {!angular.Scope=} $scope
71 | * @ngInject
72 | */
73 | leodido.directive.ExpirySelect.prototype.controller = function ($scope) {
74 | goog.DEBUG && console.log('ExpirySelectDirective::controller', $scope);
75 | /**
76 | * @expose
77 | * @type {!Object}
78 | */
79 | $scope.expiry = $scope.expiry || {};
80 | /** @type {!Function} getOptions */
81 | $scope.getOptions;
82 | var options = $scope.getOptions() || {};
83 | /** @type {?string} name */
84 | $scope.name;
85 | // Extend/override options
86 | angular.extend(
87 | $scope,
88 | {
89 | /**
90 | * @expose
91 | */
92 | name: $scope.name || leodido.constants.ExpirySelect.DEFAULT_NAME,
93 | /**
94 | * @expose
95 | */
96 | getOptions: function () {
97 | // Assure objects exist
98 | options.month = options.month || {};
99 | options.year = options.year || {};
100 | // Create child names
101 | var mName = options.month.name || leodido.constants.ExpirySelect.DEFAULT_MONTH_NAME,
102 | yName = options.year.name || leodido.constants.ExpirySelect.DEFAULT_YEAR_NAME;
103 | mName = $scope.name + '[' + mName + ']';
104 | yName = $scope.name + '[' + yName + ']';
105 | // Assign child names
106 | options.month.name = mName;
107 | options.year.name = yName;
108 | // Return options
109 | return options;
110 | }
111 | }
112 | );
113 | // API
114 | this.setMonth = function (month) {
115 | $scope.expiry.month = month;
116 | return this;
117 | };
118 | this.setYear = function (year) {
119 | $scope.expiry.year = year;
120 | return this;
121 | };
122 | this.isPast = function (m, yyyy) {
123 | return Date.now() >= new Date(yyyy, m, 0);
124 | };
125 | };
126 |
127 | /**
128 | * ExpirySelect compile function
129 | *
130 | * @param {!angular.JQLite=} tElement Template element
131 | * @param {!angular.Attributes=} tAttrs Template attributes
132 | * @return {Function|angular.LinkingFunctions|undefined}
133 | * @ngInject
134 | */
135 | leodido.directive.ExpirySelect.prototype.build = function (tElement, tAttrs) {
136 | goog.DEBUG && console.log('ExpirySelectDirective::compile');
137 | // Force 'name' attribute (if it exists, also if empty) to be 'data-name' attribute
138 | if (angular.isDefined(tElement.attr('name'))) {
139 | tElement.attr('data-name', tElement.attr('name'));
140 | tAttrs.$attr.name = 'data-name'; // Needed to support interpolation that comes ...
141 | tElement.removeAttr('name');
142 | }
143 |
144 | var self = this;
145 | return goog.bind(self.postlink, self);
146 | };
147 |
148 | /**
149 | * ExpirySelect post-link function
150 | *
151 | * @param {!angular.Scope=} $scope
152 | * @param {!angular.JQLite=} $element
153 | * @param {!angular.Attributes=} $attrs
154 | * @param {!Object=} ngModelController
155 | * @ngInject
156 | */
157 | leodido.directive.ExpirySelect.prototype.postlink = function ($scope, $element, $attrs, ngModelController) {
158 | goog.DEBUG && console.log('ExpirySelectDirective::postlink');
159 |
160 | var controller = $element.data('$' + leodido.constants.ExpirySelect.DIRECTIVE_NAME + 'Controller');
161 | // Capture selections
162 | $scope.$on($scope.options.month.name + '.selection', function (event, month) {
163 | controller.setMonth(month);
164 | });
165 | $scope.$on($scope.options.year.name + '.selection', function (event, year) {
166 | controller.setYear(year);
167 | });
168 | // Watch month and year values and check if date is future (so it is a valid one) or not
169 | if (ngModelController) {
170 | $scope.$watchCollection('[expiry.month, expiry.year]', function (values) {
171 | var m = values[0],
172 | y = values[1],
173 | validity = m && y ? !controller.isPast(m.value, y.value) : false;
174 | ngModelController.$setValidity(leodido.constants.ExpirySelect.DEFAULT_NAME, validity);
175 | });
176 | }
177 | };
178 |
179 | leodido.directive.ExpirySelectFactory = function () {
180 | goog.DEBUG && console.log('ExpirySelectFactory::constructor');
181 | return (new leodido.directive.ExpirySelect()).getDefinition();
182 | };
183 |
--------------------------------------------------------------------------------
/date-elements.min.js:
--------------------------------------------------------------------------------
1 | /*
2 | * Copyright (c) 2015, Leo Di Donato
3 | * date-elements.min.js - AngularJS directives for date elements
4 | * @version 0.4.0
5 | * @link http://github.com/leodido/ng-date-elements
6 | * @license MIT
7 | */
8 | (function(){function e(a,b,c){return a.call.apply(a.bind,arguments)}function g(a,b,c){if(!a)throw Error();if(2
',controller:this.controller,
11 | compile:h(this.b,this)}};p.prototype.controller=function(a){a.expiry=a.expiry||{};var b=a.getOptions()||{};angular.extend(a,{name:a.name||'expiry',getOptions:function(){b.month=b.month||{};b.year=b.year||{};var c=b.month.name||'month',d=b.year.name||'year',c=a.name+'['+c+']',d=a.name+'['+d+']';b.month.name=c;b.year.name=d;return b}});this.setMonth=function(c){a.expiry.month=c;return this};this.setYear=function(c){a.expiry.year=c;return this};this.r=function(a,b){return Date.now()>=new Date(b,a,0)}};
12 | p.prototype.controller.$inject=['$scope'];p.prototype.b=function(a,b){angular.isDefined(a.attr('name'))&&(a.attr('data-name',a.attr('name')),b.$attr.name='data-name',a.removeAttr('name'));return h(this.j,this)};p.prototype.b.$inject=['tElement','tAttrs'];
13 | p.prototype.j=function(a,b,c,d){var f=b.data('$expirySelectController');a.$on(a.options.month.name+'.selection',function(a,c){f.setMonth(c)});a.$on(a.options.year.name+'.selection',function(a,c){f.setYear(c)});d&&a.$watchCollection('[expiry.month, expiry.year]',function(a){var c=a[0];a=a[1];d.$setValidity('expiry',c&&a?!f.r(c.value,a.value):!1)})};p.prototype.j.$inject=['$scope','$element','$attrs','ngModelController'];var q=['MMMM','MMM','MM','M'],r=q[2];function t(){}t.prototype.a=function(){return{restrict:'AC',transclude:!0,replace:!1,template:'
',controller:this.controller}};t.prototype.controller=function(a,b){a.options=a.$eval(b.options);this.f=[];this.addSelect=function(a){var b=this;this.f.push(a);a.$on('$destroy',function(){b.removeSelect(a)})};this.removeSelect=function(a){a=this.f.indexOf(a);-1!==a&&this.f.splice(a,1)}};t.prototype.controller.$inject=['$scope','$attrs'];function u(a,b){var c=this,d=b.injector().get('filterFilter');this.t=function(){a.element=a.element||{};a.element.opts=[];for(var b=c.h(),d=c.i();b<=d;b++)a.element.opts.push({index:b,label:c.c(b),value:c.d(b)})};this.s=function(a){return angular.isDefined(a)&&a.index>=this.h()&&a.index<=this.i()&&a.value===this.d(a.index)&&a.label===this.c(a.index)};this.k=function(b,c){var l={};l[b]=c;return d(a.element.opts,l,!0)};this.h=function(){return+a.first};this.i=function(){return+a.last}}
14 | u.$inject=['$scope','$element','$attrs'];function v(){var a='',b='',c='';this.g=function(){return b};this.q=function(){return c};this.p=function(){return a};this.m=function(a){if(/[^a-zA-Z]/.test(a))throw new TypeError('alpha string required; received "'+typeof a+'"');b=a;c=b.match(/([A-Z]?[^A-Z]*)/g).shift();return this};this.l=function(b){if(!angular.isString(b))throw new TypeError('string required; received "'+typeof b+'"');a=b;return this}}
15 | v.prototype.a=function(){return{restrict:'AC',replace:!0,require:[this.g(),'ngModel','?^^selectComposite'],scope:{emptyOption:'@',format:'@',first:'@',last:'@'},controller:this.p(),compile:h(this.b,this),template:'{{::emptyOption}} '}};
16 | v.prototype.b=function(a,b){angular.isDefined(a.attr('data-name'))&&(a.attr('name',a.attr('data-name')),b.$attr.name='name',a.removeAttr('data-name'));return{pre:h(this.pre,this),post:h(this.post,this)}};v.prototype.b.$inject=['tElement','tAttrs'];v.prototype.pre=function(a,b,c){this.e(a,b,c)};v.prototype.pre.$inject=['scope','iElem','iAttrs'];v.prototype.e=function(){};
17 | v.prototype.post=function(a,b,c,d){if(!(2>d.length)){var f=d[0],k=d[1];b=d[2];d=this.g();var l=this.q(),m=function(b){k.$selection=b;k.$name&&a.$emit(k.$name+'.selection',b)},x=function(a){var b=f.s(a);k.$setValidity(l,b);if(b)return m(a),a;m(null)};b&&b.addSelect(a);f.t();c.$observe(d,function(b){b=f.k('label',b);1===b.length&&(a.model=b[0])});c.$observe('value',function(b){b=f.k('value',b);1===b.length&&angular.isUndefined(a.model)&&(a.model=b[0])});k.$parsers.unshift(x);k.$formatters.unshift(x)}};
18 | v.prototype.post.$inject=['$scope','$element','$attrs','controllers'];function w(a,b){var c=b.injector().get('dateFilter');this.n=function(b){return c((new Date).setMonth(b),a.format)};u.call(this,a,b)}n(w,u);w.$inject=['$scope','$element','$attrs'];w.prototype.d=function(a){return(a+1).toString()};w.prototype.c=function(a){return this.n(a)};function y(){v.call(this)}n(y,v);y.prototype.e=function(a,b,c){c.$set('first','0');c.$set('last','11');1!==b.injector().get('filterFilter')(q,c.format,!0).length&&c.$set('format',r)};var z=['yyyy','yy','y'],A=z[0],B=''+(new Date).getFullYear();function C(a,b){var c=b.injector().get('dateFilter');this.o=function(b){return c(new Date(b.toString()),a.format)};u.call(this,a,b)}n(C,u);C.$inject=['$scope','$element','$attrs'];C.prototype.d=function(a){return a.toString()};C.prototype.c=function(a){return this.o(a)};function D(){v.call(this)}n(D,v);D.prototype.e=function(a,b,c){var d=b.injector().get('filterFilter');/^\d{4}$/.test(c.first)?a=c.first:(a=B,c.$set('first',a));a=+a;/^\d{4}$/.test(c.last)?b=c.last:(b=''+(a+10),c.$set('last',b));b=+b;if(a>b)throw Error('Last year must be greather than the first year (i.e., '+a+'); received: '+b);1!==d(z,c.format,!0).length&&c.$set('format',A)};angular.module('leodido.dateElements',[]).directive('expirySelect',function(){return(new p).a()}).directive('selectComposite',function(){return(new t).a()}).controller('MonthSelectController',w).directive('monthSelect',function(){return(new y).m('monthSelect').l('MonthSelectController').a()}).controller('YearSelectController',C).directive('yearSelect',function(){return(new D).m('yearSelect').l('YearSelectController').a()});})();
19 |
--------------------------------------------------------------------------------
/lib/genericselect.directive.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | goog.provide('leodido.directive.GenericSelect');
4 |
5 | goog.require('leodido.typedef.SelectOption');
6 |
7 | /**
8 | * A generic directive
9 | * It allows the construction of other select directives for specific date elements (e.g. month)
10 | *
11 | * @constructor
12 | */
13 | leodido.directive.GenericSelect = function () {
14 | // Privates
15 | /**
16 | * @type {!string}
17 | */
18 | var ctrlName = '';
19 | /**
20 | * @type {!string}
21 | */
22 | var directName = '';
23 | /**
24 | * @type {!string}
25 | */
26 | var elementName = '';
27 | // Privileged methods
28 | /**
29 | * Retrive the directive name
30 | *
31 | * @return {!string}
32 | */
33 | this.getDirective = function () {
34 | return directName;
35 | };
36 | /**
37 | * Retrieve the element name
38 | *
39 | * @return {!string}
40 | */
41 | this.getElement = function () {
42 | return elementName;
43 | };
44 | /**
45 | * Retrieve the controller name
46 | *
47 | * @return {!string}
48 | */
49 | this.getController = function () {
50 | return ctrlName;
51 | };
52 | /**
53 | * Set the directive name
54 | *
55 | * @param {!string} directiveName
56 | * @return {leodido.directive.GenericSelect}
57 | */
58 | this.setDirective = function (directiveName) {
59 | if (/[^a-zA-Z]/.test(directiveName)) {
60 | throw new TypeError('alpha string required; received "' + typeof directiveName + '"');
61 | }
62 | directName = directiveName;
63 | elementName = directName.match(/([A-Z]?[^A-Z]*)/g).shift();
64 | return this;
65 | };
66 | /**
67 | * Set the controller name
68 | *
69 | * @param {!string} controllerName
70 | * @return {leodido.directive.GenericSelect}
71 | */
72 | this.setController = function (controllerName) {
73 | if (!angular.isString(controllerName)) {
74 | throw new TypeError('string required; received "' + typeof controllerName + '"');
75 | }
76 | ctrlName = controllerName;
77 | return this;
78 | };
79 | };
80 |
81 | /**
82 | * Retrieve the DDO
83 | *
84 | * @return {!angular.Directive}
85 | */
86 | leodido.directive.GenericSelect.prototype.getDefinition = function () {
87 | var self = this;
88 | return {
89 | restrict: 'AC',
90 | replace: true,
91 | require: [
92 | self.getDirective(),
93 | 'ngModel',
94 | '?^^' + leodido.constants.SelectComposite.DIRECTIVE_NAME
95 | ],
96 | scope: {
97 | /**
98 | * Empty option
99 | * @expose
100 | * @type {!string}
101 | */
102 | emptyOption: '@',
103 | /**
104 | * Label format
105 | * @expose
106 | * @type {!string}
107 | */
108 | format: '@',
109 | /**
110 | * First index
111 | * @expose
112 | * @type {!string}
113 | */
114 | first: '@',
115 | /**
116 | * Last index
117 | * @expose
118 | * @type {!string}
119 | */
120 | last: '@'
121 | },
122 | controller: self.getController(),
123 | compile: goog.bind(self.build, self),
124 | // link: goog.bind(self.link, self),
125 | template: [
126 | '',
130 | '{{::emptyOption}} ',
131 | ' '
132 | ].join('')
133 | };
134 | };
135 |
136 | /**
137 | * GenericSelect compile function
138 | *
139 | * @param {!angular.JQLite=} tElement Template element
140 | * @param {!angular.Attributes=} tAttrs Template attributes
141 | * @return {Function|angular.LinkingFunctions|undefined}
142 | * @ngInject
143 | */
144 | leodido.directive.GenericSelect.prototype.build = function (tElement, tAttrs) {
145 | goog.DEBUG && console.log('GenericSelectDirective::compile');
146 | // Force 'data-name' attribute (if it exists, also if empty) to be 'name' attribute
147 | if (angular.isDefined(tElement.attr('data-name'))) {
148 | tElement.attr('name', tElement.attr('data-name'));
149 | tAttrs.$attr.name = 'name'; // Needed to support interpolation that comes ...
150 | tElement.removeAttr('data-name');
151 | }
152 |
153 | var self = this;
154 | return {
155 | pre: goog.bind(self.pre, self),
156 | post: goog.bind(self.post, self)
157 | };
158 | };
159 |
160 | /**
161 | * GenericSelect pre-link function
162 | *
163 | * @param {!angular.Scope=} scope
164 | * @param {!angular.JQLite=} iElem
165 | * @param {!angular.Attributes=} iAttrs
166 | * @ngInject
167 | */
168 | leodido.directive.GenericSelect.prototype.pre = function (scope, iElem, iAttrs) {
169 | /* jshint -W069 */
170 | this.prelink(scope, iElem, iAttrs);
171 | };
172 |
173 | /**
174 | * GenericSelect custom pre-link function
175 | *
176 | * @param {!angular.Scope=} scope
177 | * @param {!angular.JQLite=} iElem
178 | * @param {!angular.Attributes=} iAttrs
179 | */
180 | leodido.directive.GenericSelect.prototype.prelink = function (scope, iElem, iAttrs) {
181 | };
182 |
183 | /**
184 | * GenericSelect post-link function
185 | *
186 | * @param {!angular.Scope} $scope
187 | * @param {!angular.JQLite} $element
188 | * @param {!angular.Attributes} $attrs
189 | * @param {Array} controllers
190 | * @ngInject
191 | */
192 | leodido.directive.GenericSelect.prototype.post = function ($scope, $element, $attrs, controllers) {
193 | goog.DEBUG && console.log('GenericSelectDirective::link', $scope, controllers);
194 | if (controllers.length < 2) {
195 | return;
196 | }
197 | // Privates
198 | var directiveController = controllers[0];
199 | var modelController = controllers[1];
200 | var aggregateController = controllers[2];
201 | var directiveName = this.getDirective();
202 | var elementName = this.getElement();
203 | /**
204 | * Notify selected option
205 | *
206 | * @param {?SelectOption} option
207 | */
208 | var notify = function (option) {
209 | /**
210 | * @expose
211 | */
212 | modelController.$selection = option;
213 | modelController.$name && $scope.$emit(modelController.$name + '.selection', option);
214 | };
215 | /**
216 | * Handle selection change
217 | *
218 | * @param {?SelectOption} option
219 | * @return {?SelectOption}
220 | */
221 | var change = function (option) {
222 | var flag = directiveController.isValid(option);
223 | modelController.$setValidity(elementName, flag);
224 | if (flag) {
225 | notify(option);
226 | return option;
227 | }
228 | notify(null);
229 | return undefined;
230 | };
231 | // Setup
232 | aggregateController && aggregateController.addSelect($scope);
233 | directiveController.setup();
234 | // Attribute handling
235 | $attrs.$observe(directiveName, function (label) {
236 | var opts = directiveController.searchOptions('label', label);
237 | var wellFormatted = opts.length === 1;
238 | if (wellFormatted) {
239 | /**
240 | * @expose
241 | */
242 | $scope.model = opts[0];
243 | }
244 | });
245 | $attrs.$observe('value', function (value) {
246 | var opts = directiveController.searchOptions('value', value);
247 | var found = opts.length === 1;
248 | if (found && angular.isUndefined($scope.model)) {
249 | /**
250 | * @expose
251 | */
252 | $scope.model = opts[0];
253 | }
254 | });
255 | // Behaviour
256 | modelController.$parsers.unshift(change);
257 | modelController.$formatters.unshift(change);
258 | };
259 |
--------------------------------------------------------------------------------