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.
|