├── .gitignore
├── .jshintrc
├── .travis.yml
├── CHANGELOG.md
├── LICENSE
├── README.md
├── bower.json
├── config
└── karma.conf.js
├── gulpfile.js
├── package.json
├── release
├── angular-br-filters.js
└── angular-br-filters.min.js
└── src
├── filters.js
└── filters.test.js
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 |
5 | # Runtime data
6 | pids
7 | *.pid
8 | *.seed
9 |
10 | # Dependency directory
11 | node_modules
12 | bower_components
13 |
14 | # Users Environment Variables
15 | .lock-wscript
16 |
17 | coverage
18 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | // --------------------------------------------------------------------
3 | // JSHint Configuration, Strict Edition
4 | // --------------------------------------------------------------------
5 | //
6 | // This is a options template for [JSHint][1], using [JSHint example][2]
7 | // and [Ory Band's example][3] as basis and setting config values to
8 | // be most strict:
9 | //
10 | // * set all enforcing options to true
11 | // * set all relaxing options to false
12 | // * set all environment options to false, except the browser value
13 | // * set all JSLint legacy options to false
14 | //
15 | // [1]: http://www.jshint.com/
16 | // [2]: https://github.com/jshint/node-jshint/blob/master/example/config.json
17 | // [3]: https://github.com/oryband/dotfiles/blob/master/jshintrc
18 | //
19 | // @author http://michael.haschke.biz/
20 | // @license http://unlicense.org/
21 |
22 | // == Enforcing Options ===============================================
23 | //
24 | // These options tell JSHint to be more strict towards your code. Use
25 | // them if you want to allow only a safe subset of JavaScript, very
26 | // useful when your codebase is shared with a big number of developers
27 | // with different skill levels.
28 |
29 | "bitwise" : false, // Prohibit bitwise operators (&, |, ^, etc.).
30 | "camelcase" : true, // Force all variable names to use either camelCase style or UPPER_CASE with underscores.
31 | "curly" : true, // Require {} for every new block or scope.
32 | "eqeqeq" : true, // Require triple equals i.e. `===`.
33 | "forin" : true, // Tolerate `for in` loops without `hasOwnPrototype`.
34 | "immed" : true, // Require immediate invocations to be wrapped in parens e.g. `( function(){}() );`
35 | "latedef" : true, // Prohibit variable use before definition.
36 | "maxcomplexity" : 10, // Lets you control cyclomatic complexity throughout your code.
37 | "maxdepth" : 4, // Lets you control how nested do you want your blocks to be
38 | "maxlen" : 120, // Lets you set the maximum length of a line.
39 | "maxparams" : false, // Lets you set the max number of formal parameters allowed per function
40 | "maxstatements" : 20, // Lets you set the max number of statements allowed per function
41 | "newcap" : true, // Require capitalization of all constructor functions e.g. `new F()`.
42 | "noarg" : true, // Prohibit use of `arguments.caller` and `arguments.callee`.
43 | "noempty" : true, // Prohibit use of empty blocks.
44 | "nonew" : true, // Prohibit use of constructors for side-effects.
45 | "plusplus" : false, // Prohibit use of `++` & `--`.
46 | "quotmark" : "single", // Enforces the consistency of quotation marks used throughout your code.
47 | "regexp" : true, // Prohibit `.` and `[^...]` in regular expressions.
48 | "undef" : true, // Require all non-global variables be declared before they are used.
49 | "unused" : true, // Prohibit neved used defined variables.
50 | "strict" : false, // Require `use strict` pragma in every file.
51 | "trailing" : true, // Prohibit trailing whitespaces.
52 |
53 | // == Relaxing Options ================================================
54 | //
55 | // These options allow you to suppress certain types of warnings. Use
56 | // them only if you are absolutely positive that you know what you are
57 | // doing.
58 |
59 | "asi" : false, // Tolerate Automatic Semicolon Insertion (no semicolons).
60 | "boss" : false, // Tolerate assignments inside if, for & while. Usually conditions & loops are for comparison, not assignments.
61 | "debug" : false, // Allow debugger statements e.g. browser breakpoints.
62 | "eqnull" : false, // Tolerate use of `== null`.
63 | "es5" : false, // Allow EcmaScript 5 syntax.
64 | "esnext" : false, // Allow ES.next specific features such as `const` and `let`.
65 | "evil" : false, // Tolerate use of `eval`.
66 | "expr" : true, // Tolerate `ExpressionStatement` as Programs.
67 | "funcscope" : false, // Tolerate declarations of variables inside of control structures while accessing them later from the outside.
68 | "globalstrict" : false, // Allow global "use strict" (also enables 'strict').
69 | "iterator" : false, // Allow usage of __iterator__ property.
70 | "lastsemic" : false, // Tolerat missing semicolons when the it is omitted for the last statement in a one-line block.
71 | "laxbreak" : false, // Tolerate unsafe line breaks e.g. `return [\n] x` without semicolons.
72 | "laxcomma" : false, // Suppress warnings about comma-first coding style.
73 | "loopfunc" : false, // Allow functions to be defined within loops.
74 | "multistr" : false, // Tolerate multi-line strings.
75 | "onecase" : false, // Tolerate switches with just one case.
76 | "proto" : false, // Tolerate __proto__ property. This property is deprecated.
77 | "regexdash" : false, // Tolerate unescaped last dash i.e. `[-...]`.
78 | "scripturl" : false, // Tolerate script-targeted URLs.
79 | "smarttabs" : false, // Tolerate mixed tabs and spaces when the latter are used for alignmnent only.
80 | "shadow" : false, // Allows re-define variables later in code e.g. `var x=1; x=2;`.
81 | "sub" : false, // Tolerate all forms of subscript notation besides dot notation e.g. `dict['key']` instead of `dict.key`.
82 | "supernew" : false, // Tolerate `new function () { ... };` and `new Object;`.
83 | "validthis" : false, // Tolerate strict violations when the code is running in strict mode and you use this in a non-constructor function.
84 |
85 | // == Environments ====================================================
86 | //
87 | // These options pre-define global variables that are exposed by
88 | // popular JavaScript libraries and runtime environments—such as
89 | // browser or node.js.
90 |
91 | "browser" : true, // Standard browser globals e.g. `window`, `document`.
92 | "couch" : false, // Enable globals exposed by CouchDB.
93 | "devel" : false, // Allow development statements e.g. `console.log();`.
94 | "dojo" : false, // Enable globals exposed by Dojo Toolkit.
95 | "jquery" : false, // Enable globals exposed by jQuery JavaScript library.
96 | "mootools" : false, // Enable globals exposed by MooTools JavaScript framework.
97 | "node" : true, // Enable globals available when code is running inside of the NodeJS runtime environment.
98 | "nonstandard" : false, // Define non-standard but widely adopted globals such as escape and unescape.
99 | "prototypejs" : false, // Enable globals exposed by Prototype JavaScript framework.
100 | "rhino" : false, // Enable globals available when your code is running inside of the Rhino runtime environment.
101 | "wsh" : false, // Enable globals available when your code is running as a script for the Windows Script Host.
102 |
103 | // == Undocumented Options ============================================
104 | //
105 | // While I've found these options in [example1][2] and [example2][3]
106 | // they are not described in the [JSHint Options documentation][4].
107 | //
108 | // [4]: http://www.jshint.com/options/
109 | "globals": {
110 | "after": true,
111 | "angular": true,
112 | "before": true,
113 | "describe": true,
114 | "it": true
115 | },
116 | "predef" : [ // Extra globals.
117 | ],
118 | "indent" : 4 // Specify indentation spacing
119 | }
120 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: node_js
2 | node_js:
3 | - "6"
4 | - "5"
5 | - "4"
6 | - "0.11"
7 |
8 | before_install:
9 | - npm install -g bower
10 |
11 | before_script:
12 | - export CHROME_BIN=chromium-browser
13 | - export DISPLAY=:99.0
14 | - sh -e /etc/init.d/xvfb start
15 | - sleep 1
16 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | # [0.7.0](https://github.com/the-darc/angular-br-filters/compare/0.6.0...0.7.0) (2016-11-09)
3 |
4 |
5 | #### Bug Fixes
6 |
7 | * package.json: remove postinstall and postupdate from package.json ([cf42d12](https://github.com/the-darc/angular-br-filters/commit/cf42d12)), closes [#13](https://github.com/the-darc/angular-br-filters/pull/13)
8 |
9 | #### Others
10 |
11 | * Update dependencies ([e358d4d](https://github.com/the-darc/angular-br-filters/commit/e358d4d))
12 | * Travis-ci changed to build in node v6, v5 and v4 ([b4baba9](https://github.com/the-darc/angular-br-filters/commit/b4baba9))
13 | * Tests changed to use angular 1.5.x ([e358d4d](https://github.com/the-darc/angular-br-filters/commit/e358d4d))
14 |
15 |
16 | ## 0.6.0 (2016-03-06)
17 |
18 |
19 | #### Bug Fixes
20 |
21 | * **bower.json:** fix bower main script config ([884884ee](https://github.com/the-darc/angular-br-filters/commit/884884ee))
22 |
23 |
24 | #### Features
25 |
26 | * **age:** add filter 'age' to calculate the age based on the birthdate ([0884d523](https://github.com/the-darc/angular-br-filters/commit/0884d523))
27 |
28 |
29 |
30 | ## 0.5.0 (2015-09-01)
31 |
32 |
33 | #### Features
34 |
35 | * **browserify:** refactor to use common-js and allow browserify ([dcac96cd](https://github.com/the-darc/angular-br-filters/commit/dcac96cd))
36 |
37 |
38 |
39 | ## 0.4.0 (2015-05-15)
40 |
41 |
42 | #### Features
43 |
44 | * **brCpfCnpj:** new filter brCpfCnpj (resolve #2) ([7d8e4f28](https://github.com/the-darc/angular-br-filters/commit/7d8e4f28))
45 |
46 |
47 |
48 | ### 0.3.1 (2015-05-15)
49 |
50 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Daniel
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 |
23 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | angular-br-filters
2 | ==================
3 | [](https://www.npmjs.com/package/angular-br-filters)
4 | [](https://bower.io/search/?q=angular-br-filters)
5 | [](https://travis-ci.org/the-darc/angular-br-filters)
6 | [](https://coveralls.io/r/the-darc/angular-br-filters)
7 |
8 | [](https://nodei.co/npm/angular-br-filters/)
9 |
10 | An Angular library of masks applicable to several Brazilian data like I.E., CNPJ, CPF and others
11 |
12 | Installation
13 | ------------
14 |
15 | **With Bower:**
16 |
17 | ```
18 | bower install --save angular-br-filters
19 | ```
20 |
21 | **With NPM:**
22 |
23 | ```
24 | npm install --save angular-br-filters
25 | ```
26 |
27 | How to use
28 | ----------
29 |
30 | 1. Import the ```angular-br-filters.min.js``` script in your page.
31 |
32 | 2. Include the module ```idf.br-filters``` in your angular app.
33 |
34 | 3. Use it as an angular filter:
35 |
36 | ```html
37 | Percentage: {{'0.1' | percentage}}
38 | ```
39 |
40 | Demo Page
41 | ---------
42 |
43 | More exaples in http://the-darc.github.io/angular-br-filters/
44 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-br-filters",
3 | "version": "0.7.0",
4 | "homepage": "https://github.com/the-darc/angular-br-filters",
5 | "description": "An Angular library of masks applicable to several Brazilian data.",
6 | "authors": [
7 | "Igor Rafael ",
8 | "Daniel Campos "
9 | ],
10 | "main": "release/angular-br-filters.js",
11 | "keywords": [
12 | "angular",
13 | "filters",
14 | "cpnj",
15 | "cpf",
16 | "cep",
17 | "phone-number"
18 | ],
19 | "license": "MIT",
20 | "ignore": [
21 | "**/.*",
22 | "node_modules",
23 | "bower_components",
24 | "test",
25 | "tests"
26 | ],
27 | "dependencies": {
28 | "br-masks": "~0.5.0"
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/config/karma.conf.js:
--------------------------------------------------------------------------------
1 | module.exports = function(config) {
2 | var configuration = {
3 | basePath: __dirname + '/..',
4 | frameworks: ['browserify', 'jasmine'],
5 | files: [
6 | 'node_modules/angular/angular.js',
7 | 'node_modules/angular-mocks/angular-mocks.js',
8 | 'src/**/*.test.js',
9 | ],
10 | port: 9876,
11 | reporters: ['progress', 'coverage'],
12 | preprocessors: {
13 | 'src/**/*.test.js': [ 'browserify' ],
14 | 'src/**/!(*spec|*test).js': ['coverage']
15 | },
16 | browserify: {
17 | debug: true,
18 | transform: [require('browserify-istanbul')({
19 | ignore: '**/*.test.js'
20 | })]
21 | },
22 | coverageReporter: {
23 | dir: 'coverage',
24 | reporters: [{
25 | type: 'lcov',
26 | subdir: 'report-lcov'
27 | }, {
28 | type: 'html',
29 | subdir: 'report-html'
30 | }, {
31 | type: 'text',
32 | }, {
33 | type: 'text-summary',
34 | }]
35 | },
36 | colors: true,
37 | autoWatch: false,
38 | singleRun: true,
39 | browsers: ['Chrome'],
40 | customLaunchers: {
41 | Chrome_travis_ci: {
42 | base: 'Chrome',
43 | flags: ['--no-sandbox']
44 | }
45 | },
46 | };
47 |
48 | if(process.env.TRAVIS){
49 | configuration.browsers = ['Chrome_travis_ci'];
50 |
51 | configuration.reporters.push('coveralls');
52 | }
53 |
54 | config.set(configuration);
55 | };
56 |
--------------------------------------------------------------------------------
/gulpfile.js:
--------------------------------------------------------------------------------
1 | var gulp = require('gulp'),
2 | path = require('path'),
3 | browserify = require('browserify'),
4 | source = require('vinyl-source-stream'),
5 | buffer = require('vinyl-buffer'),
6 | jshintReporter = require('jshint-stylish'),
7 | pkg = require(path.join(__dirname, 'package.json')),
8 | plugins = require('gulp-load-plugins')({
9 | config: path.join(__dirname, 'package.json')
10 | });
11 |
12 | var config = {
13 | src: {
14 | files: 'src/**/*.js'
15 | }
16 | };
17 |
18 | var header = [
19 | '/**',
20 | ' * <%= pkg.name %>',
21 | ' * <%= pkg.description %>',
22 | ' * @version v<%= pkg.version %>',
23 | ' * @link <%= pkg.homepage %>',
24 | ' * @license <%= pkg.license %>',
25 | ' */',
26 | ].join('\n');
27 |
28 | gulp.task('jshint', function(done) {
29 | gulp.src(config.src.files)
30 | .pipe(plugins.jshint('.jshintrc'))
31 | .pipe(plugins.jshint.reporter(jshintReporter));
32 | done();
33 | });
34 |
35 | gulp.task('build', function() {
36 | return browserify({
37 | entries: 'filters.js',
38 | detectGlobals: false,
39 | basedir: './src/',
40 | debug: false,
41 | bundleExternal: true,
42 | })
43 | .bundle()
44 | .pipe(source('angular-br-filters.js'))
45 | .pipe(buffer())
46 | .pipe(plugins.header(header, {pkg: pkg}))
47 | .pipe(gulp.dest('./release/'))
48 | .pipe(plugins.uglify())
49 | .pipe(plugins.rename({
50 | extname: '.min.js'
51 | }))
52 | .pipe(gulp.dest('./release/'));
53 | });
54 |
55 | gulp.task('default', ['jshint', 'build'], function() {
56 | gulp.watch(config.src.files, ['jshint', 'build']);
57 | });
58 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "angular-br-filters",
3 | "version": "0.7.0",
4 | "description": "An Angular library of masks applicable to several Brazilian data.",
5 | "main": "src/filters.js",
6 | "scripts": {
7 | "test": "karma start config/karma.conf.js",
8 | "release": "conventional-changelog -p angular -i CHANGELOG.md -s"
9 | },
10 | "repository": {
11 | "type": "git",
12 | "url": "https://github.com/the-darc/angular-br-filters.git"
13 | },
14 | "keywords": [
15 | "angular",
16 | "filters",
17 | "cpnj",
18 | "cpf",
19 | "cep",
20 | "phone-number"
21 | ],
22 | "authors": [
23 | "Igor Rafael ",
24 | "Daniel Campos "
25 | ],
26 | "license": "MIT",
27 | "bugs": {
28 | "url": "https://github.com/the-darc/angular-br-filters/issues"
29 | },
30 | "homepage": "https://github.com/the-darc/angular-br-filters",
31 | "dependencies": {
32 | "br-masks": "^0.5.0"
33 | },
34 | "devDependencies": {
35 | "angular": "~1.5.8",
36 | "angular-mocks": "~1.5.8",
37 | "browserify": "^13.1.1",
38 | "browserify-istanbul": "^2.0.0",
39 | "conventional-changelog": "1.1.0",
40 | "gulp": "^3.8.8",
41 | "gulp-concat": "^2.6.0",
42 | "gulp-footer": "^1.0.5",
43 | "gulp-header": "^1.1.1",
44 | "gulp-jshint": "^2.0.2",
45 | "gulp-load-plugins": "^1.4.0",
46 | "gulp-rename": "^1.2.2",
47 | "gulp-uglify": "^2.0.0",
48 | "istanbul": "^0.4.5",
49 | "jasmine-core": "^2.3.2",
50 | "jshint": "^2.9.4",
51 | "jshint-stylish": "^2.2.1",
52 | "karma": "^1.3.0",
53 | "karma-browserify": "^5.1.0",
54 | "karma-chrome-launcher": "^2.0.0",
55 | "karma-coverage": "^1.1.1",
56 | "karma-coveralls": "^1.1.2",
57 | "karma-jasmine": "^1.0.2",
58 | "vinyl-buffer": "^1.0.0",
59 | "vinyl-source-stream": "^1.1.0",
60 | "watchify": "^3.7.0"
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/release/angular-br-filters.js:
--------------------------------------------------------------------------------
1 | /**
2 | * angular-br-filters
3 | * An Angular library of masks applicable to several Brazilian data.
4 | * @version v0.7.0
5 | * @link https://github.com/the-darc/angular-br-filters
6 | * @license MIT
7 | */(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= 0 && token && token.escape) {
39 | token = tokens[pattern.charAt(i)];
40 | count += token && token.escape ? 1 : 0;
41 | i--;
42 | }
43 | return count > 0 && count % 2 === 1;
44 | }
45 |
46 | function calcOptionalNumbersToUse(pattern, value) {
47 | var numbersInP = pattern.replace(/[^0]/g,'').length;
48 | var numbersInV = value.replace(/[^\d]/g,'').length;
49 | return numbersInV - numbersInP;
50 | }
51 |
52 | function concatChar(text, character, options, token) {
53 | if (token && typeof token.transform === 'function') {
54 | character = token.transform(character);
55 | }
56 | if (options.reverse) {
57 | return character + text;
58 | }
59 | return text + character;
60 | }
61 |
62 | function hasMoreTokens(pattern, pos, inc) {
63 | var pc = pattern.charAt(pos);
64 | var token = tokens[pc];
65 | if (pc === '') {
66 | return false;
67 | }
68 | return token && !token.escape ? true : hasMoreTokens(pattern, pos + inc, inc);
69 | }
70 |
71 | function hasMoreRecursiveTokens(pattern, pos, inc) {
72 | var pc = pattern.charAt(pos);
73 | var token = tokens[pc];
74 | if (pc === '') {
75 | return false;
76 | }
77 | return token && token.recursive ? true : hasMoreRecursiveTokens(pattern, pos + inc, inc);
78 | }
79 |
80 | function insertChar(text, char, position) {
81 | var t = text.split('');
82 | t.splice(position, 0, char);
83 | return t.join('');
84 | }
85 |
86 | function StringMask(pattern, opt) {
87 | this.options = opt || {};
88 | this.options = {
89 | reverse: this.options.reverse || false,
90 | usedefaults: this.options.usedefaults || this.options.reverse
91 | };
92 | this.pattern = pattern;
93 | }
94 |
95 | StringMask.prototype.process = function proccess(value) {
96 | if (!value) {
97 | return {result: '', valid: false};
98 | }
99 | value = value + '';
100 | var pattern2 = this.pattern;
101 | var valid = true;
102 | var formatted = '';
103 | var valuePos = this.options.reverse ? value.length - 1 : 0;
104 | var patternPos = 0;
105 | var optionalNumbersToUse = calcOptionalNumbersToUse(pattern2, value);
106 | var escapeNext = false;
107 | var recursive = [];
108 | var inRecursiveMode = false;
109 |
110 | var steps = {
111 | start: this.options.reverse ? pattern2.length - 1 : 0,
112 | end: this.options.reverse ? -1 : pattern2.length,
113 | inc: this.options.reverse ? -1 : 1
114 | };
115 |
116 | function continueCondition(options) {
117 | if (!inRecursiveMode && !recursive.length && hasMoreTokens(pattern2, patternPos, steps.inc)) {
118 | // continue in the normal iteration
119 | return true;
120 | } else if (!inRecursiveMode && recursive.length &&
121 | hasMoreRecursiveTokens(pattern2, patternPos, steps.inc)) {
122 | // continue looking for the recursive tokens
123 | // Note: all chars in the patterns after the recursive portion will be handled as static string
124 | return true;
125 | } else if (!inRecursiveMode) {
126 | // start to handle the recursive portion of the pattern
127 | inRecursiveMode = recursive.length > 0;
128 | }
129 |
130 | if (inRecursiveMode) {
131 | var pc = recursive.shift();
132 | recursive.push(pc);
133 | if (options.reverse && valuePos >= 0) {
134 | patternPos++;
135 | pattern2 = insertChar(pattern2, pc, patternPos);
136 | return true;
137 | } else if (!options.reverse && valuePos < value.length) {
138 | pattern2 = insertChar(pattern2, pc, patternPos);
139 | return true;
140 | }
141 | }
142 | return patternPos < pattern2.length && patternPos >= 0;
143 | }
144 |
145 | /**
146 | * Iterate over the pattern's chars parsing/matching the input value chars
147 | * until the end of the pattern. If the pattern ends with recursive chars
148 | * the iteration will continue until the end of the input value.
149 | *
150 | * Note: The iteration must stop if an invalid char is found.
151 | */
152 | for (patternPos = steps.start; continueCondition(this.options); patternPos = patternPos + steps.inc) {
153 | // Value char
154 | var vc = value.charAt(valuePos);
155 | // Pattern char to match with the value char
156 | var pc = pattern2.charAt(patternPos);
157 |
158 | var token = tokens[pc];
159 | if (recursive.length && token && !token.recursive) {
160 | // In the recursive portion of the pattern: tokens not recursive must be seen as static chars
161 | token = null;
162 | }
163 |
164 | // 1. Handle escape tokens in pattern
165 | // go to next iteration: if the pattern char is a escape char or was escaped
166 | if (!inRecursiveMode || vc) {
167 | if (this.options.reverse && isEscaped(pattern2, patternPos)) {
168 | // pattern char is escaped, just add it and move on
169 | formatted = concatChar(formatted, pc, this.options, token);
170 | // skip escape token
171 | patternPos = patternPos + steps.inc;
172 | continue;
173 | } else if (!this.options.reverse && escapeNext) {
174 | // pattern char is escaped, just add it and move on
175 | formatted = concatChar(formatted, pc, this.options, token);
176 | escapeNext = false;
177 | continue;
178 | } else if (!this.options.reverse && token && token.escape) {
179 | // mark to escape the next pattern char
180 | escapeNext = true;
181 | continue;
182 | }
183 | }
184 |
185 | // 2. Handle recursive tokens in pattern
186 | // go to next iteration: if the value str is finished or
187 | // if there is a normal token in the recursive portion of the pattern
188 | if (!inRecursiveMode && token && token.recursive) {
189 | // save it to repeat in the end of the pattern and handle the value char now
190 | recursive.push(pc);
191 | } else if (inRecursiveMode && !vc) {
192 | // in recursive mode but value is finished. Add the pattern char if it is not a recursive token
193 | formatted = concatChar(formatted, pc, this.options, token);
194 | continue;
195 | } else if (!inRecursiveMode && recursive.length > 0 && !vc) {
196 | // recursiveMode not started but already in the recursive portion of the pattern
197 | continue;
198 | }
199 |
200 | // 3. Handle the value
201 | // break iterations: if value is invalid for the given pattern
202 | if (!token) {
203 | // add char of the pattern
204 | formatted = concatChar(formatted, pc, this.options, token);
205 | if (!inRecursiveMode && recursive.length) {
206 | // save it to repeat in the end of the pattern
207 | recursive.push(pc);
208 | }
209 | } else if (token.optional) {
210 | // if token is optional, only add the value char if it matchs the token pattern
211 | // if not, move on to the next pattern char
212 | if (token.pattern.test(vc) && optionalNumbersToUse) {
213 | formatted = concatChar(formatted, vc, this.options, token);
214 | valuePos = valuePos + steps.inc;
215 | optionalNumbersToUse--;
216 | } else if (recursive.length > 0 && vc) {
217 | valid = false;
218 | break;
219 | }
220 | } else if (token.pattern.test(vc)) {
221 | // if token isn't optional the value char must match the token pattern
222 | formatted = concatChar(formatted, vc, this.options, token);
223 | valuePos = valuePos + steps.inc;
224 | } else if (!vc && token._default && this.options.usedefaults) {
225 | // if the token isn't optional and has a default value, use it if the value is finished
226 | formatted = concatChar(formatted, token._default, this.options, token);
227 | } else {
228 | // the string value don't match the given pattern
229 | valid = false;
230 | break;
231 | }
232 | }
233 |
234 | return {result: formatted, valid: valid};
235 | };
236 |
237 | StringMask.prototype.apply = function(value) {
238 | return this.process(value).result;
239 | };
240 |
241 | StringMask.prototype.validate = function(value) {
242 | return this.process(value).valid;
243 | };
244 |
245 | StringMask.process = function(value, pattern, options) {
246 | return new StringMask(pattern, options).process(value);
247 | };
248 |
249 | StringMask.apply = function(value, pattern, options) {
250 | return new StringMask(pattern, options).apply(value);
251 | };
252 |
253 | StringMask.validate = function(value, pattern, options) {
254 | return new StringMask(pattern, options).validate(value);
255 | };
256 |
257 | return StringMask;
258 | }));
259 |
260 | },{}],2:[function(require,module,exports){
261 | /**
262 | * br-masks
263 | * A library of masks applicable to several Brazilian data like I.E., CNPJ, CPF and others
264 | * @version v0.5.0
265 | * @link http://github.com/the-darc/br-masks
266 | * @license MIT
267 | */
268 | (function (root, factory) {
269 | /* istanbul ignore next */
270 | if (typeof define === 'function' && define.amd) {
271 | // AMD. Register as an anonymous module.
272 | define(['string-mask'], factory);
273 | } else if (typeof exports === 'object') {
274 | // Node. Does not work with strict CommonJS, but
275 | // only CommonJS-like environments that support module.exports,
276 | // like Node.
277 | module.exports = factory(require('string-mask'));
278 | } else {
279 | // Browser globals (root is window)
280 | root.BrM = factory(root.StringMask);
281 | }
282 | }(this, function (StringMask) {
283 | /* istanbul ignore if */
284 | if (!StringMask) {
285 | throw new Error('StringMask not found');
286 | }
287 | /*exported CEP */
288 | var CEP = function(value) {
289 | var cepMask = new StringMask('00000-000');
290 | if(!value) {
291 | return value;
292 | }
293 | var processed = cepMask.process(value);
294 | return processed.result;
295 | };
296 |
297 | /*exported CNPJBASE */
298 | var CNPJBASE = function(value) {
299 | if(!value) {
300 | return value;
301 | }
302 | var cnpjBasePattern = new StringMask('00.000.000');
303 | var formatedValue = cnpjBasePattern.apply(value);
304 | return formatedValue;
305 | };
306 |
307 | /*exported CNPJ */
308 | var CNPJ = function(value) {
309 | if(!value) {
310 | return value;
311 | }
312 | var cnpjPattern = new StringMask('00.000.000\/0000-00');
313 | var formatedValue = cnpjPattern.apply(value);
314 | return formatedValue;
315 | };
316 |
317 | /*exported CPFCNPJ */
318 | /*globals CPF, CNPJ*/
319 | var CPFCNPJ = function(value) {
320 | if (!value || !value.length) {
321 | return value;
322 | } else if (value.length <= 11) {
323 | return CPF(value);
324 | } else {
325 | return CNPJ(value);
326 | }
327 | };
328 |
329 | /*exported CPF */
330 | var CPF = function(value) {
331 | var cpfPattern = new StringMask('000.000.000-00');
332 | if(!value) {
333 | return value;
334 | }
335 | var formatedValue = cpfPattern.apply(value);
336 | return formatedValue;
337 | };
338 |
339 | /*exported FINANCE */
340 | var FINANCE = function(value, precision, decimalSep, groupSep) {
341 | precision = (!precision && precision !== 0) || precision < 0? 2 : precision;
342 | decimalSep = decimalSep || '.';
343 | groupSep = groupSep || '';
344 |
345 | var decimalsPattern = precision > 0 ? decimalSep + new Array(precision + 1).join('0') : '';
346 | var maskPattern = '#'+groupSep+'##0'+decimalsPattern;
347 |
348 | value = parseFloat(value);
349 | if (!value) {
350 | value = 0;
351 | }
352 |
353 | var negative = false;
354 | if (value < 0) {
355 | value = value * -1;
356 | negative = true;
357 | }
358 | var financeMask = new StringMask(maskPattern, {reverse: true});
359 | var masked = financeMask.apply(value.toFixed(precision).replace(/[^\d]+/g,''));
360 | return negative ? '('+masked+')' : masked;
361 | };
362 |
363 | /*exported IE */
364 | var IE = function(value, uf) {
365 | if (!value || typeof value !== 'string') {
366 | return value;
367 | }
368 |
369 | var ieMasks = {
370 | 'AC': [{mask: new StringMask('00.000.000/000-00')}],
371 | 'AL': [{mask: new StringMask('000000000')}],
372 | 'AM': [{mask: new StringMask('00.000.000-0')}],
373 | 'AP': [{mask: new StringMask('000000000')}],
374 | 'BA': [{chars: 8, mask: new StringMask('000000-00')},
375 | {mask: new StringMask('0000000-00')}],
376 | 'CE': [{mask: new StringMask('00000000-0')}],
377 | 'DF': [{mask: new StringMask('00000000000-00')}],
378 | 'ES': [{mask: new StringMask('00000000-0')}],
379 | 'GO': [{mask: new StringMask('00.000.000-0')}],
380 | 'MA': [{mask: new StringMask('000000000')}],
381 | 'MG': [{mask: new StringMask('000.000.000/0000')}],
382 | 'MS': [{mask: new StringMask('000000000')}],
383 | 'MT': [{mask: new StringMask('0000000000-0')}],
384 | 'PA': [{mask: new StringMask('00-000000-0')}],
385 | 'PB': [{mask: new StringMask('00000000-0')}],
386 | 'PE': [{chars: 9, mask: new StringMask('0000000-00')},
387 | {mask: new StringMask('00.0.000.0000000-0')}],
388 | 'PI': [{mask: new StringMask('000000000')}],
389 | 'PR': [{mask: new StringMask('000.00000-00')}],
390 | 'RJ': [{mask: new StringMask('00.000.00-0')}],
391 | 'RN': [{chars: 9, mask: new StringMask('00.000.000-0')},
392 | {mask: new StringMask('00.0.000.000-0')}],
393 | 'RO': [{mask: new StringMask('0000000000000-0')}],
394 | 'RR': [{mask: new StringMask('00000000-0')}],
395 | 'RS': [{mask: new StringMask('000/0000000')}],
396 | 'SC': [{mask: new StringMask('000.000.000')}],
397 | 'SE': [{mask: new StringMask('00000000-0')}],
398 | 'SP': [{mask: new StringMask('000.000.000.000')},
399 | {mask: new StringMask('-00000000.0/000')}],
400 | 'TO': [{mask: new StringMask('00000000000')}]
401 | };
402 |
403 | function clearValue (value) {
404 | return value.replace(/[^0-9]/g, '');
405 | }
406 |
407 | function getMask(uf, value) {
408 | if(!uf || !ieMasks[uf]) {
409 | return undefined;
410 | }
411 | var _uf = uf.toUpperCase();
412 | if (_uf === 'SP' && /^P/i.test(value)) {
413 | return ieMasks.SP[1].mask;
414 | }
415 | var masks = ieMasks[uf];
416 | var i = 0;
417 | while(masks[i].chars && masks[i].chars < clearValue(value).length && i < masks.length - 1) {
418 | i++;
419 | }
420 | return masks[i].mask;
421 | }
422 |
423 | var mask = getMask(uf, value);
424 | if(!mask) {
425 | return value;
426 | }
427 | var processed = mask.process(clearValue(value));
428 | if (uf && uf.toUpperCase() === 'SP' && /^p/i.test(value)) {
429 | return 'P'+processed.result;
430 | }
431 | return processed.result;
432 | };
433 |
434 | /*exported NFEACCESSKEY */
435 | var NFEACCESSKEY = function(value) {
436 | if(!value) {
437 | return value;
438 | }
439 |
440 | var maskPattern = '0000 0000 0000 0000 0000 0000 0000 0000 0000 0000 0000';
441 | var nfeMask = new StringMask(maskPattern);
442 | var formatedValue = nfeMask.apply(value);
443 | return formatedValue;
444 | };
445 |
446 | /*exported PHONE */
447 | var PHONE = function(value) {
448 | var phoneMask8D = new StringMask('(00) 0000-0000'),
449 | phoneMask9D = new StringMask('(00) 00000-0000'),
450 | phoneMask0800 = new StringMask('0000-000-0000');
451 |
452 | if(!value) {
453 | return value;
454 | }
455 |
456 | var formatedValue;
457 | value = value + '';
458 | if (value.indexOf('0800') === 0) {
459 | formatedValue = phoneMask0800.apply(value);
460 | }else if(value.length < 11){
461 | formatedValue = phoneMask8D.apply(value);
462 | }else{
463 | formatedValue = phoneMask9D.apply(value);
464 | }
465 |
466 | return formatedValue;
467 | };
468 |
469 | return {
470 | ie: IE,
471 | cpf: CPF,
472 | cnpj: CNPJ,
473 | cnpjBase: CNPJBASE,
474 | phone: PHONE,
475 | cep: CEP,
476 | finance: FINANCE,
477 | nfeAccessKey: NFEACCESSKEY,
478 | cpfCnpj: CPFCNPJ
479 | };
480 | }));
481 | },{"string-mask":1}],3:[function(require,module,exports){
482 | var BrM = require('br-masks');
483 |
484 | var m = angular.module('idf.br-filters', []);
485 |
486 | module.exports = m.name;
487 |
488 | m.filter('percentage', ['$filter', function($filter) {
489 | return function(input, decimals) {
490 | if (angular.isUndefined(input) || input === null) {
491 | return input;
492 | }
493 |
494 | return $filter('number')(input * 100, decimals) + '%';
495 | };
496 | }])
497 | .filter('brCep', [function() {
498 | return function(input) {
499 | return BrM.cep(input);
500 | };
501 | }])
502 | .filter('brPhoneNumber', [function() {
503 | return function(input) {
504 | return BrM.phone(input);
505 | };
506 | }])
507 | .filter('brCpf', [function() {
508 | return function(input) {
509 | return BrM.cpf(input);
510 | };
511 | }])
512 | .filter('brCnpj', [function() {
513 | return function(input) {
514 | return BrM.cnpj(input);
515 | };
516 | }])
517 | .filter('brCpfCnpj', [function() {
518 | return function(input) {
519 | return BrM.cpfCnpj(input);
520 | };
521 | }])
522 | .filter('brIe', [function() {
523 | return function(input, uf) {
524 | return BrM.ie(input,uf);
525 | };
526 | }])
527 | .filter('finance', ['$locale', function($locale) {
528 | return function(input, currency, decimals) {
529 | if (angular.isUndefined(input) || input === null) {
530 | return input;
531 | }
532 |
533 | var decimalDelimiter = $locale.NUMBER_FORMATS.DECIMAL_SEP,
534 | thousandsDelimiter = $locale.NUMBER_FORMATS.GROUP_SEP,
535 | currencySym = '';
536 |
537 | if (currency === true) {
538 | currencySym = $locale.NUMBER_FORMATS.CURRENCY_SYM + ' ';
539 | } else if (currency) {
540 | currencySym = currency;
541 | }
542 |
543 | return currencySym + BrM.finance(input, decimals, decimalDelimiter, thousandsDelimiter);
544 | };
545 | }])
546 | .filter('nfeAccessKey', [function() {
547 | return function(input) {
548 | return BrM.nfeAccessKey(input);
549 | };
550 | }])
551 | .filter('age', function() {
552 | /**
553 | * @param value birthdate can be a date object or a time in milliseconds
554 | * return the age based on the birthdate or undefined if value is invalid.
555 | */
556 | return function calculateAge(value) {
557 | if (!value) {
558 | return undefined;
559 | }
560 | var isDateInstance = (value instanceof Date);
561 | var isValidType = isDateInstance || !isNaN(parseInt(value));
562 | if (!isValidType) {
563 | return undefined;
564 | }
565 | var birthdate = isDateInstance ? value : new Date(value);
566 | if (birthdate > new Date()) {
567 | return undefined;
568 | }
569 | var ageDifMs = Date.now() - birthdate.getTime();
570 | var ageDate = new Date(ageDifMs); // miliseconds from epoch
571 | return Math.abs(ageDate.getUTCFullYear() - 1970);
572 | };
573 | });
574 |
575 | },{"br-masks":2}]},{},[3]);
576 |
--------------------------------------------------------------------------------
/release/angular-br-filters.min.js:
--------------------------------------------------------------------------------
1 | !function e(n,r,t){function i(a,o){if(!r[a]){if(!n[a]){var u="function"==typeof require&&require;if(!o&&u)return u(a,!0);if(s)return s(a,!0);var f=new Error("Cannot find module '"+a+"'");throw f.code="MODULE_NOT_FOUND",f}var c=r[a]={exports:{}};n[a][0].call(c.exports,function(e){var r=n[a][1][e];return i(r?r:e)},c,c.exports,e,n,r,t)}return r[a].exports}for(var s="function"==typeof require&&require,a=0;a=0&&i&&i.escape;)i=o[e.charAt(t)],r+=i&&i.escape?1:0,t--;return r>0&&r%2===1}function n(e,n){var r=e.replace(/[^0]/g,"").length,t=n.replace(/[^\d]/g,"").length;return t-r}function r(e,n,r,t){return t&&"function"==typeof t.transform&&(n=t.transform(n)),r.reverse?n+e:e+n}function t(e,n,r){var i=e.charAt(n),s=o[i];return""!==i&&(!(!s||s.escape)||t(e,n+r,r))}function i(e,n,r){var t=e.charAt(n),s=o[t];return""!==t&&(!(!s||!s.recursive)||i(e,n+r,r))}function s(e,n,r){var t=e.split("");return t.splice(r,0,n),t.join("")}function a(e,n){this.options=n||{},this.options={reverse:this.options.reverse||!1,usedefaults:this.options.usedefaults||this.options.reverse},this.pattern=e}var o={0:{pattern:/\d/,_default:"0"},9:{pattern:/\d/,optional:!0},"#":{pattern:/\d/,optional:!0,recursive:!0},A:{pattern:/[a-zA-Z0-9]/},S:{pattern:/[a-zA-Z]/},U:{pattern:/[a-zA-Z]/,transform:function(e){return e.toLocaleUpperCase()}},L:{pattern:/[a-zA-Z]/,transform:function(e){return e.toLocaleLowerCase()}},$:{escape:!0}};return a.prototype.process=function(a){function u(e){if(!k&&!m.length&&t(f,h,d.inc))return!0;if(!k&&m.length&&i(f,h,d.inc))return!0;if(k||(k=m.length>0),k){var n=m.shift();if(m.push(n),e.reverse&&l>=0)return h++,f=s(f,n,h),!0;if(!e.reverse&&l=0}if(!a)return{result:"",valid:!1};a+="";var f=this.pattern,c=!0,p="",l=this.options.reverse?a.length-1:0,h=0,v=n(f,a),w=!1,m=[],k=!1,d={start:this.options.reverse?f.length-1:0,end:this.options.reverse?-1:f.length,inc:this.options.reverse?-1:1};for(h=d.start;u(this.options);h+=d.inc){var g=a.charAt(l),y=f.charAt(h),A=o[y];if(m.length&&A&&!A.recursive&&(A=null),!k||g){if(this.options.reverse&&e(f,h)){p=r(p,y,this.options,A),h+=d.inc;continue}if(!this.options.reverse&&w){p=r(p,y,this.options,A),w=!1;continue}if(!this.options.reverse&&A&&A.escape){w=!0;continue}}if(!k&&A&&A.recursive)m.push(y);else{if(k&&!g){p=r(p,y,this.options,A);continue}if(!k&&m.length>0&&!g)continue}if(A)if(A.optional){if(A.pattern.test(g)&&v)p=r(p,g,this.options,A),l+=d.inc,v--;else if(m.length>0&&g){c=!1;break}}else if(A.pattern.test(g))p=r(p,g,this.options,A),l+=d.inc;else{if(g||!A._default||!this.options.usedefaults){c=!1;break}p=r(p,A._default,this.options,A)}else p=r(p,y,this.options,A),!k&&m.length&&m.push(y)}return{result:p,valid:c}},a.prototype.apply=function(e){return this.process(e).result},a.prototype.validate=function(e){return this.process(e).valid},a.process=function(e,n,r){return new a(n,r).process(e)},a.apply=function(e,n,r){return new a(n,r).apply(e)},a.validate=function(e,n,r){return new a(n,r).validate(e)},a})},{}],2:[function(e,n,r){!function(t,i){"function"==typeof define&&define.amd?define(["string-mask"],i):"object"==typeof r?n.exports=i(e("string-mask")):t.BrM=i(t.StringMask)}(this,function(e){if(!e)throw new Error("StringMask not found");var n=function(n){var r=new e("00000-000");if(!n)return n;var t=r.process(n);return t.result},r=function(n){if(!n)return n;var r=new e("00.000.000"),t=r.apply(n);return t},t=function(n){if(!n)return n;var r=new e("00.000.000/0000-00"),t=r.apply(n);return t},i=function(e){return e&&e.length?e.length<=11?s(e):t(e):e},s=function(n){var r=new e("000.000.000-00");if(!n)return n;var t=r.apply(n);return t},a=function(n,r,t,i){r=!r&&0!==r||r<0?2:r,t=t||".",i=i||"";var s=r>0?t+new Array(r+1).join("0"):"",a="#"+i+"##0"+s;n=parseFloat(n),n||(n=0);var o=!1;n<0&&(n*=-1,o=!0);var u=new e(a,{reverse:!0}),f=u.apply(n.toFixed(r).replace(/[^\d]+/g,""));return o?"("+f+")":f},o=function(n,r){function t(e){return e.replace(/[^0-9]/g,"")}function i(e,n){if(e&&s[e]){var r=e.toUpperCase();if("SP"===r&&/^P/i.test(n))return s.SP[1].mask;for(var i=s[e],a=0;i[a].chars&&i[a].charsnew Date)){var i=Date.now()-t.getTime(),s=new Date(i);return Math.abs(s.getUTCFullYear()-1970)}}}}})},{"br-masks":2}]},{},[3]);
--------------------------------------------------------------------------------
/src/filters.js:
--------------------------------------------------------------------------------
1 | var BrM = require('br-masks');
2 |
3 | var m = angular.module('idf.br-filters', []);
4 |
5 | module.exports = m.name;
6 |
7 | m.filter('percentage', ['$filter', function($filter) {
8 | return function(input, decimals) {
9 | if (angular.isUndefined(input) || input === null) {
10 | return input;
11 | }
12 |
13 | return $filter('number')(input * 100, decimals) + '%';
14 | };
15 | }])
16 | .filter('brCep', [function() {
17 | return function(input) {
18 | return BrM.cep(input);
19 | };
20 | }])
21 | .filter('brPhoneNumber', [function() {
22 | return function(input) {
23 | return BrM.phone(input);
24 | };
25 | }])
26 | .filter('brCpf', [function() {
27 | return function(input) {
28 | return BrM.cpf(input);
29 | };
30 | }])
31 | .filter('brCnpj', [function() {
32 | return function(input) {
33 | return BrM.cnpj(input);
34 | };
35 | }])
36 | .filter('brCpfCnpj', [function() {
37 | return function(input) {
38 | return BrM.cpfCnpj(input);
39 | };
40 | }])
41 | .filter('brIe', [function() {
42 | return function(input, uf) {
43 | return BrM.ie(input,uf);
44 | };
45 | }])
46 | .filter('finance', ['$locale', function($locale) {
47 | return function(input, currency, decimals) {
48 | if (angular.isUndefined(input) || input === null) {
49 | return input;
50 | }
51 |
52 | var decimalDelimiter = $locale.NUMBER_FORMATS.DECIMAL_SEP,
53 | thousandsDelimiter = $locale.NUMBER_FORMATS.GROUP_SEP,
54 | currencySym = '';
55 |
56 | if (currency === true) {
57 | currencySym = $locale.NUMBER_FORMATS.CURRENCY_SYM + ' ';
58 | } else if (currency) {
59 | currencySym = currency;
60 | }
61 |
62 | return currencySym + BrM.finance(input, decimals, decimalDelimiter, thousandsDelimiter);
63 | };
64 | }])
65 | .filter('nfeAccessKey', [function() {
66 | return function(input) {
67 | return BrM.nfeAccessKey(input);
68 | };
69 | }])
70 | .filter('age', function() {
71 | /**
72 | * @param value birthdate can be a date object or a time in milliseconds
73 | * return the age based on the birthdate or undefined if value is invalid.
74 | */
75 | return function calculateAge(value) {
76 | if (!value) {
77 | return undefined;
78 | }
79 | var isDateInstance = (value instanceof Date);
80 | var isValidType = isDateInstance || !isNaN(parseInt(value));
81 | if (!isValidType) {
82 | return undefined;
83 | }
84 | var birthdate = isDateInstance ? value : new Date(value);
85 | if (birthdate > new Date()) {
86 | return undefined;
87 | }
88 | var ageDifMs = Date.now() - birthdate.getTime();
89 | var ageDate = new Date(ageDifMs); // miliseconds from epoch
90 | return Math.abs(ageDate.getUTCFullYear() - 1970);
91 | };
92 | });
93 |
--------------------------------------------------------------------------------
/src/filters.test.js:
--------------------------------------------------------------------------------
1 | require('./filters.js');
2 |
3 | /* global expect,inject,beforeEach,it,describe */
4 | describe('br-filters', function() {
5 | beforeEach(angular.mock.module('idf.br-filters'));
6 |
7 | function testFilter(name) {
8 | var filter;
9 |
10 | inject(['$filter', function($filter) {
11 | filter = $filter(name);
12 | }]);
13 |
14 | return filter;
15 | }
16 |
17 | describe('percentage', function() {
18 | it('should not format if null or undefined', function(){
19 | expect(testFilter('percentage')(null)).toBe(null);
20 | expect(testFilter('percentage')(undefined)).toBe(undefined);
21 | });
22 |
23 | it('should format numbers', function() {
24 | expect(testFilter('percentage')('')).toBe('0%');
25 | expect(testFilter('percentage')(0)).toBe('0%');
26 | expect(testFilter('percentage')(0.3)).toBe('30%');
27 | expect(testFilter('percentage')(0.189)).toBe('18.9%');
28 | expect(testFilter('percentage')('0.045')).toBe('4.5%');
29 | expect(testFilter('percentage')(2.345e-4)).toBe('0.023%');
30 | });
31 |
32 | it('should format numbers with correct number of decimals', function() {
33 | expect(testFilter('percentage')(0.3, 2)).toBe('30.00%');
34 | expect(testFilter('percentage')(0.189, 3)).toBe('18.900%');
35 | expect(testFilter('percentage')('0.045', 0)).toBe('5%');
36 | expect(testFilter('percentage')(2.345e-4, 2)).toBe('0.02%');
37 | });
38 | });
39 |
40 | describe('brCep', function () {
41 | it('should not format if null or undefined', function() {
42 | expect(testFilter('brCep')(null)).toBe(null);
43 | expect(testFilter('brCep')(undefined)).toBe(undefined);
44 | });
45 |
46 | it('should format a string or a number', function() {
47 | expect(testFilter('brCep')('30480530')).toBe('30480-530');
48 | expect(testFilter('brCep')(30480530)).toBe('30480-530');
49 | });
50 | });
51 |
52 | describe('brPhoneNumber', function () {
53 | it('should not format if null or undefined', function() {
54 | expect(testFilter('brPhoneNumber')(null)).toBe(null);
55 | expect(testFilter('brPhoneNumber')(undefined)).toBe(undefined);
56 | });
57 |
58 | it('should format a string or a number', function() {
59 | expect(testFilter('brPhoneNumber')('3133340167')).toBe('(31) 3334-0167');
60 | expect(testFilter('brPhoneNumber')(3133340167)).toBe('(31) 3334-0167');
61 | expect(testFilter('brPhoneNumber')('38212201255')).toBe('(38) 21220-1255');
62 | expect(testFilter('brPhoneNumber')(38212201255)).toBe('(38) 21220-1255');
63 | });
64 | });
65 |
66 | describe('brCpf', function () {
67 | it('should not format if null or undefined', function() {
68 | expect(testFilter('brCpf')(null)).toBe(null);
69 | expect(testFilter('brCpf')(undefined)).toBe(undefined);
70 | });
71 |
72 | it('should format a string or a number', function() {
73 | expect(testFilter('brCpf')('97070868669')).toBe('970.708.686-69');
74 | expect(testFilter('brCpf')(97070868669)).toBe('970.708.686-69');
75 | expect(testFilter('brCpf')('1435151')).toBe('143.515.1');
76 | expect(testFilter('brCpf')(1435151)).toBe('143.515.1');
77 | });
78 | });
79 |
80 | describe('brCnpj', function () {
81 | it('should not format if null or undefined', function() {
82 | expect(testFilter('brCnpj')(null)).toBe(null);
83 | expect(testFilter('brCnpj')(undefined)).toBe(undefined);
84 | });
85 |
86 | it('should format a string or a number', function() {
87 | expect(testFilter('brCnpj')('10157471000161')).toBe('10.157.471/0001-61');
88 | expect(testFilter('brCnpj')(10157471000161)).toBe('10.157.471/0001-61');
89 | });
90 | });
91 |
92 | describe('brCpfCnpj', function () {
93 | it('should not format if null or undefined', function() {
94 | expect(testFilter('brCpfCnpj')(null)).toBe(null);
95 | expect(testFilter('brCpfCnpj')(undefined)).toBe(undefined);
96 | });
97 |
98 | it('should format a string or a number', function() {
99 | expect(testFilter('brCpfCnpj')('97070868669')).toBe('970.708.686-69');
100 | expect(testFilter('brCpfCnpj')('1435151')).toBe('143.515.1');
101 | expect(testFilter('brCpfCnpj')('10157471000161')).toBe('10.157.471/0001-61');
102 | });
103 | });
104 |
105 | describe('brIe', function () {
106 | it('should not format if null or undefined', function() {
107 | expect(testFilter('brIe')(null)).toBe(null);
108 | expect(testFilter('brIe')(undefined)).toBe(undefined);
109 | });
110 |
111 | it('should not format a number', function() {
112 | expect(testFilter('brIe')(32141840, 'PE')).toBe(32141840);
113 | });
114 |
115 | it('should format a string', function() {
116 | expect(testFilter('brIe')('032141840', 'PE')).toBe('0321418-40');
117 | });
118 | });
119 |
120 | describe('finance', function () {
121 | it('should not format if null or undefined', function() {
122 | expect(testFilter('finance')(null)).toBe(null);
123 | expect(testFilter('finance')(undefined)).toBe(undefined);
124 | });
125 |
126 | it('should format a string or a number', function() {
127 | expect(testFilter('finance')('123.1237123', '$ ', 3)).toBe('$ 123.124');
128 | expect(testFilter('finance')(123.1237123, 'R$ ', 3)).toBe('R$ 123.124');
129 | expect(testFilter('finance')(123.1237123, true)).toMatch(/.+ 123.12/);
130 | expect(testFilter('finance')(0)).toMatch(/0.00/);
131 | });
132 | });
133 |
134 | describe('nfeAccessKey', function () {
135 | it('should not format if null or undefined', function() {
136 | expect(testFilter('nfeAccessKey')(null)).toBe(null);
137 | expect(testFilter('nfeAccessKey')(undefined)).toBe(undefined);
138 | });
139 |
140 | it('should format a string', function() {
141 | expect(testFilter('nfeAccessKey')('35140111724258000157550010006882191630386000'))
142 | .toBe('3514 0111 7242 5800 0157 5500 1000 6882 1916 3038 6000');
143 | });
144 | });
145 | describe('age', function() {
146 | it('should be undefined if null, undefined or empty', function() {
147 | expect(testFilter('age')(null)).toBe(undefined);
148 | expect(testFilter('age')(undefined)).toBe(undefined);
149 | expect(testFilter('age')('')).toBe(undefined);
150 | });
151 |
152 | it('should be undefined if not date or time in milliseconds', function() {
153 | expect(testFilter('age')('not a date')).toBe(undefined);
154 | expect(testFilter('age')(true)).toBe(undefined);
155 | });
156 |
157 | it('should be undefined for future birthdate', function() {
158 | var futureYear = new Date();
159 | futureYear.setFullYear(futureYear.getFullYear() + 1);
160 | expect(testFilter('age')(futureYear)).toBe(undefined);
161 | var futureMonth = new Date();
162 | futureMonth.setMonth(futureMonth.getMonth() + 1);
163 | expect(testFilter('age')(futureMonth)).toBe(undefined);
164 | var futureDay = new Date();
165 | futureDay.setDate(futureDay.getDate() + 1);
166 | expect(testFilter('age')(futureDay)).toBe(undefined);
167 | var futureMinute = new Date();
168 | futureMinute.setMinutes(futureMinute.getMinutes() + 1);
169 | expect(testFilter('age')(futureMinute)).toBe(undefined);
170 | });
171 |
172 | it('should format date as 27', function() {
173 | var age = 27;
174 | var yearInMs = 366 * 24 * 60 * 60 * 1000;
175 | var born = new Date(new Date().getTime() - age*yearInMs);
176 | expect(testFilter('age')(born)).toBe(age);
177 | expect(testFilter('age')(born.getTime())).toBe(age);
178 | });
179 | });
180 | });
181 |
--------------------------------------------------------------------------------