为 Chrome 选择焦点错误寻找更好的解决方法
Posted
技术标签:
【中文标题】为 Chrome 选择焦点错误寻找更好的解决方法【英文标题】:Looking for a better workaround to Chrome select on focus bug 【发布时间】:2011-03-23 18:25:44 【问题描述】:我和this question中的用户有同样的问题,这是由于Webkit中的this bug造成的。但是,提供的解决方法不适用于我的应用程序。让我重新陈述这个问题,这样你就不必去阅读另一个问题了:
当它获得焦点时,我试图选择文本区域中的所有文本。以下 jQuery 代码适用于 IE/FF/Opera:
$('#out').focus(function()
$('#out').select();
);
但是,在 Chrome/Safari 中,文本被选中 - 非常短暂 - 但随后触发 mouseUp 事件并取消选中文本。上述链接中提供了以下解决方法:
$('#out').mouseup(function(e)
e.preventDefault();
);
但是,这种解决方法对我没有好处。当用户给 textarea 焦点时,我想选择所有文本 only。如果他选择,他必须然后能够只选择部分文本。谁能想到仍然满足此要求的解决方法?
【问题讨论】:
在最常见的问题解决方案中发现明显的明显缺陷的大 +1。 【参考方案1】:这个怎么样?
$('#out').focus(function ()
$('#out').select().mouseup(function (e)
e.preventDefault();
$(this).unbind("mouseup");
);
);
【讨论】:
可能.one()
是一个更好的方法。
+1。我不明白为什么这么多人认为基本的preventDefault()
修复就足够了。它显然有严重的缺陷,但它被建议作为你所看到的任何地方的解决方案。谢谢你解决它。 (虽然是的,我同意@InviS 的观点,.one()
可能是更好的做法)
.one() 会更好,但这不能很好地处理选项卡式焦点。
这里是如何使用 jQuery 的 .one()
来做到这一点,正如 @InviS 所建议的那样:$('#out').focus(function () $('#out').select().one('mouseup', function (e) e.preventDefault(); ); );
【参考方案2】:
接受的答案(以及到目前为止我发现的所有其他解决方案)不适用于键盘焦点,即。 e.按标签,至少在我的 Chromium 21 中没有。我使用以下 sn-p 代替:
$('#out').focus(function ()
$(this).select().one('mouseup', function (e)
$(this).off('keyup');
e.preventDefault();
).one('keyup', function ()
$(this).select().off('mouseup');
);
);
keyup
或 focus
处理程序中的e.preventDefault()
无济于事,因此键盘焦点后的取消选择似乎不会发生在它们的默认处理程序中,而是发生在 focus
和 keyup
事件之间。
正如@BarelyFitz 所建议的,使用命名空间事件可能会更好,以免意外解除绑定其他事件处理程序。将'keyup'
替换为'keyup.selectText'
,将'mouseup'
替换为'mouseup.selectText'
。
【讨论】:
当您取消绑定事件时,您可能会无意中取消绑定可能在输入上的其他处理程序。为了防止这种情况,您可以使用命名空间,例如“mouseup.selectText”而不是“mouseup”,那么只会删除您的单个事件处理程序。 结合命名空间提示,这是我为这个粘性检票口找到的最佳解决方案,我将它推荐给房子。【参考方案3】:为什么不简单:
$('#out').focus(function()
$(this).one('mouseup', function()
$(this).select();
);
);
似乎适用于所有主要浏览器...
【讨论】:
这对我有用。值得注意的是,当您通过代码专注于输入时,它似乎不起作用。为了解决这个问题,我使用$('#element').select().focus()
而不是$('#element').focus()
。【参考方案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/
【讨论】:
【参考方案5】:创建一个bool
。在焦点事件后将其设置为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; );
将重置变量的 mouseup 侦听器放在 document
上很重要,因为不能保证用户会在文本字段上释放鼠标按钮。
【讨论】:
谢谢!这激发了一个更简单的想法:而不是 document.mouseup 上的侦听器,只需在 out.mouseup 上将标志设置为 false:if(textFieldGotFocus) e.preventDefault(); textFieldGotFocus = false;
天哪。全局变量 + 事件处理 == 解决问题的方法。【参考方案6】:
onclick="var self = this;setTimeout(function() self.select();, 0);"
【讨论】:
这个答案启发了:$("#one").on('focus', null, function() var $that = $(this); setTimeout(function() $that.select(); , 0); );
【参考方案7】:
在将焦点放在输入框之前选择文本。
$('#out').select().focus();
【讨论】:
【参考方案8】:digitalfresh 的解决方案大部分都在那里,但有一个错误,即如果您使用 JS 手动触发 .focus()(因此不使用单击),或者如果您选择该字段,那么您会收到一个不需要的 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 上,因为我们要考虑用户在输入中的 mousedown-ing,将鼠标移出输入,然后 mouseup-ing。
【讨论】:
【参考方案9】: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();
);
【讨论】:
以上是关于为 Chrome 选择焦点错误寻找更好的解决方法的主要内容,如果未能解决你的问题,请参考以下文章