IE点击子节点不焦点父节点,父节点有tabindex = 0
编辑:请参阅下面的我自己的答案: https : //stackoverflow.com/a/25953721/674863
演示: http : //jsfiddle.net/fergal_doyle/anXM3/1/
我有一个tabindex = 0的div和一个固定宽度的子div。 当我点击子div时,我希望外部div能够获得焦点。 这适用于Firefox和Chrome,并且仅当子div没有应用宽度时才适用于Internet Explorer(7到10)。
使用宽度时,单击子(白色)div不会将焦点放在外部div上,如果外部的焦点与之前有焦点,则单击该子项会导致外部模糊,这对我想要做的事情来说很痛苦。
HTML:
Click
CSS:
div { border:1px solid #000; padding:20px; background-color:red; } div div { padding:8px; background-color:#FFF; cursor:default; width:200px; }
JS:
var $div = $("#test"), $inner = $("#test > div"); $div.on("blur", function (e) { console.log("blur"); }) .on("focus", function (e) { console.log("focus") });
拦截事件并使用JS设置焦点最终导致更多问题。
我最终发现使用像div或spans这样的“普通”标签会使IE表现不正常。 但是使用类似var
或任何自定义标记的东西,IE开始表现得像一个合适的浏览器。
查看更新的示例: http : //jsfiddle.net/fergal_doyle/anXM3/16/
HTML:
Works Works Doesn't work in IE Doesn't work in IE
CSS:
div { border:1px solid #000; padding:20px; background-color:red; } .iesux { border:1px solid #000; display:block; padding:8px; background-color:#FFF; cursor:default; width:200px; }
JS:
document.createElement("foo"); var $div = $("#test"); $div.on("blur", function (e) { console.log("blur"); }) .on("focus", function (e) { console.log("focus") });
你试过添加:
$inner.click(function() { $div.focus(); });
并且在焦点使用后防止外部div模糊e.stopPropagation()
更新:由于click
事件在blur
后触发我使用了Mousedown
事件,因为它在blur
之前触发。
PS:如果你想捕捉键盘发出的模糊,别忘了处理keydown
键盘事件。
在IE中单击tabindex = 0的元素将导致元素获得不可见焦点。 获得可见焦点的方法是以编程方式调用focus(),而元素尚未具有不可见焦点。 由于焦点发生在mousedown之后,这意味着我们需要:
$('#parent').mousedown(function(e){ var parent = $(e.currentTarget) if (!parent.is(':focus')) { parent.focus() } }).focus(function(e){ console.log('focused') }).blur(function(e){ console.log('blurred') })
如果子项是内联的或没有设置宽度的块,则效果与直接单击父项时的效果相同。 但是,如果子项是内联块或具有宽度设置的块,并且父项已经具有焦点,则父项将在执行mousedown处理程序后立即模糊()。 我们有三种不同的方式可以进行,具有不同的权衡。
一种选择是仅使用preventDefault()来抑制模糊; 这种方法的优点是blur()永远不会触发,而focus()不会冗余地激发,这使我们能够在焦点和模糊处理程序中编写直接的逻辑; 这种方法的缺点是它禁用了文本选择:
$('#child').mousedown(function(e){ e.preventDefault() }) $('#parent').mousedown(function(e){ var parent = $(e.currentTarget) if (!parent.is(':focus')) { parent.focus() } }).focus(function(e){ console.log('focused') }).blur(function(e){ console.log('blurred') })
如果我们不想禁用文本选择,另一个选项是关注子项的mouseup处理程序中的父项; 然而,这样父母会模糊,然后再次聚焦,这阻止我们知道焦点或模糊何时“真实”而不仅仅是我们的焦点传播逻辑的瞬态结果:
$('#child').mouseup(function(e){ $(e.currentTarget).closest('[tabindex]').focus() }) $('#parent').mousedown(function(e){ var parent = $(e.currentTarget) if (!parent.is(':focus')) { parent.focus() } }).focus(function(e){ console.log('focused') }).blur(function(e){ console.log('blurred') })
第三种选择具有上述两种方法的优点,但在逻辑上是最复杂的:
$('#parent').mousedown(function(e){ var parent = $(e.currentTarget) var parentWasClicked = parent.is(e.target) var parentHasFocus = parent.is(':focus') if (parentWasClicked && !parentHasFocus) { parent.focus() } else if (parentHasFocus && !parentWasClicked) { window.ignoreFocusChanges = true } }) .mouseup(function(e){ var parent = $(e.currentTarget) if (!parent.is(':focus')) { parent.focus() } }) .blur(function(e){ if (window.ignoreFocusChanges) { return } console.log('blurred') }) .focus(function(e){ if (window.ignoreFocusChanges) { window.ignoreFocusChanges = false return } console.log('focused') })
让root
成为你的#test
div
function prevent_blur_in_subtree = function (event) { if (event.originalEvent && event.target != root.get(0) && $(event.target).closest(root).size() == 1) { $(window).one("mousedown", prevent_blur_in_subtree); event.stopPropagation(); event.preventDefault(); return false; } } root.bind("click", function () { if (!$(this).is(":focus")) { $(this).trigger("focus"); } }) .bind("focus", function () { $(window).one("mousedown", prevent_blur_in_subtree); });
您应该在root
中的任何单击中使用event.stopPropagation()
,这不应强制焦点事件。
这个问题是任何IE(5-11)中的大量问题之一。 你可以看到IE的源代码自1999年以来就没有被清理过。当人们谈论“IE 11是现代浏览器”或“IE 11关注标准”时,我笑了。
这个问题很老,但我刚遇到这个问题,以下解决方案在IE11中运行,并且比其他任何方法都简单得多:
.iesux { border:1px solid #000; display:block; padding:8px; background-color:#FFF; cursor:default; width:200px; pointer-events: none; }
不幸的是它在IE <11中不受支持,但是如果你可以侥幸逃脱它是迄今为止最简单的。