[ Team LiB ] Previous Section Next Section

2.5 Formatting Numbers for Text Display

NN 2, IE 3

2.5.1 Problem

You want to display the results of numeric calculations with a fixed number of digits to the right of the decimal.

2.5.2 Solution

Two recent additions to the JavaScript language (and ECMA standard) simplify the display of numbers with a specific number of digits. These methods are implemented in IE 5.5 or later for Windows and Netscape 6 or later. To obtain a string containing a number with digits to the right of the decimal, use the toFixed( ) method, as in the following:

document.myForm.total.value = someNumber.toFixed(2);

The argument to the toFixed( ) method is the number of digits to the right of the decimal. Even if the number is an integer, the resulting string has a decimal and two zeros to the right of the decimal.

To obtain a string containing a number with a total fixed number of digits, use the toPrecision( ) method, as in the following:

document.myForm.rate.value = someNumber.toPrecision(5);

The argument to the toPrecision( ) method is the total number of digits in the returned string value, including digits to the left and right of the decimal (the decimal is not counted). If the original value has fewer digits than the method argument calls for, the result is padded with zeros to the right of the decimal:

var num = 98.6;
var preciseNum = num.toPrecision(5);          // preciseNum is now 98.600

For older browsers, number formatting is a more cumbersome process, but one that can be encapsulated in the formatNumber( ) utility function shown in the Discussion. Invoke the function by passing either a number or string that can be cast to a number and an integer signifying the number of places to the right of the decimal for the returned string:

document.myForm.total.value = formatNumber(someNumber, 2);

The result from this function is intended for display on the page, not further calculation. Thus, error conditions are returned as strings that would be displayed in lieu of the formatted number.

2.5.3 Discussion

Example 2-1 shows the formatNumber( ) reusable utility function.

Example 2-1. formatNumber( ) function for text display of numbers
function formatNumber (num, decplaces) {
    // convert in case it arrives as a string value
    num = parseFloat(num);
    // make sure it passes conversion
    if (!isNaN(num)) {
        // multiply value by 10 to the decplaces power;
        // round the result to the nearest integer;
        // convert the result to a string
        var str = "" + Math.round (eval(num) * Math.pow(10,decplaces));
        // exponent means value is too big or small for this routine
        if (str.indexOf("e") != -1) {
            return "Out of Range";
        }
        // if needed for small values, pad zeros
        // to the left of the number
        while (str.length <= decplaces) {
            str = "0" + str;
        }
        // calculate decimal point position
        var decpoint = str.length - decplaces;
        // assemble final result from: (a) the string up to the position of
        // the decimal point; (b) the decimal point; and (c) the balance
        // of the string. Return finished product.
        return str.substring(0,decpoint) + "." + str.substring(decpoint,str.length);
    } else {
        return "NaN";
    }
}

When you use the newer built-in methods to set the number format, you should be aware of the way truncated numbers are rounded. All rounding is based on the value of the next digit to the right of the last visible digit in the returned string. For example, if you format the number 1.2349 to two digits to the right of the decimal, the returned value is 1.23 because the next digit to the right of the 3 is a 4.

It should be clear that none of the methods or functions shown in this recipe operate in the same way that more sophisticated number formatting in other programs work. There is nothing about adding commas for large numbers or a leading currency symbol. Such extras need to be handled through your own scripts.

Inserting commas for displaying large numbers can be accomplished easily on the integer portion of a number through regular expressions. Here is a simple function that inserts commas in the appropriate places, regardless of the size of the number (in plain, nonscientific notation, that is):

function formatCommas(numString) {
    var re = /(-?\d+)(\d{3})/;
    while (re.test(numString)) {
        numString = numString.replace(re, "$1,$2");
    }
    return numString;
}

This function assumes that only the integer portion of a number is passed to it. Therefore, it works best with a script that divides a number into its integer and fractional components during the formatting process. Here is how the return statement at the end of the formatNumber( ) function in Example 2-1 can be modified to invoke formatCommas( ):

return formatCommas(str.substring(0,decpoint)) + "." + 
    str.substring(decpoint,str.length);

While on the subject of commas, it's not unusual for users to enter large numbers with commas, but the database or other backend processing does not allow commas in numbers. If that's the case, you can use the onsubmit event handler to modify the value of a text box that contains commas and strip those commas before submitting the form. It can all take place during the client-side batch validation of the form. The function to remove commas also uses regular expressions, and looks like the following:

function stripCommas(numString) {
    var re = /,/g;
    return numString.replace(re,"");
}

One final point about number formatting involves a comparatively new JavaScript method of the Number object called toLocaleString( ), invoked as:

var formattedString = myNumber.toLocaleString( );

The formal ECMAScript specification does not recommend any particular formatting for this method because it is largely dependent on how the browser maker wishes to align formatting with localized customs. For now, only Internet Explorer (at least for the U.S. version) does anything special when invoking this method on a number value. All numbers are formatted to two places to the right of the decimal (dollars and cents without any currency symbol). IE for Windows also inserts commas for large numbers. While Netscape 6 and later support this method, they perform no additional formatting for numbers.

Bear in mind that other parts of the world use different symbols where North Americans use commas and decimals. For example, in Europe, it's not uncommon to find commas and periods used in the opposite manner, so that the number 20,000.50 would be displayed as 20.000,50. If your audience uses that system, you could modify the functions above to work within that system. The most deeply nested statement of the formatCommas( ) function would be:

numString = numString.replace(re, "$1.$2");

and the first statement of the stripCommas( ) function would be:

var re = /\./g;

You'd also probably want to change the names of both functions to formatPeriods( ) and stripPeriods( ), respectively. This is just the kind of cultural variation that the toLocaleString( ) method was intended to solve. Now it is up to the browser makers to agree on an implementation that works across the board.

2.5.4 See Also

Recipe 8.3 for using the onsubmit event handler to trigger batch validation and other last-instant tasks on a form prior to submission.

    [ Team LiB ] Previous Section Next Section