Javascript IE单击子对象不关注父对象,父对象具有tabindex=0
编辑: 下面是我自己的答案: 演示: 我有一个tabindex=0的div和一个固定宽度的子div。当我单击子div时,我希望外部div接收焦点。这适用于Firefox和Chrome,仅在子div没有应用宽度时适用于Internet Explorer(7到10) 对于宽度,单击child(white)div不会为外部div提供焦点,如果外部div以前有焦点,则单击child会导致外部模糊,这对我想做的事情来说是一种痛苦 HTML: JS:Javascript IE单击子对象不关注父对象,父对象具有tabindex=0,javascript,jquery,css,internet-explorer,Javascript,Jquery,Css,Internet Explorer,编辑: 下面是我自己的答案: 演示: 我有一个tabindex=0的div和一个固定宽度的子div。当我单击子div时,我希望外部div接收焦点。这适用于Firefox和Chrome,仅在子div没有应用宽度时适用于Internet Explorer(7到10) 对于宽度,单击child(white)div不会为外部div提供焦点,如果外部div以前有焦点,则单击child会导致外部模糊,这对我想做的事情来说是一种痛苦 HTML: JS: 您是否尝试添加: $inner.click(funct
您是否尝试添加:
$inner.click(function() {
$div.focus();
});
为了防止对焦后外部div模糊,请使用e.stopPropagation()
更新:由于单击事件在模糊
之后触发,我使用了鼠标向下
事件,因为它在模糊
之前触发
PS:如果您还想捕捉键盘触发的模糊,请不要忘记处理键盘事件keydown
在IE中单击tabindex=0的元素将导致该元素获得不可见焦点。获得可见焦点的方法是在元素还没有不可见焦点的情况下,通过编程调用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')
})
如果子对象是内联的或未设置宽度的块,则效果与直接单击父对象相同。但是,如果子对象是内联块或具有宽度设置的块,并且父对象已具有焦点,则在执行mousedown处理程序后,父对象将立即模糊()。我们有三种不同的方法,有不同的权衡
一个选项是仅使用preventDefault()抑制模糊;这种方法的优点是blur()永远不会触发,focus()也不会冗余触发,这允许我们在focus和blur处理程序中编写简单的逻辑;这种方法的缺点是它禁用文本选择:
$('#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);
});
您应该在根目录中的任何单击中使用event.stopPropagation()
,这不应强制聚焦事件
这个问题是任何IE(5-11)中大量问题之一。你可以看到IE的源代码自1999年以来就没有被清理过。当人们谈论“IE 11是一款现代浏览器”或“IE 11关注标准”时,我笑了。拦截事件并使用JS设置焦点最终导致了更多问题
我最终发现,使用div或span等“普通”标记会导致IE行为不正确。但是使用var
或任何自定义标记,IE就会开始像一个合适的浏览器一样工作
请参见更新的示例:
HTML:
JS:
这个问题由来已久,但我刚刚遇到这个问题,以下解决方案在IE11中有效,比任何其他解决方案都简单:
.iesux {
border:1px solid #000;
display:block;
padding:8px;
background-color:#FFF;
cursor:default;
width:200px;
pointer-events: none;
}
在IEWell最坏的情况下,它不受支持,你可以为IE定义一些代码,只是为了解决这个问题,我做了,但它给了我一个“双击”。i、 e.点击红色,然后点击白色。你得到“聚焦”、“模糊”、“聚焦”。e、 stopPropagation()似乎做不到它应该做的。好的,我刚刚更新了jsfiddle
您现在可以检查一下吗?由于click
事件在模糊后触发,我使用了Mousedown
事件,因为它在模糊之前触发。谢谢,文档上的Mousedown解决方案很好。如果你更新你的答案以反映额外的逻辑,我会接受你的答案。非常感谢你的解决方案。。。我正准备写一些复杂的事件模拟逻辑,但简单地用一个div替换另一个元素就可以解决所有问题。
$('#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')
})
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);
});
<div tabindex="0" id="test">
<var class="iesux">Works</var>
<foo class="iesux">Works</foo>
<div class="iesux">Doesn't work in IE</div>
<span class="iesux">Doesn't work in IE</span>
</div>
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;
}
document.createElement("foo");
var $div = $("#test");
$div.on("blur", function (e) {
console.log("blur");
})
.on("focus", function (e) {
console.log("focus")
});
.iesux {
border:1px solid #000;
display:block;
padding:8px;
background-color:#FFF;
cursor:default;
width:200px;
pointer-events: none;
}