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

How do I find out which DOM element has the focus?

提问人:Tony Peterson 提问时间:1/31/2009 最后编辑:Luca KiebelTony Peterson 更新时间:10/2/2023 访问量:888520

问:

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

我寻找这个的原因:

我正在尝试制作像箭头一样的键,并在输入元素表中导航。Tab 现在有效,但 enter 和箭头似乎默认不起作用。我已经设置了密钥处理部分,但现在我需要弄清楚如何在事件处理函数中将焦点移过来。enter

JavaScript DOM

评论

4赞 ling 9/27/2016
下面是一个书签,可以控制台.log焦点元素:github.com/lingtalfi/where-is-focus-bookmarklet
1赞 Maxim Zhukov 4/22/2020
您可以使用 package: npmjs.com/package/find-focused-elementfind-focused-element
1赞 GarfieldKlon 8/27/2020
对我来说,书签不起作用。
6赞 Andrew 10/3/2020
请看这里使用的一个很好的例子:stackoverflow.com/a/64176168/1599699document.activeElement
0赞 bas080 8/9/2023
对于您的特定用例,您可以创建一个图表,您可以查询该图表,以确定应该根据键盘输入事件获得焦点的内容。nextFocus(element, keyboardEvent) // => returns the element to receive focus

答:

1903赞 7 revs, 6 users 45%Dave Jarvis #1

使用 document.activeElement,所有主流浏览器都支持它。

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

如果需要删除,可以使用模糊;它会将 更改为 .activeElementdocument.activeElement.blur()activeElementbody

相关链接:

评论

69赞 JW. 7/2/2010
不确定 IE,但 FF 和 Safari 都返回 BODY 元素。
16赞 Rudie 10/23/2012
activeElement实际上不返回聚焦元素。任何元素都可以有焦点。如果文档有 4 个“滚动div”,则可以通过箭头键滚动其中的 0 或 1 个。如果单击一个,则该 div 处于聚焦状态。如果你在全部外面点击,身体是聚焦的。你如何找出哪个 scrolldiv 是重点的?jsfiddle.net/rudiedirkx/bC5ke/show(检查控制台)
25赞 mklement0 12/22/2012
@Rudie,@Stewart:我在你的小提琴上建立了一个更精致的游乐场:jsfiddle.net/mklement/72rTF。你会发现,唯一一个主要的浏览器(截至2012年末)是Firefox 17,而且只能通过Tab键来关注它。所有主要浏览器返回的元素类型仅限于与输入相关的元素。如果没有这样的元素具有焦点,则所有主流浏览器都会返回该元素 - 除了 IE 9,它返回该元素。divdocument.activeElementbodyhtml
16赞 Marco Luglio 4/13/2013
不确定它是否有帮助,但您可以通过包含属性 tabindex=“0” 来使 div 等元素接收键盘焦点
6赞 robocat 7/2/2013
任何访问都应该包装在 a 中,因为在某些情况下它可能会引发异常(而不仅仅是 IE9 AFAIK)。请参阅 bugs.jquery.com/ticket/13393bugs.jqueryui.com/ticket/8443document.activeElementtry catch
157赞 Wookai 1/31/2009 #2

正如 JW 所说,您无法找到当前聚焦的元素,至少以独立于浏览器的方式。但是,如果你的应用是 IE only(有些是...),你可以通过以下方式找到它:

document.activeElement

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

评论

5赞 Crescent Fresh 1/31/2009
FF3也是。这实际上是围绕“焦点管理”的 HTML5 规范的一部分。
2赞 gregers 6/9/2009
它适用于当前版本的 Chrome 和 Opera (9.62)。在OS X上的Safari 3.2.3中不起作用,但它可以在昨天发布的Safari 4中:)
0赞 Sebas 6/21/2012
chrome 19 仍然相同:S
1赞 Dawn 7/5/2012
它仅适用于 chrome (20) / safari (5.1.3) 当您使用键盘按 Tab 键到元素上时。如果单击它,则 jquery :focus 选择器和 document.activeElement 都无法成功返回您单击的内容(分别返回 undefined 和 document body 元素)。PS 我简直不敢相信这个线程已经有 2 年的历史了,webkit 上仍然存在回归问题,以及跳过链接不起作用的问题,但是在添加实验性 css3 方面做了很多工作。我想我可能会回去向我的家人和朋友推荐 firefox。
1赞 Cornelius 3/21/2020
它为大多数元素返回“body”。几乎没用。
5赞 Tony Peterson 5/18/2009 #3

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

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

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

不过,这很容易搞砸,因为如果你的系统中有一个错误,并且焦点不在你认为的位置,那么就很难恢复正确的焦点。

12赞 Joel S 2/4/2010 #4

我在 Mootools 中用于这些目的的一个小帮手:

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

12赞 Jason 9/9/2010 #5

我喜欢 Joel S 使用的方法,但我也喜欢 .我使用了jQuery并将两者结合起来。不支持的旧版浏览器将用于存储“hasFocus”的值。较新的浏览器将使用 .我认为这将有更好的性能。document.activeElementdocument.activeElementjQuery.data()document.activeElementdocument.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);

评论

3赞 Pylinux 7/30/2015
这可以被 @William Denniss 取代吗?$("*:focus")
0赞 Jason 8/22/2015
我想可以。我很久以前就写了这篇文章,现在已经过去了 5 年,再也没有理由重新审视更好的解决方案。试试看!我可能会做同样的事情。我在我们的网站上少了插件!:)
9赞 Andrew Wynham 3/11/2011 #6

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

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

评论

1赞 Martijn 12/15/2015
你应该(总是?)使用而不是 ,或者至少(当你准备好你的jQuery对象时)。这个级别的原生 Javascript 更快、更高效。在这种情况下可能并不明显,但在系统范围内,您会注意到差异。this.id$(this).attr('id')$(this)[0].id
6赞 rjmunro 8/5/2011 #7

阅读其他答案,并尝试自己,它似乎会为您提供大多数浏览器中所需的元素。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
  });
}
97赞 William Denniss 8/28/2011 #8

如果你可以使用jQuery,它现在支持:focus,只要确保你使用的是1.6+版本。

此语句将为您提供当前重点的元素。

$(":focus")

From:如何使用 jQuery 选择一个专注于它的元素

评论

6赞 Harry Pehkonen 10/13/2017
这很好,但是jQuery是如何做到的呢?document.activeElement?我发现了这个:return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
1赞 V.Volkov 8/21/2022
@HarryPehkonen 看起来 common 工作得很好,并且被 jQuery 使用document.querySelector( ':focus' )
52赞 Andy E 10/19/2011 #9

document.activeElement现在是 HTML5 工作草案规范的一部分,但在某些非主要/移动/较旧的浏览器中可能尚不支持它。您可以回退到(如果支持)。还值得一提的是,如果没有元素被聚焦,即使浏览器窗口没有聚焦,也会返回。querySelectordocument.activeElementdocument.body

以下代码将解决此问题,并回退到提供更好的支持。querySelector

var focused = document.activeElement;
if (!focused || focused == document.body)
    focused = null;
else if (document.querySelector)
    focused = document.querySelector(":focus");

另外需要注意的是这两种方法之间的性能差异。使用选择器查询文档总是比访问属性慢得多。请参阅此 jsperf.com 测试activeElement

5赞 Daniel Hartmann 1/13/2012 #10

在 dojo 中,你可以使用 dijit.getFocus()

7赞 Arne 2/15/2012 #11

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

$("input#id").is(":active");
22赞 Nate Whittaker 8/7/2014 #12

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

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

评论

0赞 Manfred 5/10/2015
很酷,是的,就我而言,您的方法绝对有意义。我可以用'tabindex=“-1” '设置我的可聚焦元素,如果它们都没有焦点(比如说,一些我不关心的文本或图片),document.querySelector( ':focus') 返回 null。
0赞 1j01 11/30/2016
请参阅我的答案以避免使用:stackoverflow.com/a/40873560/2624876querySelector
8赞 Nathan K 3/1/2015 #13

使用 document.activeElement 存在潜在问题。考虑:

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

评论

3赞 Tim Down 7/19/2015
这并不是一个真正的问题:内部元素实际上无法接收焦点,因为您可以通过将伪类设置为可见的东西来直观地看到(例如:jsfiddle.net/4gasa1t2/1)。您正在谈论的是哪个内部 s 包含选择或插入符号,这是一个单独的问题。document.activeElement<div>:focus<div>
9赞 rplaurindo 7/17/2016 #14

如果要获取 的实例对象,则必须使用 ,但如果要获取 的实例,则必须使用 。Elementdocument.activeElementTextdocument.getSelection().focusNode

我希望对你有所帮助。

评论

0赞 1j01 11/30/2016
以什么方式更好?
0赞 rplaurindo 11/30/2016
打开浏览器的检查器,单击页面的任何位置,经过此位置并点击 Enter。在那之后,过去并做同样的事情。;)document.getSelection().focusNode.parentElementdocument.activeElement
0赞 1j01 12/1/2016
聚焦此注释框后,给出 while 给出包含 (并给出包含document.activeElement<textarea>document.getSelection().focusNode<td><textarea>document.getSelection().focusNode.parentElement<tr><td>)
0赞 rplaurindo 12/1/2016
对不起,我很抱歉。我没有解释清楚。如果要获取 的实例对象,则必须使用 ,但如果要获取 的实例,则必须使用 。请再测试一次。我希望我能帮到你。Elementdocument.activeElementTextdocument.getSelection().focusNode
2赞 1j01 12/2/2016
问题是询问当前哪个元素具有焦点。而且也不能保证是文本节点。focusNode
44赞 1j01 11/30/2016 #15

就其本身而言,如果文档未聚焦,仍可以返回元素(因此文档中没有任何内容未聚焦!document.activeElement

你可能想要这种行为,或者它可能无关紧要(例如,在一个事件中),但如果你需要知道某些东西实际上是有焦点的,你可以另外检查document.hasFocus()。keydown

如果有聚焦元素,下面将为您提供重点元素,否则.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.documentElementnull

它没有考虑(或可能)是否具有属性,因此实际上可以聚焦。如果你正在编写一个库或其他东西,并希望它是健壮的,你可能应该以某种方式处理它。<body><html>tabIndex


这是一个(语引号)获取聚焦元素的“单行”版本,这在概念上更复杂,因为你必须了解短路,而且你知道,它显然不适合一行,假设你希望它是可读的。
我不会推荐这个。但如果你是 1337 hax0r,idk...它就在那里。
如果您不介意在某些情况下获得,您也可以删除该部分。(如果 is ,你仍然可以得到):
|| nullfalsenulldocument.activeElementnull

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

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

15赞 vegemite4me 10/20/2017 #16

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

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

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

3赞 Rahul Daksh 3/17/2022 #17

简单使用 document.activeElement 查找当前活动元素

0赞 Mina 6/30/2022 #18

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

$(":focus")

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

Add focus attribute to the input

$(":focus" vs document.activeElement)

0赞 Christian 7/15/2022 #19

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

示例:您单击一个按钮并需要上一个活动元素。由于按钮一旦点击它就会成为焦点。

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

评论

0赞 Ahmed Syed 7/17/2022
Tony 需要当前活动元素,您的代码将返回最后一个活动元素。
0赞 Community 7/17/2022
您的答案可以通过其他支持信息进行改进。请编辑以添加更多详细信息,例如引文或文档,以便其他人可以确认您的答案是正确的。您可以在帮助中心找到有关如何写出好答案的更多信息。
5赞 cloudxix 7/18/2022 #20

document.activeElement.id

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

2赞 bas080 3/14/2023 #21

我认为克里斯蒂安的答案最接近正确答案;此外,该事件具有一个名为的属性,该属性允许人们找出获得焦点的内容。focusoutrelatedTarget

document.addEventListener("focusout",ev => {
  const focusedElement = ev.relatedTarget;

  // ...
});

其他使用并具有烦人的警告的答案。querySelector(':focus')activeElement

https://developer.mozilla.org/en-US/docs/Web/API/FocusEvent/relatedTarget

2赞 Afzal K. 10/2/2023 #22

可以使用 document.activeElement 属性来确定当前具有焦点的 DOM 元素。此属性将返回文档中当前聚焦的元素,如果没有元素具有焦点,则返回 null。可以将此属性与事件侦听器结合使用,以检测焦点何时更改。例如:

document.addEventListener('focusin', function(event) {
  console.log('Focused element:', document.activeElement);
});