HTML 数字输入异常的自定义验证

Custom Validation on HTML Number Input Misbehaving

在构建一个小型 Web 应用程序时,我试图确保最终用户无法将无效字符放置在可以容纳带符号浮点数的数字字段中。我正在使用 Dojo 搜索已应用的 CSS class(在本例中为 ogInputNumber)并在输入、键盘输入和模糊上设置事件。

理想情况下,我希望输入为 type="number" 并且只允许数字、连字符(用于带符号的浮点数)和句点字符作为小数位。如果用户包含多个连字符或句点字符,则 JS 应截断输入中的第二个无效字符及其后的所有字符。不幸的是,JS 的行为取决于输入是 type="number" 还是 type="text".

对于 type="text",如果我尝试输入文本 2.6a2.6 没问题,但 a 会在输入事件中被捕获并阻止出现在输入中。这是所需的行为,但我希望输入为 type="number",这样数字微调器就会出现,并且便于在移动设备上使用(因此默认情况下会显示数字键盘)。

对于type="number",如果我尝试输入文本2.6a,允许保留2.6,但是一旦输入a,整个字段被清除。这将防止任何无效字符,但令人讨厌的过度热心。我已经在 Chrome、Firefox、IE11 和 Opera 上复制了这种行为。

任何人都可以就为什么 JS 在 type="text"type="number" 输入之间的运行方式不同提出任何建议吗?

HTML:

<p>
    <label for="numberInput1">Text Input</label>
    <input id="numberInput1" class="ogInputNumber" type="text" />
</p>
<p>
    <label for="numberInput2">Number Input</label>
    <input id="numberInput2" class="ogInputNumber" type="number" />
</p>

JS:

// Checks number input fields for proper formatting
require(["dojo/domReady!", "dojo/on", "dojo/query"],

function (ready, on, query) {
    query(".ogInputNumber").forEach(function (node) {
        // Replace all the non-numeric, non-period, and non-hyphen characters with nothing while the user is typing
        on(node, "input, keyup", function () {
            this.value = this.value.replace(/[^\d\.-]/g, '');
        });
        // When the user leaves the input, format it properly as a signed float (or zero if it's something weird)
        on(node, "blur", function () {
            try {
                if (this.value) {
                    this.value = parseFloat(this.value).toString();
                } else {}
            } catch (error) {
                this.value = 0;
            }
        });
    });
});

工作 JSFiddle:http://jsfiddle.net/etehy6o6/1/

我认为这是数字输入类型的默认行为,但我不确定。认为输入不应该让用户输入任何非数字的东西是合乎逻辑的,因此它会在您触发 keyup 事件之前清除所有值。

因此,为了保留最后一个有效值,请在您的事件范围之外声明一个变量,并将其设置为因无效键输入而未被清除的替换值。

使用您 Fiddle 中的代码:

已编辑,因为解决了评论中的错误

HTML

<!-- I asigned default values to test other scenarios -->
<p>
    <label for="numberInput1">Text Input</label>
    <input id="numberInput2" class="ogInputNumber" type="text" value="3.1416" />
</p>
<p>
    <label for="numberInput">Number Input</label>
    <input id="numberInput" class="ogInputNumber" type="number" value="3.1416" />
</p>

Javascript

// Checks number input fields for proper formatting
require(["dojo/domReady!", "dojo/on", "dojo/query"],

function (ready, on, query) {
    query(".ogInputNumber").forEach(function (node) {
        var validValue = this.value;
        // Replace all the non-numeric, non-period, and non-hyphen characters with nothing while the user is typing
        on(node, "input, keyup", function () {
            if (this.value == '' && validValue.length > 1) {
                this.value = validValue;
            }
            this.value = this.value.replace(/[^\d\.-]/g, '');
            validValue = this.value;
        });
        // When the user leaves the input, format it properly as a signed float (or zero if it's something weird)
        on(node, "blur", function () {
            try {
                if (this.value) {
                    this.value = parseFloat(this.value).toString();
                } else {}
            } catch (error) {
                this.value = 0;
            }
        });
    });
});