Using input.validity.valid, why does my number input return valid for the value 0.
in this scenario?
<input type="number" min="1" max="999" step="1" value="0." id="one" /> <!--Valid??-->
<input type="number" min="1" max="999" step="1" value="0.0" id="two" /> <!--fine-->
<input type="number" min="1" max="999" step="1" value="0" id="three" /> <!--fine-->
Chrome 37.0.2062.103 m
jsFiddle
Edit:
Oddly, any negative number with a period at the end also breaks the validation:
<input type="number" min="1" max="999" step="1" value="-14." id="one" />
jsFiddle
Note: since this answer was written, the Chrome bug mentioned in #1 has been fixed and so now only #2 applies.
There are actually two answers here:
0.
is not validated correctly when you enter/set it in an input field.required
.Strictly speaking, it is the first one that is causing the behaviour you are seeing, because it stops #2 from ever happening, but if the bug were fixed in Chrome then as the question stands (i.e. only dealing with the initial markup, not any subsequent user interaction), #2 would apply.
It's also worth noting that #2 is what causes the similar (but not identical) behaviour in Firefox.
rangeUnderflow
uses Decimal::fromString(...)
which returns NaN
if the input ends in a .
causing rangeUnderflow
to returnfalse
:
if (!numericValue.isFinite())
return false;
In contrast, badInput
uses StringToDoubleConverter::StringToDouble(...)
which basically ignores a trailing .
so the input is not considered 'bad'.
According to the spec:
A string is a valid floating-point number if it consists of:
- Optionally, a U+002D HYPHEN-MINUS character (-).
- One or both of the following, in the given order:
- A series of one or more ASCII digits.
- A single U+002E FULL STOP character (.).
- A series of one or more ASCII digits.
Note that 2.2.2 is not optional - i.e if you have a .
you must have digits after it.
So it's the badInput
that's incorrect. (If Chrome was at least consistent about treating 0.
as valid, the rangeUnderflow
would then have been detected)
Take for example if you set value="aaa"
in the HTML. The input will still show as valid, even though aaa
would cause badInput
to be true
.
This is because while parsing/rendering the page, Chrome runs a value sanitization algorithm on the attribute value. When it sees a value that is not a valid floating point number, it must set the input's value to the empty string as required by the spec. And the empty string is considered valid unless the input is marked required
. This currently doesn't occur in Chrome for value="0."
because it (incorrectly) passes the value sanitization algorithm. However, if/when they fix the bug in Chrome, this is what you would expect to happen.
If you actually type aaa
into the input, it will then show as invalid, i.e. badInput===true
. Similarly, in Firefox, and in Chrome if/when they fix the bug, if you type 0.
into the field, it will give badInput===true
and therefore valid===false
.
In the spec it says:
User agents must not allow the user to set the value to a non-empty string that is not a valid floating-point number. If the user agent provides a user interface for selecting a number, then the value must be set to the best representation of the number representing the user's selection as a floating-point number.
The spec goes on to say:
The value sanitization algorithm is as follows: If the value of the element is not a valid floating-point number, then set it to the empty string instead.
In Firefox the value
in DOM is being set to an empty string for the first input. This is a valid state). If you want the first field to be invalid in this situation, you must make it required
:
<input type="number" min="1" max="999" step="1" value="0." id="one" required />
The spec also says:
Constraint validation: While the user interface describes input that the user agent cannot convert to a valid floating-point number, the control is suffering from bad input.
I think in this case what Firefox (32.0) is doing is correct as long as the #one
input is not displaying the 0.
value. In Firefox if I manually type the value 0.
into the #one
input then it is correctly highlighted as invalid.
However in Chrome 38.0.2125.58 beta-m the 0.
value is displayed when the page has loaded even though document.querySelector("#one").value
evaluates to an empty string. This means it fails to be caught by both required
as well as by the constraint validation. I believe this is a bug in Chrome.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With