在Chrome中不再允许输入类型为“ number”的selectionStart / selectionEnd结束


81

我们的应用程序使用selectionStart输入字段,以确定是否自动移动用户到下一个/前场,当他们按箭头键(即,当选择是在文本的结束和用户按下右箭头我们进入下一个字段,否则)

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

有什么方法可以确定插入符在类型=“ number”的输入字段中的位置吗?


3
嗯没有更新。好奇为什么要删除此功能。
苹果

1
另一个用途:如果您将jquery-maskmoney插件与输入类型编号一起使用,则会发生相同的问题
Alexandre

您是否可以暂时将输入类型更改为text,检查插入符号的位置,然后再将类型更改回为number
Stan

1
@Stan我认为交换类型不是很可行,尽管我还没有尝试过。
史蒂文

2
@Steven,它不起作用,selectionStart / End始终返回零:jsfiddle.net/Mottie/wMYKU
Mottie 2014年

Answers:


42

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


6
我了解到某些设备可能不会显示插入符号,但似乎使事情复杂化了。如果我们最终将type =“ text”用于所有内容,那么它甚至达不到具有类型的目的。它也失去了对手机显示数值输入不同的键盘等等。我对自己的选择不同意删除输入选择的能力,但我不知道解决的办法是什么?
史蒂芬

48
这真糟。我已经联系了WHAT-WG,因为我认为这是一个重大错误。99.9%的用户代理将一个<input type="number"/>字段呈现为文本字段,该字段将默认的屏幕键盘(如果有)设置为数字键盘,但仍将该字段呈现为“文本输入”字段。现在,任何为字段添加计算器或类似的值操纵功能的现有/将来尝试都将变得无用,除非我们强迫字段返回文本并破坏用户体验。
scunliffe 2014年

3
我同意你们俩 正如我在这篇文章中指出的那样,我认为IDL值属性应始终包含输入所包含内容的文本呈现。同样,如果用户代理允许选择,则selectionStart / End应该可用。
Patrice Chalin 2014年

6
Whaaaaat o_0 Chrome刚刚中断了互联网..和我的测试。更严重的是,我没有逻辑。用户为什么不能选择他们的电子邮件地址或号码?stackoverflow.com/questions/22171694/…–
彼得

21

我找到了一个简单的解决方法(已在Chrome上测试)setSelectionRange()。您可以在使用前简单地将更type改为,然后再将其更改回。textsetSelectionRange()number

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

矮人


这种方法也适用于email输入(这就是我最终想知道为什么setSelectionRange()在IE11(!)而不是Chrome中工作的方式)。
jdunning

这不需要jQuery,因为纯JavaScript obj.type =“ text”; 然后返回obj.type =“ number”;
雅各

但是plunkr不再允许用户使用鼠标进行选择。
李斯特先生,

对我来说(在Chrome版本80中),它不再起作用,因为如果我使用将输入类型设置为“文本” input.type = 'text',Chrome将从输入中移开焦点,并且光标消失,input.selectionStart等返回null。
阿南达·马斯里

16

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

<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

1
@PetarMI嗨,通过约束我的意思是一个<input>元素只能接受数字字符,它是通过JavaScript完成的,这是因为不是所有的浏览器与HTML5的新的<input>标签的正常工作。
jherax


5

解决方法是,type="tel"输入类型提供与type="number"Chrome中非常相似的功能,并且没有此限制(如Patrice所指出)。


首先,这在android上提供了电话专用的小键盘,而数字在数字上给出了不同的小键盘
patrick

5

您可以通过一种方法在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


3

我们不能仅仅将元素检查反转为仅包含受支持的元素,如下所示:

if (deviceIsIOS &&
    targetElement.setSelectionRange &&
    (
        targetElement.type === 'text' ||
        targetElement.type === 'search' ||
        targetElement.type === 'password' ||
        targetElement.type === 'url' ||
        targetElement.type === 'tel'
    )
) {

代替这个:

if (deviceIsIOS && 
    targetElement.setSelectionRange && 
    targetElement.type.indexOf('date') !== 0 && 
    targetElement.type !== 'time' && 
    targetElement.type !== 'month'
) {

1

尽管对于这种类型的表单字段而言,不赞成使用的事件的问题可能仍然很重要,但据我所知,可以像往常一样通过“ change”事件来监听此类字段。

在为此类字段寻找事件问题的答案时,我在这里读了这篇文章,但是在测试它时,我发现我可以简单地依靠所提到的“更改”事件。


1

我在angularjs网站上收到此错误。

我在输入上创建了一个自定义数据属性,并且还在使用ng-blur(带有$ event)。

当我的回调被调用时,我试图访问“ data-id”值,例如:

var id = $event.target.attributes["data-id"]

它应该是这样的:

var id = $event.target.attributes["data-id"].value

这个错误似乎在任何地方都没有太多,因此我将其留在这里。



0

解决Failed to read the 'selectionStart' property from 'HTMLInputElement': The input element's type ('number') does not support selection.方法如下:

var checkFocus = false;
var originalValue = "";
$(document).ready(function() {
  $("input").focus(function() {
    var that = this;
    if ($('#' + $(this).context.id).attr("type") == "text") {
      setTimeout(function() {
        if (that.selectionStart != null || that.selectionEnd != null) {
          that.selectionStart = that.selectionEnd = 10000;
        }
      }, 0);
    } else if ($('#' + $(this).context.id).attr("type") == "number") {
      if (checkFocus) {
        moveCursorToEnd($('#' + $(this).context.id), $(this).context.id);
        checkValue($('#' + $(this).context.id))
        checkFocus = false;
      } else {
        $('#' + $(this).context.id).blur();
      }
    }
  });
});

function FocusTextBox(id) {
  checkFocus = true;
  document.getElementById(id).focus();
}

function checkValue(input) {
  if ($(input).val() == originalValue || $(input).val() == "") {
    $(input).val(originalValue)
  }
}

function moveCursorToEnd(input, id) {
  originalValue = input.val();
  input.val('');
  document.getElementById(id).focus();
  return originalValue;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<button onclick="FocusTextBox('textid')">
   <input id="textid" type="number" value="1234" > 
</button>


0

如果使用Chrome的设备测试模式,请在Angular中警惕此错误。

因此,这显然是Chrome,而不是实际的iPhone-但仍然会引发错误,因为_platform.IOS返回true,然后setSelectionRange失败。

这是Angular,但其他框架/环境中可能存在类似问题。

在此处输入图片说明

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.