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

Ton*_*son 1234 javascript dom

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

我之所以在寻找这个:

我正在尝试制作像箭头一样的键,并enter在输入元素表中导航.选项卡现在可以使用,但是输入,并且默认情况下不显示箭头.我已经设置了密钥处理部分,但现在我需要弄清楚如何在事件处理函数中移动焦点.

JW.*_*JW. 1453

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

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

相关链接:

  • 不确定IE,但FF和Safari都返回BODY元素. (50认同)
  • @Rudie,@斯图尔特:我已经建立了你的小提琴来创建一个更精致的游乐场:http://jsfiddle.net/mklement/72rTF/.您会发现唯一可以实际关注这种"div"的主要浏览器(截至2012年底)是Firefox 17,并且只能通过_tabbing_来实现.所有主要浏览器通过`document.activeElement`返回的元素类型仅限于与_input_相关的元素.如果没有这样的元素有焦点,所有主流浏览器都返回`body`元素 - 除了IE 9,它返回`html`元素. (18认同)
  • 不确定它是否有帮助,但您可以通过包含属性tabindex ="0"来创建一个元素,例如div接收键盘焦点 (10认同)
  • `activeElement`实际上不返回focus元素.任何元素都可以有焦点.如果文档具有4'滚动',那么这些div中的0或1可通过箭头键滚动.如果单击一个,则该div将被聚焦.如果你点击所有外部,身体就会聚焦.你怎么知道哪个都是重点?http://jsfiddle.net/rudiedirkx/bC5ke/show/(检查控制台) (9认同)
  • 对`document.activeElement`的任何访问都应该包含在`try catch`中,因为在某些情况下它可以抛出异常(不仅仅是IE9 AFAIK).见http://bugs.jquery.com/ticket/13393和http://bugs.jqueryui.com/ticket/8443 (4认同)
  • 如果没有元素被聚焦,document.activeElement 返回什么?我们可以依靠它在支持它的浏览器之间保持一致吗? (2认同)
  • 我更新了@mklement / Rudie 的 jsfiddle。正如 facildelembrar 所说,您可以使用 tabindex 访问它。见 http://jsfiddle.net/72rTF/34/ (2认同)

Woo*_*kai 120

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

document.activeElement
Run Code Online (Sandbox Code Playgroud)

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

  • FF3也是.这实际上是关于"焦点管理"的HTML5规范的一部分. (5认同)
  • 现在不能在chrome(15.0 ...)中工作,它返回body. (5认同)
  • 它适用于当前版本的Chrome和Opera(9.62).在OS X上的Safari 3.2.3中不起作用,但它适用于昨天发布的Safari 4 :) (2认同)

Wil*_*iss 81

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

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

$(":focus")
Run Code Online (Sandbox Code Playgroud)

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

  • 很好,但是jQuery如何做到这一点?document.activeElement?我发现了这个:`return elem === document.activeElement &&(!document.hasFocus || document.hasFocus())&& !!(elem.type || elem.href ||〜〜elem.tabIndex);` (2认同)

And*_*y E 43

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");
Run Code Online (Sandbox Code Playgroud)

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


1j0*_*j01 18

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;
}
Run Code Online (Sandbox Code Playgroud)

要检查特定元素是否具有焦点,它更简单:

var input_focused = document.activeElement === input && document.hasFocus();
Run Code Online (Sandbox Code Playgroud)

要检查是否有任何重点,它会再次变得更复杂:

var anything_is_focused = (
    document.hasFocus() &&
    document.activeElement !== null &&
    document.activeElement !== document.body &&
    document.activeElement !== document.documentElement
);
Run Code Online (Sandbox Code Playgroud)

稳健性注:在代码中它检查反对document.bodydocument.documentElement,这是因为一些浏览器返回的其中之一或null没事的时候集中.

它没有考虑<body>(或者<html>)是否具有tabIndex属性,因此实际上可以集中注意力.如果你正在编写一个库或某些东西,并希望它是健壮的,你应该以某种方式处理它.


这是一个(重型气流)"单线"版本获得聚焦元素,这在概念上更复杂,因为你必须知道短路,你知道,它显然不适合在一条线上,假设你希望它具有可读性.
我不打算推​​荐这个.但是,如果你是一个1337 hax0r,idk ......就在那里.如果您不介意进入某些情况,
也可以删除该|| null部件false.(您仍然可以得到null,如果document.activeElementnull):

var focused_element = (
    document.hasFocus() &&
    document.activeElement !== document.body &&
    document.activeElement !== document.documentElement &&
    document.activeElement
) || null;
Run Code Online (Sandbox Code Playgroud)

为了检查特定元素是否被聚焦,或者您可以使用事件,但这种方式需要设置(并且可能被拆除),并且重要的是,假设初始状态:

var input_focused = false;
input.addEventListener("focus", function() {
    input_focused = true;
});
input.addEventListener("blur", function() {
    input_focused = false;
});
Run Code Online (Sandbox Code Playgroud)

您可以使用非事件方式修复初始状态假设,但是您可能只是使用它.


Nat*_*ker 14

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

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


veg*_*4me 12

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

setInterval(function() { console.log(document.querySelector(":focus")); }, 1000);
Run Code Online (Sandbox Code Playgroud)

console.log如果打印出整个元素不能帮助您查明元素,请随意修改以注销不同的东西以帮助您查明确切的元素。


Jas*_*son 10

我喜欢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);
Run Code Online (Sandbox Code Playgroud)

  • 这可以被@William Denniss的`$("*:focus")取代吗? (3认同)

Joe*_*l S 9

我在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);
Run Code Online (Sandbox Code Playgroud)

这样,您就可以检查是否元素具有焦点与el.hasFocus()前提是startFocusTracking()被称为给定元素上.


Dee*_*ews 7

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

$(":focus").each(function() {
  alert($(this).attr("id") + " has focus!");
});
Run Code Online (Sandbox Code Playgroud)


rpl*_*ndo 7

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

我希望有所帮助.

  • 问题是询问目前关注哪个元素.并且`focusNode`也不保证是文本节点. (2认同)

Nat*_*n K 6

使用document.activeElement可能存在问题.考虑:

<div contentEditable="true">
  <div>Some text</div>
  <div>Some text</div>
  <div>Some text</div>
</div>
Run Code Online (Sandbox Code Playgroud)

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

以下函数解决了这个问题,并返回了焦点节点:

function active_node(){
  return window.getSelection().anchorNode;
}
Run Code Online (Sandbox Code Playgroud)

如果您希望获得焦点元素,请使用:

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

  • 这对`document.activeElement`来说并不是一个问题:内部`<div>`元素实际上无法获得焦点,因为你可以通过将`:focus`伪类设置为可见的东西来直观地看到(例如:http: //jsfiddle.net/4gasa1t2/1/).你所说的是哪个内部`<div>包含选择或插入符号,这是一个单独的问题. (3认同)

Ton*_*son 5

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

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

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

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


rjm*_*nro 5

阅读其他答案,并尝试自己,它似乎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
  });
}
Run Code Online (Sandbox Code Playgroud)


Dan*_*ann 5

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


Arn*_*rne 5

如果您正在使用jQuery,则可以使用它来查明元素是否处于活动状态:

$("input#id").is(":active");
Run Code Online (Sandbox Code Playgroud)


clo*_*xix 5

使用document.activeElement.id

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