IE点击子节点不焦点父节点,父节点有tabindex = 0

时间:2013-08-15 19:01:30

标签: javascript jquery css internet-explorer

编辑: 请参阅下面的我自己的答案: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:

<div tabindex="0" id="test">
    <div>Click</div>
</div> 

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")
});

5 个答案:

答案 0 :(得分:7)

拦截事件并使用JS设置焦点最终导致更多问题。

我最终发现使用&#34;正常&#34;像div或spans这样的标签会让IE表现不正常。但是使用像var或任何自定义标记这样的东西,IE开始表现得像一个合适的浏览器。

请参阅更新示例:http://jsfiddle.net/fergal_doyle/anXM3/16/

HTML:

<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>

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")
});

答案 1 :(得分:5)

您是否尝试添加:

$inner.click(function() {
  $div.focus();
});

并在焦点使用e.stopPropagation()

后防止外部div模糊

更新:由于click事件在blur我使用了Mousedown事件后触发,因为它会在blur之前触发。

PS:如果您还希望捕捉键盘触发的模糊,请不要忘记处理键盘事件keydown

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

答案 2 :(得分:0)

在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')
})

答案 3 :(得分:0)

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()中的任何点击中使用root,这不应强制焦点事件。

这个问题是任何IE(5-11)中的大量问题之一。你可以看到IE的源代码自1999年以来就没有被清理过。我在笑的时候人们在谈论&#34; IE 11是一个现代浏览器&#34;或者&#34; IE 11关心标准&#34;。

答案 4 :(得分:-1)

这个问题很老,但我刚遇到这个问题,以下解决方案在IE11中运行,并且比其他任何一个简单得多:

.iesux {
     border:1px solid #000;
     display:block;
     padding:8px;
     background-color:#FFF;
     cursor:default;
     width:200px;
     pointer-events: none;
}

不幸的是IE&lt; 11不支持它,但是如果你可以侥幸成功那么它是迄今为止最简单的。

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