首页 文章

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

提问于
浏览
1094

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

我之所以在寻找这个:

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

16 回答

  • 16

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

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

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

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

  • 78

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

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

    只是把它放在这里给出解决方案我最终想出来了 .

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

    然后我每次焦点改变时都调整了activeInputArea,所以我可以使用该属性来找出我的位置 .

    虽然很容易搞砸了,但是如果你的系统中有一个bug并且焦点不是你想象的那么,那么很难恢复正确的焦点 .

  • 3

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

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

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

    $(":focus")
    

    来自:How to select an element that has focus on it with jQuery

  • 10

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

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

  • 3

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

    我希望有所帮助 .

  • 7

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

    这样,只要在给定元素上调用了 startFocusTracking() ,就可以检查元素是否具有 el.hasFocus() 焦点 .

  • 6

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

    document.activeElement
    

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

  • 13

    document.activeElement 现在是part of the HTML5 working draft规范,但在某些非主要/移动/旧版浏览器中可能尚不支持 . 您可以回退到 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 test .

  • 5

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

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

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

    相关链接:

  • 110

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

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

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

  • 39

    如果文档没有聚焦, 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
    );
    

    Robustness Note :在对 document.bodydocument.documentElement 进行检查的代码中,这是因为某些浏览器在没有任何焦点时返回其中一个或 null .

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


    这是获得聚焦元素的(重型引用)"one-liner"版本,这在概念上更复杂,因为你必须知道短路,并且y 'know, it obviously doesn' t适合在一条线上,假设你想要它是可读的 .
    我'm not gonna recommend this one. But if you'是一个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;
    });
    

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

相关问题