繁体   English   中英

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

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

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

我一直在寻找这个的原因:

我正在尝试制作像箭头一样的键并通过输入元素表enter导航。 选项卡现在可以工作,但输入和箭头默认情况下似乎没有。 我已经设置了关键处理部分,但现在我需要弄清楚如何将焦点移到事件处理函数中。

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

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

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

相关链接:

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

document.activeElement

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

如果你可以使用 jQuery,它现在支持 :focus,只要确保你使用的是 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 测试

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

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


这是获取焦点元素的(引号)“单线”版本,它在概念上更复杂,因为您必须了解短路,并且您知道,假设您显然不适合在一条线上希望它是可读的。
我不会推荐这个。 但如果你是 1337 hax0r,idk……它就在那里。
您也可以删除|| null 如果您不介意在某些情况下出现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;
});

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

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

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

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

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

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

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

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

如果要获取Element实例的对象,则必须使用document.activeElement ,但如果要获取Text实例的对象,则必须使用document.getSelection().focusNode

我希望有所帮助。

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

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

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

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

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

阅读其他答案并尝试自己,似乎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
  });
}

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

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

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

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

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

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

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

$(":focus")

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

将焦点属性添加到输入

$(":focus" 与 document.activeElement)

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM