├── .editorconfig
├── .gitignore
├── README.md
├── angular-autonumeric.iml
├── angular.json
├── e2e
├── protractor.conf.js
├── src
│ ├── app.e2e-spec.ts
│ └── app.po.ts
└── tsconfig.e2e.json
├── package-lock.json
├── package.json
├── src
├── README.md
├── browserslist
├── index.ts
├── karma.conf.js
├── lib
│ ├── autonumeric-defaults.service.ts
│ ├── autonumeric.directive.ts
│ ├── autonumeric.model.ts
│ ├── autonumeric.module.ts
│ └── index.ts
├── ng-package.json
├── ng-package.prod.json
├── package-lock.json
├── package.json
├── public_api.ts
├── test.ts
├── tsconfig.json
├── tsconfig.spec.json
└── tslint.json
├── tsconfig.json
└── tslint.json
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see https://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 2
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = false
14 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # See http://help.github.com/ignore-files/ for more about ignoring files.
2 |
3 | # compiled output
4 | /dist
5 | /tmp
6 | /out-tsc
7 |
8 | # dependencies
9 | /node_modules
10 | src/node_modules
11 | # profiling files
12 | chrome-profiler-events.json
13 | speed-measure-plugin.json
14 |
15 | # IDEs and editors
16 | /.idea
17 | .project
18 | .classpath
19 | .c9/
20 | *.launch
21 | .settings/
22 | *.sublime-workspace
23 |
24 | # IDE - VSCode
25 | .vscode/*
26 | !.vscode/settings.json
27 | !.vscode/tasks.json
28 | !.vscode/launch.json
29 | !.vscode/extensions.json
30 | .history/*
31 |
32 | # misc
33 | /.sass-cache
34 | /connect.lock
35 | /coverage
36 | /libpeerconnection.log
37 | npm-debug.log
38 | yarn-error.log
39 | testem.log
40 | /typings
41 |
42 | # System Files
43 | .DS_Store
44 | Thumbs.db
45 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## @angularfy/autonumeric
2 |
3 | An Angular library that wraps the awesome [AutoNumeric](https://github.com/autoNumeric/autoNumeric/) library
4 |
5 | Get in touch : abdelghani@ainouss.fr
6 |
7 | ---
8 |
9 | @angularfy/autonumeric supports most of [AutoNumeric](https://github.com/autoNumeric/autoNumeric/) options.
10 |
11 | **Checkout the [demo](https://angularfy-autonumeric.stackblitz.io)**
12 |
13 | *Note: In order to minimize the size of the @angularfy/autonumeric, the AutoNumeric library dependency **is not** bundled with it.*
14 |
15 | This means you **need** to include the [AutoNumeric](https://github.com/autoNumeric/autoNumeric/) library.
16 |
17 | ## Dependencies
18 |
19 | The dependency is [autoNumeric 4](https://github.com/autoNumeric/autoNumeric/).
20 | Here is the list of minimal required versions:
21 |
22 | | @angularfy/autonumeric | angular | autoNumeric |
23 | | ---------------------- | ------- | ------------- |
24 | | 1.x.x | ^4.0.0 | ^4.0.0 |
25 | | 2.x.x | ^4.0.0 | ^4.0.0 |
26 | | 3.x.x | ^4.0.0 | ^4.0.0 |
27 |
28 | ---
29 | ## Installation
30 |
31 | After installing the above dependencies, install `@angularfy/autonumeric` via npm:
32 |
33 | ```shell
34 | npm install --save @angularfy/autonumeric
35 | ```
36 | or yarn :
37 |
38 | ```shell
39 | yarn add @angularfy/autonumeric
40 | ```
41 |
42 | Once installed you need to import our main module:
43 | ```js
44 | import { AutonumericModule } from '@angularfy/autonumeric';
45 |
46 | @NgModule({
47 | //...
48 | imports: [
49 | AutonumericModule.forRoot(), // ...
50 | ],
51 | //...
52 | })
53 | export class YourAppModule {
54 | }
55 | ```
56 | ---
57 | ### How to use the @angularfy/autonumeric ?
58 |
59 | The AutoNumeric component can be instantiated the same way `AutoNumeric` can.
60 |
61 | After importing the AutonumericModule
62 | in your component, you can define your options as follow :
63 | ```ts
64 | this.myOptions = {
65 | digitGroupSeparator: '.',
66 | decimalCharacter: ',',
67 | decimalCharacterAlternative: '.',
68 | currencySymbol: '\u00a0€',
69 | currencySymbolPlacement: 's',
70 | roundingMethod: 'U',
71 | minimumValue: '0'
72 | }
73 |
74 | ```
75 | in your HTML :
76 | ```html
77 |
78 | ```
79 |
80 | or simply with a predefined option name:
81 | ```html
82 |
83 | ```
84 | you can also use object literal as options directly in HTML
85 |
86 | ```html
87 |
96 | ```
97 | The library supports also reactive forms.
98 |
99 | ---
100 | #### Customize autonumeric defaults
101 |
102 | You can override autonumeric default by providing default configuration:
103 |
104 | ```js
105 | import { AutonumericModule } from '@angularfy/autonumeric';
106 |
107 | @NgModule({
108 | //...
109 | imports: [
110 | AutonumericModule.forRoot({
111 | // user defaults here
112 | }), // ...
113 | ],
114 | //...
115 | })
116 | export class YourAppModule {
117 | }
118 | ```
119 | You can also use providers to achieve this :
120 |
121 | ```js
122 | const userDefaults :AutonumericOptions= {
123 | // default options
124 | }
125 | export function defaultsFactory(userDefaults: AutonumericOptions): AutonumericDefaults {
126 | const defaults: AutonumericDefaults = new AutonumericDefaults();
127 | Object.assign(defaults, userDefaults);
128 | return defaults;
129 | }
130 | @NgModule({
131 | imports: [AutonumericModule],
132 | providers: [{
133 | provide: USER_DEFAULTS,
134 | useValue: userDefaults
135 | },
136 | {
137 | provide: AutonumericDefaults,
138 | useFactory: defaultsFactory,
139 | deps: [USER_DEFAULTS]
140 | }]
141 | })
142 | export class YourAppModule {
143 | }
144 | ```
145 |
146 | #### Supported events
147 |
148 | Alongside with native events, autonumeric emits two events : formatted, rawValueModified, those events are bubbled from the
149 | native library. Please refer to official docs for more details
150 |
151 | ``` HTML
152 |
153 | ```
154 | If you want to keep your ngModel synchronized please use two-way binding otherwise, you can capture the change or format event.
155 | (format is more verbose, happens every time the input visually changes, the change event in the other hand, is triggered only when the user types something and leaves the input.)
156 |
157 | #### Readonly mode
158 |
159 | you can use the component in a reardonly mode :
160 | ``` HTML
161 |
163 |
164 | ```
165 | you can also use an input with {..., readOnly : true } in options.
166 |
167 | #### Styling
168 | we are agnostic about how the input should be styled. you can define your own style rules
169 | ```css
170 | input[autonumeric],span[autonumeric] {
171 | text-align:right;
172 | }
173 |
174 | ```
175 | #### Integration with other scripts & events support
176 |
177 | If some reason you need to access the native autonumeric instance, you can reference your element using
178 | @ViewChild.
179 | ``` HTML
180 |
181 | ```
182 | in your component :
183 | ``` ts
184 | @ViewChild('myNumericField', { static: true })
185 | myNumericField:AutonumericDirective;
186 |
187 | ...
188 | reset(){
189 | this.myNumericField.instance.reset();
190 | }
191 | set(val:any){
192 | this.myNumericField.instance.set(val);
193 | }
194 |
195 | ...
196 | ```
197 |
198 | ### Demo
199 |
200 | The official AutoNumeric [documentation](http://autonumeric.org/#/guide)
201 |
202 |
203 | ### Requirements
204 |
205 | - [AutoNumeric](https://github.com/autoNumeric/autoNumeric) `^v4`
206 | - [Angular](https://angular.io/) `^v4`
207 |
208 | ### Browser support
209 |
210 | This supports the same browsers than AutoNumeric supports:
211 | - Firefox and
212 | - Chrome
213 |
214 | *(latest 2 versions)*
215 | If you use IE/Edge/Safari/Opera, this *might* work ;)
216 |
217 | ### What's next ?
218 |
219 | I will be working on supporting more AutoNumeric options. If you have any suggestions please feel free to reach by email bellow.
220 |
221 | ### Greetings
222 |
223 | This project is hugely inspired from [vue-js implementtation of AutoNumeric](https://github.com/autoNumeric/vue-autoNumeric) by [Alexandre Bonneau](https://github.com/AlexandreBonneau)
224 |
225 |
226 | ### Support
227 |
228 | As always, if you find this useful, please consider [supporting its development](https://www.patreon.com/ainouss)!
229 | Huge Thanks :)
230 |
231 | ### License
232 |
233 | `@angularfy/autonumeric` is open-source and released under the [MIT License]
234 |
235 | > PS:
236 | I would love to know how you're using @angularfy/autonumeric.
237 | Contact and tell me!, abdelghani@ainouss.fr :)
238 |
239 |
--------------------------------------------------------------------------------
/angular-autonumeric.iml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular-devkit/core/src/workspace/workspace-schema.json",
3 | "version": 1,
4 | "newProjectRoot": "",
5 | "projects": {
6 | "autonumeric": {
7 | "root": "",
8 | "sourceRoot": "src",
9 | "projectType": "library",
10 | "architect": {
11 | "build": {
12 | "builder": "@angular-devkit/build-ng-packagr:build",
13 | "options": {
14 | "project": "src/ng-package.json"
15 | },
16 | "configurations": {
17 | "production": {
18 | "tsConfig": "src/tsconfig.json",
19 | "project": "src/ng-package.prod.json"
20 | }
21 | }
22 | },
23 | "test": {
24 | "builder": "@angular-devkit/build-angular:karma",
25 | "options": {
26 | "main": "src/test.ts",
27 | "tsConfig": "src/tsconfig.spec.json",
28 | "codeCoverageExclude": [
29 | "src/test.ts",
30 | "src/test/**"
31 | ],
32 | "karmaConfig": "src/karma.conf.js"
33 | }
34 | },
35 | "lint": {
36 | "builder": "@angular-devkit/build-angular:tslint",
37 | "options": {
38 | "tsConfig": [
39 | "src/tsconfig.json"
40 | ],
41 | "exclude": [
42 | "**/node_modules/**"
43 | ]
44 | }
45 | }
46 | }
47 | }
48 | },
49 | "cli": {
50 | "packageManager": "yarn"
51 | }
52 | }
53 |
--------------------------------------------------------------------------------
/e2e/protractor.conf.js:
--------------------------------------------------------------------------------
1 | // Protractor configuration file, see link for more information
2 | // https://github.com/angular/protractor/blob/master/lib/config.ts
3 |
4 | const { SpecReporter } = require('jasmine-spec-reporter');
5 |
6 | exports.config = {
7 | allScriptsTimeout: 11000,
8 | specs: [
9 | './src/**/*.e2e-spec.ts'
10 | ],
11 | capabilities: {
12 | 'browserName': 'chrome'
13 | },
14 | directConnect: true,
15 | baseUrl: 'http://localhost:4200/',
16 | framework: 'jasmine',
17 | jasmineNodeOpts: {
18 | showColors: true,
19 | defaultTimeoutInterval: 30000,
20 | print: function() {}
21 | },
22 | onPrepare() {
23 | require('ts-node').register({
24 | project: require('path').join(__dirname, './tsconfig.e2e.json')
25 | });
26 | jasmine.getEnv().addReporter(new SpecReporter({ spec: { displayStacktrace: true } }));
27 | }
28 | };
--------------------------------------------------------------------------------
/e2e/src/app.e2e-spec.ts:
--------------------------------------------------------------------------------
1 | import { AppPage } from './app.po';
2 | import { browser, logging } from 'protractor';
3 |
4 | describe('workspace-project App', () => {
5 | let page: AppPage;
6 |
7 | beforeEach(() => {
8 | page = new AppPage();
9 | });
10 |
11 | it('should display welcome message', () => {
12 | page.navigateTo();
13 | expect(page.getTitleText()).toEqual('Welcome to autonumeric!');
14 | });
15 |
16 | afterEach(async () => {
17 | // Assert that there are no errors emitted from the browser
18 | const logs = await browser.manage().logs().get(logging.Type.BROWSER);
19 | expect(logs).not.toContain(jasmine.objectContaining({
20 | level: logging.Level.SEVERE,
21 | }));
22 | });
23 | });
24 |
--------------------------------------------------------------------------------
/e2e/src/app.po.ts:
--------------------------------------------------------------------------------
1 | import { browser, by, element } from 'protractor';
2 |
3 | export class AppPage {
4 | navigateTo() {
5 | return browser.get(browser.baseUrl) as Promise;
6 | }
7 |
8 | getTitleText() {
9 | return element(by.css('app-root h1')).getText() as Promise;
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/e2e/tsconfig.e2e.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "../out-tsc/app",
5 | "module": "commonjs",
6 | "target": "es5",
7 | "types": [
8 | "jasmine",
9 | "jasminewd2",
10 | "node"
11 | ]
12 | }
13 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@angularfy/autonumeric",
3 | "version": "3.0.0",
4 | "scripts": {
5 | "ng": "ng",
6 | "start": "ng serve",
7 | "build": "ng-packagr -p package.json",
8 | "pack": "cd dist/autonumeric && npm pack",
9 | "lint": "ng lint",
10 | "e2e": "ng e2e"
11 | },
12 | "repository": {
13 | "url": "git://github.com/angularfy/autonumeric.git"
14 | },
15 | "dependencies": {},
16 | "devDependencies": {
17 | "@angular-devkit/build-angular": "~0.13.0",
18 | "@angular-devkit/build-ng-packagr": "~0.10.0",
19 | "@angular/cli": "~7.3.0",
20 | "@angular/compiler-cli": "~7.2.0",
21 | "@angular/language-service": "~7.2.0",
22 | "@angular/compiler": "7.2.15",
23 | "@types/jasmine": "~2.8.8",
24 | "@types/jasminewd2": "~2.0.3",
25 | "@types/node": "~8.9.4",
26 | "autonumeric": "^4.0.0",
27 | "codelyzer": "~4.5.0",
28 | "jasmine-core": "~2.99.1",
29 | "jasmine-spec-reporter": "~4.2.1",
30 | "karma": "~3.1.1",
31 | "karma-chrome-launcher": "~2.2.0",
32 | "karma-coverage-istanbul-reporter": "~2.0.1",
33 | "karma-jasmine": "~1.1.2",
34 | "karma-jasmine-html-reporter": "^0.2.2",
35 | "ng-packagr": "^4.2.0",
36 | "protractor": "~5.4.0",
37 | "ts-node": "~7.0.0",
38 | "tsickle": "^0.34.2",
39 | "tslint": "~5.11.0",
40 | "typescript": "~3.2.2"
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/src/README.md:
--------------------------------------------------------------------------------
1 | ## @angularfy/autonumeric
2 |
3 | An Angular library that wraps the awesome [AutoNumeric](https://github.com/autoNumeric/autoNumeric/) library
4 |
5 | Get in touch on autonumeric@angularfy.com
6 |
7 | ---
8 |
9 | @angularfy/autonumeric supports most of [AutoNumeric](https://github.com/autoNumeric/autoNumeric/) options.
10 |
11 | **Checkout the [demo](https://angularfy-autonumeric.stackblitz.io)**
12 |
13 | _Note: In order to minimize the size of the @angularfy/autonumeric, the AutoNumeric library dependency **is not** bundled with it._
14 |
15 | This means you **need** to include the [AutoNumeric](https://github.com/autoNumeric/autoNumeric/) library.
16 |
17 | ## Dependencies
18 |
19 | The dependency is [autoNumeric 4](https://github.com/autoNumeric/autoNumeric/).
20 | Here is the list of minimal required versions:
21 |
22 | | @angularfy/autonumeric | angular | autoNumeric |
23 | | ---------------------- | ------- | ----------- |
24 | | 1.x.x | ^4.0.0 | ^4.0.0 |
25 | | 2.x.x | ^4.0.0 | ^4.0.0 |
26 | | 3.x.x | ^4.0.0 | ^4.0.0 |
27 |
28 | ---
29 |
30 | ## Installation
31 |
32 | After installing the above dependencies, install `@angularfy/autonumeric` via npm:
33 |
34 | ```shell
35 | npm install --save @angularfy/autonumeric
36 | ```
37 |
38 | or yarn :
39 |
40 | ```shell
41 | yarn add @angularfy/autonumeric
42 | ```
43 |
44 | Once installed you need to import our main module:
45 |
46 | ```js
47 | import { AutonumericModule } from "@angularfy/autonumeric";
48 |
49 | @NgModule({
50 | //...
51 | imports: [
52 | AutonumericModule.forRoot(), // ...
53 | ],
54 | //...
55 | })
56 | export class YourAppModule {}
57 | ```
58 |
59 | ---
60 |
61 | ### How to use the @angularfy/autonumeric ?
62 |
63 | The AutoNumeric component can be instantiated the same way `AutoNumeric` can.
64 |
65 | After importing the AutonumericModule
66 | in your component, you can define your options as follow :
67 |
68 | ```ts
69 | this.myOptions = {
70 | digitGroupSeparator: ".",
71 | decimalCharacter: ",",
72 | decimalCharacterAlternative: ".",
73 | currencySymbol: "\u00a0€",
74 | currencySymbolPlacement: "s",
75 | roundingMethod: "U",
76 | minimumValue: "0",
77 | };
78 | ```
79 |
80 | in your HTML :
81 |
82 | ```html
83 |
84 | ```
85 |
86 | or simply with a predefined option name:
87 |
88 | ```html
89 |
90 | ```
91 |
92 | you can also use object literal as options directly in HTML
93 |
94 | ```html
95 |
108 | ```
109 |
110 | The library supports also reactive forms.
111 |
112 | ---
113 |
114 | #### Customize autonumeric defaults
115 |
116 | You can override autonumeric default by providing default configuration:
117 |
118 | ```js
119 | import { AutonumericModule } from "@angularfy/autonumeric";
120 |
121 | @NgModule({
122 | //...
123 | imports: [
124 | AutonumericModule.forRoot({
125 | // user defaults here
126 | }), // ...
127 | ],
128 | //...
129 | })
130 | export class YourAppModule {}
131 | ```
132 |
133 | You can also use providers to achieve this :
134 |
135 | ```js
136 | const userDefaults: AutonumericOptions = {
137 | // default options
138 | };
139 | export function defaultsFactory(
140 | userDefaults: AutonumericOptions
141 | ): AutonumericDefaults {
142 | const defaults: AutonumericDefaults = new AutonumericDefaults();
143 | Object.assign(defaults, userDefaults);
144 | return defaults;
145 | }
146 | @NgModule({
147 | imports: [AutonumericModule],
148 | providers: [
149 | {
150 | provide: USER_DEFAULTS,
151 | useValue: userDefaults,
152 | },
153 | {
154 | provide: AutonumericDefaults,
155 | useFactory: defaultsFactory,
156 | deps: [USER_DEFAULTS],
157 | },
158 | ],
159 | })
160 | export class YourAppModule {}
161 | ```
162 |
163 | #### Supported events
164 |
165 | Alongside with native events, autonumeric emits two events : formatted, rawValueModified, those events are bubbled from the
166 | native library. Please refer to official docs for more details
167 |
168 | ```HTML
169 |
170 | ```
171 |
172 | If you want to keep your ngModel synchronized please use two-way binding otherwise, you can capture the change or format event.
173 | (format is more verbose, happens every time the input visually changes, the change event in the other hand, is triggered only when the user types something and leaves the input.)
174 |
175 | #### Readonly mode
176 |
177 | you can use the component in a reardonly mode :
178 |
179 | ```HTML
180 |
182 |
183 | ```
184 |
185 | you can also use an input with {..., readOnly : true } in options.
186 |
187 | #### Styling
188 |
189 | we are agnostic about how the input should be styled. you can define your own style rules
190 |
191 | ```css
192 | input[autonumeric],
193 | span[autonumeric] {
194 | text-align: right;
195 | }
196 | ```
197 |
198 | #### Integration with other scripts & events support
199 |
200 | If some reason you need to access the native autonumeric instance, you can reference your element using
201 | @ViewChild.
202 |
203 | ```HTML
204 |
205 | ```
206 |
207 | in your component :
208 |
209 | ```ts
210 | @ViewChild('myNumericField', { static: true })
211 | myNumericField:AutonumericDirective;
212 |
213 | ...
214 | reset(){
215 | this.myNumericField.instance.reset();
216 | }
217 | set(val:any){
218 | this.myNumericField.instance.set(val);
219 | }
220 |
221 | ...
222 | ```
223 |
224 | ### Demo
225 |
226 | The official AutoNumeric [documentation](http://autonumeric.org/#/guide)
227 |
228 | ### Requirements
229 |
230 | - [AutoNumeric](https://github.com/autoNumeric/autoNumeric) `^v4`
231 | - [Angular](https://angular.io/) `^v4`
232 |
233 | ### Browser support
234 |
235 | This supports the same browsers than AutoNumeric supports:
236 |
237 | - Firefox and
238 | - Chrome
239 |
240 | _(latest 2 versions)_
241 | If you use IE/Edge/Safari/Opera, this _might_ work ;)
242 |
243 | ### What's next ?
244 |
245 | I will be working on supporting more AutoNumeric options. If you have any suggestions please feel free to reach by email bellow.
246 |
247 | ### Greetings
248 |
249 | This project is hugely inspired from [vue-js implementtation of AutoNumeric](https://github.com/autoNumeric/vue-autoNumeric) by [Alexandre Bonneau](https://github.com/AlexandreBonneau)
250 |
251 | ### Support
252 |
253 | As always, if you find this useful, please consider [supporting its development](https://www.patreon.com/ainouss)!
254 | Huge Thanks :)
255 |
256 | ### License
257 |
258 | `@angularfy/autonumeric` is open-source and released under the [MIT License]
259 |
260 | > PS:
261 | > I would love to know how you're using @angularfy/autonumeric.
262 | > Contact and tell me!, abdelghani@ainouss.fr :)
263 |
--------------------------------------------------------------------------------
/src/browserslist:
--------------------------------------------------------------------------------
1 | # This file is currently used by autoprefixer to adjust CSS to support the below specified browsers
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 | #
5 | # For IE 9-11 support, please remove 'not' from the last line of the file and adjust as needed
6 |
7 | > 0.5%
8 | last 2 versions
9 | Firefox ESR
10 | not dead
11 | not IE 9-11
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './lib/index';
2 |
--------------------------------------------------------------------------------
/src/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, '../coverage/autonumeric'),
20 | reports: ['html', 'lcovonly', 'text-summary'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false
30 | });
31 | };
32 |
--------------------------------------------------------------------------------
/src/lib/autonumeric-defaults.service.ts:
--------------------------------------------------------------------------------
1 | import {Injectable} from "@angular/core";
2 | import {AutonumericOptions} from "./autonumeric.model";
3 | import AutoNumeric from 'autonumeric';
4 | @Injectable()
5 | export class AutonumericDefaults implements AutonumericOptions {
6 | allowDecimalPadding = AutoNumeric.options.allowDecimalPadding.always;
7 | alwaysAllowDecimalCharacter = AutoNumeric.options.alwaysAllowDecimalCharacter.doNotAllow;
8 | caretPositionOnFocus = AutoNumeric.options.caretPositionOnFocus.doNoForceCaretPosition;
9 | createLocalList = AutoNumeric.options.createLocalList.createList;
10 | currencySymbol = AutoNumeric.options.currencySymbol.none;
11 | currencySymbolPlacement = AutoNumeric.options.currencySymbolPlacement.prefix;
12 | decimalCharacter = AutoNumeric.options.decimalCharacter.dot;
13 | decimalCharacterAlternative = AutoNumeric.options.decimalCharacterAlternative.none;
14 | decimalPlaces = AutoNumeric.options.decimalPlaces.two;
15 | decimalPlacesRawValue = AutoNumeric.options.decimalPlacesRawValue.useDefault;
16 | decimalPlacesShownOnBlur = AutoNumeric.options.decimalPlacesShownOnBlur.useDefault;
17 | decimalPlacesShownOnFocus = AutoNumeric.options.decimalPlacesShownOnFocus.useDefault;
18 | defaultValueOverride = AutoNumeric.options.defaultValueOverride.doNotOverride;
19 | digitalGroupSpacing = AutoNumeric.options.digitalGroupSpacing.three;
20 | digitGroupSeparator = AutoNumeric.options.digitGroupSeparator.comma;
21 | divisorWhenUnfocused = AutoNumeric.options.divisorWhenUnfocused.none;
22 | emptyInputBehavior = AutoNumeric.options.emptyInputBehavior.focus;
23 | eventBubbles = AutoNumeric.options.eventBubbles.bubbles;
24 | eventIsCancelable = AutoNumeric.options.eventIsCancelable.isCancelable;
25 | failOnUnknownOption = AutoNumeric.options.failOnUnknownOption.ignore;
26 | formatOnPageLoad = AutoNumeric.options.formatOnPageLoad.format;
27 | formulaMode = AutoNumeric.options.formulaMode.disabled;
28 | historySize = AutoNumeric.options.historySize.medium;
29 | isCancellable = AutoNumeric.options.isCancellable.cancellable;
30 | leadingZero = AutoNumeric.options.leadingZero.deny;
31 | maximumValue = AutoNumeric.options.maximumValue.tenTrillions;
32 | minimumValue = AutoNumeric.options.minimumValue.tenTrillions;
33 | modifyValueOnWheel = AutoNumeric.options.modifyValueOnWheel.modifyValue;
34 | negativeBracketsTypeOnBlur = AutoNumeric.options.negativeBracketsTypeOnBlur.none;
35 | negativePositiveSignPlacement = AutoNumeric.options.negativePositiveSignPlacement.none;
36 | negativeSignCharacter = AutoNumeric.options.negativeSignCharacter.hyphen;
37 | noEventListeners = AutoNumeric.options.noEventListeners.addEvents;
38 | onInvalidPaste = AutoNumeric.options.onInvalidPaste.error;
39 | outputFormat = AutoNumeric.options.outputFormat.none;
40 | overrideMinMaxLimits = AutoNumeric.options.overrideMinMaxLimits.doNotOverride;
41 | positiveSignCharacter = AutoNumeric.options.positiveSignCharacter.plus;
42 | rawValueDivisor = AutoNumeric.options.rawValueDivisor.none;
43 | readOnly = AutoNumeric.options.readOnly.readWrite;
44 | roundingMethod = AutoNumeric.options.roundingMethod.halfUpSymmetric;
45 | saveValueToSessionStorage = AutoNumeric.options.saveValueToSessionStorage.doNotSave;
46 | selectNumberOnly = AutoNumeric.options.selectNumberOnly.selectNumbersOnly;
47 | selectOnFocus = AutoNumeric.options.selectOnFocus.select;
48 | serializeSpaces = AutoNumeric.options.serializeSpaces.plus;
49 | showOnlyNumbersOnFocus = AutoNumeric.options.showOnlyNumbersOnFocus.showAll;
50 | showPositiveSign = AutoNumeric.options.showPositiveSign.hide;
51 | showWarnings = AutoNumeric.options.showWarnings.show;
52 | styleRules = AutoNumeric.options.styleRules.none;
53 | suffixText = AutoNumeric.options.suffixText.none;
54 | symbolWhenUnfocused = AutoNumeric.options.symbolWhenUnfocused.none;
55 | unformatOnHover = AutoNumeric.options.unformatOnHover.unformat;
56 | unformatOnSubmit = AutoNumeric.options.unformatOnSubmit.keepCurrentValue;
57 | valuesToStrings = AutoNumeric.options.valuesToStrings.none;
58 | watchExternalChanges = AutoNumeric.options.watchExternalChanges.doNotWatch;
59 | wheelOn = AutoNumeric.options.wheelOn.focus;
60 | wheelStep = AutoNumeric.options.wheelStep.progressive;
61 | }
62 |
--------------------------------------------------------------------------------
/src/lib/autonumeric.directive.ts:
--------------------------------------------------------------------------------
1 | import {
2 | AfterViewInit,
3 | Directive,
4 | ElementRef,
5 | EventEmitter,
6 | forwardRef,
7 | Input,
8 | OnChanges,
9 | OnDestroy,
10 | OnInit,
11 | Output,
12 | Renderer2,
13 | SimpleChanges,
14 | } from '@angular/core';
15 | import {ControlValueAccessor, NG_VALUE_ACCESSOR} from '@angular/forms';
16 | import AutoNumeric from 'autonumeric';
17 | import {AutonumericDefaults} from './autonumeric-defaults.service';
18 | import {AutonumericOptions} from './autonumeric.model';
19 |
20 | export const AUTONUMERIC_CONTROL_VALUE_ACCESSOR: any = {
21 | provide: NG_VALUE_ACCESSOR,
22 | useExisting: forwardRef(() => AutonumericDirective),
23 | multi: true
24 | };
25 |
26 | @Directive({
27 | selector: '[autonumeric]',
28 | providers: [AUTONUMERIC_CONTROL_VALUE_ACCESSOR],
29 | // tslint:disable-next-line:use-host-property-decorator
30 | host: {
31 | '(blur)': 'onTouchedFn()'
32 | },
33 | })
34 | export class AutonumericDirective implements OnInit, AfterViewInit, OnChanges, OnDestroy, ControlValueAccessor {
35 |
36 | /* Defines the strategy to apply when options change.
37 | * reset will drop any previous options
38 | * update will change old values one by one but keep those that are not mentioned in the new options
39 | */
40 | @Input()
41 | strategy: 'reset' | 'update' = 'reset';
42 |
43 | @Input()
44 | options: AutonumericOptions;
45 | @Input()
46 | predefined: string;
47 | instance: any;
48 | private isDisabled = false;
49 | private initialValue: any;
50 | unsubscribeFormat: () => void;
51 | unsubscribeRawValueModified: () => void;
52 | @Output()
53 | formatted = new EventEmitter();
54 | @Output()
55 | rawValueModified = new EventEmitter();
56 | onChangeFn: (value: any) => void = () => {
57 | };
58 |
59 | onTouchedFn = () => {
60 | };
61 |
62 | constructor(
63 | private elm: ElementRef,
64 | private defaults: AutonumericDefaults,
65 | private renderer: Renderer2,
66 | ) {
67 | }
68 |
69 | ngOnInit(): void {
70 | }
71 |
72 | private normalize(options: any) {
73 | const normalized = {};
74 | Object.keys(AutoNumeric.options).forEach(key => {
75 | if (typeof options[key] === 'undefined') {
76 | normalized[key] = (this.defaults as any)[key];
77 | } else {
78 | normalized[key] = options[key];
79 | }
80 | });
81 | return normalized;
82 | }
83 |
84 | ngAfterViewInit(): void {
85 | this.instance = new AutoNumeric(
86 | this.elm.nativeElement,
87 | this.getOptions()
88 | );
89 | this.setDisabledState(this.isDisabled);
90 | this.unsubscribeFormat = this.renderer.listen(this.elm.nativeElement, 'autoNumeric:formatted', ($event) => {
91 | this.formatted.emit($event);
92 | });
93 | this.unsubscribeRawValueModified = this.renderer.listen(this.elm.nativeElement, 'autoNumeric:rawValueModified', ($event) => {
94 | this.onChangeFn($event.detail.newRawValue);
95 | this.rawValueModified.emit($event);
96 | });
97 | }
98 |
99 | private getOptions() {
100 | if (this.options === undefined && this.predefined === undefined) {
101 | return this.defaults;
102 | }
103 | if (this.options !== undefined && this.predefined !== undefined) {
104 | throw new Error('predefined attribute could not be combined with options. Please use either predefined or options');
105 | }
106 | if (this.options !== undefined) {
107 | return this.normalize(this.options);
108 | }
109 | const predefined = AutoNumeric.getPredefinedOptions()[this.predefined];
110 | return this.normalize(predefined);
111 | }
112 |
113 | ngOnChanges(changes: SimpleChanges): void {
114 | if (!this.instance) {
115 | return;
116 | }
117 | if (changes.options || changes.predefined) {
118 | if (this.strategy === 'reset') {
119 | this.instance.options.reset();
120 | }
121 | this.instance.update(this.getOptions());
122 | }
123 | }
124 |
125 | ngOnDestroy(): void {
126 | this.unsubscribeFormat();
127 | this.unsubscribeRawValueModified();
128 | try {
129 | this.instance.remove(); // remove listeners
130 | } catch (e) {
131 | }
132 | }
133 |
134 | writeValue(value: any): void {
135 | if (this.instance) {
136 | this.instance.set(value);
137 | } else {
138 | // autonumeric hasn't been initialised yet, store the value for later use
139 | this.initialValue = value;
140 | }
141 | }
142 |
143 | registerOnChange(fn: any): void {
144 | this.onChangeFn = fn;
145 | }
146 |
147 | registerOnTouched(fn: () => void): void {
148 | this.onTouchedFn = fn;
149 | }
150 |
151 | setDisabledState(isDisabled: boolean): void {
152 | this.isDisabled = isDisabled;
153 | if (this.instance) {
154 | if (this.isDisabled) {
155 | this.renderer.setProperty(this.instance.domElement, 'disabled', 'disabled');
156 | } else {
157 | this.renderer.removeAttribute(this.instance.domElement, 'disabled');
158 | }
159 | }
160 | }
161 | }
162 |
--------------------------------------------------------------------------------
/src/lib/autonumeric.model.ts:
--------------------------------------------------------------------------------
1 | // tslint:disable-next-line:max-line-length
2 | export interface AutonumericOptions {
3 | /* Defines if the decimal places should be padded with zeroes
4 | * `true` : always pad decimals with zeros (ie. '12.3400')
5 | * `false` : never pad with zeros (ie. '12.34')
6 | * `'floats'` : pad with zeroes only when there are decimals (ie. '12' and '12.3400')
7 | * Note: setting allowDecimalPadding to 'false' will override the 'decimalPlaces' setting.
8 | */
9 | allowDecimalPadding?: boolean | string;
10 |
11 | /* Defines if the decimal character or decimal character alternative should be accepted when there is already
12 | * a decimal character shown in the element.
13 | * If set to `true`| any decimal character input will be accepted and will subsequently modify the decimal character position|
14 | * as well as the `rawValue`.
15 | * If set to `false`| the decimal character and its alternative key will be dropped as before. This is the default setting.
16 | */
17 | alwaysAllowDecimalCharacter?: boolean;
18 |
19 | /* Defines where should be positioned the caret on focus
20 | * null : Do not enforce any caret positioning on focus (this is needed when using `selectOnFocus`)
21 | * `'start'` : put the caret of the far left side of the value (excluding the positive/negative sign and currency symbol| if any)
22 | * `'end'` : put the caret of the far right side of the value (excluding the positive/negative sign and currency symbol| if any)
23 | * `'decimalLeft'` : put the caret of the left of the decimal character if any
24 | * `'decimalRight'` : put the caret of the right of the decimal character if any
25 | */
26 | caretPositionOnFocus?: string | null;
27 |
28 | /* Defines if a local list of AutoNumeric objects should be kept when initializing this object.
29 | * This list is used by the `global.*` functions.
30 | */
31 | createLocalList?: boolean;
32 |
33 | /* Defines the currency symbol string.
34 | * It can be a string of more than one character (allowing for instance to use a space on either side of it| example: '$ ' or ' $')
35 | * cf. https://en.wikipedia.org/wiki/Currency_symbol
36 | */
37 | currencySymbol?: string;
38 |
39 |
40 | /* Defines where the currency symbol should be placed (before of after the numbers)
41 | * for prefix currencySymbolPlacement: "p" (default)
42 | * for suffix currencySymbolPlacement: "s"
43 | */
44 | currencySymbolPlacement?: string;
45 |
46 | /* Defines what decimal separator character is used
47 | */
48 | decimalCharacter?: string;
49 |
50 | /* Allow to declare an alternative decimal separator which is automatically replaced by `decimalCharacter` when typed.
51 | * This is used by countries that use a comma '|' as the decimal character and have keyboards with a numeric pads that have
52 | * a period 'full stop' as the decimal character (France or Spain for instance).
53 | */
54 | decimalCharacterAlternative?: null | string;
55 |
56 | /* Defines the default number of decimal places to show on the formatted value| and keep for the precision.
57 | * Incidentally| since we need to be able to show that many decimal places| this also defines the raw value precision by default.
58 | */
59 | decimalPlaces?: number;
60 | /* Defines how many decimal places should be kept for the raw value (ie. This is the precision for float values).
61 | *
62 | * If this option is set to `null` (which is the default)| then the value of `decimalPlaces` is used for `decimalPlacesRawValue` as well.
63 | * Note: Setting this to a lower number of decimal places than the one to be shown will lead to confusion for the users.
64 | */
65 | decimalPlacesRawValue?: null | number;
66 |
67 | /* Defines how many decimal places should be visible when the element is unfocused.
68 | * If this is set to `null`| then this option is ignored| and the `decimalPlaces` option value will be used instead.
69 | * This means this is optional ; if omitted the decimal places will be the same when the input has the focus.
70 | *
71 | * This option can be used in conjonction with the two other `scale*` options| which allows to display
72 | a different formatted value when the element is unfocused| while another formatted value is shown when focused.
73 | */
74 | decimalPlacesShownOnBlur?: null | number;
75 |
76 | /* Defines how many decimal places should be visible when the element has the focus.
77 | * If this is set to `null`| then this option is ignored| and the `decimalPlaces` option value will be used instead.
78 | *
79 | * Example:
80 | * For instance if `decimalPlacesShownOnFocus` is set to `5` and the default number of decimal places is `2`| then on focus `1|000.12345`
81 | * will be shown| while without focus `1|000.12` will be set back.
82 | * Note 1: the results depends on the rounding method used.
83 | * Note 2: the `getNumericString()` method returns the extended decimal places
84 | */
85 | decimalPlacesShownOnFocus?: null | number;
86 |
87 | /* Helper option for ASP.NET postback
88 | * This should be set as the value of the unformatted default value
89 | * examples:
90 | * no default value="" {defaultValueOverride: ""}
91 | * value=1234.56 {defaultValueOverride: '1234.56'}
92 | */
93 | defaultValueOverride?: null;
94 |
95 | /* Defines how many numbers should be grouped together (usually for the thousand separator)
96 | * - "2"| results in 99|99|99|999 India's lakhs
97 | * - "2s"| results in 99|999|99|99|999 India's lakhs scaled
98 | * - "3"| results in 999|999|999 (default)
99 | * - "4"| results in 9999|9999|9999 used in some Asian countries
100 | * Note: This option does not accept other grouping choice.
101 | */
102 | digitalGroupSpacing?: string | number;
103 |
104 | /* Defines the thousand grouping separator character
105 | * Example : If `'.'` is set| then you'll get `'1.234.567'`
106 | */
107 | digitGroupSeparator?: string;
108 |
109 | /* The `divisorWhenUnfocused` divide the element value on focus.
110 | * On blur| the element value is multiplied back.
111 | * Example : Display percentages using { divisorWhenUnfocused: 100 } (or directly in the Html with
112 | *``)
113 | * The divisor value does not need to be an integer| but please understand that Javascript has limited accuracy in math;
114 | use with caution.
115 | * Note: The `getNumericString` method returns the full value| including the 'hidden' decimals.
116 | */
117 | divisorWhenUnfocused?: null | number;
118 |
119 | /* Defines what should be displayed in the element if the raw value is an empty string ('').
120 | * - 'focus' : The currency sign is displayed when the input receives focus (default)
121 | * - 'press' : The currency sign is displayed whenever a key is being pressed
122 | * - 'always' : The currency sign is always displayed
123 | * - 'zero' : A zero is displayed ('rounded' with or without a currency sign) if the input has no value on focus out
124 | * - 'min' : The minimum value is displayed if the input has no value on focus out
125 | * - 'max' : The maximum value is displayed if the input has no value on focus out
126 | * - 'null' : When the element is empty| the `rawValue` and the element value/text is set to `null`. This also allows to set
127 | * the value to `null` using `anElement.set(null)`.
128 | */
129 | emptyInputBehavior?: string;
130 |
131 | /* Defines if the custom and native events triggered by AutoNumeric should bubble up or not.
132 | */
133 | eventBubbles?: boolean;
134 |
135 | /* Defines if the custom and native events triggered by AutoNumeric should be cancelable.
136 | */
137 | eventIsCancelable?: boolean;
138 |
139 | /* This option is the 'strict mode' (aka 'debug' mode)| which allows autoNumeric to strictly analyse the options passed|
140 | * and fails if an unknown options is used in the settings object.
141 | * You should set that to `true` if you want to make sure you are only using 'pure' autoNumeric settings objects in your code.
142 | * If you see uncaught errors in the console and your code starts to fail| this means somehow those options gets polluted by
143 | * another program (which usually happens when using frameworks).
144 | */
145 | failOnUnknownOption?: boolean;
146 |
147 | /* Determine if the default value will be formatted on initialization.
148 | */
149 | formatOnPageLoad?: boolean;
150 |
151 | /* Defines if the 'formula mode' can be activated by the user.
152 | * If set to `true`| then the user can enter the formula mode by entering the '=' character.
153 | * He will then be allowed to enter any simple math formula using numeric characters as well as
154 | * the following operators +| -| *| /| ( and ).
155 | * The formula mode is closed when the user either validate their math expression using the `Enter` key| or when the element is blurred.
156 | * If the formula is invalid| the previous valid `rawValue` is set back| and the `autoNumeric:invalidFormula` event is sent.
157 | * When a valid formula is accepted| then its result is `set()`| and the `autoNumeric:validFormula` event is sent.
158 | *
159 | * By default| this mode is disabled.
160 | */
161 | formulaMode?: boolean;
162 |
163 | /* Set the undo/redo history table size.
164 | * Each record keeps the raw value as well and the last known caret/selection positions.
165 | */
166 | historySize?: number;
167 | /* Allow the user to 'cancel' and undo the changes he made to the given autonumeric-managed element| by pressing the 'Escape' key.
168 | * Whenever the user 'validate' the input (either by hitting 'Enter'| or blurring the element)| the new value is saved for subsequent
169 | * 'cancellation'.
170 | * The process :
171 | * - save the input value on focus
172 | * - if the user change the input value| and hit `Escape`| then the initial value saved on focus is set back
173 | * - on the other hand if the user either have used `Enter` to validate (`Enter` throws a change event) his entries|
174 | * or if the input value has been changed by another script in the mean time| then we save the new input value
175 | * - on a successful 'cancel'| select the whole value (while respecting the `selectNumberOnly` option)
176 | * - bonus; if the value has not changed| hitting 'Esc' just select all the input value (while respecting the `selectNumberOnly` option)
177 | */
178 | isCancellable?: boolean;
179 |
180 | /* Controls the leading zero behavior
181 | * - 'allow' : allows leading zeros to be entered. Zeros will be truncated when entering additional digits.
182 | * On focusout zeros will be deleted
183 | * - 'deny' : allows only one leading zero on values that are between 1 and -1
184 | * - 'keep' : allows leading zeros to be entered. on focusout zeros will be retained
185 | */
186 | leadingZero?: string;
187 |
188 | /* Defines the maximum possible value a user can enter.
189 | * Notes:
190 | * - this value must be a string and use the period for the decimal point
191 | * - this value needs to be larger than `minimumValue`
192 | */
193 | maximumValue?: string | number;
194 |
195 | /* Defines the minimum possible value a user can enter.
196 | * Notes:
197 | * - this value must be a string and use the period for the decimal point
198 | * - this value needs to be smaller than `maximumValue`
199 | * - if this is superior to 0| then you'll effectively prevent your user to entirely delete the content of your element
200 | */
201 | minimumValue?: string | number;
202 |
203 | /* Allows the user to increment or decrement the element value with the mouse wheel.
204 | * The wheel behavior can be modified by the `wheelStep` option.
205 | * This `wheelStep` option can be used in two ways| either by setting:
206 | * - a 'fixed' step value (`wheelStep : 1000`)| or
207 | * - the 'progressive' string (`wheelStep : 'progressive'`)| which will then activate a special mode where the step is automatically
208 | * calculated based on the element value size.
209 | *
210 | * Note :
211 | * You can activate/deactivate the wheel event for each `wheelOn` option value by using the 'Shift' modifier key while using
212 | * the mouse wheel.
213 | */
214 | modifyValueOnWheel?: boolean;
215 |
216 | /* Adds brackets on negative values (ie. transforms '-$ 999.99' to '($999.99)')
217 | * Those brackets are visible only when the field does NOT have the focus.
218 | * The left and right symbols should be enclosed in quotes and separated by a comma.
219 | */
220 | negativeBracketsTypeOnBlur?: string | null;
221 |
222 | /* Placement of the negative/positive sign relative to the `currencySymbol` option.
223 | *
224 | * Example:
225 | * // Default values
226 | * -1|234.56 => default no options required
227 | * $-1|234.56 => {currencySymbol: "$"| negativePositiveSignPlacement: "r"} // Default if negativePositiveSignPlacement is
228 | * 'null' and currencySymbol is not empty
229 | *
230 | * // Sign on the left hand side of the whole number
231 | * -$1|234.56 => {currencySymbol: "$"} or {currencySymbol: "$"| negativePositiveSignPlacement: "l"}
232 | * -1|234.56$ => {currencySymbol: "$"| currencySymbolPlacement: "s"| negativePositiveSignPlacement: "p"}
233 | * // Default if negativePositiveSignPlacement is 'null' and currencySymbol is not empty
234 | *
235 | * // Sign on the right hand side of the whole number
236 | * 1|234.56- => {negativePositiveSignPlacement: "s"}
237 | * $1|234.56- => {currencySymbol: "$"| negativePositiveSignPlacement: "s"}
238 | * 1|234.56-$ => {currencySymbol: "$"| currencySymbolPlacement: "s"}
239 | * 1|234.56$- => {currencySymbol: "$"| currencySymbolPlacement: "s"| negativePositiveSignPlacement: "r"}
240 | */
241 | negativePositiveSignPlacement?: string | null;
242 |
243 | /* Defines the negative sign symbol.
244 | * It can be a string of only one character.
245 | */
246 | negativeSignCharacter?: string;
247 |
248 | /* Defines if the element should have event listeners activated on it.
249 | * By default| those event listeners are only added to elements and html element with the `contenteditable`
250 | * attribute set to `true`| but not on the other html tags.
251 | * This allows to initialize elements without any event listeners.
252 | * Warning: Since AutoNumeric will not check the input content after its initialization| using some autoNumeric
253 | * methods afterwards *will* probably leads to formatting problems.
254 | */
255 | noEventListeners?: boolean;
256 |
257 | /* Manage how autoNumeric react when the user tries to paste an invalid number.
258 | * - 'error' : (This is the default behavior) The input value is not changed and an error is output in the console.
259 | * - 'ignore' : idem than 'error'| but fail silently without outputting any error/warning in the console.
260 | * - 'clamp' : if the pasted value is either too small or too big regarding the minimumValue and maximumValue range|
261 | * then the result is clamped to those limits.
262 | * - 'truncate' : autoNumeric will insert as many pasted numbers it can at the initial caret/selection| until everything is pasted|
263 | * or the range limit is hit.
264 | * The non-pasted numbers are dropped and therefore not used at all.
265 | * - 'replace' : autoNumeric will first insert as many pasted numbers it can at the initial caret/selection| then if the range limit
266 | * is hit| it will try
267 | * to replace one by one the remaining initial numbers (on the right side of the caret) with the rest of the pasted
268 | * numbers.
269 | *
270 | * Note 1 : A paste content starting with a negative sign '-' will be accepted anywhere in the input| and will set the resulting value
271 | * as a negative number
272 | * Note 2 : A paste content starting with a number will be accepted| even if the rest is gibberish (ie. '123foobar456').
273 | * Only the first number will be used (here '123').
274 | * Note 3 : The paste event works with the `decimalPlacesShownOnFocus` option too.
275 | */
276 | onInvalidPaste?: string;
277 |
278 | /* Defines how the value should be formatted when wanting a 'localized' version of it.
279 | * - null or 'string' => 'nnnn.nn' or '-nnnn.nn' as text type. This is the default behavior.
280 | * - 'number' => nnnn.nn or -nnnn.nn as a Number (Warning: this works only for integers inferior to Number.MAX_SAFE_INTEGER)
281 | * - '|' or '-|' => 'nnnn|nn' or '-nnnn|nn'
282 | * - '.-' => 'nnnn.nn' or 'nnnn.nn-'
283 | * - '|-' => 'nnnn|nn' or 'nnnn|nn-'
284 | *
285 | * Note: The hyphen '-' is translated to the custom negative sign defined in `negativeSignCharacter`
286 | */
287 | outputFormat?: string | null;
288 | /* Override the minimum and maximum limits
289 | * overrideMinMaxLimits: "ceiling" adheres to maximumValue and ignores minimumValue settings
290 | * overrideMinMaxLimits: "floor" adheres to minimumValue and ignores maximumValue settings
291 | * overrideMinMaxLimits: "ignore" ignores both minimumValue & maximumValue
292 | */
293 | overrideMinMaxLimits?: string | null;
294 | /* Defines the positive sign symbol.
295 | * It can be a string of only one character.
296 | * This is shown only if `showPositiveSign` is set to `true`.
297 | */
298 | positiveSignCharacter?: string | null;
299 |
300 | /* The `rawValueDivisor` divides the formatted value shown in the AutoNumeric element and store the result in `rawValue`.
301 | * @example { rawValueDivisor: '100' } or
302 | * Given the `0.01234` raw value| the formatted value will be displayed as `'1.234'`.
303 | * This is useful when displaying percentage for instance| and avoid the need to divide/multiply by 100
304 | * between the number shown and the raw value.
305 | */
306 | rawValueDivisor?: null | number;
307 |
308 | /* Defines if the element (`` or another allowed html tag) should be set as read-only on initialization.
309 | * When set to `true`| then:
310 | * - the `readonly` html property is added to the element on initialization| or
311 | * - the `contenteditable` attribute is set to `false` on non-input elements.
312 | */
313 | readOnly?: boolean;
314 |
315 | /* Defines the rounding method to use.
316 | * roundingMethod: "S"| Round-Half-Up Symmetric (default)
317 | * roundingMethod: "A"| Round-Half-Up Asymmetric
318 | * roundingMethod: "s"| Round-Half-Down Symmetric (lower case s)
319 | * roundingMethod: "a"| Round-Half-Down Asymmetric (lower case a)
320 | * roundingMethod: "B"| Round-Half-Even "Bankers Rounding"
321 | * roundingMethod: "U"| Round Up "Round-Away-From-Zero"
322 | * roundingMethod: "D"| Round Down "Round-Toward-Zero" - same as truncate
323 | * roundingMethod: "C"| Round to Ceiling "Toward Positive Infinity"
324 | * roundingMethod: "F"| Round to Floor "Toward Negative Infinity"
325 | * roundingMethod: "N05" Rounds to the nearest .05 => same as "CHF" used in 1.9X and still valid
326 | * roundingMethod: "U05" Rounds up to next .05
327 | * roundingMethod: "D05" Rounds down to next .05
328 | */
329 | roundingMethod?: string;
330 | /* Set to `true` to allow the `decimalPlacesShownOnFocus` value to be saved with sessionStorage
331 | * If IE 6 or 7 is detected| the value will be saved as a session cookie.
332 | */
333 | saveValueToSessionStorage?: boolean;
334 |
335 | /* Determine if the select all keyboard command will select the complete input text| or only the input numeric value
336 | * Note : If the currency symbol is between the numeric value and the negative sign| only the numeric value will be selected
337 | */
338 | selectNumberOnly?: boolean;
339 |
340 | /* Defines if the element value should be selected on focus.
341 | * Note: The selection is done using the `selectNumberOnly` option.
342 | */
343 | selectOnFocus?: boolean;
344 |
345 | /* Defines how the serialize functions should treat the spaces.
346 | * Those spaces ' ' can either be converted to the plus sign '+'| which is the default| or to '%20'.
347 | * Both values being valid per the spec (http://www.w3.org/Addressing/URL/uri-spec.html).
348 | * Also see the summed up answer on http://stackoverflow.com/a/33939287.
349 | *
350 | * tl;dr : Spaces should be converted to '%20' before the '?' sign| then converted to '+' after.
351 | * In our case since we serialize the query| we use '+' as the default (but allow the user to get back the old *wrong* behavior).
352 | */
353 | serializeSpaces?: string;
354 | /* Defines if the element value should be converted to the raw value on focus (and back to the formatted on blur).
355 | * If set to `true`| then autoNumeric remove the thousand separator| currency symbol and suffix on focus.
356 | * Example:
357 | * If the input value is '$ 1|999.88 suffix'| on focus it becomes '1999.88' and back to '$ 1|999.88 suffix' on blur.
358 | */
359 | showOnlyNumbersOnFocus?: boolean;
360 |
361 | /* Allow the positive sign symbol `+` to be displayed for positive numbers.
362 | * By default| this positive sign is not shown.
363 | * The sign placement is controlled by the 'negativePositiveSignPlacement' option| mimicking the negative sign placement rules.
364 | */
365 | showPositiveSign?: boolean;
366 |
367 | /* Defines if warnings should be shown in the console.
368 | * Those warnings can be ignored| but are usually printed when something could be improved by the user (ie. option conflicts).
369 | */
370 | showWarnings?: boolean;
371 |
372 | /* Defines the rules that calculate the CSS class(es) to apply on the element| based on the raw unformatted value.
373 | * This can also be used to call callbacks whenever the `rawValue` is updated.
374 | * Important: all callbacks must return `null` if no ranges/userDefined classes are selected
375 | * @example
376 | * {
377 | * positive : 'autoNumeric-positive'| // Or `null` to not use it
378 | * negative : 'autoNumeric-negative'|
379 | * ranges : [
380 | * { min: 0| max: 25| class: 'autoNumeric-red' }|
381 | * { min: 25| max: 50| class: 'autoNumeric-orange' }|
382 | * { min: 50| max: 75| class: 'autoNumeric-yellow' }|
383 | * { min: 75| max: Number.MAX_SAFE_INTEGER| class: 'autoNumeric-green' }|
384 | * ]|
385 | * userDefined: [
386 | * // If 'classes' is a string| set it if `true`| remove it if `false`
387 | * { callback: rawValue => { return true; }| classes: 'thisIsTrue' }|
388 | * // If 'classes' is an array with only 2 elements| set the first class if `true`| the second if `false`
389 | * { callback: rawValue => rawValue % 2 === 0| classes: ['autoNumeric-even'| 'autoNumeric-odd'] }|
390 | * // Return only one index to use on the `classes` array (here| 'class3')
391 | * { callback: rawValue => { return 2; }| classes: ['class1'| 'class2'| 'class3'] }|
392 | * // Return an array of indexes to use on the `classes` array (here| 'class1' and 'class3')
393 | * { callback: rawValue => { return [0| 2]; }| classes: ['class1'| 'class2'| 'class3'] }|
394 | * // If 'classes' is `undefined` or `null`| then the callback is called with the AutoNumeric object passed as a parameter
395 | * { callback: anElement => { return anElement.getFormatted(); } }|
396 | * ]|
397 | * }
398 | */
399 | styleRules?: any;
400 | /* Add a text on the right hand side of the element value.
401 | * This suffix text can have any characters in its string| except numeric characters and the negative/positive sign.
402 | * Example: ' dollars'
403 | */
404 | suffixText?: string;
405 |
406 | /* The three options (divisorWhenUnfocused| decimalPlacesShownOnBlur & symbolWhenUnfocused) handle scaling
407 | * of the input when the input does not have focus
408 | * Please note that the non-scaled value is held in data and it is advised that you use the `saveValueToSessionStorage`
409 | * option to ensure retaining the value
410 | * ["divisor"| "decimal places"| "symbol"]
411 | * Example: with the following options set {divisorWhenUnfocused: '1000'| decimalPlacesShownOnBlur: '1'| symbolWhenUnfocused: ' K'}
412 | * Example: focusin value "1|111.11" focusout value "1.1 K"
413 | */
414 |
415 | /* The `symbolWhenUnfocused` option is a symbol placed as a suffix when not in focus.
416 | * This is optional too.
417 | */
418 | symbolWhenUnfocused?: null | string;
419 |
420 | /* Defines if the element value should be unformatted when the user hover his mouse over it while holding the `Alt` key.
421 | * Unformatting there means that this removes any non-number characters and displays the *raw* value| as understood
422 | * by Javascript (ie. `12.34` is a valid number| while `12|34` is not).
423 | * We reformat back before anything else if :
424 | * - the user focus on the element by tabbing or clicking into it|
425 | * - the user releases the `Alt` key| and
426 | * - if we detect a mouseleave event.
427 | *
428 | * We unformat again if :
429 | * - while the mouse is over the element| the user hit `Alt` again
430 | */
431 | unformatOnHover?: boolean;
432 |
433 | /* Removes the formatting and use the raw value in each autoNumeric elements of the parent form element| on the form `submit` event.
434 | * The output format is a numeric string (nnnn.nn or -nnnn.nn).
435 | */
436 | unformatOnSubmit?: boolean;
437 |
438 | /* Provides a way for automatically replacing the formatted value with a pre-defined string| when the raw value is equal to a
439 | * specific value
440 | * Here you can specify as many 'conversion' as needed.
441 | */
442 | valuesToStrings?: null | { 0: '-', } | { '-1': 'Min', 1: 'Max', };
443 | /* Defines if the AutoNumeric element should watch external changes made without using `.set()`| but by using the basic
444 | * `aNElement.node().value = 42` notation.
445 | * If set to `watch`| then AutoNumeric will format the new value using `.set()` internally.
446 | * Otherwise it will neither format it| nor save it in the history.
447 | */
448 | watchExternalChanges?: boolean;
449 |
450 | /* Defines when the wheel event will increment or decrement the element value.
451 | * When set to `'focus'`| the AutoNumeric-managed element needs to be focused for the wheel event to change the value.
452 | * When set to `'hover'`| using the wheel event while the mouse is hovering the element is sufficient (no focus needed).
453 | *
454 | * Note :
455 | * When `wheelOn` is set to `'focus'`| you can use the 'Shift' modifier key while using the mouse wheel in order
456 | * to temporarily activate the increment/decrement feature even if the element is not focused.
457 | * When `wheelOn` is set to `'hover'`| you can use the 'Shift' modifier key while using the mouse wheel in order
458 | * to temporarily disable the increment/decrement feature even if the element is not hovered.
459 | */
460 | wheelOn?: string;
461 |
462 | /* That option is linked to the `modifyValueOnWheel` one and will only be used if the latter is set to `true`.
463 | * This option will modify the wheel behavior and can be used in two ways| either by setting :
464 | * - a 'fixed' step value (a positive float or integer number `1000`)| or
465 | * - the `'progressive'` string.
466 | *
467 | * The 'fixed' mode always increment/decrement the element value by that amount| while respecting
468 | * the `minimumValue` and `maximumValue` settings.
469 | * The 'progressive' mode will increment/decrement the element value based on its current value. The bigger the
470 | * number| the bigger the step| and vice versa.
471 | */
472 | wheelStep?: string;
473 |
474 | /* Options Change strategy,
475 | *
476 | */
477 | }
478 |
--------------------------------------------------------------------------------
/src/lib/autonumeric.module.ts:
--------------------------------------------------------------------------------
1 | import {InjectionToken, ModuleWithProviders, NgModule} from '@angular/core';
2 | import {AutonumericOptions} from "./autonumeric.model";
3 | import {AutonumericDefaults} from "./autonumeric-defaults.service";
4 | import {AutonumericDirective} from "./autonumeric.directive";
5 | import {CommonModule} from '@angular/common';
6 |
7 | export const USER_DEFAULTS = new InjectionToken('autonumeric defaults');
8 |
9 | export function defaultsFactory(userDefaults: AutonumericOptions): AutonumericDefaults {
10 | const defaults: AutonumericDefaults = new AutonumericDefaults();
11 | Object.assign(defaults, userDefaults);
12 | return defaults;
13 | }
14 |
15 | @NgModule({
16 | imports: [CommonModule],
17 | declarations: [AutonumericDirective],
18 | exports: [AutonumericDirective]
19 | })
20 | export class AutonumericModule {
21 | static forRoot(userDefaults: AutonumericOptions = {}): ModuleWithProviders {
22 | return {
23 | ngModule: AutonumericModule,
24 | providers: [
25 | {
26 | provide: USER_DEFAULTS,
27 | useValue: userDefaults
28 | },
29 | {
30 | provide: AutonumericDefaults,
31 | useFactory: defaultsFactory,
32 | deps: [USER_DEFAULTS]
33 | }
34 | ]
35 | };
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/lib/index.ts:
--------------------------------------------------------------------------------
1 | export * from './autonumeric.module';
2 | export {AutonumericDefaults} from './autonumeric-defaults.service';
3 |
--------------------------------------------------------------------------------
/src/ng-package.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../node_modules/ng-packagr/ng-package.schema.json",
3 | "dest": "../dist/autonumeric",
4 | "deleteDestPath": false,
5 | "lib": {
6 | "entryFile": "./index.ts",
7 | "umdId": "nga",
8 | "amdId": "nga"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/ng-package.prod.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "../node_modules/ng-packagr/ng-package.schema.json",
3 | "dest": "../dist/autonumeric",
4 | "lib": {
5 | "flatModuleFile": "autonumeric",
6 | "entryFile": "./index.ts",
7 | "umdId": "nga",
8 | "amdId": "nga"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@angularfy/autonumeric",
3 | "version": "3.0.0",
4 | "lockfileVersion": 1,
5 | "requires": true,
6 | "dependencies": {
7 | "@angular/common": {
8 | "version": "4.4.7",
9 | "resolved": "https://registry.npmjs.org/@angular/common/-/common-4.4.7.tgz",
10 | "integrity": "sha512-5R0POjbT4CR+8vXS7P33SiozJpTEKDsHq07EMm90OCwoofU5DIKDLNyEqr362zsbpzGUTmhGbSiLZib5Qt4djA==",
11 | "dev": true,
12 | "requires": {
13 | "tslib": "^1.7.1"
14 | }
15 | },
16 | "@angular/core": {
17 | "version": "4.4.7",
18 | "resolved": "https://registry.npmjs.org/@angular/core/-/core-4.4.7.tgz",
19 | "integrity": "sha512-Jxs6gNTl5KjXflg5vi5rlnokq1johFccN94qSOgDv+Mg1iuGF2i9p7EHkw3Y8jBCVaSLw1qgHE+wMb6KTlJDLA==",
20 | "dev": true,
21 | "requires": {
22 | "tslib": "^1.7.1"
23 | }
24 | },
25 | "@angular/forms": {
26 | "version": "4.4.7",
27 | "resolved": "https://registry.npmjs.org/@angular/forms/-/forms-4.4.7.tgz",
28 | "integrity": "sha512-EXGutI4GNBptpwkCQdCTxWAlJll8aCV7m3cA1FHZgFP7VNSgYF0pD+PscM5jSeajG30cRjaKxgL4cqj6yMMtww==",
29 | "dev": true,
30 | "requires": {
31 | "tslib": "^1.7.1"
32 | }
33 | },
34 | "autonumeric": {
35 | "version": "4.5.10",
36 | "resolved": "https://registry.npmjs.org/autonumeric/-/autonumeric-4.5.10.tgz",
37 | "integrity": "sha512-/PAltg7FZe6YvXLI1b1ndB8JAHWDp8mAq344Nr23SP43Kvdrsk+pM62C1ca4wf+5CUZAri6AQwKQj7gU2MT7Zw==",
38 | "dev": true
39 | },
40 | "tslib": {
41 | "version": "1.10.0",
42 | "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz",
43 | "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==",
44 | "dev": true
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@angularfy/autonumeric",
3 | "version": "3.0.3",
4 | "description": "Angular implementation of autoNumeric",
5 | "keywords": [
6 | "angular",
7 | "numeric",
8 | "components",
9 | "autonumeric",
10 | "autonumeric",
11 | "auto",
12 | "numeric",
13 | "number",
14 | "mask",
15 | "decimal",
16 | "regex",
17 | "mask"
18 | ],
19 | "author": "Abdelghani AINOUSS",
20 | "repository": {
21 | "type": "git",
22 | "url": "git+https://github.com/angularfy/autonumeric.git"
23 | },
24 | "license": "MIT",
25 | "bugs": {
26 | "url": "https://github.com/angularfy/autonumeric/issues"
27 | },
28 | "homepage": "http://www.angularfy.com/projects/autonumeric",
29 | "peerDependencies": {
30 | "@angular/common": "^4.0.1",
31 | "@angular/core": "^4.0.1",
32 | "@angular/forms": "^4.0.1",
33 | "autonumeric": "^4.0.1"
34 | },
35 | "devDependencies": {
36 | "@angular/common": "^4.0.1",
37 | "@angular/core": "^4.0.1",
38 | "@angular/forms": "^4.0.1",
39 | "autonumeric": "^4.0.1"
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/public_api.ts:
--------------------------------------------------------------------------------
1 | export * from './index';
2 |
--------------------------------------------------------------------------------
/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/dist/zone-testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import {
6 | BrowserDynamicTestingModule,
7 | platformBrowserDynamicTesting
8 | } from '@angular/platform-browser-dynamic/testing';
9 |
10 | declare const require: any;
11 |
12 | // First, initialize the Angular testing environment.
13 | getTestBed().initTestEnvironment(
14 | BrowserDynamicTestingModule,
15 | platformBrowserDynamicTesting()
16 | );
17 | // Then we find all the tests.
18 | const context = require.context('./', true, /\.spec\.ts$/);
19 | // And load the modules.
20 | context.keys().map(context);
21 |
--------------------------------------------------------------------------------
/src/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "inlineSources": true,
5 | "importHelpers": true
6 | },
7 | "angularCompilerOptions": {
8 | "annotateForClosureCompiler": true,
9 | "skipTemplateCodegen": true,
10 | "strictMetadataEmit": true,
11 | "fullTemplateTypeCheck": true,
12 | "strictInjectionParameters": true
13 | },
14 | "include": [
15 | "./**/*.ts"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/src/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "./out-tsc/spec",
5 | "types": [
6 | "jasmine",
7 | "node"
8 | ]
9 | },
10 | "files": [
11 | "./test.ts"
12 | ],
13 | "include": [
14 | "./**/*.spec.ts",
15 | "./**/*.d.ts"
16 | ]
17 | }
18 |
--------------------------------------------------------------------------------
/src/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tslint.json"
3 | }
4 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "angularCompilerOptions": {
4 | "annotationsAs": "decorators"
5 | },
6 | "compilerOptions": {
7 | "baseUrl": "./",
8 | "outDir": "./dist/out-tsc",
9 | "sourceMap": true,
10 | "declaration": false,
11 | "module": "es2015",
12 | "moduleResolution": "node",
13 | "emitDecoratorMetadata": true,
14 | "experimentalDecorators": true,
15 | "importHelpers": true,
16 | "target": "es5",
17 | "typeRoots": [
18 | "node_modules/@types"
19 | ],
20 | "lib": [
21 | "es2018",
22 | "dom"
23 | ]
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "tslint:recommended",
3 | "rulesDirectory": [
4 | "codelyzer"
5 | ],
6 | "rules": {
7 | "array-type": false,
8 | "arrow-parens": false,
9 | "deprecation": {
10 | "severity": "warn"
11 | },
12 | "import-blacklist": [
13 | true,
14 | "rxjs/Rx"
15 | ],
16 | "interface-name": false,
17 | "max-classes-per-file": false,
18 | "max-line-length": [
19 | true,
20 | 140
21 | ],
22 | "member-access": false,
23 | "member-ordering": [
24 | true,
25 | {
26 | "order": [
27 | "static-field",
28 | "instance-field",
29 | "static-method",
30 | "instance-method"
31 | ]
32 | }
33 | ],
34 | "no-consecutive-blank-lines": false,
35 | "no-console": [
36 | true,
37 | "debug",
38 | "info",
39 | "time",
40 | "timeEnd",
41 | "trace"
42 | ],
43 | "no-empty": false,
44 | "no-inferrable-types": [
45 | true,
46 | "ignore-params"
47 | ],
48 | "no-non-null-assertion": true,
49 | "no-redundant-jsdoc": true,
50 | "no-switch-case-fall-through": true,
51 | "no-use-before-declare": true,
52 | "no-var-requires": false,
53 | "object-literal-key-quotes": [
54 | true,
55 | "as-needed"
56 | ],
57 | "object-literal-sort-keys": false,
58 | "ordered-imports": false,
59 | "quotemark": [
60 | true,
61 | "single"
62 | ],
63 | "trailing-comma": false,
64 | "no-output-on-prefix": true,
65 | "use-input-property-decorator": true,
66 | "use-output-property-decorator": true,
67 | "use-host-property-decorator": true,
68 | "no-input-rename": true,
69 | "no-output-rename": true,
70 | "use-life-cycle-interface": true,
71 | "use-pipe-transform-interface": true,
72 | "component-class-suffix": true,
73 | "directive-class-suffix": true
74 | }
75 | }
76 |
--------------------------------------------------------------------------------