//////////////////////////////////////////////////////////////////////////////// // // Licensed to the Apache Software Foundation (ASF) under one or more // contributor license agreements. See the NOTICE file distributed with // this work for additional information regarding copyright ownership. // The ASF licenses this file to You under the Apache License, Version 2.0 // (the "License"); you may not use this file except in compliance with // the License. You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. // //////////////////////////////////////////////////////////////////////////////// package mx.formatters { import mx.managers.ISystemManager; import mx.managers.SystemManager; [ResourceBundle("formatters")] [ResourceBundle("SharedResources")] [Alternative(replacement="spark.formatters.NumberFormatter", since="4.5")] /** * The NumberFormatter class formats a valid number * by adjusting the decimal rounding and precision, * the thousands separator, and the negative sign. * *

If you use both the rounding and precision * properties, rounding is applied first, and then you set the decimal length * by using the specified precision value. * This lets you round a number and still have a trailing decimal; * for example, 303.99 = 304.00.

* *

If an error occurs, an empty String is returned and a String * describing the error is saved to the error property. * The error property can have one of the following values:

* * * * @mxml * *

The <mx:NumberFormatter> tag * inherits all of the tag attributes of its superclass, * and adds the following tag attributes:

* *
 *  <mx:NumberFormatter
 *    decimalSeparatorFrom="."
 *    decimalSeparatorTo="."
 *    precision="-1"
 *    rounding="none|up|down|nearest"
 *    thousandsSeparatorFrom=","
 *    thousandsSeparatorTo=","
 *    useNegativeSign="true|false"
 *    useThousandsSeparator="true|false"/>  
 *  
* * @includeExample examples/NumberFormatterExample.mxml * * @see mx.formatters.NumberBase * @see mx.formatters.NumberBaseRoundType * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public class NumberFormatter extends Formatter { include "../core/Version.as"; //-------------------------------------------------------------------------- // // Constructor // //-------------------------------------------------------------------------- /** * Constructor. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function NumberFormatter() { super(); } //-------------------------------------------------------------------------- // // Properties // //-------------------------------------------------------------------------- //---------------------------------- // decimalSeparatorFrom //---------------------------------- /** * @private * Storage for the decimalSeparatorFrom property. */ private var _decimalSeparatorFrom:String; /** * @private */ private var decimalSeparatorFromOverride:String; [Inspectable(category="General", defaultValue="null")] /** * Decimal separator character to use * when parsing an input String. * *

When setting this property, ensure that the value of the * thousandsSeparatorFrom property does not equal this property. * Otherwise, an error occurs when formatting the value.

* * @default "." * * @see #format() * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get decimalSeparatorFrom():String { return _decimalSeparatorFrom; } /** * @private */ public function set decimalSeparatorFrom(value:String):void { decimalSeparatorFromOverride = value; _decimalSeparatorFrom = value != null ? value : resourceManager.getString( "SharedResources", "decimalSeparatorFrom"); } //---------------------------------- // decimalSeparatorTo //---------------------------------- /** * @private * Storage for the decimalSeparatorTo property. */ private var _decimalSeparatorTo:String; /** * @private */ private var decimalSeparatorToOverride:String; [Inspectable(category="General", defaultValue="null")] /** * Decimal separator character to use * when outputting formatted decimal numbers. * *

When setting this property, ensure that the value of the * thousandsSeparatorTo property does not equal this property. * Otherwise, an error occurs when formatting the value.

* * @default "." * * @see #format() * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get decimalSeparatorTo():String { return _decimalSeparatorTo; } /** * @private */ public function set decimalSeparatorTo(value:String):void { decimalSeparatorToOverride = value; _decimalSeparatorTo = value != null ? value : resourceManager.getString( "SharedResources", "decimalSeparatorTo"); } //---------------------------------- // precision //---------------------------------- /** * @private * Storage for the precision property. */ private var _precision:Object; /** * @private */ private var precisionOverride:Object; [Inspectable(category="General", defaultValue="null")] /** * Number of decimal places to include in the output String. * You can disable precision by setting it to -1. * A value of -1 means do not change the precision. For example, * if the input value is 1.453 and rounding * is set to NumberBaseRoundType.NONE, return a value of 1.453. * If precision is -1 and you have set some form of * rounding, return a value based on that rounding type. * * @default -1 * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get precision():Object { return _precision; } /** * @private */ public function set precision(value:Object):void { precisionOverride = value; _precision = value != null ? int(value) : resourceManager.getInt( "formatters", "numberFormatterPrecision"); } //---------------------------------- // rounding //---------------------------------- /** * @private * Storage for the rounding property. */ private var _rounding:String; /** * @private */ private var roundingOverride:String; [Inspectable(category="General", enumeration="none,up,down,nearest", defaultValue="null")] // !!@ Should enumeration include null? /** * Specifies how to round the number. * *

In ActionScript, you can use the following constants to set this property: * NumberBaseRoundType.NONE, NumberBaseRoundType.UP, * NumberBaseRoundType.DOWN, or NumberBaseRoundType.NEAREST. * Valid MXML values are "down", "nearest", "up", and "none".

* * @default NumberBaseRoundType.NONE * * @see mx.formatters.NumberBaseRoundType * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get rounding():String { return _rounding; } /** * @private */ public function set rounding(value:String):void { roundingOverride = value; _rounding = value != null ? value : resourceManager.getString( "formatters", "rounding"); } //---------------------------------- // thousandsSeparatorFrom //---------------------------------- /** * @private * Storage for the thousandsSeparatorFrom property. */ private var _thousandsSeparatorFrom:String; /** * @private */ private var thousandsSeparatorFromOverride:String; [Inspectable(category="General", defaultValue="null")] /** * Character to use as the thousands separator * in the input String. * *

When setting this property, ensure that the value of the * decimalSeparatorFrom property does not equal this property. * Otherwise, an error occurs when formatting the value.

* * @default "," * * @see #format() * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get thousandsSeparatorFrom():String { return _thousandsSeparatorFrom; } /** * @private */ public function set thousandsSeparatorFrom(value:String):void { thousandsSeparatorFromOverride = value; _thousandsSeparatorFrom = value != null ? value : resourceManager.getString( "SharedResources", "thousandsSeparatorFrom"); } //---------------------------------- // thousandsSeparatorTo //---------------------------------- /** * @private * Storage for the thousandsSeparatorTo property. */ private var _thousandsSeparatorTo:String; /** * @private */ private var thousandsSeparatorToOverride:String; [Inspectable(category="General", defaultValue="null")] /** * Character to use as the thousands separator * in the output String. * *

When setting this property, ensure that the value of the * decimalSeparatorTo property does not equal this property. * Otherwise, an error occurs when formatting the value.

* * @default "," * * @see #format() * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get thousandsSeparatorTo():String { return _thousandsSeparatorTo; } /** * @private */ public function set thousandsSeparatorTo(value:String):void { thousandsSeparatorToOverride = value; _thousandsSeparatorTo = value != null ? value : resourceManager.getString( "SharedResources", "thousandsSeparatorTo"); } //---------------------------------- // useNegativeSign //---------------------------------- /** * @private * Storage for the useNegativeSign property. */ private var _useNegativeSign:Object; /** * @private */ private var useNegativeSignOverride:Object; [Inspectable(category="General", defaultValue="null")] /** * If true, format a negative number * by preceding it with a minus "-" sign. * If false, format the number * surrounded by parentheses, for example (400). * * @default true * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get useNegativeSign():Object { return _useNegativeSign; } /** * @private */ public function set useNegativeSign(value:Object):void { useNegativeSignOverride = value; _useNegativeSign = value != null ? Boolean(value) : resourceManager.getBoolean( "formatters", "useNegativeSignInNumber"); } //---------------------------------- // useThousandsSeparator //---------------------------------- /** * @private * Storage for the useThousandsSeparator property. */ private var _useThousandsSeparator:Object; /** * @private */ private var useThousandsSeparatorOverride:Object; [Inspectable(category="General", defaultValue="null")] /** * If true, split the number into thousands increments * by using a separator character. * * @default true * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ public function get useThousandsSeparator():Object { return _useThousandsSeparator; } /** * @private */ public function set useThousandsSeparator(value:Object):void { useThousandsSeparatorOverride = value; _useThousandsSeparator = value != null ? Boolean(value) : resourceManager.getBoolean( "formatters", "useThousandsSeparator"); } //-------------------------------------------------------------------------- // // Overridden methods // //-------------------------------------------------------------------------- /** * @private */ override protected function resourcesChanged():void { super.resourcesChanged(); decimalSeparatorFrom = decimalSeparatorFromOverride; decimalSeparatorTo = decimalSeparatorToOverride; precision = precisionOverride; rounding = roundingOverride; thousandsSeparatorFrom = thousandsSeparatorFromOverride; thousandsSeparatorTo = thousandsSeparatorToOverride; useNegativeSign = useNegativeSignOverride; useThousandsSeparator = useThousandsSeparatorOverride; } /** * Formats the number as a String. * If value cannot be formatted, return an empty String * and write a description of the error to the error property. * * @param value Value to format. * * @return Formatted String. Empty if an error occurs. * * @langversion 3.0 * @playerversion Flash 9 * @playerversion AIR 1.1 * @productversion Flex 3 */ override public function format(value:Object):String { // Reset any previous errors. if (error) error = null; if (useThousandsSeparator && ((decimalSeparatorFrom == thousandsSeparatorFrom) || (decimalSeparatorTo == thousandsSeparatorTo))) { error = defaultInvalidFormatError; return ""; } if (decimalSeparatorTo == "" || !isNaN(Number(decimalSeparatorTo))) { error = defaultInvalidFormatError; return ""; } var dataFormatter:NumberBase = new NumberBase(decimalSeparatorFrom, thousandsSeparatorFrom, decimalSeparatorTo, thousandsSeparatorTo); // -- value -- if (value is String) value = dataFormatter.parseNumberString(String(value)); if (value === null || isNaN(Number(value))) { error = defaultInvalidValueError; return ""; } // -- format -- var isNegative:Boolean = (Number(value) < 0); var numStr:String = value.toString(); numStr.toLowerCase(); var e:int = numStr.indexOf("e"); if (e != -1) //deal with exponents numStr = dataFormatter.expandExponents(numStr); var numArrTemp:Array = numStr.split("."); var numFraction:int = numArrTemp[1] ? String(numArrTemp[1]).length : 0; if (precision <= numFraction) { if (rounding != NumberBaseRoundType.NONE) { numStr = dataFormatter.formatRoundingWithPrecision( numStr, rounding, int(precision)); } } var numValue:Number = Number(numStr); if (Math.abs(numValue) >= 1) { numArrTemp = numStr.split("."); var front:String = useThousandsSeparator ? dataFormatter.formatThousands(String(numArrTemp[0])) : String(numArrTemp[0]); if (numArrTemp[1] != null && numArrTemp[1] != "") numStr = front + decimalSeparatorTo + numArrTemp[1]; else numStr = front; } else if (Math.abs(numValue) > 0) { // Check if the string is in scientific notation if (numStr.indexOf("e") != -1) { var temp:Number = Math.abs(numValue) + 1; numStr = temp.toString(); } numStr = decimalSeparatorTo + numStr.substring(numStr.indexOf(".") + 1); } numStr = dataFormatter.formatPrecision(numStr, int(precision)); // If our value is 0, then don't show -0 if (Number(numStr) == 0) { isNegative = false; } if (isNegative) numStr = dataFormatter.formatNegative(numStr, useNegativeSign); if (!dataFormatter.isValid) { error = defaultInvalidFormatError; return ""; } return numStr; } } }