寻找更好的解决方案来应对Chrome在聚焦时选择的bug

37

我有和这个问题中用户一样的问题,这是由于Webkit中这个bug引起的。然而,提供的解决方法对我的应用程序不起作用。为了让你不必再去读另一个问题,让我重新陈述一下问题:

当文本区域获取焦点时,我想选择其中的所有文本。下面的jQuery代码在IE/FF/Opera中有效:

$('#out').focus(function(){
  $('#out').select();
});

然而,在Chrome/Safari浏览器中,文本会被选择--非常短暂地--但随后mouseUp事件会被触发,导致文本被取消选择。以上链接提供了以下解决方法:

$('#out').mouseup(function(e){
  e.preventDefault();
});

然而,这个解决方法对我来说不好用。我想要当用户聚焦于文本区域时仅选择所有文本而不是一部分。如果用户选择,他必须能够选择文本的一部分。有没有人想到一个仍然满足此要求的解决方法?


5
发现最常被提出的解决问题的方法中明显的缺陷,十分明智。+1 - SDC
9个回答

29
这个怎么样?
$('#out').focus(function () {
    $('#out').select().mouseup(function (e) {
        e.preventDefault();
        $(this).unbind("mouseup");
    });
});

9
可能在这里使用.one()更好。 - ValeriiVasin
+1. 我不明白为什么有那么多人认为基本的 preventDefault() 修复就足够了。它显然存在严重缺陷,但却被建议作为解决方案出现在你所看到的每个地方。感谢您解决了这个问题。(尽管我同意 @InviS 的观点,使用 .one() 可能是更好的方法) - SDC
1
使用 .one() 更好,而这种方式无法很好地处理选项卡聚焦。 - Jimmy Bosse
1
以下是使用jQuery的.one()完成此操作的方法,就像@InviS所建议的那样: $('#out').select().one('mouseup', function(e) { e.preventDefault(); }); });``` - evanrmurphy

25

目前为止,被接受的答案(以及我发现的其他解决方案)在键盘焦点下并不起作用,也就是说按tab键时至少在我的Chromium 21中无法使用。我反而使用以下代码片段:

$('#out').focus(function () {
  $(this).select().one('mouseup', function (e) {
    $(this).off('keyup');
    e.preventDefault();
  }).one('keyup', function () {
    $(this).select().off('mouseup');
  });
});

e.preventDefault()keyupfocus处理程序中并没有帮助,因此在默认处理程序中似乎无法发生键盘焦点后取消选择,而是在focuskeyup事件之间的某个位置。

如@BarelyFitz所建议的那样,最好使用命名空间事件,以避免意外解除其他事件处理程序的绑定。将'keyup'替换为'keyup.selectText',将'mouseup'替换为'mouseup.selectText'


4
当你解绑事件时,可能会无意中解绑其他在输入框上的处理程序。为了防止这种情况,你可以使用名称空间,例如 "mouseup.selectText" 而不是 "mouseup",这样只有你单一的事件处理程序会被移除。 - BarelyFitz
结合命名空间提示,这是我找到的解决这个棘手问题的最佳方案,我向大家推荐。 - dartacus

4

一种稍微不同的方法是将焦点事件与鼠标序列分开。这对我来说非常好用——没有状态变量,没有泄漏处理程序,没有意外删除处理程序,可以使用点击、选项卡或编程焦点。下面是代码和jsFiddle——

$('#out').focus(function() {
    $(this).select();
});
$('#out').on('mousedown.selectOnFocus', function() {
    if (!($(this).is(':focus'))) {
        $(this).focus();
        $(this).one('mouseup.selectOnFocus', function(up) {
            up.preventDefault();
        });
    }
});

https://jsfiddle.net/tpankake/eob9eb26/27/


4
为什么不直接这样做:
$('#out').focus(function(){
    $(this).one('mouseup', function() {
        $(this).select();
    });
});

看起来在所有主流浏览器中都可以正常工作...


4
这对我有用。值得注意的是,当你通过代码聚焦输入时,似乎它不起作用。为了解决这个问题,我使用$('#element').select().focus()而不是$('#element').focus() - Amy Barrett

2
onclick="var self = this;setTimeout(function() {self.select();}, 0);"

这个答案很有启发性:$("#one").on('focus', null, function() { var $that = $(this); setTimeout(function() { $that.select(); }, 0); }); - Jimmy Bosse

2
创建一个布尔变量。在焦点事件后将其设置为true,在鼠标弹起事件后将其重置。在鼠标弹起期间,如果它是true,则知道用户刚刚选择了文本字段;因此,您必须防止鼠标弹起事件发生。否则,您必须让它通过。
var textFieldGotFocus = false;

$('#out').focus(function()
{
    $('#out').select();
    textFieldGotFocus = true;
});

$('#out').mouseup(function(e)
{
    if (textFieldGotFocus)
        e.preventDefault();
});

$(document).mouseup(function() { textFieldGotFocus = false; });

很重要的一点是,你需要在document上放置一个mouseup监听器来重置变量,因为不能保证用户会在文本字段上释放鼠标按钮。


谢谢!这启发了我一个更简单的想法:不需要在document.mouseup上添加监听器,只需在out.mouseup上将标志设置为false: if(textFieldGotFocus){ e.preventDefault(); textFieldGotFocus = false;} - Jenni
不要啊,全局变量加上事件处理会导致麻烦。 - SDC

2

在将焦点放在输入框上之前,先选择文本。

$('#out').select().focus();

0

digitalfresh的解决方案基本上已经到位了,但是存在一个bug,即如果您使用JS手动触发.focus()(而不是使用点击),或者如果您通过Tab键到达该字段,则会绑定一个不需要的mouseup事件-这会导致应该取消选择文本的第一次单击被忽略。

解决方法:

var out = $('#out');
var mouseCurrentlyDown = false;

out.focus(function () {
  out.select();

  if (mouseCurrentlyDown) {
    out.one('mouseup', function (e) {
      e.preventDefault();
    });  
  }
}).mousedown(function() {
  mouseCurrentlyDown = true;
});

$('body').mouseup(function() {
  mouseCurrentlyDown = false;
});

注意:mouseup事件应该在body上而不是input上,因为我们想考虑用户在输入框内按下鼠标、移出输入框并松开鼠标的情况。

0

将tpankake的答案转换为可重用的jQuery函数..
(如果您点赞此回答,请同时点赞他的回答)

在加载jQuery库之后加载以下内容:

$.fn.focusSelect = function () {
    return this.each(function () {
        var me = $(this);
        me.focus(function () {
            $(this).select();
        });
        me.on('mousedown.selectOnFocus', function () {
            var me2 = $(this);
            if (me2.is(':focus') === false) {
                me2.focus();
                me2.one('mouseup.selectOnFocus', function (up) {
                    up.preventDefault();
                });
            }
        });
    });
};

使用方法如下:

$(document).ready(function () {
    // apply to all inputs on the page:
    $('input[type=text]').focusSelect();

    // apply only to one input
    $('#out').focusSelect();
});

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