我想知道在JavaScript中,哪个元素当前具有焦点。我一直在浏览DOM,还没有找到我需要的东西。有没有办法做到这一点,以及如何做到?
我找这个的原因是:
我正在尝试制作像箭头一样的键,并输入在输入元素表中导航。Tab键现在起作用了,但输入和箭头在默认情况下似乎不起作用。我已经设置了关键处理部分,但现在我需要弄清楚如何将焦点转移到事件处理功能上。
我想知道在JavaScript中,哪个元素当前具有焦点。我一直在浏览DOM,还没有找到我需要的东西。有没有办法做到这一点,以及如何做到?
我找这个的原因是:
我正在尝试制作像箭头一样的键,并输入在输入元素表中导航。Tab键现在起作用了,但输入和箭头在默认情况下似乎不起作用。我已经设置了关键处理部分,但现在我需要弄清楚如何将焦点转移到事件处理功能上。
当前回答
我喜欢Joel S使用的方法,但我也喜欢document.activeElement的简单性。我使用了jQuery并将两者结合起来。不支持document.activeElement的旧浏览器将使用jQuery.data()来存储“hasFocus”的值。较新的浏览器将使用document.activeElement。我认为document.activeElement将具有更好的性能。
(function($) {
var settings;
$.fn.focusTracker = function(options) {
settings = $.extend({}, $.focusTracker.defaults, options);
if (!document.activeElement) {
this.each(function() {
var $this = $(this).data('hasFocus', false);
$this.focus(function(event) {
$this.data('hasFocus', true);
});
$this.blur(function(event) {
$this.data('hasFocus', false);
});
});
}
return this;
};
$.fn.hasFocus = function() {
if (this.length === 0) { return false; }
if (document.activeElement) {
return this.get(0) === document.activeElement;
}
return this.data('hasFocus');
};
$.focusTracker = {
defaults: {
context: 'body'
},
focusedElement: function(context) {
var focused;
if (!context) { context = settings.context; }
if (document.activeElement) {
if ($(document.activeElement).closest(context).length > 0) {
focused = document.activeElement;
}
} else {
$(':visible:enabled', context).each(function() {
if ($(this).data('hasFocus')) {
focused = this;
return false;
}
});
}
return $(focused);
}
};
})(jQuery);
其他回答
如果文档没有聚焦,document.activeElement本身仍然可以返回一个元素(因此文档中的任何内容都没有聚焦!)
您可能想要这样的行为,或者这可能无关紧要(例如,在keydown事件中),但如果您需要知道某些事情实际上是聚焦的,您可以另外检查document.hasFocus()。
如果有聚焦元素,则以下内容将为您提供聚焦元素,否则为空。
var focused_element = null;
if (
document.hasFocus() &&
document.activeElement !== document.body &&
document.activeElement !== document.documentElement
) {
focused_element = document.activeElement;
}
要检查特定元素是否具有焦点,更简单:
var input_focused = document.activeElement === input && document.hasFocus();
要检查是否有任何内容被聚焦,这又一次变得更加复杂:
var anything_is_focused = (
document.hasFocus() &&
document.activeElement !== null &&
document.activeElement !== document.body &&
document.activeElement !== document.documentElement
);
健壮性注意:在对document.body和document.documentElement进行检查的代码中,这是因为某些浏览器在没有焦点时返回其中一个或null。
它不考虑<body>(或者<html>)是否具有tabIndex属性,因此实际上可以被聚焦。如果您正在编写一个库或其他东西,并且希望它是健壮的,那么您可能应该以某种方式处理它。
这里有一个(重引号)“单行”版本的获取聚焦元素,这在概念上更复杂,因为你必须了解短路,而且你知道,如果你想让它可读,它显然不适合一行。我不推荐这个。但如果你是1337 hax0r,idk。。。就在那里。如果您不介意在某些情况下出错,也可以删除||null部分。(如果document.activeElement为null,则仍可能为null):
var focused_element = (
document.hasFocus() &&
document.activeElement !== document.body &&
document.activeElement !== document.documentElement &&
document.activeElement
) || null;
为了检查某个特定元素是否聚焦,您也可以使用事件,但这种方式需要设置(并且可能需要拆除),并且重要的是,假设初始状态:
var input_focused = false;
input.addEventListener("focus", function() {
input_focused = true;
});
input.addEventListener("blur", function() {
input_focused = false;
});
您可以通过使用非事件方式修复初始状态假设,但也可以使用它。
阅读其他答案,并尝试自己,看起来document.activeElement将为您提供大多数浏览器所需的元素。
如果你有一个不支持document.activeElement的浏览器,如果你有jQuery,你应该可以在所有焦点事件中使用类似这样的简单方法(未经测试,因为我手头没有一个满足这些条件的浏览器)来填充它:
if (typeof document.activeElement === 'undefined') { // Check browser doesn't do it anyway
$('*').live('focus', function () { // Attach to all focus events using .live()
document.activeElement = this; // Set activeElement to the element that has been focussed
});
}
如果您可以使用jQuery,它现在支持:focus,只需确保您使用的是1.6+版本。
此语句将为您提供当前关注的元素。
$(":focus")
From:如何使用jQuery选择关注它的元素
对于dojo,可以使用dijit.getFocus()
document.activeElement现在是HTML5工作草案规范的一部分,但在一些非主流/移动/旧浏览器中可能还不支持它。您可以返回到querySelector(如果支持)。还值得一提的是,如果没有元素聚焦,document.activeElement将返回document.body,即使浏览器窗口没有聚焦。
下面的代码将解决这个问题,并返回到querySelector,提供更好的支持。
var focused = document.activeElement;
if (!focused || focused == document.body)
focused = null;
else if (document.querySelector)
focused = document.querySelector(":focus");
另外需要注意的是这两种方法之间的性能差异。使用选择器查询文档总是比访问activeElement属性慢得多。请参阅此jsperf.com测试。