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键盘事件。

http://jsfiddle.net/ouadie/x4nAX/

在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中不受支持,但是如果你可以侥幸逃脱它是迄今为止最简单的。

http://jsfiddle.net/anXM3/22/