【问题标题】:Why is this input valid为什么这个输入有效
【发布时间】:2014-09-11 12:32:26
【问题描述】:

使用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-->

铬 37.0.2062.103 米

jsFiddle

编辑:

奇怪的是,任何以句点结尾的负数也会破坏验证:

<input type="number" min="1" max="999" step="1" value="-14." id="one" />

jsFiddle

【问题讨论】:

  • 你可以添加一个显式的pattern属性
  • @vsync 我无法将pattern 属性添加到数字输入 - 它得到ignored
  • 您的个人资料图片适合您的情况 :)
  • 删除的答案在 cmets 中有一个有用的小提琴进行测试。特别是因为当您以编程方式设置内容时,您会得到不同的结果,因为您将它们输入到输入中。不确定是谁创建的,但它在这里jsfiddle.net/8pucueqr

标签: javascript html validation


【解决方案1】:

注意:由于编写了此答案,因此 #1 中提到的 Chrome 错误已得到修复,因此现在仅适用于 #2。

这里其实有两个答案:

  1. Chrome 中存在一个错误,这意味着当您在输入字段中输入/设置类似 0. 的值时,它不会被正确验证。
  2. 如果您在 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(...),它基本上忽略了尾随 .,因此输入不会被视为“坏”。

根据the spec

一个字符串是一个有效的浮点数,如果它包含:

  1. (可选)U+002D 连字符减号 (-)。
  2. 以下一项或两项,按给定顺序:
  3. 一系列一个或多个 ASCII 数字。
    1. 单个 U+002E 句号 (.)。
    2. 一系列一个或多个 ASCII 数字。

请注意,2.2.2 不是可选的 - 即,如果您有 .,则后面必须有数字。

所以badInput 是不正确的。 (如果 Chrome 至少一致地将 0. 视为有效,那么 rangeUnderflow 就会被检测到)

2。标记与用户输入

**但是**如果/当他们修复 Chrome 中的错误时,使用问题中的 HTML,它将 *仍然* 显示为有效。为什么?

例如,如果您在 HTML 中设置了value="aaa"。即使aaa 会导致badInput 变为true,输入仍将显示为有效。

这是因为在解析/渲染页面时,Chrome 会对属性值运行 值清理算法。当它看到一个不是valid floating point number 的值时,它必须按照the spec 的要求将输入的值设置为空字符串。除非输入标记为required,否则空字符串被认为是有效的。这目前在 Chrome for value="0." 中不会发生,因为它(错误地)通过了值清理算法。但是,如果/当他们修复 Chrome 中的错误时,这就是您所期望的。

如果您实际在输入中键入aaa,它将显示为无效,即badInput===true。同样,在 Firefox 和 Chrome 中,如果/当他们修复错误时,如果您在字段中输入 0.,它将给出 badInput===true,因此会给出 valid===false

【讨论】:

    【解决方案2】:

    the spec 中写道:

    用户代理不得允许用户将值设置为非空 不是有效浮点数的字符串。如果用户代理 提供选择数字的用户界面,则该值必须 设置为代表数字的最佳表示 用户选择的浮点数。

    规范接着说:

    值净化算法如下:如果 元素不是有效的浮点数,然后将其设置为空 而是字符串。

    在 Firefox 中,DOM 中的 value 被设置为第一个输入的空字符串。这是一个有效的状态)。如果你想让第一个字段在这种情况下无效,you must make it required

    <input type="number" min="1" max="999" step="1" value="0." id="one" required />
    

    规范还说:

    约束验证:虽然用户界面描述了用户代理无法转换为有效浮点数的输入, 控件输入错误。

    我认为在这种情况下,只要#one 输入不显示0. 值,Firefox (32.0) 所做的就是正确的。在 Firefox 中,如果我在 #one 输入中手动键入值 0.,那么它会正确突出显示为无效。

    然而,在 Chrome 38.0.2125.58 beta-m 中,0. 值会在页面加载时显示,即使 document.querySelector("#one").value 的计算结果为空字符串。这意味着它无法被required 以及约束验证捕获。我相信这是 Chrome 中的一个错误。

    【讨论】:

    • 我也阅读了关于什么是有效浮点数的规范。 0. 似乎应该解析为 0,因此会导致在有效性对象上设置下溢标志。对我来说似乎也是一个错误。
    • 其实@robertc 最后一段是不正确的。在 Chrome 中,document.querySelector("#one").value 返回"0." - 请参阅jsfiddle.net/qa9orh37。我在 Chromium 源中挖掘并发现了问题,这是 rangeUnderflowbadInput 中的解析不一致 - 请参阅我的答案
    • @CupawnTae 在我工作的 Windows PC 上,我得到了空字符串,在家里的 Linux 笔记本电脑上,我看到“0”。像你所做地。明天我会再次检查工作电脑以检查我没有想到任何东西:)
    • 奇怪 - 我在 Windows 7 上得到了 "0.",在 Chrome 37.x 和 38.x-beta 上。我的钱花在了宇宙射线上 ;) 无论如何,即使我得到了 "0." 回来(以及 0 得到 valueAsNumber),它仍然给出了 rangeUnderflow===false,这证实了我从 Chrome 源代码中得出的结论。
    • @CupawnTae 好的,我在 Windows 7 上也收到了 0.。我一定是对昨天尝试的其中一种变体感到困惑。
    【解决方案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 我认为验证被绕过了。

    【讨论】:

    • Chrome 正确地将"0." 的数值报告为0。此外,可能也会产生NaN 值的其他非数字值(例如"aaa")会正确失败,而"0. 会错误地通过。也许valueAsNumber 是故事的一部分,但它似乎并不能解释整个事情。
    • @apsillers 实际上,如果您将第二个示例中的 "0." 替换为 "aaa" 它在 Chrome 中显示为有效 - 似乎是在代码中设置值和用户将其输入输入
    • 另外,也许相关的是,如果您在 DOM 的输入中以编程方式将其设置为 "aaa",它会显示为空白,而 "0." 会显示在屏幕上。大概是因为虽然"0." 至少正在成为一个有效数字,但"aaa" 不是。
    【解决方案4】:

    在输入类型编号中,包含的floating-point number

    floating-point number 由以下部分组成,完全按照以下顺序:

    1. (可选)第一个字符可以是“-”字符。
    2. “0—9”范围内的一个或多个字符。
    3. (可选)以下部分,完全按照以下顺序:
      1. 一个“。”人物
      2. “0—9”范围内的一个或多个字符
    4. (可选)以下部分,完全按照以下顺序:
      1. “e”字符或“E”字符
      2. (可选)“-”字符或“+”字符
      3. “0—9”范围内的一个或多个字符。

    你可能知道浮点数0. == 0.0 == 0。和其他的 0、0.0 验证一样好,所以0. 也是很好的验证。

    【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-21
    • 2018-06-27
    • 2021-07-24
    • 2023-03-07
    • 2018-01-17
    相关资源
    最近更新 更多