可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
EDIT:
See my own answer below: https://stackoverflow.com/a/25953721/674863
Demo:
http://jsfiddle.net/fergal_doyle/anXM3/1/
I have a div with tabindex=0, and a child div with a fixed width. When I click on the child div I expect the outer div to recieve focus. This works fine with Firefox and Chrome, and only works with Internet Explorer (7 to 10) when the child div has no width applied.
With a width, clicking the child (white) div does not give focus to the outer one, and if the outer one previously had focus, clicking the child causes the outer to blur, which is a pain for what I want to do.
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")
});
回答1:
Intercepting events and using JS to set focus ended up causing more problems.
I eventually figured out that using "normal" tags like divs or spans makes IE behave incorrectly. But use something like var
or any custom tag and IE starts to behave like a proper browser.
See updated example: 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")
});
回答2:
Have you tried to add :
$inner.click(function() {
$div.focus();
});
and to prevent the outer div to blur after a focus use e.stopPropagation()
UPDATE: Since the click
event fires after the blur
I used the Mousedown
event, because it fires before blur
.
PS: Don't forget to handle keyboard events keydown
if you want also to catch blurs fired by the keyboard.
http://jsfiddle.net/ouadie/x4nAX/
回答3:
Clicking on an element with tabindex=0 in IE will result in the element gaining invisible focus. The way to gain visible focus is by programmatically calling focus() while the element does not already have invisible focus. Since focus happens right after mousedown, this means we need:
$('#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')
})
If the child is inline or a block with no width set, the effect is the same as clicking directly on the parent. However, if the child is an inline-block or a block with a width set, and the parent already had focus, then the parent will blur() right after the mousedown handlers are executed. We have three different ways to proceed, with different tradeoffs.
One option is to merely suppress the blur with preventDefault(); the virtue of this approach is that blur() will never fire and focus() will not fire redundantly, which allows us to write straightforward logic in our focus and blur handlers; the vice of this approach is that it disables text selection:
$('#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')
})
If we don't want to disable text selection, another option is to focus on the parent from the child's mouseup handler; however, this way the parent will blur and then focus again, which prevents us from knowing when a focus or blur is "real" rather than merely a transient consequence of our focus-propagation logic:
$('#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')
})
The third option has the virtues of both of the above approaches, but is the most complicated logically:
$('#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')
})
回答4:
Let root
be your #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);
});
You should use event.stopPropagation()
in any click in root
, that should not force focus event.
This problem is one of the great amount of problems in any IE (5-11). You can see that IE's source code was not cleaned since 1999. I am laughing when people are talking about "IE 11 is a modern browser" or "IE 11 care about standards".
回答5:
This question is old, but I just came across this problem and the following solution works in IE11 and is much simpler than any other:
.iesux {
border:1px solid #000;
display:block;
padding:8px;
background-color:#FFF;
cursor:default;
width:200px;
pointer-events: none;
}
It's not supported in IE<11 unfortunately but if you can get away with that it's by far the easiest.
http://jsfiddle.net/anXM3/22/