NN 2, IE 3

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

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.

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

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.

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