@syncfusion/ej2-base 24.2.8 → 25.1.35-579988
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.eslintrc.json +2 -1
- package/CHANGELOG.md +641 -677
- package/{README.md → ReadMe.md} +100 -100
- package/dist/ej2-base.umd.min.js +1 -10
- package/dist/ej2-base.umd.min.js.map +1 -1
- package/dist/es6/ej2-base.es2015.js +178 -1025
- package/dist/es6/ej2-base.es2015.js.map +1 -1
- package/dist/es6/ej2-base.es5.js +226 -934
- package/dist/es6/ej2-base.es5.js.map +1 -1
- package/dist/global/ej2-base.min.js +1 -10
- package/dist/global/ej2-base.min.js.map +1 -1
- package/dist/global/index.d.ts +0 -9
- package/dist/ts/ajax.ts +236 -0
- package/dist/ts/animation.ts +544 -0
- package/dist/ts/base.ts +357 -0
- package/dist/ts/browser.ts +387 -0
- package/dist/ts/child-property.ts +192 -0
- package/dist/ts/component.ts +519 -0
- package/dist/ts/dom.ts +488 -0
- package/dist/ts/draggable.ts +1155 -0
- package/dist/ts/droppable.ts +172 -0
- package/dist/ts/event-handler.ts +169 -0
- package/dist/ts/internationalization.ts +369 -0
- package/dist/ts/intl/date-formatter.ts +317 -0
- package/dist/ts/intl/date-parser.ts +426 -0
- package/dist/ts/intl/intl-base.ts +1104 -0
- package/dist/ts/intl/number-formatter.ts +411 -0
- package/dist/ts/intl/number-parser.ts +158 -0
- package/dist/ts/intl/parser-base.ts +394 -0
- package/dist/ts/keyboard.ts +238 -0
- package/dist/ts/l10n.ts +94 -0
- package/dist/ts/module-loader.ts +149 -0
- package/dist/ts/notify-property-change.ts +726 -0
- package/dist/ts/observer.ts +236 -0
- package/dist/ts/sanitize-helper.ts +224 -0
- package/dist/ts/template-engine.ts +191 -0
- package/dist/ts/template.ts +329 -0
- package/dist/ts/touch.ts +544 -0
- package/dist/ts/util.ts +523 -0
- package/dist/ts/validate-lic.ts +0 -0
- package/e2e/crypto.js +16 -16
- package/e2e/m.protractor.config.js +286 -286
- package/e2e/modified-protractor/protractor.config.js +316 -316
- package/e2e/protractor.config.js +389 -332
- package/helpers/e2e/index.js +3 -3
- package/license +10 -10
- package/package.json +225 -174
- package/src/ajax.d.ts +1 -1
- package/src/ajax.js +3 -8
- package/src/animation-model.d.ts +41 -41
- package/src/animation.d.ts +6 -6
- package/src/animation.js +25 -25
- package/src/base.d.ts +2 -1
- package/src/base.js +9 -7
- package/src/component-model.d.ts +16 -16
- package/src/component.d.ts +9 -3
- package/src/component.js +50 -38
- package/src/draggable-model.d.ts +113 -113
- package/src/draggable.d.ts +2 -0
- package/src/draggable.js +45 -29
- package/src/droppable-model.d.ts +23 -23
- package/src/droppable.js +19 -19
- package/src/event-handler.js +2 -1
- package/src/index.d.ts +0 -3
- package/src/index.js +0 -3
- package/src/intl/date-formatter.js +2 -6
- package/src/intl/date-parser.js +1 -20
- package/src/intl/intl-base.js +1 -164
- package/src/intl/number-formatter.d.ts +3 -0
- package/src/intl/number-formatter.js +7 -7
- package/src/intl/number-parser.js +1 -0
- package/src/keyboard-model.d.ts +16 -16
- package/src/keyboard.js +19 -19
- package/src/module-loader.d.ts +12 -0
- package/src/module-loader.js +11 -0
- package/src/notify-property-change.js +3 -2
- package/src/observer.js +2 -0
- package/src/sanitize-helper.js +5 -0
- package/src/template-engine.js +1 -0
- package/src/template.js +3 -2
- package/src/touch-model.d.ts +39 -39
- package/src/touch.js +19 -19
- package/src/validate-lic.d.ts +0 -11
- package/src/validate-lic.js +1 -259
- package/styles/_all.scss +2 -2
- package/styles/_bds-dark-definition.scss +15 -0
- package/styles/_bds-definition.scss +15 -0
- package/styles/_bootstrap-dark-definition.scss +42 -42
- package/styles/_bootstrap-definition.scss +42 -42
- package/styles/_bootstrap4-definition.scss +11 -11
- package/styles/_bootstrap5-dark-definition.scss +9 -9
- package/styles/_bootstrap5-definition.scss +8 -8
- package/styles/_fabric-dark-definition.scss +42 -42
- package/styles/_fabric-definition.scss +42 -42
- package/styles/_fluent-dark-definition.scss +9 -9
- package/styles/_fluent-definition.scss +9 -9
- package/styles/_fluent2-definition.scss +9 -0
- package/styles/_fusionnew-dark-definition.scss +8 -8
- package/styles/_fusionnew-definition.scss +8 -8
- package/styles/_highcontrast-definition.scss +42 -42
- package/styles/_highcontrast-light-definition.scss +42 -42
- package/styles/_material-dark-definition.scss +48 -48
- package/styles/_material-definition.scss +49 -49
- package/styles/_material3-dark-definition.scss +14 -14
- package/styles/_material3-definition.scss +15 -15
- package/styles/_tailwind-dark-definition.scss +15 -15
- package/styles/_tailwind-definition.scss +15 -15
- package/styles/animation/_all.scss +560 -560
- package/styles/bootstrap-dark.css +10 -1
- package/styles/bootstrap.css +10 -1
- package/styles/bootstrap4.css +10 -1
- package/styles/bootstrap5-dark.css +10 -1
- package/styles/bootstrap5.css +10 -1
- package/styles/common/_all.scss +2 -2
- package/styles/common/_core.scss +117 -117
- package/styles/common/_mixin.scss +9 -9
- package/styles/definition/_bds-dark.scss +1179 -0
- package/styles/definition/_bds.scss +1474 -0
- package/styles/definition/_bootstrap-dark.scss +219 -219
- package/styles/definition/_bootstrap.scss +215 -215
- package/styles/definition/_bootstrap4.scss +167 -167
- package/styles/definition/_bootstrap5-dark.scss +493 -493
- package/styles/definition/_bootstrap5.scss +494 -494
- package/styles/definition/_fabric-dark.scss +200 -200
- package/styles/definition/_fabric.scss +198 -198
- package/styles/definition/_fluent-dark.scss +557 -557
- package/styles/definition/_fluent.scss +558 -558
- package/styles/definition/_fluent2.scss +2198 -0
- package/styles/definition/_fusionnew-dark.scss +362 -362
- package/styles/definition/_fusionnew.scss +363 -363
- package/styles/definition/_highcontrast-light.scss +193 -193
- package/styles/definition/_highcontrast.scss +195 -195
- package/styles/definition/_material-dark.scss +198 -198
- package/styles/definition/_material.scss +192 -192
- package/styles/definition/_material3-dark.scss +710 -710
- package/styles/definition/_material3.scss +792 -792
- package/styles/definition/_tailwind-dark.scss +488 -488
- package/styles/definition/_tailwind.scss +485 -485
- package/styles/fabric-dark.css +10 -1
- package/styles/fabric.css +10 -1
- package/styles/fluent-dark.css +10 -1
- package/styles/fluent.css +10 -1
- package/styles/highcontrast-light.css +10 -1
- package/styles/highcontrast.css +10 -1
- package/styles/material-dark.css +10 -1
- package/styles/material.css +10 -1
- package/styles/material3-dark.css +10 -1
- package/styles/material3.css +10 -1
- package/styles/offline-theme/material-dark.css +10 -1
- package/styles/offline-theme/material.css +10 -1
- package/styles/offline-theme/tailwind-dark.css +10 -1
- package/styles/offline-theme/tailwind.css +10 -1
- package/styles/tailwind-dark.css +10 -1
- package/styles/tailwind.css +10 -1
- package/.github/PULL_REQUEST_TEMPLATE/Bug.md +0 -60
- package/.github/PULL_REQUEST_TEMPLATE/feature.md +0 -42
- package/bin/syncfusion-license.js +0 -2
- package/dist/ej2-base.min.js +0 -10
- package/e2e/index.d.ts +0 -27
- package/src/fetch.d.ts +0 -114
- package/src/fetch.js +0 -116
- package/src/hijri-parser.d.ts +0 -19
- package/src/hijri-parser.js +0 -204
|
@@ -0,0 +1,411 @@
|
|
|
1
|
+
import { isUndefined, throwError, isNullOrUndefined, extend, isBlazor, getValue } from '../util';
|
|
2
|
+
import { NumberFormatOptions, defaultCurrencyCode } from '../internationalization';
|
|
3
|
+
import { IntlBase as base } from './intl-base';
|
|
4
|
+
import { ParserBase as parser, NumberMapper } from './parser-base';
|
|
5
|
+
/**
|
|
6
|
+
* Interface for default formatting options
|
|
7
|
+
*
|
|
8
|
+
* @private
|
|
9
|
+
*/
|
|
10
|
+
export interface FormatParts extends base.NumericSkeleton, NumberFormatOptions {
|
|
11
|
+
groupOne?: boolean;
|
|
12
|
+
isPercent?: boolean;
|
|
13
|
+
isCurrency?: boolean;
|
|
14
|
+
isNegative?: boolean;
|
|
15
|
+
groupData?: GroupDetails;
|
|
16
|
+
groupSeparator?: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Interface for common formatting options
|
|
20
|
+
*/
|
|
21
|
+
export interface CommonOptions {
|
|
22
|
+
numberMapper?: NumberMapper;
|
|
23
|
+
currencySymbol?: string;
|
|
24
|
+
percentSymbol?: string;
|
|
25
|
+
minusSymbol?: string;
|
|
26
|
+
isCustomFormat?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/* eslint-disable */
|
|
29
|
+
/**
|
|
30
|
+
* Interface for currency processing
|
|
31
|
+
*/
|
|
32
|
+
interface CurrencyOptions {
|
|
33
|
+
position?: string;
|
|
34
|
+
symbol?: string;
|
|
35
|
+
currencySpace?: boolean;
|
|
36
|
+
}
|
|
37
|
+
/* eslint-enable */
|
|
38
|
+
/**
|
|
39
|
+
* Interface for grouping process
|
|
40
|
+
*/
|
|
41
|
+
export interface GroupDetails {
|
|
42
|
+
primary?: number;
|
|
43
|
+
secondary?: number;
|
|
44
|
+
}
|
|
45
|
+
const errorText: Object = {
|
|
46
|
+
'ms': 'minimumSignificantDigits',
|
|
47
|
+
'ls': 'maximumSignificantDigits',
|
|
48
|
+
'mf': 'minimumFractionDigits',
|
|
49
|
+
'lf': 'maximumFractionDigits'
|
|
50
|
+
};
|
|
51
|
+
const percentSign: string = 'percentSign';
|
|
52
|
+
const minusSign: string = 'minusSign';
|
|
53
|
+
const mapper: string[] = ['infinity', 'nan', 'group', 'decimal', 'exponential'];
|
|
54
|
+
/**
|
|
55
|
+
* Module for number formatting.
|
|
56
|
+
*
|
|
57
|
+
* @private
|
|
58
|
+
*/
|
|
59
|
+
export class NumberFormat {
|
|
60
|
+
/**
|
|
61
|
+
* Returns the formatter function for given skeleton.
|
|
62
|
+
*
|
|
63
|
+
* @param {string} culture - Specifies the culture name to be which formatting.
|
|
64
|
+
* @param {NumberFormatOptions} option - Specific the format in which number will format.
|
|
65
|
+
* @param {Object} cldr - Specifies the global cldr data collection.
|
|
66
|
+
* @returns {Function} ?
|
|
67
|
+
*/
|
|
68
|
+
public static numberFormatter(culture: string, option: NumberFormatOptions, cldr: Object): Function {
|
|
69
|
+
const fOptions: FormatParts = extend({}, option);
|
|
70
|
+
let cOptions: base.GenericFormatOptions = {};
|
|
71
|
+
const dOptions: CommonOptions = {};
|
|
72
|
+
let symbolPattern: string;
|
|
73
|
+
const dependable: base.Dependables = base.getDependables(cldr, culture, '', true);
|
|
74
|
+
const numObject: Object = dependable.numericObject;
|
|
75
|
+
dOptions.numberMapper = isBlazor() ? extend({}, numObject) :
|
|
76
|
+
parser.getNumberMapper(dependable.parserObject, parser.getNumberingSystem(cldr), true);
|
|
77
|
+
dOptions.currencySymbol = isBlazor() ? getValue('currencySymbol', numObject) : base.getCurrencySymbol(
|
|
78
|
+
dependable.numericObject, fOptions.currency || defaultCurrencyCode, option.altSymbol);
|
|
79
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
80
|
+
dOptions.percentSymbol = isBlazor() ? getValue('numberSymbols.percentSign', numObject) :
|
|
81
|
+
(<any>dOptions).numberMapper.numberSymbols[`${percentSign}`];
|
|
82
|
+
dOptions.minusSymbol = isBlazor() ? getValue('numberSymbols.minusSign', numObject) :
|
|
83
|
+
(<any>dOptions).numberMapper.numberSymbols[`${minusSign}`];
|
|
84
|
+
const symbols: any = dOptions.numberMapper.numberSymbols;
|
|
85
|
+
if ((option.format) && !(base.formatRegex.test(option.format))) {
|
|
86
|
+
cOptions = base.customFormat(option.format, dOptions, dependable.numericObject);
|
|
87
|
+
} else {
|
|
88
|
+
extend(fOptions, base.getProperNumericSkeleton(option.format || 'N'));
|
|
89
|
+
fOptions.isCurrency = fOptions.type === 'currency';
|
|
90
|
+
fOptions.isPercent = fOptions.type === 'percent';
|
|
91
|
+
if (!isBlazor()) {
|
|
92
|
+
symbolPattern = base.getSymbolPattern(
|
|
93
|
+
fOptions.type, dOptions.numberMapper.numberSystem, dependable.numericObject, fOptions.isAccount);
|
|
94
|
+
}
|
|
95
|
+
fOptions.groupOne = this.checkValueRange(fOptions.maximumSignificantDigits, fOptions.minimumSignificantDigits, true);
|
|
96
|
+
this.checkValueRange(fOptions.maximumFractionDigits, fOptions.minimumFractionDigits, false, true);
|
|
97
|
+
if (!isUndefined(fOptions.fractionDigits)) {
|
|
98
|
+
fOptions.minimumFractionDigits = fOptions.maximumFractionDigits = fOptions.fractionDigits;
|
|
99
|
+
}
|
|
100
|
+
if (isUndefined(fOptions.useGrouping)) {
|
|
101
|
+
fOptions.useGrouping = true;
|
|
102
|
+
}
|
|
103
|
+
if (fOptions.isCurrency && !isBlazor()) {
|
|
104
|
+
symbolPattern = symbolPattern.replace(/\u00A4/g, base.defaultCurrency);
|
|
105
|
+
}
|
|
106
|
+
if (!isBlazor()) {
|
|
107
|
+
const split: string[] = symbolPattern.split(';');
|
|
108
|
+
cOptions.nData = base.getFormatData(split[1] || '-' + split[0], true, dOptions.currencySymbol);
|
|
109
|
+
cOptions.pData = base.getFormatData(split[0], false, dOptions.currencySymbol);
|
|
110
|
+
if (fOptions.useGrouping) {
|
|
111
|
+
fOptions.groupSeparator = symbols[mapper[2]];
|
|
112
|
+
fOptions.groupData = this.getGroupingDetails(split[0]);
|
|
113
|
+
}
|
|
114
|
+
} else {
|
|
115
|
+
cOptions.nData = extend({}, {}, getValue(fOptions.type + 'nData', numObject));
|
|
116
|
+
cOptions.pData = extend({}, {}, getValue(fOptions.type + 'pData', numObject));
|
|
117
|
+
if (fOptions.type === 'currency' && option.currency) {
|
|
118
|
+
base.replaceBlazorCurrency([cOptions.pData, cOptions.nData], dOptions.currencySymbol, option.currency);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const minFrac: boolean = isUndefined(fOptions.minimumFractionDigits);
|
|
122
|
+
if (minFrac) {
|
|
123
|
+
fOptions.minimumFractionDigits = cOptions.nData.minimumFraction;
|
|
124
|
+
}
|
|
125
|
+
if (isUndefined(fOptions.maximumFractionDigits)) {
|
|
126
|
+
const mval: number = cOptions.nData.maximumFraction;
|
|
127
|
+
fOptions.maximumFractionDigits = isUndefined(mval) && fOptions.isPercent ? 0 : mval;
|
|
128
|
+
}
|
|
129
|
+
const mfrac: number = fOptions.minimumFractionDigits;
|
|
130
|
+
const lfrac: number = fOptions.maximumFractionDigits;
|
|
131
|
+
if (!isUndefined(mfrac) && !isUndefined(lfrac)) {
|
|
132
|
+
if (mfrac > lfrac) {
|
|
133
|
+
fOptions.maximumFractionDigits = mfrac;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
extend(cOptions.nData, fOptions);
|
|
138
|
+
extend(cOptions.pData, fOptions);
|
|
139
|
+
return (value: number): string => {
|
|
140
|
+
if (isNaN(value)) {
|
|
141
|
+
return symbols[mapper[1]];
|
|
142
|
+
} else if (!isFinite(value)) {
|
|
143
|
+
return symbols[mapper[0]];
|
|
144
|
+
}
|
|
145
|
+
return this.intNumberFormatter(value, cOptions, dOptions, option);
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Returns grouping details for the pattern provided
|
|
150
|
+
*
|
|
151
|
+
* @param {string} pattern ?
|
|
152
|
+
* @returns {GroupDetails} ?
|
|
153
|
+
*/
|
|
154
|
+
public static getGroupingDetails(pattern: string): GroupDetails {
|
|
155
|
+
const ret: GroupDetails = {};
|
|
156
|
+
const match: string[] = pattern.match(base.negativeDataRegex);
|
|
157
|
+
if (match && match[4]) {
|
|
158
|
+
const pattern: string = match[4];
|
|
159
|
+
const p: number = pattern.lastIndexOf(',');
|
|
160
|
+
if (p !== -1) {
|
|
161
|
+
const temp: string = pattern.split('.')[0];
|
|
162
|
+
ret.primary = (temp.length - p) - 1;
|
|
163
|
+
const s: number = pattern.lastIndexOf(',', p - 1);
|
|
164
|
+
if (s !== -1) {
|
|
165
|
+
ret.secondary = p - 1 - s;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return ret;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Returns if the provided integer range is valid.
|
|
173
|
+
*
|
|
174
|
+
* @param {number} val1 ?
|
|
175
|
+
* @param {number} val2 ?
|
|
176
|
+
* @param {boolean} checkbothExist ?
|
|
177
|
+
* @param {boolean} isFraction ?
|
|
178
|
+
* @returns {boolean} ?
|
|
179
|
+
*/
|
|
180
|
+
private static checkValueRange(val1: number, val2: number, checkbothExist: boolean, isFraction?: true): boolean {
|
|
181
|
+
const decide: string = isFraction ? 'f' : 's';
|
|
182
|
+
let dint: number = 0;
|
|
183
|
+
const str1: string = (<any>errorText)['l' + decide];
|
|
184
|
+
// eslint-disable-next-line
|
|
185
|
+
let str2: string = (<any>errorText)['m' + decide];
|
|
186
|
+
if (!isUndefined(val1)) {
|
|
187
|
+
this.checkRange(val1, str1, isFraction);
|
|
188
|
+
dint++;
|
|
189
|
+
}
|
|
190
|
+
if (!isUndefined(val2)) {
|
|
191
|
+
this.checkRange(val2, str2, isFraction);
|
|
192
|
+
dint++;
|
|
193
|
+
}
|
|
194
|
+
if (dint === 2) {
|
|
195
|
+
if (val1 < val2) {
|
|
196
|
+
throwError(str2 + 'specified must be less than the' + str1);
|
|
197
|
+
} else {
|
|
198
|
+
return true;
|
|
199
|
+
}
|
|
200
|
+
} else if (checkbothExist && dint === 1) {
|
|
201
|
+
throwError('Both' + str2 + 'and' + str2 + 'must be present');
|
|
202
|
+
}
|
|
203
|
+
return false;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Check if the provided fraction range is valid
|
|
207
|
+
*
|
|
208
|
+
* @param {number} val ?
|
|
209
|
+
* @param {string} text ?
|
|
210
|
+
* @param {boolean} isFraction ?
|
|
211
|
+
* @returns {void} ?
|
|
212
|
+
*/
|
|
213
|
+
private static checkRange(val: number, text: string, isFraction?: boolean): void {
|
|
214
|
+
const range: number[] = isFraction ? [0, 20] : [1, 21];
|
|
215
|
+
if (val < range[0] || val > range[1]) {
|
|
216
|
+
throwError(text + 'value must be within the range' + range[0] + 'to' + range[1]);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Returns formatted numeric string for provided formatting options
|
|
221
|
+
*
|
|
222
|
+
* @param {number} value ?
|
|
223
|
+
* @param {base.GenericFormatOptions} fOptions ?
|
|
224
|
+
* @param {CommonOptions} dOptions ?
|
|
225
|
+
* @param {NumberFormatOptions} [option] ?
|
|
226
|
+
* @returns {string} ?
|
|
227
|
+
*/
|
|
228
|
+
private static intNumberFormatter(value: number, fOptions: base.GenericFormatOptions, dOptions: CommonOptions,
|
|
229
|
+
option ?: NumberFormatOptions): string {
|
|
230
|
+
let curData: base.NegativeData;
|
|
231
|
+
if (isUndefined(fOptions.nData.type)) {
|
|
232
|
+
return undefined;
|
|
233
|
+
} else {
|
|
234
|
+
if (value < 0) {
|
|
235
|
+
value = value * -1;
|
|
236
|
+
curData = fOptions.nData;
|
|
237
|
+
} else if (value === 0) {
|
|
238
|
+
curData = fOptions.zeroData || fOptions.pData;
|
|
239
|
+
} else {
|
|
240
|
+
curData = fOptions.pData;
|
|
241
|
+
}
|
|
242
|
+
let fValue: string = '';
|
|
243
|
+
if (curData.isPercent) {
|
|
244
|
+
value = value * 100;
|
|
245
|
+
}
|
|
246
|
+
if (curData.groupOne) {
|
|
247
|
+
fValue = this.processSignificantDigits(value, curData.minimumSignificantDigits, curData.maximumSignificantDigits);
|
|
248
|
+
} else {
|
|
249
|
+
fValue = this.processFraction(value, curData.minimumFractionDigits, curData.maximumFractionDigits, option);
|
|
250
|
+
if (curData.minimumIntegerDigits) {
|
|
251
|
+
fValue = this.processMinimumIntegers(fValue, curData.minimumIntegerDigits);
|
|
252
|
+
}
|
|
253
|
+
if (dOptions.isCustomFormat && curData.minimumFractionDigits < curData.maximumFractionDigits
|
|
254
|
+
&& /\d+\.\d+/.test(fValue)) {
|
|
255
|
+
const temp: string[] = fValue.split('.');
|
|
256
|
+
let decimalPart: string = temp[1];
|
|
257
|
+
const len: number = decimalPart.length;
|
|
258
|
+
for (let i: number = len - 1; i >= 0; i--) {
|
|
259
|
+
if (decimalPart[`${i}`] === '0' && i >= curData.minimumFractionDigits) {
|
|
260
|
+
decimalPart = decimalPart.slice(0, i);
|
|
261
|
+
} else {
|
|
262
|
+
break;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
fValue = temp[0] + '.' + decimalPart;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
if (curData.type === 'scientific') {
|
|
269
|
+
fValue = value.toExponential(curData.maximumFractionDigits);
|
|
270
|
+
fValue = fValue.replace('e', dOptions.numberMapper.numberSymbols[mapper[4]]);
|
|
271
|
+
}
|
|
272
|
+
fValue = fValue.replace('.', (<any>dOptions).numberMapper.numberSymbols[mapper[3]]);
|
|
273
|
+
fValue = curData.format === '#,###,,;(#,###,,)' ? this.customPivotFormat(parseInt(fValue, 10)) : fValue;
|
|
274
|
+
if (curData.useGrouping) {
|
|
275
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
276
|
+
fValue = this.groupNumbers(
|
|
277
|
+
fValue, curData.groupData.primary, curData.groupSeparator || ',',
|
|
278
|
+
(<any>dOptions).numberMapper.numberSymbols[mapper[3]] || '.', curData.groupData.secondary);
|
|
279
|
+
}
|
|
280
|
+
fValue = parser.convertValueParts(fValue, base.latnParseRegex, dOptions.numberMapper.mapper);
|
|
281
|
+
if (curData.nlead === 'N/A') {
|
|
282
|
+
return curData.nlead;
|
|
283
|
+
} else {
|
|
284
|
+
if (fValue === '0' && option && option.format === '0') {
|
|
285
|
+
return fValue + curData.nend;
|
|
286
|
+
}
|
|
287
|
+
return curData.nlead + fValue + curData.nend;
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Returns significant digits processed numeric string
|
|
293
|
+
*
|
|
294
|
+
* @param {number} value ?
|
|
295
|
+
* @param {number} min ?
|
|
296
|
+
* @param {number} max ?
|
|
297
|
+
* @returns {string} ?
|
|
298
|
+
*/
|
|
299
|
+
private static processSignificantDigits(value: number, min: number, max: number): string {
|
|
300
|
+
let temp: string = value + '';
|
|
301
|
+
let tn: number;
|
|
302
|
+
const length: number = temp.length;
|
|
303
|
+
if (length < min) {
|
|
304
|
+
return value.toPrecision(min);
|
|
305
|
+
} else {
|
|
306
|
+
temp = value.toPrecision(max);
|
|
307
|
+
tn = +temp;
|
|
308
|
+
return tn + '';
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Returns grouped numeric string
|
|
313
|
+
*
|
|
314
|
+
* @param {string} val ?
|
|
315
|
+
* @param {number} level1 ?
|
|
316
|
+
* @param {string} sep ?
|
|
317
|
+
* @param {string} decimalSymbol ?
|
|
318
|
+
* @param {number} level2 ?
|
|
319
|
+
* @returns {string} ?
|
|
320
|
+
*/
|
|
321
|
+
private static groupNumbers(val: string, level1: number, sep: string, decimalSymbol: string, level2?: number): string {
|
|
322
|
+
let flag: boolean = !isNullOrUndefined(level2) && level2 !== 0;
|
|
323
|
+
const split: string[] = val.split(decimalSymbol);
|
|
324
|
+
const prefix: string = split[0];
|
|
325
|
+
let length: number = prefix.length;
|
|
326
|
+
let str: string = '';
|
|
327
|
+
while (length > level1) {
|
|
328
|
+
str = prefix.slice(length - level1, length) + (str.length ?
|
|
329
|
+
(sep + str) : '');
|
|
330
|
+
length -= level1;
|
|
331
|
+
if (flag) {
|
|
332
|
+
level1 = level2;
|
|
333
|
+
flag = false;
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
split[0] = prefix.slice(0, length) + (str.length ? sep : '') + str;
|
|
337
|
+
return split.join(decimalSymbol);
|
|
338
|
+
}
|
|
339
|
+
/**
|
|
340
|
+
* Returns fraction processed numeric string
|
|
341
|
+
*
|
|
342
|
+
* @param {number} value ?
|
|
343
|
+
* @param {number} min ?
|
|
344
|
+
* @param {number} max ?
|
|
345
|
+
* @param {NumberFormatOptions} [option] ?
|
|
346
|
+
* @returns {string} ?
|
|
347
|
+
*/
|
|
348
|
+
private static processFraction(value: number, min: number, max: number, option ?: NumberFormatOptions): string {
|
|
349
|
+
const temp: string = (value + '').split('.')[1];
|
|
350
|
+
const length: number = temp ? temp.length : 0;
|
|
351
|
+
if (min && length < min) {
|
|
352
|
+
let ret: string = '';
|
|
353
|
+
if (length === 0) {
|
|
354
|
+
ret = value.toFixed(min);
|
|
355
|
+
} else {
|
|
356
|
+
ret += value;
|
|
357
|
+
for (let j: number = 0; j < min - length; j++) {
|
|
358
|
+
ret += '0';
|
|
359
|
+
}
|
|
360
|
+
return ret;
|
|
361
|
+
}
|
|
362
|
+
return value.toFixed(min);
|
|
363
|
+
} else if (!isNullOrUndefined(max) && (length > max || max === 0)) {
|
|
364
|
+
return value.toFixed(max);
|
|
365
|
+
}
|
|
366
|
+
let str: string = value + '';
|
|
367
|
+
if (str[0] === '0' && option && option.format === '###.00')
|
|
368
|
+
{
|
|
369
|
+
str = str.slice(1);
|
|
370
|
+
}
|
|
371
|
+
return str;
|
|
372
|
+
}
|
|
373
|
+
/**
|
|
374
|
+
* Returns integer processed numeric string
|
|
375
|
+
*
|
|
376
|
+
* @param {string} value ?
|
|
377
|
+
* @param {number} min ?
|
|
378
|
+
* @returns {string} ?
|
|
379
|
+
*/
|
|
380
|
+
private static processMinimumIntegers(value: string, min: number): string {
|
|
381
|
+
const temp: string[] = value.split('.');
|
|
382
|
+
let lead: string = temp[0];
|
|
383
|
+
const len: number = lead.length;
|
|
384
|
+
if (len < min) {
|
|
385
|
+
for (let i: number = 0; i < min - len; i++) {
|
|
386
|
+
lead = '0' + lead;
|
|
387
|
+
}
|
|
388
|
+
temp[0] = lead;
|
|
389
|
+
}
|
|
390
|
+
return temp.join('.');
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Returns custom format for pivot table
|
|
395
|
+
*
|
|
396
|
+
* @param {number} value ?
|
|
397
|
+
* @returns {string} ?
|
|
398
|
+
*/
|
|
399
|
+
private static customPivotFormat(value: number): string {
|
|
400
|
+
if (value >= 500000) {
|
|
401
|
+
value /= 1000000;
|
|
402
|
+
// eslint-disable-next-line
|
|
403
|
+
const [integer, decimal] = value.toString().split('.');
|
|
404
|
+
return decimal && +decimal.substring(0, 1) >= 5
|
|
405
|
+
? Math.ceil(value).toString()
|
|
406
|
+
: Math.floor(value).toString();
|
|
407
|
+
}
|
|
408
|
+
return '';
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { NumberFormatOptions } from '../internationalization';
|
|
2
|
+
import { extend, isNullOrUndefined, isBlazor, getValue } from '../util';
|
|
3
|
+
import { ParserBase as parser, NumericOptions } from './parser-base';
|
|
4
|
+
import { IntlBase as base } from './intl-base';
|
|
5
|
+
const regExp: RegExpConstructor = RegExp;
|
|
6
|
+
// eslint-disable-next-line
|
|
7
|
+
const parseRegex: RegExp = new regExp('^([^0-9]*)' + '(([0-9,]*[0-9]+)(\.[0-9]+)?)' + '([Ee][+-]?[0-9]+)?([^0-9]*)$');
|
|
8
|
+
const groupRegex: RegExp = /,/g;
|
|
9
|
+
|
|
10
|
+
const keys: string[] = ['minusSign', 'infinity'];
|
|
11
|
+
/**
|
|
12
|
+
* interface for Numeric Formatting Parts
|
|
13
|
+
*/
|
|
14
|
+
export interface NumericParts {
|
|
15
|
+
symbolRegex?: RegExp;
|
|
16
|
+
nData?: base.NegativeData;
|
|
17
|
+
pData?: base.NegativeData;
|
|
18
|
+
infinity?: string;
|
|
19
|
+
type?: string;
|
|
20
|
+
fractionDigits?: number;
|
|
21
|
+
isAccount?: boolean;
|
|
22
|
+
custom?: boolean;
|
|
23
|
+
maximumFractionDigits?: number;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* interface for numeric parse options
|
|
27
|
+
*/
|
|
28
|
+
// eslint-disable-next-line
|
|
29
|
+
interface NumberParseOptions {
|
|
30
|
+
parseRegex: string;
|
|
31
|
+
numbericMatcher: Object;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Module for Number Parser.
|
|
37
|
+
*
|
|
38
|
+
* @private
|
|
39
|
+
*/
|
|
40
|
+
export class NumberParser {
|
|
41
|
+
/**
|
|
42
|
+
* Returns the parser function for given skeleton.
|
|
43
|
+
*
|
|
44
|
+
* @param {string} culture - Specifies the culture name to be which formatting.
|
|
45
|
+
* @param {NumberFormatOptions} option - Specific the format in which number will parsed.
|
|
46
|
+
* @param {Object} cldr - Specifies the global cldr data collection.
|
|
47
|
+
* @returns {Function} ?
|
|
48
|
+
*/
|
|
49
|
+
public static numberParser(culture: string, option: NumberFormatOptions, cldr: Object): Function {
|
|
50
|
+
const dependable: base.Dependables = base.getDependables(cldr, culture, '', true);
|
|
51
|
+
const parseOptions: NumericParts = { custom: true };
|
|
52
|
+
let numOptions: NumericOptions;
|
|
53
|
+
if ((base.formatRegex.test(option.format)) || !(option.format)) {
|
|
54
|
+
extend(parseOptions, base.getProperNumericSkeleton(option.format || 'N'));
|
|
55
|
+
parseOptions.custom = false;
|
|
56
|
+
if (!parseOptions.fractionDigits) {
|
|
57
|
+
if (option.maximumFractionDigits) {
|
|
58
|
+
parseOptions.maximumFractionDigits = option.maximumFractionDigits;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
} else {
|
|
62
|
+
extend(parseOptions, base.customFormat(option.format, null, null));
|
|
63
|
+
}
|
|
64
|
+
const numbers: Object = getValue('numbers', dependable.parserObject);
|
|
65
|
+
// eslint-disable-next-line
|
|
66
|
+
numOptions = parser.getCurrentNumericOptions(dependable.parserObject, parser.getNumberingSystem(cldr), true, isBlazor());
|
|
67
|
+
parseOptions.symbolRegex = parser.getSymbolRegex(Object.keys(numOptions.symbolMatch));
|
|
68
|
+
// eslint-disable-next-line
|
|
69
|
+
parseOptions.infinity = (<any>numOptions).symbolNumberSystem[keys[1]];
|
|
70
|
+
let symbolpattern: string;
|
|
71
|
+
if (!isBlazor()) {
|
|
72
|
+
symbolpattern = base.getSymbolPattern(
|
|
73
|
+
parseOptions.type, numOptions.numberSystem, dependable.numericObject, parseOptions.isAccount);
|
|
74
|
+
if (symbolpattern) {
|
|
75
|
+
symbolpattern = symbolpattern.replace(/\u00A4/g, base.defaultCurrency);
|
|
76
|
+
const split: string[] = symbolpattern.split(';');
|
|
77
|
+
parseOptions.nData = base.getFormatData(split[1] || '-' + split[0], true, '');
|
|
78
|
+
parseOptions.pData = base.getFormatData(split[0], true, '');
|
|
79
|
+
}
|
|
80
|
+
} else {
|
|
81
|
+
parseOptions.nData = extend({}, {}, getValue(parseOptions.type + 'nData', numbers));
|
|
82
|
+
parseOptions.pData = extend({}, {}, getValue(parseOptions.type + 'pData', numbers));
|
|
83
|
+
if (parseOptions.type === 'currency' && option.currency) {
|
|
84
|
+
base.replaceBlazorCurrency([parseOptions.pData, parseOptions.nData], getValue('currencySymbol', numbers), option.currency);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return (value: string): number => {
|
|
89
|
+
return this.getParsedNumber(value, parseOptions, numOptions);
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Returns parsed number for the provided formatting options
|
|
94
|
+
*
|
|
95
|
+
* @param {string} value ?
|
|
96
|
+
* @param {NumericParts} options ?
|
|
97
|
+
* @param {NumericOptions} numOptions ?
|
|
98
|
+
* @returns {number} ?
|
|
99
|
+
*/
|
|
100
|
+
private static getParsedNumber(value: string, options: NumericParts, numOptions: NumericOptions): number {
|
|
101
|
+
let isNegative: boolean;
|
|
102
|
+
let isPercent: boolean;
|
|
103
|
+
let tempValue: string;
|
|
104
|
+
let lead: string;
|
|
105
|
+
let end: string;
|
|
106
|
+
let ret: number;
|
|
107
|
+
if (value.indexOf(options.infinity) !== -1) {
|
|
108
|
+
return Infinity;
|
|
109
|
+
} else {
|
|
110
|
+
value = parser.convertValueParts(value, options.symbolRegex, numOptions.symbolMatch);
|
|
111
|
+
value = parser.convertValueParts(value, numOptions.numberParseRegex, numOptions.numericPair);
|
|
112
|
+
value = value.indexOf('-') !== -1 ? value.replace('-.', '-0.') : value;
|
|
113
|
+
if (value.indexOf('.') === 0) {
|
|
114
|
+
value = '0' + value;
|
|
115
|
+
}
|
|
116
|
+
const matches: string[] = value.match(parseRegex);
|
|
117
|
+
if (isNullOrUndefined(matches)) {
|
|
118
|
+
return NaN;
|
|
119
|
+
}
|
|
120
|
+
lead = matches[1];
|
|
121
|
+
tempValue = matches[2];
|
|
122
|
+
const exponent: string = matches[5];
|
|
123
|
+
end = matches[6];
|
|
124
|
+
isNegative = options.custom ? ((lead === options.nData.nlead) && (end === options.nData.nend)) :
|
|
125
|
+
((lead.indexOf(options.nData.nlead) !== -1) && (end.indexOf(options.nData.nend) !== -1));
|
|
126
|
+
isPercent = isNegative ?
|
|
127
|
+
options.nData.isPercent :
|
|
128
|
+
options.pData.isPercent;
|
|
129
|
+
tempValue = tempValue.replace(groupRegex, '');
|
|
130
|
+
if (exponent) {
|
|
131
|
+
tempValue += exponent;
|
|
132
|
+
}
|
|
133
|
+
ret = +tempValue;
|
|
134
|
+
if (options.type === 'percent' || isPercent) {
|
|
135
|
+
ret = ret / 100;
|
|
136
|
+
}
|
|
137
|
+
if (options.custom || options.fractionDigits) {
|
|
138
|
+
ret = parseFloat(ret.toFixed(options.custom ?
|
|
139
|
+
(isNegative ? options.nData.maximumFractionDigits : options.pData.maximumFractionDigits) : options.fractionDigits));
|
|
140
|
+
}
|
|
141
|
+
if (options.maximumFractionDigits) {
|
|
142
|
+
ret = this.convertMaxFracDigits(tempValue, options, ret, isNegative);
|
|
143
|
+
}
|
|
144
|
+
if (isNegative) {
|
|
145
|
+
ret *= -1;
|
|
146
|
+
}
|
|
147
|
+
return ret;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
private static convertMaxFracDigits(value: string, options: NumericParts, ret: number, isNegative: boolean): number {
|
|
151
|
+
const decimalSplitValue: string[] = value.split('.');
|
|
152
|
+
if (decimalSplitValue[1] && decimalSplitValue[1].length > options.maximumFractionDigits) {
|
|
153
|
+
ret = +(ret.toFixed(options.custom ?
|
|
154
|
+
(isNegative ? options.nData.maximumFractionDigits : options.pData.maximumFractionDigits) : options.maximumFractionDigits));
|
|
155
|
+
}
|
|
156
|
+
return ret;
|
|
157
|
+
}
|
|
158
|
+
}
|