Phil Sowden wrote:
[snip]
Can anybody help me with the code below? I just get Error on page,
irrespective of what values I use. [snip]
function setnum(fldid) {
if ( isNaN(parseFloat(fldid)) {
return 0
[snip]
Try replacing the above with:
function setnum(fldid) {
var a = parseFloat(fldid);
if (isNaN(a)) {
return 0;
Of course, you still have lots of work to do to validate the input.
parseFloat keeps grabbing characters until it doesn't get any more
numbers, so "16.7abc" will be returned as "16.7". So what your
function does is make a half-hearted attempt to make a number from
whatever is entered. Also, you are only testing for numbers - do you
want dollars and cents? Fractions? How many significant digits?
If I enter:
txtInvAmount: 1/5
txtCourier: 2.5
your function returns:
txtTotalCost: 3.5
You function also explicitly returns zero (0) if text is entered
(though if the first characters are digits, parseFloat will return them
as noted above).
You need to format txtTotalCost to give $0.00 (I think) too, and you
should disable the field so users can't simply put whatever they like
in there. Even better, write it to the document itself so users are
not tempted to modify it.
Anyhow, enough beating around the head! Here is what you need to do:
1. Test that only digits and one decimal point have been entered. If
not, give an alert and ask the user to fix it.
2. If the above test is passed, make sure a max of two decimal places
have been used.
3. If 2. is passed, format whatever they have typed in so it has two
places (5.2 becomes 5.20) and tidy the field.
3. Test that the numbers are reasonable - you should have some idea what
that should be.
4. Do the maths and write your formatted answer to the total.
Here is the text of a couple of posts from a few weeks ago - between the
two you should get the idea.
This one just tests if a number is an int or float:
Testing strings using regular expressions to see if they have
decimal places (and how many), surplus characters, scientific
notation, etc. requires exhaustive testing... let JS do
the work.
How about:
var x = someValue;
if (x == parseInt(x) && x == parseFloat(x)) {
alert(x + ' is a int');
} else if (x == parseFloat(x)) {
alert(x + ' is a float');
} else {
alert(x + ' is not a number I like...');
}
You can even use scientific notation if you like, so 1.2e+03 is
recognised as a float quite happily without complex pattern
matching.
Here is the followup from Mike Winter that shows how to use regular
expresions to test number input:
Testing strings using regular expressions to see if they have
decimal places (and how many), surplus characters, scientific
notation, etc. requires exhaustive testing [...]
Not at all:
/^(0|[1-9])\d*$/
ensures that the string contains an integer with no leading zeros.
/^(-|+)?(0|[1-9])\d*$/
allows for signed integers.
To check for basic real numbers, it can be modified to:
/^(0|[1-9])\d*(\.\d+)?$/
which allows integer or real number inputs. To force decimal places and
to limit their number again, only simple modification is necessary:
/^(0|[1-9])\d*\.\d+$/ // must be real
/^(0|[1-9])\d*\.\d\d$/ // must be real with two decimal places
/^(0|[1-9])\d*\.\d{1,5}$/ // must be real with at most five d.p.
Scientific notation:
/^(0|[1-9])\d*\.\d+e(-|+)?\d+$/i
Optional scientific notation:
/^(0|[1-9])\d*\.\d+(e(-|+)?\d+)?$/i
Optional scientific notation with positive and negative numbers:
/^(-|+)?(0|[1-9])\d*\.\d+(e(-|+)?\d+)?$/i
Mandatory canonical scientific notation:
/^(-|+)?[1-9]\.\d+e(-|+)?[1-9]\d*$/i
Hexadecimal:
/^0x[0-9a-f]+$/i
[Note: these are untested]
The problem with using parseInt and parseFloat is that parsing stops at
an unrecognised character. That doesn't really tell you if the value's
format is correct or not, just that part of it converts to a number. If
you want check an input format, regular expressions are the best approach.
As you can see from the above, it doesn't take much effort once you've
established some basic patterns. After that point, it's simply a matter
of adding the components in the appropriate places.
How about:
var x = someValue;
if (x == parseInt(x) && x == parseFloat(x)) {
Calling parseInt without a radix argument can be unpredictable. Don't do
it.
[snip]
Mike