diff options
author | Beat Schwarzentrub | 2016-11-14 16:06:27 +0000 |
---|---|---|
committer | Beat Schwarzentrub | 2016-11-14 16:06:27 +0000 |
commit | 475c19a7e38fa9363dd64fabfa1968444832bea9 (patch) | |
tree | 6e856149b6430e02b6826b8bc3a5eec03b6217df | |
parent | 814b75ea28dab352b7f0c84c8b7f91da3e6983d0 (diff) | |
download | org.eclipse.scout.rt-features/bschwarzent/decimalformat.tar.gz org.eclipse.scout.rt-features/bschwarzent/decimalformat.tar.xz org.eclipse.scout.rt-features/bschwarzent/decimalformat.zip |
*** TMP *** Fix decimalformatfeatures/bschwarzent/decimalformat
Change-Id: Ie449e202f0ed0f1f7fa9c5527990df271190f4f0
3 files changed, 152 insertions, 61 deletions
diff --git a/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/text/DecimalFormatSpec.js b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/text/DecimalFormatSpec.js index 70e0dc65f4..1535a46644 100644 --- a/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/text/DecimalFormatSpec.js +++ b/org.eclipse.scout.rt.ui.html.test/src/test/js/scout/text/DecimalFormatSpec.js @@ -278,7 +278,6 @@ describe("DecimalFormat", function() { expect(decimalFormat.format(-12345.6789)).toBe('M12~345!67'); decimalFormat.allAfter = 0; - decimalFormat.pattern = '#,##0'; expect(decimalFormat.format(-1000.1234)).toBe('M1~000'); expect(decimalFormat.format(1000.1234)).toBe('1~001'); }); diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/numberfield/NumberField.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/numberfield/NumberField.js index a3b5ea13ac..5350660ffa 100644 --- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/numberfield/NumberField.js +++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/form/fields/numberfield/NumberField.js @@ -61,10 +61,10 @@ scout.NumberField.prototype.acceptInput = function(whileTyping) { scout.NumberField.parent.prototype.acceptInput.call(this, whileTyping); }; -scout.NumberField.prototype.parse = function() { +scout.NumberField.prototype.parse = function(displayText) { var number = null; try { - number = this.decimalFormat.parse(this.displayText); + number = this.decimalFormat.parse(scout.nvl(displayText, this.displayText)); } catch(e) { // catch Error thrown when number isNaN } @@ -75,10 +75,7 @@ scout.NumberField.prototype._parse = function() { var input = this.$field.val(); if (input) { // Convert to JS number format (remove groupingChar, replace decimalSeparatorChar with '.') - input = input - .replace(new RegExp('[' + this.decimalFormat.groupingChar + ']', 'g'), '') - .replace(new RegExp('[' + this.decimalFormat.decimalSeparatorChar + ']', 'g'), '.') - .replace(/\s/g, ''); + input = this.decimalFormat.normalizeString(input); // if only math symbols are in the input string... if (this.calc.isFormula(input)) { @@ -94,3 +91,11 @@ scout.NumberField.prototype._parse = function() { } } }; + +scout.NumberField.prototype._parseValue = function(displayText) { + return this.parse(displayText); +}; + +scout.NumberField.prototype._formatValue = function(value) { + return this.decimalFormat.format(value, false); +}; diff --git a/org.eclipse.scout.rt.ui.html/src/main/js/scout/text/DecimalFormat.js b/org.eclipse.scout.rt.ui.html/src/main/js/scout/text/DecimalFormat.js index d685fcabf4..0d515a0812 100644 --- a/org.eclipse.scout.rt.ui.html/src/main/js/scout/text/DecimalFormat.js +++ b/org.eclipse.scout.rt.ui.html/src/main/js/scout/text/DecimalFormat.js @@ -20,10 +20,11 @@ */ scout.DecimalFormat = function(locale, decimalFormatConfiguration) { // format function will use these (defaults) - this.positivePrefix = ''; - this.positiveSuffix = ''; - this.negativePrefix = locale.decimalFormatSymbols.minusSign; - this.negativeSuffix = ''; + this.positivePrefix; + this.positiveSuffix; + this.negativePrefix; + this.negativeSuffix; + this.minusSign = locale.decimalFormatSymbols.minusSign; this.groupingChar = locale.decimalFormatSymbols.groupingSeparator; this.groupLength = 0; this.decimalSeparatorChar = locale.decimalFormatSymbols.decimalSeparator; @@ -40,45 +41,67 @@ scout.DecimalFormat = function(locale, decimalFormatConfiguration) { // Check if there are separate subpatterns for positive and negative numbers ("PositivePattern;NegativePattern") var split = this.pattern.split(SYMBOLS.patternSeparator); // Use the first subpattern as positive prefix/suffix - var positivePrefixAndSuffix = findPrefixAndSuffix(split[0]); - this.positivePrefix = positivePrefixAndSuffix.prefix; - this.positiveSuffix = positivePrefixAndSuffix.suffix; + var positivePatternParts = scout.DecimalFormat.findPatternParts(split[0]); + this.positivePrefix = positivePatternParts.prefix; + this.positiveSuffix = positivePatternParts.suffix; + this.numberPattern = positivePatternParts.number; if (split.length > 1) { // Yes, there is a negative subpattern - var negativePrefixAndSuffix = findPrefixAndSuffix(split[1]); - this.negativePrefix = negativePrefixAndSuffix.prefix; - this.negativeSuffix = negativePrefixAndSuffix.suffix; - // from now on, only look at the positive subpattern - this.pattern = split[0]; + var negativePatternParts = scout.DecimalFormat.findPatternParts(split[1]); + this.negativePrefix = negativePatternParts.prefix; + this.negativeSuffix = negativePatternParts.suffix; + if (negativePatternParts.prefixMinusMask.indexOf(SYMBOLS.minusSign) !== -1) { + this.minusSignInNegativePrefix = true; + } + if (negativePatternParts.suffixMinusMask.indexOf(SYMBOLS.minusSign) !== -1) { + this.minusSignInNegativeSuffix = true; + } + // "number" part is ignored, positive and negative number pattern are the same } else { // No, there is no negative subpattern, so the positive prefix/suffix are used for both positive and negative numbers. + this.negativePrefix = this.positivePrefix; + this.negativeSuffix = this.positiveSuffix; // Check if there is a minus sign in the prefix/suffix. - if (this.positivePrefix.indexOf(SYMBOLS.minusSign) !== -1 || this.positiveSuffix.indexOf(SYMBOLS.minusSign) !== -1) { - // Yes, there is a minus sign in the prefix/suffix. Use this a negativePrefix/Suffix and remove the minus sign from the posistivePrefix/Suffix. - this.negativePrefix = this.positivePrefix.replace(SYMBOLS.minusSign, locale.decimalFormatSymbols.minusSign); - this.negativeSuffix = this.positiveSuffix.replace(SYMBOLS.minusSign, locale.decimalFormatSymbols.minusSign); - this.positivePrefix = this.positivePrefix.replace(SYMBOLS.minusSign, ''); - this.positiveSuffix = this.positiveSuffix.replace(SYMBOLS.minusSign, ''); - } else { - // No, there is no minus sign in the prefix/suffix. Therefore, use the default negativePrefix/Suffix, but append the positivePrefix/Suffix - this.negativePrefix = this.positivePrefix + this.negativePrefix; - this.negativeSuffix = this.negativeSuffix + this.positiveSuffix; + var prefixMinusSignIndex = positivePatternParts.prefixMinusMask.indexOf(SYMBOLS.minusSign); + if (prefixMinusSignIndex !== -1) { + // Yes, there is a minus sign in the prefix. Use this a negativePrefix and remove the minus sign from the posistivePrefix. + while (prefixMinusSignIndex !== -1) { + this.positivePrefix = replaceCharAt(this.positivePrefix, prefixMinusSignIndex, ''); + this.negativePrefix = replaceCharAt(this.negativePrefix, prefixMinusSignIndex, this.minusSign); + prefixMinusSignIndex = positivePatternParts.prefixMinusMask.indexOf(SYMBOLS.minusSign, prefixMinusSignIndex + 1); + } + this.minusSignInNegativePrefix = true; + } + var suffixMinusSignIndex = positivePatternParts.suffixMinusMask.indexOf(SYMBOLS.minusSign); + if (suffixMinusSignIndex !== -1) { + // Yes, there is a minus sign in the suffix. Use this a negativeSuffix and remove the minus sign from the posistiveSuffix. + while (suffixMinusSignIndex !== -1) { + this.positiveSuffix = replaceCharAt(this.positiveSuffix, suffixMinusSignIndex, ''); + this.negativeSuffix = replaceCharAt(this.negativePrefix, suffixMinusSignIndex, this.minusSign); + suffixMinusSignIndex = positivePatternParts.suffixMinusMask.indexOf(SYMBOLS.minusSign, suffixMinusSignIndex + 1); + } + this.minusSignInNegativeSuffix = true; + } + if (!this.minusSignInNegativePrefix && !this.minusSignInNegativeSuffix) { + // No, there is no minus sign in the prefix/suffix. Therefore, automatically prepend the minus sign to the prefix. + this.negativePrefix = this.minusSign + this.positivePrefix; + this.minusSignInNegativePrefix = true; } } // find group length - var posDecimalSeparator = this.pattern.indexOf(SYMBOLS.decimalSeparator); + var posDecimalSeparator = this.numberPattern.indexOf(SYMBOLS.decimalSeparator); if (posDecimalSeparator === -1) { - posDecimalSeparator = this.pattern.length; // assume decimal separator at end + posDecimalSeparator = this.numberPattern.length; // assume decimal separator at end } - var posGroupingSeparator = this.pattern.lastIndexOf(SYMBOLS.groupingSeparator, posDecimalSeparator); // only search before decimal separator + var posGroupingSeparator = this.numberPattern.lastIndexOf(SYMBOLS.groupingSeparator, posDecimalSeparator); // only search before decimal separator if (posGroupingSeparator > 0) { this.groupLength = posDecimalSeparator - posGroupingSeparator - 1; } - this.pattern = this.pattern.replace(new RegExp('[' + SYMBOLS.groupingSeparator + ']', 'g'), ''); + this.numberPattern = this.numberPattern.replace(new RegExp('[' + SYMBOLS.groupingSeparator + ']', 'g'), ''); // split on decimal point - split = this.pattern.split(SYMBOLS.decimalSeparator); + split = this.numberPattern.split(SYMBOLS.decimalSeparator); // find digits before and after decimal point this.zeroBefore = scout.strings.count(split[0], SYMBOLS.zeroDigit); @@ -87,29 +110,10 @@ scout.DecimalFormat = function(locale, decimalFormatConfiguration) { this.allAfter = this.zeroAfter + scout.strings.count(split[1], SYMBOLS.digit); } - // Returns an object with the properties 'prefix' and 'suffix', which contain all characters - // before or after any 'digit-like' character in the given pattern string. - function findPrefixAndSuffix(pattern) { - var result = { - prefix: '', - suffix: '' - }; - // Find prefix (anything before the first 'digit-like' character) - var digitLikeCharacters = SYMBOLS.digit + SYMBOLS.zeroDigit + SYMBOLS.decimalSeparator + SYMBOLS.groupingSeparator; - var r = new RegExp('^(.*?)[' + digitLikeCharacters + '].*$'); - var matches = r.exec(pattern); - if (matches !== null) { - // Ignore single quotes (for special, quoted characters - e.g. Java quotes percentage sign like '%') - result.prefix = matches[1].replace(new RegExp('\'([^\']+)\'', 'g'), '$1'); - } - // Find suffix (anything before the first 'digit-like' character) - r = new RegExp('^.*[' + digitLikeCharacters + '](.*?)$'); - matches = r.exec(pattern); - if (matches !== null) { - // Ignore single quotes (for special, quoted characters - e.g. Java quotes percentage sign like '%') - result.suffix = matches[1].replace(new RegExp('\'([^\']+)\'', 'g'), '$1'); - } - return result; + // ----- Helper functions ----- + + function replaceCharAt(s, pos, replacement) { + return s.substring(0, pos) + replacement + s.substring(pos + 1); } }; @@ -121,10 +125,7 @@ scout.DecimalFormat.prototype.parse = function(numberString) { if (scout.strings.empty(numberString)) { return null; } - var pureNumber = numberString - .replace(new RegExp('[' + this.groupingChar + ']', 'g'), '') - .replace(new RegExp('[' + this.decimalSeparatorChar + ']', 'g'), '.') - .replace(/\s/g, ''); + var pureNumber = this.normalizeString(numberString); var number = Number(pureNumber); if (isNaN(number)) { throw new Error(numberString + ' is not a number (NaN)'); @@ -132,6 +133,27 @@ scout.DecimalFormat.prototype.parse = function(numberString) { return number; }; +scout.DecimalFormat.prototype.normalizeString = function(numberString) { + if (scout.strings.empty(numberString)) { + return ''; + } + var negativePrefixRegEx = new RegExp('^' + scout.strings.quote(this.negativePrefix)); + var negativeSuffixRegEx = new RegExp(scout.strings.quote(this.negativeSuffix) + '$'); + var minus = ''; + if ((this.minusSignInNegativePrefix && negativePrefixRegEx.test(numberString)) || + (this.minusSignInNegativeSuffix && negativeSuffixRegEx.test(numberString))) { + minus = '-'; + } + return minus + numberString + .replace(new RegExp('^' + scout.strings.quote(this.positivePrefix)), '') + .replace(new RegExp(scout.strings.quote(this.positiveSuffix) + '$'), '') + .replace(negativePrefixRegEx, '') + .replace(negativeSuffixRegEx, '') + .replace(new RegExp('[' + this.groupingChar + ']', 'g'), '') + .replace(new RegExp('[' + this.decimalSeparatorChar + ']', 'g'), '.') + .replace(/\s/g, ''); +}; + scout.DecimalFormat.prototype.format = function(number, applyMultiplier) { applyMultiplier = scout.nvl(applyMultiplier, true); if (number === null || number === undefined) { @@ -217,3 +239,68 @@ scout.DecimalFormat.ensure = function(locale, format) { } return new scout.DecimalFormat(locale, format); }; + +/** + * Returns an object with the properties 'prefix', 'number' and 'suffix'. Number contains + * the part of the pattern that consists of 'digit-like' characters. Prefix and suffix + * contain the literal part before and after the number part, respectively. Single quotes + * that can be used to escape characters are removed from the result. + */ +scout.DecimalFormat.findPatternParts = function(pattern) { + var result = { + prefix: '', + prefixMinusMask: '', + number: '', + suffix: '', + suffixMinusMask: '' + }; + var SYMBOLS = scout.DecimalFormat.PATTERN_SYMBOLS; + // Pattern that matches digit-like characters + var r = new RegExp('[' + SYMBOLS.digit + SYMBOLS.zeroDigit + SYMBOLS.decimalSeparator + SYMBOLS.groupingSeparator + ']'); + var escape = false; + var scope = 'PREFIX'; + for (var i = 0; i < pattern.length; i++) { + var ch = pattern.charAt(i); + if (scope === 'PREFIX') { + // prefix + if (ch === '\'') { // toggle escape + if (escape && pattern.charAt(i - 1) === '\'') { // two consecutive ' are equal to one literal ' + result.prefix += '\''; + result.prefixMinusMask += ' '; + } + escape = !escape; + continue; + } else if (!escape && r.test(ch)) { // digit-like character, belongs to 'number' part + scope = 'NUMBER'; + } else { // part of prefix + result.prefix += ch; + result.prefixMinusMask += (ch === SYMBOLS.minusSign && !escape ? '-' : ' '); + continue; + } + } + if (scope === 'NUMBER') { + // number + if (r.test(ch)) { // digit-like character + result.number += ch; + continue; + } else { // number is finished, belongs to suffix + scope = 'SUFFIX'; + } + } + if (scope === 'SUFFIX') { + // suffix + if (ch === '\'') { // toggle escape + if (escape && pattern.charAt(i - 1) === '\'') { // two consecutive ' are equal to one literal ' + result.suffix += '\''; + result.suffixMinusMask += ' '; + } + escape = !escape; + continue; + } else { // part of suffix + result.suffix += ch; + result.suffixMinusMask += (ch === SYMBOLS.minusSign && !escape ? '-' : ' '); + } + } + } + return result; +}; |