com.smartclient.debug.public.sc.client.language.Number.js Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of smartgwt Show documentation
Show all versions of smartgwt Show documentation
SmartGWT - GWT API's for SmartClient
The newest version!
/*
* Isomorphic SmartClient
* Version SC_SNAPSHOT-2011-08-08 (2011-08-08)
* Copyright(c) 1998 and beyond Isomorphic Software, Inc. All rights reserved.
* "SmartClient" is a trademark of Isomorphic Software, Inc.
*
* [email protected]
*
* http://smartclient.com/license
*/
//>DEBUG
// This lets us label methods with a name within addMethods
Number.prototype.Class = "Number";
// @object Number
//
// Extra methods added to the Number object, available on all number variables.
//
// @visibility external
// @treeLocation Client Reference/System
//<
//
// add methods to all Numbers
//
isc.addMethods(Number.prototype, {
//> @method number.stringify()
//
// Return this number as a string padded out to digits length.
//
// @visibility external
// @example var str = myNumberVar.stringify(2);
// @group stringProcessing
// @param [digits] (number : 2) Number of digits to pad to. (Default is 2)
// @return (string) Padded string version of the number
//<
stringify : function (totalDigits, predecimal) {
// default to 2 digits
if (!totalDigits) totalDigits = 2;
var numberString = this.toString(),
zeroes = totalDigits - numberString.length;
// predecimal: ignore any decimal digits, such that two numbers with differing decimal
// precision get the same total number of characters before the decimal.
if (predecimal) {
var dotIndex = numberString.indexOf(isc.dot);
if (dotIndex != -1) {
zeroes += (numberString.length - dotIndex);
}
}
var pad = Number._getZeroString(zeroes);
if (pad == null) return numberString;
return pad + numberString;
},
//> @method number.toCurrencyString()
// Return this number as a currency-formatted string.
// @group stringProcessing
// @param [currencyChar] (string)
// Currency symbol, can be set to an empty string. If unset "$"
will be used.
// @param [decimalChar] (string) Decimal separator symbol. If unset "."
will be used.
// @param [padDecimal] (boolean) Should decimal portion be padded out to two digits? True
// by default.
// @param [currencyCharLast] (boolean) Should currency symbol come at the end of the string?
// If unspecified, currency symbol will be shown at the beginning of the string.
// @return (string) Currency-formatted string version of the number
// @visibility external
//<
toCurrencyString : function(currencyChar, decimalChar, padDecimal, currencyCharLast) {
var wholeNumber = Math.floor(this),
decimalNumber = Math.round((this - wholeNumber)*100),
output = isc.StringBuffer.create();
// default currency/decimal symbols and decimal padding on
// allow empty string for no currency character
if (!isc.isA.String(currencyChar)) currencyChar = "$";
if (!isc.isA.nonemptyString(decimalChar)) decimalChar = ".";
if (padDecimal == null) padDecimal = true;
// output currency symbol first by default
if (currencyCharLast != true) output.append(currencyChar);
// output whole number
output.append(wholeNumber.stringify(1));
// output decimal symbol and decimal number
// (unless padding is off and decimal portion is 0)
if (padDecimal) {
output.append(decimalChar);
output.append(decimalNumber.stringify(2));
} else if (decimalNumber != 0) {
output.append(decimalChar);
if (decimalNumber % 10 == 0) output.append(decimalNumber/10);
else output.append(decimalNumber.stringify(2));
}
// output currency symbol last if specified
if (currencyCharLast == true) output.append(currencyChar);
return output.toString();
}
// NOTE:
// We don't provide 'setFormatter' or 'setStandardFormatter' instance methods for Numbers.
// This is because
// a) we don't want to confuse the issue of where formatters are stored (we have a pattern here
// and on Dates of having standard formatters for all instances only)
// b) (at least in IE), numbers are not allocated as "true instances", so having a
// number instance (var theVar = 2;) does not mean that you can set up properties on it,
// such as theVar.formatter -- when you next refer to 'theVar', you are really given
// another '2' instance, so your properties have been wiped out.
});
//
// add class-methods to the Number object
//
isc.addMethods(Number, {
//> @classMethod Number.setStandardFormatter()
// Set the standard "toString()" formatter for Number objects.
// After this call, all number.toString()
calls will yield a number
// in this format.
//
// @group stringProcessing
// @param functionName (string) name of a formatting function on the number object
// prototype
//<
setStandardFormatter : function (functionName) {
if (isc.isA.Function(Number.prototype[functionName]))
Number.prototype.formatter = functionName;
},
//> @classMethod Number.setStandardLocaleStringFormatter()
// Set the standard locale formatter for all Number objects.
// After this call, all isc.iscToLocaleString(number)
for number instances
// calls will yield the string returned by the formatter specified.
// @group stringProcessing
//
// @param functionName (string) name of a formatting function (on number instances)
//<
setStandardLocaleStringFormatter : function (functionName) {
if (isc.isA.Function(Number.prototype[functionName]))
Number.prototype.localeStringFormatter = functionName;
},
_1zero : "0",
_2zero : "00",
_3zero : "000",
_4zero : "0000",
_getZeroString : function (length) {
if (length <= 0) return;
var pad;
// with > 4 zeros (very rare), build up a leading pad 4 0's at a time
while (length > 4) {
if (pad == null) pad = this._4zero;
else pad += this._4zero;
length -= 4;
}
var finalPad;
switch (length) {
case 4: finalPad = this._4zero; break;
case 3: finalPad = this._3zero; break;
case 2: finalPad = this._2zero; break;
case 1: finalPad = this._1zero; break;
}
// no leading pad (less than 4 zeros total)
if (pad == null) return finalPad;
return pad + finalPad;
}
});
// set the standard formatter for the date prototype to the native browser string
// so 'toFormattedString()' defaults to returning the standard number format string
if (!Number.prototype.formatter) Number.prototype.formatter = "toString";
if (!Number.prototype.localeStringFormatter)
Number.prototype.localeStringFormatter = "toString";
isc.addProperties(Number.prototype, {
//> @method number.iscToLocaleString()
// Customizeable version of the toLocaleString()
method for numbers.
// Called by isc.iscToLocaleString()
.
// Uses the formatter set by Number.setStandardLocaleStringFormatter(), or at the instance
// level by number.setLocaleStringFormatter()
//
// @group stringProcessing
//
// @return (string) formatted number as a string
//<
iscToLocaleString : function () {
return this[this.localeStringFormatter]();
},
//> @method number.toFormattedString()
// Allow use of a custom number formatter - can be passed in as a parameter, or set by
// Number.setStandardFormatter()
//
// @group stringProcessing
//
// @param [formatter] (string) name of a Number function to use
//
// @return (string) formatted number as a string
//<
toFormattedString : function (formatter) {
return this[(formatter ? formatter : this.formatter)]();
},
localeProperties : {
decimalSymbol : ".",
groupingSymbol : ",",
negativeSymbol : "-",
currencySymbol : "$",
negativeFormat : 1, // 1 = before, 2 = after, 3 = beforeSpace, 4 = afterSpace, 5 = parens
groupingFormat : 1 // 0 = none; 1 = 123,456,789; 2 = 12,34,56,789
},
_jsDecimalSymbol : ".",
//> @method toLocalizedString()
// Format this number for readability, with:
//
// - separators between three-digit groups
// - optional fixed decimal precision (so decimal points align on right-aligned numbers)
// - localized decimal, grouping, and negative symbols
//
// Decimal symbol, grouping symbol, and negative symbol will normally come from
// SmartClient locale settings (which may come from either client OS or application locale
// settings), but they are also supported as arguments for mixed-format applications
// (eg normalize all currency to US format, but use the current locale format for other numbers).
// @param [decimalPrecision] (number)
// @param [decimalSymbol] (string)
// @param [groupingSymbol] (string)
// @param [negativeSymbol] (string)
// @return (string) formatted number
// @visibility internal
//<
toLocalizedString : function (decimalPrecision, decimalSymbol, groupingSymbol, negativeSymbol) {
var roundedValue = !decimalPrecision ? this : Math.round(this * Math.pow(10, decimalPrecision)) / Math.pow(10, decimalPrecision);
var absNum = Math.abs(roundedValue), // remove sign for now; deal with it at the very end of this method
wholeNum = Math.floor(absNum), // whole part of the number (no decimal)
wholeString, // string representation of whole part, before formatting
decimalString, // string representation of decimal part, after formatting (padding)
wholeChunks = []; // chunks of the whole number, based on 3-digit groupings
// decimal part - doing this first because this code may round the whole part
if (decimalPrecision) {
// decimalPrecision specified and > 0, so
// round/pad the decimal part to the specified number of digits
var decimalNum = Math.round( (absNum-wholeNum) * Math.pow(10,decimalPrecision) );
decimalString = decimalNum.stringify(decimalPrecision); // NOTE: stringify() could use a better name
} else if (decimalPrecision == 0) {
// decimalPrecision of 0 explicitly specified, so
// round the whole number and drop the decimal part entirely
wholeNum = Math.round(absNum);
} else {
// decimalPrecision not specified, so
// show the decimal part iff there is one
if (absNum-wholeNum > 0) {
// PRECISION ERROR - the next line of code introduces noise that makes a very long decimal part,
// e.g. 1.1 becomes 1.10000000000000009 - what causes this? some int to float conversion?
// decimalString = (absNum-wholeNum).toString().substring(2); // drops the leading "0."
// So using this alternate approach - just split the toString() on the decimal point
// and take the decimal part
var absString = absNum.toString();
decimalString = absString.substring(absString.indexOf(this._jsDecimalSymbol)+1);
}
}
// whole part - slice it into chunks to be joined with grouping symbols
wholeString = wholeNum.toString();
var wholeLength = wholeString.length;
var tripletCount = Math.floor(wholeLength/3); // number of complete chunks of 3 digits
if (wholeLength%3) {
// start with the incomplete chunk (first 1 or 2 digits) if any
wholeChunks[0] = wholeString.substr(0, wholeLength%3);
}
for (var i=0; i