我想在JavaScript中找出目前关注哪个元素.我一直在浏览DOM,但还没找到我需要的东西.有没有办法做到这一点,以及如何?
我之所以在寻找这个:
我正在尝试制作像箭头一样的键,并enter
在输入元素表中导航.选项卡现在可以使用,但是输入,并且默认情况下不显示箭头.我已经设置了密钥处理部分,但现在我需要弄清楚如何在事件处理函数中移动焦点.
使用document.activeElement
,它在所有主流浏览器中都受支持.
以前,如果您试图找出哪个表单字段具有焦点,则不能.要在旧浏览器中模拟检测,请向所有字段添加"焦点"事件处理程序,并将最后一个焦点字段记录在变量中.添加"模糊"处理程序以清除最后一个焦点字段的模糊事件时的变量.
相关链接:
activeElement浏览器兼容性
document.activeElement的jQuery替代方案
正如JW所说,至少在与浏览器无关的方式中,你无法找到当前的焦点元素.但如果您的应用程序仅限IE(有些是......),您可以通过以下方式找到它:
document.activeElement
编辑:看起来IE毕竟没有出错,这是HTML5草案的一部分,似乎至少得到了最新版本的Chrome,Safari和Firefox的支持.
如果您可以使用jQuery,它现在支持:focus,只需确保您使用的是1.6+版本.
此语句将为您提供当前关注的元素.
$(":focus")
From:如何使用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.body
和document.documentElement
,这是因为一些浏览器返回的其中之一或null
没事的时候集中.
它没有考虑(或者
)是否具有
tabIndex
属性,因此实际上可以集中注意力.如果你正在编写一个库或某些东西,并希望它是健壮的,你应该以某种方式处理它.
这是一个(重型气流)"单线"版本获得聚焦元素,这在概念上更复杂,因为你必须知道短路,你知道,它显然不适合在一条线上,假设你希望它具有可读性.
我不打算推荐这个.但是,如果你是一个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; });
您可以使用非事件方式修复初始状态假设,但是您可能只是使用它.
document.activeElement
如果没有可聚焦元素聚焦,则可以默认为元素.此外,如果元素被聚焦并且浏览器窗口模糊,
activeElement
则将继续保持聚焦元素.
如果不希望这两种行为中的任何一种,请考虑基于CSS的方法:document.querySelector( ':focus' )
.
我喜欢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);
我在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()
被称为给定元素上.
JQuery确实支持当前的:focus
伪类.如果您在JQuery文档中查找它,请在"选择器"下查看它指向W3C CSS文档.我已经使用Chrome,FF和IE 7+进行了测试.请注意,要在IE中工作,必须存在于html页面上.这是一个假设您已为具有焦点的元素指定了id的示例:
$(":focus").each(function() { alert($(this).attr("id") + " has focus!"); });
如果你想获得一个对象,它是实例Element
,你必须使用document.activeElement
,但如果你想获得一个对象,它是实例Text
,你必须使用document.getSelection().focusNode
.
我希望有所帮助.
使用document.activeElement可能存在问题.考虑:
Some textSome textSome text
如果用户关注内部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; } }
阅读其他答案,并尝试自己,它似乎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 }); }
如果您正在使用jQuery,则可以使用它来查明元素是否处于活动状态:
$("input#id").is(":active");