使用jQuery在Safari和Chrome中无法在焦点上选择文本

85

我有以下类似于这个问题的jQuery代码,可以在Firefox和IE中运行,但在Chrome和Safari中无法正常工作(没有错误,只是不起作用)。 有什么解决方法吗?

$("#souper_fancy").focus(function() { $(this).select() });

我想要在iPad/iPhone的Safari浏览器中实现精确的行为。但是在iPod/iPhone浏览器中无法正常工作。有什么线索吗?下面接受的答案仅适用于基于桌面的Chrome/Safari浏览器。 - Anand
5
注意:这里的被接受的答案只解决了问题的一半。它让选取操作起作用,但会使得后续点击难以取消选择。一个更好的解决方案可以在这里找到:https://dev59.com/VnA75IYBdhLWcg3wSm64 - SDC
9个回答

188

是onmouseup事件导致选择被取消,所以您只需要添加:

$("#souper_fancy").mouseup(function(e){
    e.preventDefault();
});

3
更多关于该漏洞的参考资料在这里:http://code.google.com/p/chromium/issues/detail?id=4505 - Rajat
你也可以尝试绑定到“click”事件,避免进行两次绑定。 - gxc
2
我想要在iPad/iPhone的Safari浏览器中实现精确的行为。但是在iPod/iPhone浏览器中无法正常工作。有什么线索吗? - Anand
你觉得这是因为某个事件触发了,导致选择的内容被取消了吗(在iPad/iPhone/Android上)? 我的应用是基于PhoneGap开发的,而且这个.select()方法也不起作用。 - r4ccoon
按照uglymunky的建议去做 - 绑定到点击事件:https://dev59.com/h3A75IYBdhLWcg3ws7Yh#3150370 - jrjensen
显示剩余3条评论

25
$('#randomfield').focus(function(event) {
    setTimeout(function() {$('#randomfield').select();}, 0);
});

3
如果您正在尝试选择 PhoneGap 应用程序在 Android 上运行时表单字段中的文本,这是最佳答案。这样可以向用户提供视觉指示,以表示文本已被选中,而其他答案则没有此功能。 - BallisticPugh

4

对于输入类型为"text"的元素,这个方法可以很好地工作。那么#souper_fancy是什么类型的元素?

$("#souper_fancy").focus(function() {
    $(this).select();
});

这是一个 type="text" 的元素。我也尝试了 $("input[type=text]"),但在 Safari 中使用 jQuery 1.3.2 仍然无法正常工作。 - user140550

3

仅仅在鼠标抬起时阻止默认行为会导致文本选择一直处于开启状态。MOUSEUP事件负责清除文本选择。然而,通过阻止其默认行为,您无法使用鼠标取消选择文本。

为了避免这种情况并使文本选择再次正常工作,您可以在FOCUS时设置一个标志,在MOUSEUP中读取它并重置它,以便未来的MOUSEUP事件将按预期工作。

$("#souper_fancy").focus(function() {
    $(this).select();

    //set flag for preventing MOUSEUP event....
    $this.data("preventMouseUp", true);
});

$("#souper_fancy").mouseup(function(e) {
    var preventEvent = $this.data("preventMouseUp");

    //only prevent default if the flag is TRUE
    if (preventEvent) {
        e.preventDefault();
    }

    //reset flag so MOUSEUP event deselect the text
    $this.data("preventMouseUp", false);
});

2

requestAnimationFrame()的回调函数中使用setSelectionRange()

$(document).on('focus', '._selectTextOnFocus', (e) => {
    var input = e.currentTarget;
    var initialType = e.currentTarget.type;

    requestAnimationFrame(() => {
        // input.select() is not supported on iOS
        // If setSelectionRange is use on a number input in Chrome it throws an exception,
        // so here we switch to type text first.
        input.type = "text";
        input.setSelectionRange(0, Number.MAX_SAFE_INTEGER || 9999);
        input.type = initialType;
    });
});

在移动Safari中,使用setSelectionRange()而不是select(),因为select()无法工作(请参见在iOS设备上(移动Safari)在输入字段中以编程方式选择文本)。

在选择文本之前,必须使用requestAnimationFrame等待一段时间,否则在iOS上键盘弹出后,元素将无法正确滚动到视图中。

使用setSelectionRange()时,重要的是要将输入类型设置为text,否则在Chrome上可能会抛出异常(请参见在Chrome中不再允许对input type="number"使用selectionStart / selectionEnd)。


1
由于使用setTimeout时会出现闪烁,因此有另一种基于事件的解决方案。这种方式通过“focus”事件附加“mouseup”事件,并且事件处理程序再次将其自身分离。
    function selectAllOnFocus(e) {
    if (e.type == "mouseup") { // Prevent default and detach the handler
        console.debug("Mouse is up. Preventing default.");
        e.preventDefault();
        $(e.target).off('mouseup', selectAllOnFocus);
        return;
    }
    $(e.target).select();
    console.debug("Selecting all text");
    $(e.target).on('mouseup', selectAllOnFocus);
}

然后连接第一个事件。
    $('.varquantity').on('focus', selectAllOnFocus);

1

这也应该在Chrome中有效:

$("#souper_fancy").focus(function() {
    var tempSouper = $(this);
    setTimeout(function(){
        tempSouper.select();
    },100);
});

请考虑添加建设性反馈,解释为什么原帖作者遇到了问题,以及你的解决方案如何解决它。 - Mirko Adari

1

虽然这在IE、Firefox、Chrome、Safari和Opera中选择它是有效的,但在Firefox、Chrome和Safari中第二次点击时无法编辑。我不太确定,但我认为这可能是由于这三个浏览器即使该字段已经获得焦点,仍会重新发出焦点事件,从而永远不允许您实际插入光标(因为您再次选择它),而在IE和Opera中似乎没有这样做,因此焦点事件没有再次触发,因此光标被插入。

我在这篇Stack文章中找到了一个更好的解决方法,它没有这个问题,并且在所有浏览器中都有效。


0
如果有人再次遇到这个问题,我提供了一个纯JS解决方案,目前在所有浏览器(包括移动端)上都可以正常工作。
<input type="text" value="Hello world..." onFocus="window.setTimeout(() => this.select());">

(如果没有setTimeout(),它在Safari,移动版Safari和MS Edge上无法正常工作)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接