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


我想在Javascript中找出目前有焦点的元素。我一直在浏览DOM,但还没找到我需要的东西。有办法做到这一点,怎么样?

我之所以在寻找这个:

我正在尝试制作像箭头一样的键 enter 浏览输入元素表。选项卡现在可以使用,但默认情况下输入和箭头似乎没有。我已经设置了密钥处理部分,但现在我需要弄清楚如何在事件处理函数中移动焦点。


1039
2018-01-30 20:21


起源


这是一个bookmark.log具有焦点的元素: github.com/lingtalfi/where-is-focus-bookmarklet - ling


答案:


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

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

相关链接:


1224
2018-01-30 20:34



不确定IE,但FF和Safari都返回BODY元素。 - JW.
activeElement 实际上并没有返回聚焦元素。任何元素都可以有焦点。如果文档具有4'滚动',那么这些div中的0或1可通过箭头键滚动。如果单击一个,则该div将被聚焦。如果你点击所有外部,身体就会聚焦。你如何找出哪个都是重点? jsfiddle.net/rudiedirkx/bC5ke/show (检查控制台) - Rudie
@Rudie,@斯图尔特:我建立了一个更加精致的游乐场: jsfiddle.net/mklement/72rTF。您会发现唯一能够真正关注此类的主要浏览器(截至2012年底) div 是Firefox 17,只有 黏合 它。所有主要浏览器返回的元素类型 document.activeElement 仅限于 输入相关的元素。如果没有这样的元素有焦点,所有主流浏览器都返回 body element - 除了IE 9,它返回 html 元件。 - mklement0
不确定它是否有帮助,但您可以通过包含属性tabindex =“0”来创建一个元素,例如div接收键盘焦点 - Marco Luglio
任何访问权限 document.activeElement 应该包裹在一个 try catch 因为在某些情况下它可以抛出异常(不仅仅是IE9 AFAIK)。看到 bugs.jquery.com/ticket/13393 和 bugs.jqueryui.com/ticket/8443 - robocat


正如JW所说,至少在与浏览器无关的方式中,你无法找到当前的焦点元素。但如果你的应用只是IE(有些是......),你可以通过以下方式找到它:

document.activeElement

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


106
2017-08-27 17:33



FF3也是。这实际上是关于“焦点管理”的HTML5规范的一部分。 - Crescent Fresh
它适用于当前版本的Chrome和Opera(9.62)。在OS X上的Safari 3.2.3中不起作用,但它适用于昨天发布的Safari 4 :) - gregers
是的,它在最新的Chrome(稳定版)中运行良好。 - Thomson
现在在chrome(15.0 ...)中不起作用,它返回正文。 - jeromeyers
铬19:S仍然相同 - Sebas


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

此语句将为您提供当前关注的元素。

$(":focus")

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


77
2017-10-19 13:01



这很好,但jQuery是如何做到的? document.activeElement?我找到了这个: return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex); - Harry Pehkonen


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


39
2017-08-06 19:32





document.activeElement 可能默认为 <body> 如果没有可聚焦元素聚焦的元素。此外,如果元素被聚焦并且浏览器窗口模糊, activeElement 将继续保持专注的元素。

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


13
2017-11-29 18:51



很酷,是的,在我的情况下,你的方法绝对有道理。我可以用'tabindex =“ - 1”'设置我的可聚焦元素,如果它们都没有焦点(比方说,一些文字或图片,我不关心)document.querySelector(':focus')返回空值。 - Manfred
请参阅我的回答以避免使用 querySelector: stackoverflow.com/a/40873560/2624876 - 1j01


通过它自己, document.activeElement 如果文档没有聚焦,那么仍然可以返回一个元素(因此 文件中没有任何内容 很专注!)

可能 想要那种行为,或者它 可能 没关系(例如在一个 keydown 事件),但如果您需要知道实际上有重点,您可以另外检查 document.hasFocus()

如果存在,则以下将给出焦点元素,否则 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.body 和 document.documentElement,这是因为有些浏览器返回其中一个或 null 什么都没有集中。

它没有说明是否 <body> (或者可能 <html>有一个 tabIndex 属性因此 实际上可以集中精力。如果你正在编写一个库或类似的东西,并希望它是健壮的,你应该以某种方式处理它。


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

您可以使用非偶数方式修复初始状态假设,但是您可能只是使用它来代替。


12
2017-09-08 18:47





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

10
2018-02-04 12:36



这可能被@William Denniss所取代 $("*:focus") ? - Pylinux
我想它可以。我很久以前写过这篇文章,并且从未有理由重新审视一个更好的解决方案,因为它已经存在了5年之后。试试看!我可能会这样做。我在网站上插件少了! :) - Jason


我在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() 已被调用给定元素。


9
2018-03-10 23:10





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

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

7
2017-07-17 05:52



你应该(总是?)使用 this.id 代替 $(this).attr('id')或者至少(当你已经拥有你的jQuery对象时) $(this)[0].id。此级别的原生Javascript更快,更高效。在这种情况下可能不明显,但在整个系统范围内你会注意到差异。 - Martijn