如何找出哪个DOM元素具有焦点?

我想知道在JavaScript中,哪个元素当前具有焦点。我一直在查看DOM,还没有找到我需要的东西。有没有办法做到这一点,以及如何做到这一点?

我找这个的原因:

我正在尝试使箭头和enter之类的键在输入元素表中导航。制表符现在可以工作,但输入,默认情况下箭头似乎不可用。我已经设置了键处理部分,但现在我需要弄清楚如何在事件处理函数中移动焦点。

828984 次浏览

使用#0,所有主要浏览器都支持它。

以前,如果您试图找出哪个表单字段有焦点,则无法。要在旧浏览器中模拟检测,请向所有字段添加“焦点”事件处理程序并将最后一个焦点字段记录在变量中。添加“模糊”处理程序以在最后一个焦点字段的模糊事件时清除变量。

如果您需要删除activeElement,您可以使用blur;document.activeElement.blur()。它会将activeElement更改为body

相关链接:

正如JW所说,你找不到当前关注的元素,至少以独立于浏览器的方式。但是如果你的应用程序只是IE(有些是…),你可以通过以下方式找到它:

document.activeElement

看起来IE并没有完全出错,这是HTML5草案的一部分,似乎至少得到了最新版本的Chrome,Safari和Firefox的支持。

只是把这个放在这里给出我最终想出的解决方案。

我创建了一个名为document.activeInputArea的属性,并使用jQuery的HotKeys插件来捕获箭头键、制表符和回车键的键盘事件,并创建了一个用于单击输入元素的事件处理程序。

然后,每次焦点改变时,我都会调整activeInputArea,这样我就可以使用该属性找出我在哪里。

但是很容易搞砸,因为如果你在系统中有一个bug,焦点不是你认为的地方,那么很难恢复正确的焦点。

我在Moools中用于这些目的的一个小助手:

FocusTracker = {startFocusTracking: function() {this.store('hasFocus', false);this.addEvent('focus', function() { this.store('hasFocus', true); });this.addEvent('blur', function() { this.store('hasFocus', false); });},
hasFocus: function() {return this.retrieve('hasFocus');}}
Element.implement(FocusTracker);

通过这种方式,您可以检查元素是否具有el.hasFocus()焦点,前提是已在给定元素上调用了startFocusTracking()

我喜欢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);

截至目前,JQuery确实支持:focus伪类。如果您在JQuery留档中查找它,请查看“选择器”下的W3C CSS文档。我已经用Chrome、FF和IE 7+进行了测试。请注意,要使它在IE中工作,<!DOCTYPE...必须存在于html页面上。这是一个假设您为具有焦点的元素分配了一个id的示例:

$(":focus").each(function() {alert($(this).attr("id") + " has focus!");});

阅读其他答案,并尝试自己,似乎document.activeElement将为您提供大多数浏览器中所需的元素。

如果你有一个不支持document.active元素的浏览器,如果你有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,它现在支持:焦点,只需确保您使用的是1.6+版本。

此语句将为您获取当前关注的元素。

$(":focus")

来自:如何使用jQuery选择一个关注它的元素

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

使用dojo,您可以使用dijit.getFocus()

如果您使用的是jQuery,您可以使用它来确定元素是否处于活动状态:

$("input#id").is(":active");

如果没有可聚焦元素处于焦点中,document.activeElement可能默认为<body>元素。此外,如果一个元素处于焦点并且浏览器窗口模糊,activeElement将继续保持焦点元素。

如果这两种行为中的任何一种都不理想,请考虑基于CSS的方法:document.querySelector( ':focus' )

使用document.active元素存在潜在问题。考虑:

<div contentEditable="true"><div>Some text</div><div>Some text</div><div>Some text</div></div>

如果用户关注内部div,则document.activeElement仍然引用外部div。您不能使用document.activeElement来确定哪个内部div具有焦点。

以下函数绕过这个问题,并返回焦点节点:

function active_node(){return window.getSelection().anchorNode;}

如果你想得到焦点元素,使用:

function active_element(){var anchor = window.getSelection().anchorNode;if(anchor.nodeType == 3){return anchor.parentNode;}else if(anchor.nodeType == 1){return anchor;}}

如果你想得到一个对象是Element的实例,你必须使用document.activeElement,但如果你想得到一个对象是Text的实例,你必须使用document.getSelection().focusNode

我希望有帮助。

如果文档没有聚焦,document.activeElement本身仍然可以返回一个元素(因此文件中没有任何内容是聚焦的!)

可能想要那个行为,或者它可能无关紧要(例如在keydown事件中),但是如果你需要知道某些事情实际上是集中的,你可以另外检查#1

如果有焦点元素,下面将为您提供焦点元素,否则null

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.bodydocument.documentElement的代码中,这是因为一些浏览器在没有焦点时返回其中一个或null

它不考虑<body>(或者<html>)是否有tabIndex属性,因此可以集中精力。如果您正在编写一个库或其他东西并希望它是健壮的,您可能应该以某种方式处理它。


这是一个( airquote)“单行”版本的获得聚焦元素,这是概念上更复杂,因为你必须了解短路,你知道,它显然不适合一行,假设你希望它是可读的。
我不会推荐这个。但如果你是1337 hax0r,idk…它就在那里。
如果你不介意在某些情况下得到false,你也可以删除|| null部分。(如果document.activeElementnull,你仍然可以得到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;});

您可以通过使用非事件方式来修复初始状态假设,但是您也可以使用它来代替。

我发现以下代码片段在尝试确定当前具有焦点的元素时很有用。将以下内容复制到浏览器的控制台中,每秒钟它都会打印出具有焦点的当前元素的详细信息。

setInterval(function() { console.log(document.querySelector(":focus")); }, 1000);

如果打印整个元素不能帮助您精确定位元素,请随意修改console.log以注销不同的内容以帮助您精确定位元素。

使用document.active元素找到当前的活动元素

如果您想在开发工具上测试焦点元素,我建议使用。

$(":focus")

当您单击开发工具中的任何内容时,document.activeElement将更改为body

添加焦点属性到输入

$(

要获取前一个活动元素,请添加此项。

示例:您单击一个按钮并需要前一个活动元素。因为按钮一旦单击就会获得焦点。

document.addEventListener("focusout",ev => {document.previousActiveElement = ev.target;});

使用document.activeElement.id

附加.id过滤掉返回整个DOM并允许您仅使用已识别的元素