1 | import { forwardRef, EventEmitter, Component, ChangeDetectionStrategy, ViewEncapsulation, ElementRef, ChangeDetectorRef, Input, ViewChild, Output, NgModule } from '@angular/core';
|
2 | import { CommonModule } from '@angular/common';
|
3 | import { InputTextModule } from 'primeng/inputtext';
|
4 | import { ButtonModule } from 'primeng/button';
|
5 | import { NG_VALUE_ACCESSOR } from '@angular/forms';
|
6 |
|
7 | const INPUTNUMBER_VALUE_ACCESSOR = {
|
8 | provide: NG_VALUE_ACCESSOR,
|
9 | useExisting: forwardRef(() => InputNumber),
|
10 | multi: true
|
11 | };
|
12 | class InputNumber {
|
13 | constructor(el, cd) {
|
14 | this.el = el;
|
15 | this.cd = cd;
|
16 | this.showButtons = false;
|
17 | this.format = true;
|
18 | this.buttonLayout = "stacked";
|
19 | this.incrementButtonIcon = 'pi pi-angle-up';
|
20 | this.decrementButtonIcon = 'pi pi-angle-down';
|
21 | this.step = 1;
|
22 | this.onInput = new EventEmitter();
|
23 | this.onFocus = new EventEmitter();
|
24 | this.onBlur = new EventEmitter();
|
25 | this.onModelChange = () => { };
|
26 | this.onModelTouched = () => { };
|
27 | this.groupChar = '';
|
28 | this._modeOption = "decimal";
|
29 | this._useGroupingOption = true;
|
30 | }
|
31 | get locale() {
|
32 | return this._localeOption;
|
33 | }
|
34 | set locale(localeOption) {
|
35 | this._localeOption = localeOption;
|
36 | this.updateConstructParser();
|
37 | }
|
38 | get localeMatcher() {
|
39 | return this._localeMatcherOption;
|
40 | }
|
41 | set localeMatcher(localeMatcherOption) {
|
42 | this._localeMatcherOption = localeMatcherOption;
|
43 | this.updateConstructParser();
|
44 | }
|
45 | get mode() {
|
46 | return this._modeOption;
|
47 | }
|
48 | set mode(modeOption) {
|
49 | this._modeOption = modeOption;
|
50 | this.updateConstructParser();
|
51 | }
|
52 | get currency() {
|
53 | return this._currencyOption;
|
54 | }
|
55 | set currency(currencyOption) {
|
56 | this._currencyOption = currencyOption;
|
57 | this.updateConstructParser();
|
58 | }
|
59 | get currencyDisplay() {
|
60 | return this._currencyDisplayOption;
|
61 | }
|
62 | set currencyDisplay(currencyDisplayOption) {
|
63 | this._currencyDisplayOption = currencyDisplayOption;
|
64 | this.updateConstructParser();
|
65 | }
|
66 | get useGrouping() {
|
67 | return this._useGroupingOption;
|
68 | }
|
69 | set useGrouping(useGroupingOption) {
|
70 | this._useGroupingOption = useGroupingOption;
|
71 | this.updateConstructParser();
|
72 | }
|
73 | get minFractionDigits() {
|
74 | return this._minFractionDigitsOption;
|
75 | }
|
76 | set minFractionDigits(minFractionDigitsOption) {
|
77 | this._minFractionDigitsOption = minFractionDigitsOption;
|
78 | this.updateConstructParser();
|
79 | }
|
80 | get maxFractionDigits() {
|
81 | return this._maxFractionDigitsOption;
|
82 | }
|
83 | set maxFractionDigits(maxFractionDigitsOption) {
|
84 | this._maxFractionDigitsOption = maxFractionDigitsOption;
|
85 | this.updateConstructParser();
|
86 | }
|
87 | get prefix() {
|
88 | return this._prefixOption;
|
89 | }
|
90 | set prefix(prefixOption) {
|
91 | this._prefixOption = prefixOption;
|
92 | this.updateConstructParser();
|
93 | }
|
94 | get suffix() {
|
95 | return this._suffixOption;
|
96 | }
|
97 | set suffix(suffixOption) {
|
98 | this._suffixOption = suffixOption;
|
99 | this.updateConstructParser();
|
100 | }
|
101 | ngOnInit() {
|
102 | this.constructParser();
|
103 | this.initialized = true;
|
104 | }
|
105 | getOptions() {
|
106 | return {
|
107 | localeMatcher: this.localeMatcher,
|
108 | style: this.mode,
|
109 | currency: this.currency,
|
110 | currencyDisplay: this.currencyDisplay,
|
111 | useGrouping: this.useGrouping,
|
112 | minimumFractionDigits: this.minFractionDigits,
|
113 | maximumFractionDigits: this.maxFractionDigits
|
114 | };
|
115 | }
|
116 | constructParser() {
|
117 | this.numberFormat = new Intl.NumberFormat(this.locale, this.getOptions());
|
118 | const numerals = [...new Intl.NumberFormat(this.locale, { useGrouping: false }).format(9876543210)].reverse();
|
119 | const index = new Map(numerals.map((d, i) => [d, i]));
|
120 | this._numeral = new RegExp(`[${numerals.join('')}]`, 'g');
|
121 | this._decimal = this.getDecimalExpression();
|
122 | this._group = this.getGroupingExpression();
|
123 | this._minusSign = this.getMinusSignExpression();
|
124 | this._currency = this.getCurrencyExpression();
|
125 | this._suffix = new RegExp(`${this.escapeRegExp(this.suffix || '')}`, 'g');
|
126 | this._prefix = new RegExp(`${this.escapeRegExp(this.prefix || '')}`, 'g');
|
127 | this._index = d => index.get(d);
|
128 | }
|
129 | updateConstructParser() {
|
130 | if (this.initialized) {
|
131 | this.constructParser();
|
132 | }
|
133 | }
|
134 | escapeRegExp(text) {
|
135 | return text.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
136 | }
|
137 | getDecimalExpression() {
|
138 | const formatter = new Intl.NumberFormat(this.locale, { useGrouping: false });
|
139 | return new RegExp(`[${formatter.format(1.1).trim().replace(this._numeral, '')}]`, 'g');
|
140 | }
|
141 | getGroupingExpression() {
|
142 | const formatter = new Intl.NumberFormat(this.locale, { useGrouping: true });
|
143 | this.groupChar = formatter.format(1000000).trim().replace(this._numeral, '').charAt(0);
|
144 | return new RegExp(`[${this.groupChar}]`, 'g');
|
145 | }
|
146 | getMinusSignExpression() {
|
147 | const formatter = new Intl.NumberFormat(this.locale, { useGrouping: false });
|
148 | return new RegExp(`[${formatter.format(-1).trim().replace(this._numeral, '')}]`, 'g');
|
149 | }
|
150 | getCurrencyExpression() {
|
151 | if (this.currency) {
|
152 | const formatter = new Intl.NumberFormat(this.locale, { style: 'currency', currency: this.currency, currencyDisplay: this.currencyDisplay });
|
153 | return new RegExp(`[${formatter.format(1).replace(/\s/g, '').replace(this._numeral, '').replace(this._decimal, '').replace(this._group, '')}]`, 'g');
|
154 | }
|
155 | return new RegExp(`[]`, 'g');
|
156 | }
|
157 | formatValue(value) {
|
158 | if (value != null) {
|
159 | if (value === '-') {
|
160 | return value;
|
161 | }
|
162 | if (this.format) {
|
163 | let formatter = new Intl.NumberFormat(this.locale, this.getOptions());
|
164 | let formattedValue = formatter.format(value);
|
165 | if (this.prefix) {
|
166 | formattedValue = this.prefix + formattedValue;
|
167 | }
|
168 | if (this.suffix) {
|
169 | formattedValue = formattedValue + this.suffix;
|
170 | }
|
171 | return formattedValue;
|
172 | }
|
173 | return value;
|
174 | }
|
175 | return '';
|
176 | }
|
177 | parseValue(text) {
|
178 | let filteredText = text
|
179 | .replace(this._suffix, '')
|
180 | .replace(this._prefix, '')
|
181 | .trim()
|
182 | .replace(/\s/g, '')
|
183 | .replace(this._currency, '')
|
184 | .replace(this._group, '')
|
185 | .replace(this._minusSign, '-')
|
186 | .replace(this._decimal, '.')
|
187 | .replace(this._numeral, this._index);
|
188 | if (filteredText) {
|
189 | if (filteredText === '-')
|
190 | return filteredText;
|
191 | let parsedValue = +filteredText;
|
192 | return isNaN(parsedValue) ? null : parsedValue;
|
193 | }
|
194 | return null;
|
195 | }
|
196 | repeat(event, interval, dir) {
|
197 | let i = interval || 500;
|
198 | this.clearTimer();
|
199 | this.timer = setTimeout(() => {
|
200 | this.repeat(event, 40, dir);
|
201 | }, i);
|
202 | this.spin(event, dir);
|
203 | }
|
204 | spin(event, dir) {
|
205 | let step = this.step * dir;
|
206 | let currentValue = this.parseValue(this.input.nativeElement.value) || 0;
|
207 | let newValue = this.validateValue(currentValue + step);
|
208 | if (this.maxlength && this.maxlength < this.formatValue(newValue).length) {
|
209 | return;
|
210 | }
|
211 | this.updateInput(newValue, null, 'spin');
|
212 | this.updateModel(event, newValue);
|
213 | this.handleOnInput(event, currentValue, newValue);
|
214 | }
|
215 | onUpButtonMouseDown(event) {
|
216 | this.input.nativeElement.focus();
|
217 | this.repeat(event, null, 1);
|
218 | event.preventDefault();
|
219 | }
|
220 | onUpButtonMouseUp() {
|
221 | this.clearTimer();
|
222 | }
|
223 | onUpButtonMouseLeave() {
|
224 | this.clearTimer();
|
225 | }
|
226 | onUpButtonKeyDown(event) {
|
227 | if (event.keyCode === 32 || event.keyCode === 13) {
|
228 | this.repeat(event, null, 1);
|
229 | }
|
230 | }
|
231 | onUpButtonKeyUp() {
|
232 | this.clearTimer();
|
233 | }
|
234 | onDownButtonMouseDown(event) {
|
235 | this.input.nativeElement.focus();
|
236 | this.repeat(event, null, -1);
|
237 | event.preventDefault();
|
238 | }
|
239 | onDownButtonMouseUp() {
|
240 | this.clearTimer();
|
241 | }
|
242 | onDownButtonMouseLeave() {
|
243 | this.clearTimer();
|
244 | }
|
245 | onDownButtonKeyUp() {
|
246 | this.clearTimer();
|
247 | }
|
248 | onDownButtonKeyDown(event) {
|
249 | if (event.keyCode === 32 || event.keyCode === 13) {
|
250 | this.repeat(event, null, -1);
|
251 | }
|
252 | }
|
253 | onUserInput(event) {
|
254 | if (this.isSpecialChar) {
|
255 | event.target.value = this.lastValue;
|
256 | }
|
257 | this.isSpecialChar = false;
|
258 | }
|
259 | onInputKeyDown(event) {
|
260 | this.lastValue = event.target.value;
|
261 | if (event.shiftKey || event.altKey) {
|
262 | this.isSpecialChar = true;
|
263 | return;
|
264 | }
|
265 | let selectionStart = event.target.selectionStart;
|
266 | let selectionEnd = event.target.selectionEnd;
|
267 | let inputValue = event.target.value;
|
268 | let newValueStr = null;
|
269 | if (event.altKey) {
|
270 | event.preventDefault();
|
271 | }
|
272 | switch (event.which) {
|
273 |
|
274 | case 38:
|
275 | this.spin(event, 1);
|
276 | event.preventDefault();
|
277 | break;
|
278 |
|
279 | case 40:
|
280 | this.spin(event, -1);
|
281 | event.preventDefault();
|
282 | break;
|
283 |
|
284 | case 37:
|
285 | if (!this.isNumeralChar(inputValue.charAt(selectionStart - 1))) {
|
286 | event.preventDefault();
|
287 | }
|
288 | break;
|
289 |
|
290 | case 39:
|
291 | if (!this.isNumeralChar(inputValue.charAt(selectionStart))) {
|
292 | event.preventDefault();
|
293 | }
|
294 | break;
|
295 |
|
296 | case 8: {
|
297 | event.preventDefault();
|
298 | if (selectionStart === selectionEnd) {
|
299 | let deleteChar = inputValue.charAt(selectionStart - 1);
|
300 | let decimalCharIndex = inputValue.search(this._decimal);
|
301 | this._decimal.lastIndex = 0;
|
302 | if (this.isNumeralChar(deleteChar)) {
|
303 | if (this._group.test(deleteChar)) {
|
304 | this._group.lastIndex = 0;
|
305 | newValueStr = inputValue.slice(0, selectionStart - 2) + inputValue.slice(selectionStart - 1);
|
306 | }
|
307 | else if (this._decimal.test(deleteChar)) {
|
308 | this._decimal.lastIndex = 0;
|
309 | this.input.nativeElement.setSelectionRange(selectionStart - 1, selectionStart - 1);
|
310 | }
|
311 | else if (decimalCharIndex > 0 && selectionStart > decimalCharIndex) {
|
312 | newValueStr = inputValue.slice(0, selectionStart - 1) + '0' + inputValue.slice(selectionStart);
|
313 | }
|
314 | else if (decimalCharIndex > 0 && decimalCharIndex === 1) {
|
315 | newValueStr = inputValue.slice(0, selectionStart - 1) + '0' + inputValue.slice(selectionStart);
|
316 | newValueStr = this.parseValue(newValueStr) > 0 ? newValueStr : '';
|
317 | }
|
318 | else {
|
319 | newValueStr = inputValue.slice(0, selectionStart - 1) + inputValue.slice(selectionStart);
|
320 | }
|
321 | }
|
322 | this.updateValue(event, newValueStr, null, 'delete-single');
|
323 | }
|
324 | else {
|
325 | newValueStr = this.deleteRange(inputValue, selectionStart, selectionEnd);
|
326 | this.updateValue(event, newValueStr, null, 'delete-range');
|
327 | }
|
328 | break;
|
329 | }
|
330 |
|
331 | case 46:
|
332 | event.preventDefault();
|
333 | if (selectionStart === selectionEnd) {
|
334 | let deleteChar = inputValue.charAt(selectionStart);
|
335 | let decimalCharIndex = inputValue.search(this._decimal);
|
336 | this._decimal.lastIndex = 0;
|
337 | if (this.isNumeralChar(deleteChar)) {
|
338 | if (this._group.test(deleteChar)) {
|
339 | this._group.lastIndex = 0;
|
340 | newValueStr = inputValue.slice(0, selectionStart) + inputValue.slice(selectionStart + 2);
|
341 | }
|
342 | else if (this._decimal.test(deleteChar)) {
|
343 | this._decimal.lastIndex = 0;
|
344 | this.input.nativeElement.setSelectionRange(selectionStart + 1, selectionStart + 1);
|
345 | }
|
346 | else if (decimalCharIndex > 0 && selectionStart > decimalCharIndex) {
|
347 | newValueStr = inputValue.slice(0, selectionStart) + '0' + inputValue.slice(selectionStart + 1);
|
348 | }
|
349 | else if (decimalCharIndex > 0 && decimalCharIndex === 1) {
|
350 | newValueStr = inputValue.slice(0, selectionStart) + '0' + inputValue.slice(selectionStart + 1);
|
351 | newValueStr = this.parseValue(newValueStr) > 0 ? newValueStr : '';
|
352 | }
|
353 | else {
|
354 | newValueStr = inputValue.slice(0, selectionStart) + inputValue.slice(selectionStart + 1);
|
355 | }
|
356 | }
|
357 | this.updateValue(event, newValueStr, null, 'delete-back-single');
|
358 | }
|
359 | else {
|
360 | newValueStr = this.deleteRange(inputValue, selectionStart, selectionEnd);
|
361 | this.updateValue(event, newValueStr, null, 'delete-range');
|
362 | }
|
363 | break;
|
364 | default:
|
365 | break;
|
366 | }
|
367 | }
|
368 | onInputKeyPress(event) {
|
369 | event.preventDefault();
|
370 | let code = event.which || event.keyCode;
|
371 | let char = String.fromCharCode(code);
|
372 | const isDecimalSign = this.isDecimalSign(char);
|
373 | const isMinusSign = this.isMinusSign(char);
|
374 | if ((48 <= code && code <= 57) || isMinusSign || isDecimalSign) {
|
375 | this.insert(event, char, { isDecimalSign, isMinusSign });
|
376 | }
|
377 | }
|
378 | onPaste(event) {
|
379 | event.preventDefault();
|
380 | let data = (event.clipboardData || window['clipboardData']).getData('Text');
|
381 | if (data) {
|
382 | let filteredData = this.parseValue(data);
|
383 | if (filteredData != null) {
|
384 | this.insert(event, filteredData.toString());
|
385 | }
|
386 | }
|
387 | }
|
388 | isMinusSign(char) {
|
389 | if (this._minusSign.test(char)) {
|
390 | this._minusSign.lastIndex = 0;
|
391 | return true;
|
392 | }
|
393 | return false;
|
394 | }
|
395 | isDecimalSign(char) {
|
396 | if (this._decimal.test(char)) {
|
397 | this._decimal.lastIndex = 0;
|
398 | return true;
|
399 | }
|
400 | return false;
|
401 | }
|
402 | insert(event, text, sign = { isDecimalSign: false, isMinusSign: false }) {
|
403 | let selectionStart = this.input.nativeElement.selectionStart;
|
404 | let selectionEnd = this.input.nativeElement.selectionEnd;
|
405 | let inputValue = this.input.nativeElement.value.trim();
|
406 | const decimalCharIndex = inputValue.search(this._decimal);
|
407 | this._decimal.lastIndex = 0;
|
408 | const minusCharIndex = inputValue.search(this._minusSign);
|
409 | this._minusSign.lastIndex = 0;
|
410 | let newValueStr;
|
411 | if (sign.isMinusSign) {
|
412 | if (selectionStart === 0) {
|
413 | newValueStr = inputValue;
|
414 | if (minusCharIndex === -1 || selectionEnd !== 0) {
|
415 | newValueStr = this.insertText(inputValue, text, 0, selectionEnd);
|
416 | }
|
417 | this.updateValue(event, newValueStr, text, 'insert');
|
418 | }
|
419 | }
|
420 | else if (sign.isDecimalSign) {
|
421 | if (decimalCharIndex > 0 && selectionStart === decimalCharIndex) {
|
422 | this.updateValue(event, inputValue, text, 'insert');
|
423 | }
|
424 | else if (decimalCharIndex > selectionStart && decimalCharIndex < selectionEnd) {
|
425 | newValueStr = this.insertText(inputValue, text, selectionStart, selectionEnd);
|
426 | this.updateValue(event, newValueStr, text, 'insert');
|
427 | }
|
428 | }
|
429 | else {
|
430 | const maxFractionDigits = this.numberFormat.resolvedOptions().maximumFractionDigits;
|
431 | if (decimalCharIndex > 0 && selectionStart > decimalCharIndex) {
|
432 | if ((selectionStart + text.length - (decimalCharIndex + 1)) <= maxFractionDigits) {
|
433 | newValueStr = inputValue.slice(0, selectionStart) + text + inputValue.slice(selectionStart + text.length);
|
434 | this.updateValue(event, newValueStr, text, 'insert');
|
435 | }
|
436 | }
|
437 | else {
|
438 | newValueStr = this.insertText(inputValue, text, selectionStart, selectionEnd);
|
439 | const operation = selectionStart !== selectionEnd ? 'range-insert' : 'insert';
|
440 | this.updateValue(event, newValueStr, text, operation);
|
441 | }
|
442 | }
|
443 | }
|
444 | insertText(value, text, start, end) {
|
445 | let textSplit = text.split('.');
|
446 | if (textSplit.length == 2) {
|
447 | const decimalCharIndex = value.slice(start, end).search(this._decimal);
|
448 | this._decimal.lastIndex = 0;
|
449 | return (decimalCharIndex > 0) ? value.slice(0, start) + this.formatValue(text) + value.slice(end) : value;
|
450 | }
|
451 | else if ((end - start) === value.length) {
|
452 | return this.formatValue(text);
|
453 | }
|
454 | else if (start === 0) {
|
455 | return text + value.slice(end);
|
456 | }
|
457 | else if (end === value.length) {
|
458 | return value.slice(0, start) + text;
|
459 | }
|
460 | else {
|
461 | return value.slice(0, start) + text + value.slice(end);
|
462 | }
|
463 | }
|
464 | deleteRange(value, start, end) {
|
465 | let newValueStr;
|
466 | if ((end - start) === value.length)
|
467 | newValueStr = '';
|
468 | else if (start === 0)
|
469 | newValueStr = value.slice(end);
|
470 | else if (end === value.length)
|
471 | newValueStr = value.slice(0, start);
|
472 | else
|
473 | newValueStr = value.slice(0, start) + value.slice(end);
|
474 | return newValueStr;
|
475 | }
|
476 | initCursor() {
|
477 | let selectionStart = this.input.nativeElement.selectionStart;
|
478 | let inputValue = this.input.nativeElement.value;
|
479 | let valueLength = inputValue.length;
|
480 | let index = null;
|
481 | let char = inputValue.charAt(selectionStart);
|
482 | if (this.isNumeralChar(char)) {
|
483 | return;
|
484 | }
|
485 |
|
486 | let i = selectionStart - 1;
|
487 | while (i >= 0) {
|
488 | char = inputValue.charAt(i);
|
489 | if (this.isNumeralChar(char)) {
|
490 | index = i;
|
491 | break;
|
492 | }
|
493 | else {
|
494 | i--;
|
495 | }
|
496 | }
|
497 | if (index !== null) {
|
498 | this.input.nativeElement.setSelectionRange(index + 1, index + 1);
|
499 | }
|
500 | else {
|
501 | i = selectionStart + 1;
|
502 | while (i < valueLength) {
|
503 | char = inputValue.charAt(i);
|
504 | if (this.isNumeralChar(char)) {
|
505 | index = i;
|
506 | break;
|
507 | }
|
508 | else {
|
509 | i++;
|
510 | }
|
511 | }
|
512 | if (index !== null) {
|
513 | this.input.nativeElement.setSelectionRange(index, index);
|
514 | }
|
515 | }
|
516 | }
|
517 | onInputClick() {
|
518 | this.initCursor();
|
519 | }
|
520 | isNumeralChar(char) {
|
521 | if (char.length === 1 && (this._numeral.test(char) || this._decimal.test(char) || this._group.test(char) || this._minusSign.test(char))) {
|
522 | this.resetRegex();
|
523 | return true;
|
524 | }
|
525 | return false;
|
526 | }
|
527 | resetRegex() {
|
528 | this._numeral.lastIndex = 0;
|
529 | this._decimal.lastIndex = 0;
|
530 | this._group.lastIndex = 0;
|
531 | this._minusSign.lastIndex = 0;
|
532 | }
|
533 | updateValue(event, valueStr, insertedValueStr, operation) {
|
534 | let currentValue = this.input.nativeElement.value;
|
535 | let newValue = null;
|
536 | if (valueStr != null) {
|
537 | newValue = this.parseValue(valueStr);
|
538 | this.updateInput(newValue, insertedValueStr, operation);
|
539 | }
|
540 | this.handleOnInput(event, currentValue, newValue);
|
541 | }
|
542 | handleOnInput(event, currentValue, newValue) {
|
543 | if (this.isValueChanged(currentValue, newValue)) {
|
544 | this.onInput.emit({ originalEvent: event, value: newValue });
|
545 | }
|
546 | }
|
547 | isValueChanged(currentValue, newValue) {
|
548 | if (newValue === null && currentValue !== null) {
|
549 | return true;
|
550 | }
|
551 | if (newValue != null) {
|
552 | let parsedCurrentValue = (typeof currentValue === 'string') ? this.parseValue(currentValue) : currentValue;
|
553 | return newValue !== parsedCurrentValue;
|
554 | }
|
555 | return false;
|
556 | }
|
557 | validateValue(value) {
|
558 | if (this.min !== null && value < this.min) {
|
559 | return this.min;
|
560 | }
|
561 | if (this.max !== null && value > this.max) {
|
562 | return this.max;
|
563 | }
|
564 | if (value === '-') {
|
565 | return null;
|
566 | }
|
567 | return value;
|
568 | }
|
569 | updateInput(value, insertedValueStr, operation) {
|
570 | let inputValue = this.input.nativeElement.value;
|
571 | let newValue = this.formatValue(value);
|
572 | let currentLength = inputValue.length;
|
573 | if (currentLength === 0) {
|
574 | this.input.nativeElement.value = newValue;
|
575 | this.input.nativeElement.setSelectionRange(0, 0);
|
576 | this.initCursor();
|
577 | const prefixLength = (this.prefix || '').length;
|
578 | const selectionEnd = prefixLength + insertedValueStr.length;
|
579 | this.input.nativeElement.setSelectionRange(selectionEnd, selectionEnd);
|
580 | }
|
581 | else {
|
582 | let selectionStart = this.input.nativeElement.selectionStart;
|
583 | let selectionEnd = this.input.nativeElement.selectionEnd;
|
584 | if (this.maxlength && this.maxlength < newValue.length) {
|
585 | return;
|
586 | }
|
587 | this.input.nativeElement.value = newValue;
|
588 | let newLength = newValue.length;
|
589 | if (operation === 'range-insert') {
|
590 | const startValue = this.parseValue((inputValue || '').slice(0, selectionStart));
|
591 | const startValueStr = startValue !== null ? startValue.toString() : '';
|
592 | const startExpr = startValueStr.split('').join(`(${this.groupChar})?`);
|
593 | const sRegex = new RegExp(startExpr, 'g');
|
594 | sRegex.test(newValue);
|
595 | const tExpr = insertedValueStr.split('').join(`(${this.groupChar})?`);
|
596 | const tRegex = new RegExp(tExpr, 'g');
|
597 | tRegex.test(newValue.slice(sRegex.lastIndex));
|
598 | selectionEnd = sRegex.lastIndex + tRegex.lastIndex;
|
599 | this.input.nativeElement.setSelectionRange(selectionEnd, selectionEnd);
|
600 | }
|
601 | else if (newLength === currentLength) {
|
602 | if (operation === 'insert' || operation === 'delete-back-single')
|
603 | this.input.nativeElement.setSelectionRange(selectionEnd + 1, selectionEnd + 1);
|
604 | else if (operation === 'delete-single')
|
605 | this.input.nativeElement.setSelectionRange(selectionEnd - 1, selectionEnd - 1);
|
606 | else if (operation === 'delete-range' || operation === 'spin')
|
607 | this.input.nativeElement.setSelectionRange(selectionEnd, selectionEnd);
|
608 | }
|
609 | else if (operation === 'delete-back-single') {
|
610 | let prevChar = inputValue.charAt(selectionEnd - 1);
|
611 | let nextChar = inputValue.charAt(selectionEnd);
|
612 | let diff = currentLength - newLength;
|
613 | let isGroupChar = this._group.test(nextChar);
|
614 | if (isGroupChar && diff === 1) {
|
615 | selectionEnd += 1;
|
616 | }
|
617 | else if (!isGroupChar && this.isNumeralChar(prevChar)) {
|
618 | selectionEnd += (-1 * diff) + 1;
|
619 | }
|
620 | this._group.lastIndex = 0;
|
621 | this.input.nativeElement.setSelectionRange(selectionEnd, selectionEnd);
|
622 | }
|
623 | else {
|
624 | selectionEnd = selectionEnd + (newLength - currentLength);
|
625 | this.input.nativeElement.setSelectionRange(selectionEnd, selectionEnd);
|
626 | }
|
627 | }
|
628 | this.input.nativeElement.setAttribute('aria-valuenow', value);
|
629 | }
|
630 | onInputFocus(event) {
|
631 | this.focused = true;
|
632 | this.onFocus.emit(event);
|
633 | }
|
634 | onInputBlur(event) {
|
635 | this.focused = false;
|
636 | let newValue = this.validateValue(this.parseValue(this.input.nativeElement.value));
|
637 | this.input.nativeElement.value = this.formatValue(newValue);
|
638 | this.input.nativeElement.setAttribute('aria-valuenow', newValue);
|
639 | this.updateModel(event, newValue);
|
640 | this.onBlur.emit(event);
|
641 | }
|
642 | formattedValue() {
|
643 | return this.formatValue(this.value);
|
644 | }
|
645 | updateModel(event, value) {
|
646 | if (this.value !== value) {
|
647 | this.value = value;
|
648 | this.onModelChange(value);
|
649 | }
|
650 | this.onModelTouched();
|
651 | }
|
652 | writeValue(value) {
|
653 | this.value = value;
|
654 | this.cd.markForCheck();
|
655 | }
|
656 | registerOnChange(fn) {
|
657 | this.onModelChange = fn;
|
658 | }
|
659 | registerOnTouched(fn) {
|
660 | this.onModelTouched = fn;
|
661 | }
|
662 | setDisabledState(val) {
|
663 | this.disabled = val;
|
664 | this.cd.markForCheck();
|
665 | }
|
666 | get filled() {
|
667 | return (this.value != null && this.value.toString().length > 0);
|
668 | }
|
669 | clearTimer() {
|
670 | if (this.timer) {
|
671 | clearInterval(this.timer);
|
672 | }
|
673 | }
|
674 | }
|
675 | InputNumber.decorators = [
|
676 | { type: Component, args: [{
|
677 | selector: 'p-inputNumber',
|
678 | template: `
|
679 | <span [ngClass]="{'p-inputnumber p-component': true,'p-inputnumber-buttons-stacked': this.showButtons && this.buttonLayout === 'stacked',
|
680 | 'p-inputnumber-buttons-horizontal': this.showButtons && this.buttonLayout === 'horizontal', 'p-inputnumber-buttons-vertical': this.showButtons && this.buttonLayout === 'vertical'}"
|
681 | [ngStyle]="style" [class]="styleClass">
|
682 | <input #input [ngClass]="'p-inputnumber-input'" [ngStyle]="inputStyle" [class]="inputStyleClass" pInputText [value]="formattedValue()" [attr.placeholder]="placeholder" [attr.title]="title" [attr.id]="inputId"
|
683 | [attr.size]="size" [attr.name]="name" [attr.autocomplete]="autocomplete" [attr.maxlength]="maxlength" [attr.tabindex]="tabindex" [attr.aria-label]="ariaLabel"
|
684 | [attr.aria-required]="ariaRequired" [disabled]="disabled" [attr.required]="required" [attr.aria-valumin]="min" [attr.aria-valuemax]="max"
|
685 | (input)="onUserInput($event)" (keydown)="onInputKeyDown($event)" (keypress)="onInputKeyPress($event)" (paste)="onPaste($event)" (click)="onInputClick()"
|
686 | (focus)="onInputFocus($event)" (blur)="onInputBlur($event)">
|
687 | <span class="p-inputnumber-button-group" *ngIf="showButtons && buttonLayout === 'stacked'">
|
688 | <button type="button" pButton [ngClass]="{'p-inputnumber-button p-inputnumber-button-up': true}" [class]="incrementButtonClass" [icon]="incrementButtonIcon" [disabled]="disabled"
|
689 | (mousedown)="this.onUpButtonMouseDown($event)" (mouseup)="onUpButtonMouseUp()" (mouseleave)="onUpButtonMouseLeave()" (keydown)="onUpButtonKeyDown($event)" (keyup)="onUpButtonKeyUp()"></button>
|
690 | <button type="button" pButton [ngClass]="{'p-inputnumber-button p-inputnumber-button-down': true}" [class]="decrementButtonClass" [icon]="decrementButtonIcon" [disabled]="disabled"
|
691 | (mousedown)="this.onDownButtonMouseDown($event)" (mouseup)="onDownButtonMouseUp()" (mouseleave)="onDownButtonMouseLeave()" (keydown)="onDownButtonKeyDown($event)" (keyup)="onDownButtonKeyUp()"></button>
|
692 | </span>
|
693 | <button type="button" pButton [ngClass]="{'p-inputnumber-button p-inputnumber-button-up': true}" [class]="incrementButtonClass" [icon]="incrementButtonIcon" *ngIf="showButtons && buttonLayout !== 'stacked'" [disabled]="disabled"
|
694 | (mousedown)="this.onUpButtonMouseDown($event)" (mouseup)="onUpButtonMouseUp()" (mouseleave)="onUpButtonMouseLeave()" (keydown)="onUpButtonKeyDown($event)" (keyup)="onUpButtonKeyUp()"></button>
|
695 | <button type="button" pButton [ngClass]="{'p-inputnumber-button p-inputnumber-button-down': true}" [class]="decrementButtonClass" [icon]="decrementButtonIcon" *ngIf="showButtons && buttonLayout !== 'stacked'" [disabled]="disabled"
|
696 | (mousedown)="this.onDownButtonMouseDown($event)" (mouseup)="onDownButtonMouseUp()" (mouseleave)="onDownButtonMouseLeave()" (keydown)="onDownButtonKeyDown($event)" (keyup)="onDownButtonKeyUp()"></button>
|
697 | </span>
|
698 | `,
|
699 | changeDetection: ChangeDetectionStrategy.OnPush,
|
700 | providers: [INPUTNUMBER_VALUE_ACCESSOR],
|
701 | encapsulation: ViewEncapsulation.None,
|
702 | host: {
|
703 | '[class.p-inputwrapper-filled]': 'filled',
|
704 | '[class.p-inputwrapper-focus]': 'focused'
|
705 | },
|
706 | styles: [".p-inputnumber{display:-ms-inline-flexbox;display:inline-flex}.p-inputnumber-button{-ms-flex:0 0 auto;-ms-flex-align:center;-ms-flex-pack:center;align-items:center;display:-ms-flexbox;display:flex;flex:0 0 auto;justify-content:center}.p-inputnumber-buttons-horizontal .p-button.p-inputnumber-button .p-button-label,.p-inputnumber-buttons-stacked .p-button.p-inputnumber-button .p-button-label{display:none}.p-inputnumber-buttons-stacked .p-button.p-inputnumber-button-up{border-bottom-left-radius:0;border-bottom-right-radius:0;border-top-left-radius:0;padding:0}.p-inputnumber-buttons-stacked .p-inputnumber-input{border-bottom-right-radius:0;border-top-right-radius:0}.p-inputnumber-buttons-stacked .p-button.p-inputnumber-button-down{border-bottom-left-radius:0;border-top-left-radius:0;border-top-right-radius:0;padding:0}.p-inputnumber-buttons-stacked .p-inputnumber-button-group{-ms-flex-direction:column;display:-ms-flexbox;display:flex;flex-direction:column}.p-inputnumber-buttons-stacked .p-inputnumber-button-group .p-button.p-inputnumber-button{-ms-flex:1 1 auto;flex:1 1 auto}.p-inputnumber-buttons-horizontal .p-button.p-inputnumber-button-up{-ms-flex-order:3;border-bottom-left-radius:0;border-top-left-radius:0;order:3}.p-inputnumber-buttons-horizontal .p-inputnumber-input{-ms-flex-order:2;border-radius:0;order:2}.p-inputnumber-buttons-horizontal .p-button.p-inputnumber-button-down{-ms-flex-order:1;border-bottom-right-radius:0;border-top-right-radius:0;order:1}.p-inputnumber-buttons-vertical{-ms-flex-direction:column;flex-direction:column}.p-inputnumber-buttons-vertical .p-button.p-inputnumber-button-up{-ms-flex-order:1;border-bottom-left-radius:0;border-bottom-right-radius:0;order:1;width:100%}.p-inputnumber-buttons-vertical .p-inputnumber-input{-ms-flex-order:2;border-radius:0;order:2;text-align:center}.p-inputnumber-buttons-vertical .p-button.p-inputnumber-button-down{-ms-flex-order:3;border-top-left-radius:0;border-top-right-radius:0;order:3;width:100%}.p-inputnumber-input{-ms-flex:1 1 auto;flex:1 1 auto}.p-fluid .p-inputnumber{width:100%}.p-fluid .p-inputnumber .p-inputnumber-input{width:1%}.p-fluid .p-inputnumber-buttons-vertical .p-inputnumber-input{width:100%}"]
|
707 | },] }
|
708 | ];
|
709 | InputNumber.ctorParameters = () => [
|
710 | { type: ElementRef },
|
711 | { type: ChangeDetectorRef }
|
712 | ];
|
713 | InputNumber.propDecorators = {
|
714 | showButtons: [{ type: Input }],
|
715 | format: [{ type: Input }],
|
716 | buttonLayout: [{ type: Input }],
|
717 | disabled: [{ type: Input }],
|
718 | inputId: [{ type: Input }],
|
719 | styleClass: [{ type: Input }],
|
720 | style: [{ type: Input }],
|
721 | placeholder: [{ type: Input }],
|
722 | size: [{ type: Input }],
|
723 | maxlength: [{ type: Input }],
|
724 | tabindex: [{ type: Input }],
|
725 | title: [{ type: Input }],
|
726 | ariaLabel: [{ type: Input }],
|
727 | ariaRequired: [{ type: Input }],
|
728 | name: [{ type: Input }],
|
729 | required: [{ type: Input }],
|
730 | autocomplete: [{ type: Input }],
|
731 | min: [{ type: Input }],
|
732 | max: [{ type: Input }],
|
733 | incrementButtonClass: [{ type: Input }],
|
734 | decrementButtonClass: [{ type: Input }],
|
735 | incrementButtonIcon: [{ type: Input }],
|
736 | decrementButtonIcon: [{ type: Input }],
|
737 | step: [{ type: Input }],
|
738 | inputStyle: [{ type: Input }],
|
739 | inputStyleClass: [{ type: Input }],
|
740 | input: [{ type: ViewChild, args: ['input',] }],
|
741 | onInput: [{ type: Output }],
|
742 | onFocus: [{ type: Output }],
|
743 | onBlur: [{ type: Output }],
|
744 | locale: [{ type: Input }],
|
745 | localeMatcher: [{ type: Input }],
|
746 | mode: [{ type: Input }],
|
747 | currency: [{ type: Input }],
|
748 | currencyDisplay: [{ type: Input }],
|
749 | useGrouping: [{ type: Input }],
|
750 | minFractionDigits: [{ type: Input }],
|
751 | maxFractionDigits: [{ type: Input }],
|
752 | prefix: [{ type: Input }],
|
753 | suffix: [{ type: Input }]
|
754 | };
|
755 | class InputNumberModule {
|
756 | }
|
757 | InputNumberModule.decorators = [
|
758 | { type: NgModule, args: [{
|
759 | imports: [CommonModule, InputTextModule, ButtonModule],
|
760 | exports: [InputNumber],
|
761 | declarations: [InputNumber]
|
762 | },] }
|
763 | ];
|
764 |
|
765 |
|
766 |
|
767 |
|
768 |
|
769 | export { INPUTNUMBER_VALUE_ACCESSOR, InputNumber, InputNumberModule };
|
770 |
|