Chrome 中不再允许输入 type="number" 上的 selectionStart/selectionEnd

IT技术 javascript google-chrome
2021-01-17 03:14:12

Our application uses selectionStart on input fields to determine whether to automatically move the user to the next/previous field when they press the arrow keys (ie, when the selection is at the end of the text and the user presses the right arrow we move to下一个字段,否则)

Chrome 现在可以防止在 type="number" 的地方使用 selectionStart。它现在抛出异常:

Failed to read the 'selectionStart' property from 'HTMLInputElement': The input element's type ('number') does not support selection.

请参阅以下内容:

https://codereview.chromium.org/100433008/#ps60001

http://www.whatwg.org/specs/web-apps/current-work/multipage/the-input-element.html#do-not-apply

有没有办法确定 type="number" 输入字段中插入符号的位置?

6个回答

仅允许使用 text/search、URL、tel 和 password 进行选择对于类型编号的输入禁用选择的可能原因是在某些设备上或在某些情况下(例如,当输入显示为 short 时list),可能没有插入符号。我发现的唯一解决方案是将输入类型更改为文本(使用适当的模式来限制输入)。我仍在寻找一种无需更改输入类型的方法,并且会在找到某些内容时发布更新。

我知道有些设备可能不会显示插入符号,但它似乎使事情复杂化。如果我们最终对所有内容都使用 type="text",它甚至失去了拥有类型的目的。它也失去了手机为数字输入等显示不同键盘的能力。我不同意他们选择从输入中删除选择,但我不确定解决方案是什么......
2021-03-14 03:14:12
这真的很糟糕。我已就此与 WHAT-WG 联系,因为我认为这是一个重大错误。99.9% 的用户代理将<input type="number"/>字段呈现为文本字段,将默认屏幕键盘(如果可用)设置为数字键盘,但仍将字段呈现为“文本输入”字段。任何现有/未来为该字段添加计算器或类似值操作功能的尝试现在都变得毫无用处,除非我们强制该字段返回文本并破坏用户体验。
2021-03-16 03:14:12
我同意你们两个。正如我在这篇文章中指出的那样,我认为 value IDL 属性应该始终包含输入内容的文本呈现。此外,如果用户代理允许选择,则 selectionStart/End 应该可用。
2021-03-26 03:14:12
Whaaaaat o_0 Chrome 刚刚破坏了互联网......还有我的测试。更严重的是,我不明白其中的逻辑。为什么用户不能选择他们的电子邮件地址或号码?stackoverflow.com/questions/22171694/...
2021-03-29 03:14:12

我找到了一个简单的解决方法(在 Chrome 上测试过)用于setSelectionRange(). 你可以简单地改变typetext你使用之前setSelectionRange()再改回number

这是一个简单的 jquery 示例,每当您单击输入时,它都会将插入符号定位在数字输入中的位置 4(在输入中添加 5 个以上的数字以查看行为)

笨蛋

这种方法也适用于email输入(这就是我在这个页面上结束的方式,想知道为什么setSelectionRange()在 IE11 (!) 而不是 Chrome 中工作)。
2021-03-22 03:14:12
对我来说(在 Chrome 80 版中)这不再有效,因为如果我使用 将输入类型设置为“文本” input.type = 'text',Chrome 将从输入中移除焦点,并且光标消失,以便input.selectionStart等返回空值。
2021-03-23 03:14:12
但是 plunkr 不再允许用户使用鼠标进行选择。
2021-04-01 03:14:12
这在没有 jQuery 的情况下工作,因为纯 JavaScript obj.type = "text"; 然后返回 obj.type = "number";
2021-04-09 03:14:12

目前唯一允许安全选择文本的元素是:

<input type="text|search|password|tel|url">如:
whatwg: selectionStart 属性中所述

您还可以阅读HTMLInputElement 接口的文档以仔细查看输入元素。

为了安全地克服这个“问题”,目前最好的方法是处理<input type="text">并应用只接受数字的掩码/约束。有一些插件可以满足要求:

您可以在此处查看之前插件之一的现场演示:

如果你想安全使用selectionStart,那么你可以检查那些支持它的元素(参见输入类型属性

执行

// Fix: failed to read the 'selectionStart' property from 'HTMLInputElement'
// The @fn parameter provides a callback to execute additional code
var _fixSelection = (function() {
    var _SELECTABLE_TYPES = /text|password|search|tel|url/;
    return function fixSelection (dom, fn) {
        var validType = _SELECTABLE_TYPES.test(dom.type),
            selection = {
                start: validType ? dom.selectionStart : 0,
                end: validType ? dom.selectionEnd : 0
            };
        if (validType && fn instanceof Function) fn(dom);
        return selection;
    };
}());

// Gets the current position of the cursor in the @dom element
function getCaretPosition (dom) {
    var selection, sel;
    if ('selectionStart' in dom) {
        return _fixSelection(dom).start;
    } else { // IE below version 9
        selection = document.selection;
        if (selection) {
            sel = selection.createRange();
            sel.moveStart('character', -dom.value.length);
            return sel.text.length;
        }
    }
    return -1;
}

用法

// If the DOM element does not support `selectionStart`,
// the returned object sets its properties to -1.
var box = document.getElementById("price"),
    pos = getCaretPosition(box);
console.log("position: ", pos);

上面的例子可以在这里找到:jsu.fnGetCaretPosition()

嗨@PetarMI,约束是指 <input> 元素只能接受数字字符,它是通过 JavaScript 完成的,这是因为并非所有浏览器都可以使用新的 HTML5 <input> 标签正常工作。
2021-03-13 03:14:12
你好,谢谢你的帖子。你能解释一下“只接受数字的约束”是什么意思吗?
2021-03-24 03:14:12

有一种方法可以在 Chrome 上完成此操作(也许还有其他一些浏览器,但 Chrome 是这里的大罪人)。用于window.getSelection()从当前输入中检索选择对象,然后测试向后(或向前)扩展选择并查看toString()选择是否发生变化。如果不是,则光标位于输入的末尾,您可以移动到下一个输入。如果是,则必须反转操作以撤消选择。

s = window.getSelection();
len = s.toString().length;
s.modify('extend', 'backward', 'character');
if (len < s.toString().length) {
    // It's not at the beginning of the input, restore previous selection
    s.modify('extend', 'forward', 'character');
} else {
    // It's at the end, you can move to the previous input
}

我从这个 SO 答案中得到了这个想法:https : //stackoverflow.com/a/24247942

这完全是疯狂的,但它确实有效。为这个答案点赞!
2021-03-14 03:14:12

我们在使用 jQuery Numeric Plugin 版本 1.3.x 时发生了这种情况,因此将selectionStartselectionEnd用 a包装try...catch{}我们能够抑制错误。

来源:https : //github.com/joaquingatica/jQuery-Plugins/commit/a53f82044759d29ff30bac698b09e3202b456545