Почему этот ввод действителен
Используя input.validity.valid, почему мой номер ввода возвращает допустимый для значения 0.
в этом сценарии?
<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 м
jsFiddle
Edit:
Как ни странно, любое отрицательное число с периодом в конце также нарушает валидацию:
<input type="number" min="1" max="999" step="1" value="-14." id="one" />
jsFiddle
Ответы
Ответ 1
Здесь есть два ответа:
- В Chrome есть ошибка, которая означает, что значение, подобное
0.
, неверно проверено при вводе/установке в поле ввода.
- Если вы установите недопустимое значение в разметке HTML, браузер должен проигнорировать его и установить значение в пустую строку, которая считается действительной, если поле не отмечено
required
.
Строго говоря, это первое, что вызывает поведение, которое вы видите, потому что оно останавливает # 2 от когда-либо происходящего, но если ошибка была исправлена в Chrome, тогда как вопрос стоит (т.е. имеет дело только с начальной разметкой, а не любое последующее взаимодействие с пользователем), # 2 будет применяться.
Также стоит отметить, что # 2 является причиной аналогичного (но не идентичного) поведения в Firefox.
1. Ошибка Chrome
Причина № 1 заключается в том, что Chrome использует разные алгоритмы разбора в своем обнаружении rangeUnderflow
и обнаружении badInput
.
rangeUnderflow
использует Decimal::fromString(...)
, который возвращает NaN
, если вход заканчивается на .
, заставляя rangeUnderflow
возвращать false
:
if (!numericValue.isFinite())
return false;
Напротив, badInput
использует StringToDoubleConverter::StringToDouble(...)
который в основном игнорирует конечный .
, поэтому вход не считается "плохим".
В соответствии с спецификацией:
Строка является допустимым числом с плавающей запятой, если она состоит из:
- Необязательно, символ U + 002D HYPHEN-MINUS (-).
- Одно или оба из следующего, в данном порядке:
- Серия из одной или нескольких цифр ASCII.
-
- Один символ U + 002E FULL STOP (.).
- Серия из одной или нескольких цифр ASCII.
Обратите внимание, что 2.2.2 не является необязательным - если у вас есть .
, вы должны иметь цифры после него.
Так что это значение badInput
неверно. (Если бы Chrome был, по крайней мере, совместим с тем, что обработка 0.
действительна, тогда был бы обнаружен rangeUnderflow
)
2. Пометка и ввод пользователя
Но, если/когда они исправляют ошибку в Chrome, с HTML в вопросе, она все равно будет отображаться как действительная. Почему?
Возьмем, например, если вы установили value="aaa"
в HTML. Ввод по-прежнему будет отображаться как действительный, хотя aaa
приведет к badInput
true
.
Это связано с тем, что во время разбора/рендеринга страницы Chrome запускает алгоритм дезактивации значений по значению атрибута. Когда он видит значение, которое не является допустимым числом с плавающей запятой, оно должно установить входное значение в пустую строку, как требуется спецификация. И пустая строка считается действительной, если входной знак не отмечен required
. В настоящее время это не происходит в Chrome для value="0."
, потому что он (неправильно) передает алгоритм дезактивации значения. Однако, если/когда они исправляют ошибку в Chrome, это то, что вы ожидаете.
Если вы на самом деле набираете aaa
на вход, он будет отображаться как недопустимый, т.е. badInput===true
. Аналогично, в Firefox и в Chrome, если/когда они исправляют ошибку, если вы введете 0.
в поле, оно даст badInput===true
и, следовательно, valid===false
.
Ответ 2
В спецификация:
Пользовательские агенты не должны позволять пользователю устанавливать значение непустого строка, которая не является допустимым числом с плавающей запятой. Если пользовательский агент предоставляет пользовательский интерфейс для выбора номера, тогда значение должно задано наилучшее представление числа, представляющего выбор пользователя как число с плавающей запятой.
Далее идет спецификация:
Алгоритм дезактивации значений выглядит следующим образом: Если значение элемент не является допустимым числом с плавающей запятой, а затем устанавливает его в пустой строка вместо.
В Firefox value
в DOM устанавливается пустая строка для первого ввода. Это действительное состояние). Если вы хотите, чтобы первое поле было недопустимым в этой ситуации, вы должны сделать его required
:
<input type="number" min="1" max="999" step="1" value="0." id="one" required />
В спецификации также говорится:
Проверка ограничений. Хотя пользовательский интерфейс описывает ввод, который пользовательский агент не может преобразовать в действительный номер с плавающей запятой, контроль страдает от плохого ввода.
Я думаю, что в этом случае то, что делает Firefox (32.0), является правильным, если вход #one
не отображает значение 0.
. В Firefox, если я вручную введите значение 0.
в ввод #one
, то он будет правильно выделен как недопустимый.
Однако в Chrome 38.0.2125.58 beta-m значение 0.
отображается, когда страница загружается, хотя document.querySelector("#one").value
оценивает пустую строку. Это означает, что он не может быть пойман как с помощью required
, так и с помощью проверки ограничений. Я считаю, что это ошибка в Chrome.
Ответ 3
Насколько я могу судить, атрибут value
для проверки анализируется с использованием функции html5 valueAsNumber
. Это имеет разные правила от JavaScript, так что в FF32:
var el = document.createElement("input");
el.type = "number";
el.value = "1";
el.valueAsNumber;
/*
1
*/
но
var el = document.createElement("input");
el.type = "number";
el.value = "0.";
el.valueAsNumber;
/*
NaN
*/
Если "0." поэтому анализируется как NaN
Я думаю, что проверка не выполняется.
Ответ 4
В поле типа ввода, содержащем значение, является число с плавающей запятой.
A число с плавающей запятой состоит из следующих частей в точно следующем порядке:
- Необязательно, первый символ может быть символом "-".
- Один или несколько символов в диапазоне "0-9" .
- Дополнительно, следующие части, в точности в следующем порядке:
- a "." символ
- один или несколько символов в диапазоне "0-9"
- Дополнительно, следующие части, в точности в следующем порядке:
- символ "e" или символ "E"
- необязательно, символ "-" или символ "+"
- Один или несколько символов в диапазоне "0-9" .
И вы можете узнать число с плавающей запятой 0. == 0.0 == 0
. Как и другие 0, 0.0 проверка достоверна, поэтому 0.
также является прекрасной проверкой.