Подтвердить что ты не робот

Почему этот ввод действителен

Используя 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

4b9b3361

Ответ 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. также является прекрасной проверкой.