#html #html5-input-number
Вопрос:
Когда я создаю HTML <input type="number"/>
с step="0.010000000000000009"
помощью . Я могу нажать кнопку, чтобы увеличить значение только один раз, чтобы заполнить min
значение, а затем только один раз для первого увеличения на значение шага, затем оно застревает на этом значении, и дальнейшие щелчки не имеют никакого эффекта. Я могу воспроизвести это только с min="1.2" max="1.3"
помощью .
Все остальные комбинации min
, max
и step
я попытался разрешить нажимать кнопку несколько раз, пока она не достигнет максимума в определенных шагах.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>input with decimal step</title>
</head>
<body>
<input type="number" min="1.2" max="1.3" step="0.010000000000000009"/>
</body>
</html>
Комментарии:
1. Firefox позволяет вам дважды щелкнуть, прежде чем застрять.
2. Никакого упрека в Хроме. Если это только FF, то сообщение об ошибке может быть оправдано.
3. Мне приходит на ум арифметика с плавающей запятой.
4. @Dominik Я был недостаточно точен в своем вопросе, отредактированном
5. Я не уверен, что это обязательно ошибка в Firefox, скорее, Chrome более снисходителен. Согласно MDN,
max
значения, если они указаны, должны быть равныmin ( n * step )
— если я правильно читаю их (не совсем ясные) замечания: developer.mozilla.org/en-US/docs/Web/HTML/Attributes/step
Ответ №1:
Я считаю, что, согласно спецификации HTML5 Living, ваш <input />
элемент «страдает от несоответствия шагов».:
- https://html.spec.whatwg.org/multipage/input.html#the-step-attribute
- https://html.spec.whatwg.org/multipage/input.html#concept-input-min-zero
Следуя спецификациям вашего дела…
step
Значение равно0.010000000000000009
(отparseFloat
).step-scale-factor
Значение всегда1
для<input type="number" />
- Это тот
step-base
min
атрибут, который есть1.2
. - То
allowed-value-step
естьstep
*step-scale-factor
то, что есть1 * 0.010000000000000009 === 0.010000000000000009
. - Re: «Проверка ограничений», в спецификации говорится следующее:
Проверка ограничений: Когда у элемента есть
allowed-value-step
, и результат применения алгоритма преобразования строки в число к строке, заданной элементомvalue=""
, является числом, и это число, вычитаемое изstep-base
, не является целым кратнымallowed-value-step
, элемент страдает от несоответствия шага.Я перефразирую это так…:
- Если элемент имеет
allowed-value-step
числовойvalue=""
атрибут и.- (Так что это только после
<input/>
того, как он не пуст, например, один раз нажмите кнопки вверх/вниз, чтобы присвоить ему значение1.2
) - …затем вычитаем
1.2
(тоstep-base
) из1.2
(тоvalue=""
), чтобы дать0
. - И
0
не является целым кратным от0.010000000000000009
. - Следовательно, элемент страдает от несоответствия шага.
- (Так что это только после
- Если элемент имеет
Теперь, с вашими выводами:
Я могу только нажать кнопку, чтобы увеличить значение один раз, чтобы заполнить
min
значение
Да, это следует спецификации HTML5: начальное value=""
значение пусто, поэтому браузеры будут выбирать следующее допустимое наибольшее значение, которое является min="1.2"
значением.
и затем только один раз для первого увеличения на значение шага
Да, это потому , что следующий шаг 1.2 0.010000000000000009
1.210000000000000009
— это то, к чему оба браузера обрезают отображение 1.21
, однако, как только это происходит, мы видим разницу в поведении браузера:
- Firefox, похоже, правильно соответствует спецификации, и он устанавливает
HTMLInputElement.validity.stepMismatch
true
и отключает кнопки вверх/вниз из-за несоответствия шага. - Chrome 92 этого не делает, и использование кнопок вверх/вниз для установки других значений все равно приводит к
HTMLInputElement.validity.stepMismatch === false
.
Вот фрагмент, который показывает информацию о достоверности:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>input with decimal step</title>
</head>
<body>
<input id="inp" type="number" min="1.2" max="1.3" step="0.010000000000000009" />
<ul id="eventsList"></ul>
<script>
const inp = document.getElementById('inp');
const ul = document.getElementById('eventsList');
inp.addEventListener( 'input', logInfo );
inp.addEventListener( 'change', logInfo );
inp.addEventListener( 'click', logInfo );
function logInfo( e ) {
const li = document.createElement('li');
li.textContent = e.type ". Value: " inp.value ", valid: " inp.validity.valid ", stepMismatch: " inp.validity.stepMismatch;
ul.appendChild( li );
}
</script>
</body>
</html>
- В Chrome он позволяет мне нажать кнопку «Вверх» 10 раз (
1.2
,1.21
,1.22
,1.23
, …,1.28
, до1.29
), прежде чем он остановится, хотя он никогда не сообщаетstepIsmatch: true
. - В Firefox это позволяет мне нажать кнопку «Вверх» 1 раз (
1.2
и1.21
), прежде чем она установитсяstepMismatch: true
.
Мои деньги на том, что Chrome делает свое дело, учитывая, что их интерпретация (или, по крайней мере, их реализация) спецификации более снисходительна и с меньшей вероятностью приведет к разочарованию конечного пользователя, когда step
установлено странное значение.
Что интересно, так это то, что Number
тип в браузерах, похоже, способен точно представлять 0.010000000000000009
без каких-либо контрольных округлений IEEE 754 (то же самое с Python), в то время как типы C#/.NET Single
(32-разрядные) и Double
(64-разрядные) с плавающей запятой и подавляют, и дают мне довольно плохие приближения.