All Downloads are FREE. Search and download functionalities are using the official Maven repository.

scout.text.DecimalFormat.js Maven / Gradle / Ivy

There is a newer version: 25.1.0-beta.0
Show newest version
/*******************************************************************************
 * Copyright (c) 2014-2015 BSI Business Systems Integration AG.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     BSI Business Systems Integration AG - initial API and implementation
 ******************************************************************************/
/**
 * Provides formatting of numbers using java format pattern.
 * 

* Compared to the java DecimalFormat the following pattern characters are not considered: *

    *
  • prefix and suffix
  • *
  • E
  • *
  • %
  • *
*/ scout.DecimalFormat = function(locale, decimalFormatConfiguration) { // format function will use these (defaults) this.positivePrefix = ''; this.positiveSuffix = ''; this.negativePrefix = locale.decimalFormatSymbols.minusSign; this.negativeSuffix = ''; this.groupingChar = locale.decimalFormatSymbols.groupingSeparator; this.groupLength = 0; this.decimalSeparatorChar = locale.decimalFormatSymbols.decimalSeparator; this.zeroBefore = 1; this.zeroAfter = 0; this.allAfter = 0; decimalFormatConfiguration = decimalFormatConfiguration || {}; this.pattern = decimalFormatConfiguration.pattern || locale.decimalFormatPatternDefault; this.multiplier = decimalFormatConfiguration.multiplier || 1; this.roundingMode = decimalFormatConfiguration.roundingMode || scout.numbers.RoundingMode.HALF_UP; var SYMBOLS = scout.DecimalFormat.PATTERN_SYMBOLS; // 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; 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]; } else { // No, there is no negative subpattern, so the positive prefix/suffix are used for both positive and negative numbers. // 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; } } // find group length var posDecimalSeparator = this.pattern.indexOf(SYMBOLS.decimalSeparator); if (posDecimalSeparator === -1) { posDecimalSeparator = this.pattern.length; // assume decimal separator at end } var posGroupingSeparator = this.pattern.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'), ''); // split on decimal point split = this.pattern.split(SYMBOLS.decimalSeparator); // find digits before and after decimal point this.zeroBefore = scout.strings.count(split[0], SYMBOLS.zeroDigit); if (split.length > 1) { // has decimal point? this.zeroAfter = scout.strings.count(split[1], SYMBOLS.zeroDigit); 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; } }; /** * Returns a number for the given numberString, if the string can be converted into a number. * Throws an Error otherwise */ 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 number = Number(pureNumber); if (isNaN(number)) { throw new Error(numberString + ' is not a number (NaN)'); } return number; }; scout.DecimalFormat.prototype.format = function(number, applyMultiplier) { applyMultiplier = scout.nvl(applyMultiplier, true); if (number === null || number === undefined) { return null; } var prefix = this.positivePrefix; var suffix = this.positiveSuffix; // apply multiplier if (applyMultiplier && this.multiplier !== 1) { number *= this.multiplier; } // round number = scout.numbers.round(number, this.roundingMode, this.allAfter); // after decimal point var after = ''; if (this.allAfter) { after = number.toFixed(this.allAfter).split('.')[1]; for (var j = after.length - 1; j > this.zeroAfter - 1; j--) { if (after[j] !== '0') { break; } after = after.slice(0, -1); } if (after) { // did we find any non-zero characters? after = this.decimalSeparatorChar + after; } } // absolute value if (number < 0) { prefix = this.negativePrefix; suffix = this.negativeSuffix; number = -number; } // before decimal point var before = Math.floor(number); before = (before === 0) ? '' : String(before); before = scout.strings.padZeroLeft(before, this.zeroBefore); // group digits if (this.groupLength) { for (var i = before.length - this.groupLength; i > 0; i -= this.groupLength) { before = before.substr(0, i) + this.groupingChar + before.substr(i); } } // put together and return return prefix + before + after + suffix; }; /* --- STATIC HELPERS ------------------------------------------------------------- */ /** * Literal (not localized!) pattern symbols as defined in http://docs.oracle.com/javase/7/docs/api/java/text/DecimalFormat.html */ scout.DecimalFormat.PATTERN_SYMBOLS = { digit: '#', zeroDigit: '0', decimalSeparator: '.', groupingSeparator: ',', minusSign: '-', patternSeparator: ';' };




© 2015 - 2025 Weber Informatics LLC | Privacy Policy