我想在JavaScript中找出目前关注的元素。我一直在浏览DOM,但还没找到我需要的东西。有没有办法做到这一点,以及如何?
我正在寻找这个的原因:
我正在尝试制作像箭头一样的键,enter
在输入元素表中导航。选项卡现在可以使用,但是输入,并且默认情况下不显示箭头。我已经设置了密钥处理部分,但现在我需要弄清楚如何在事件处理函数中移动焦点。
答案 0 :(得分:1388)
使用document.activeElement
,所有主流浏览器均支持此功能。
以前,如果你试图找出哪个表单字段有焦点,你就不能。要在旧浏览器中模拟检测,请向所有字段添加“焦点”事件处理程序,并将最后一个焦点字段记录在变量中。添加“模糊”处理程序,以便在最后一个焦点字段的模糊事件上清除变量。
相关链接:
答案 1 :(得分:114)
正如JW所说,至少在与浏览器无关的方式中,你无法找到当前的焦点元素。但如果你的应用只是IE(有些是......),你可以通过以下方式找到它:
document.activeElement
编辑:看起来IE似乎并没有出现任何问题,这是HTML5草案的一部分,似乎至少得到了最新版Chrome,Safari和Firefox的支持。
答案 2 :(得分:78)
如果您可以使用jQuery,它现在支持:focus,只需确保您使用的是1.6 +版。
此声明将为您提供当前关注的元素。
$(":focus")
来自:How to select an element that has focus on it with jQuery
答案 3 :(得分:41)
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。
答案 4 :(得分:17)
如果文档没有被聚焦,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)&#34; one-liner&#34;获取聚焦元素的版本,在概念上更复杂因为你必须知道短路,而且你知道,它显然不适合在一条线上,假设你希望它具有可读性
我不推荐这个。但如果你是一个1337 hax0r,那就......那就是它
如果您不介意在某些情况下获取|| 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;
});
您可以使用非偶数方式修复初始状态假设,但之后您也可以使用它来代替。
答案 5 :(得分:14)
document.activeElement
可能默认为<body>
元素。此外,如果元素被聚焦且浏览器窗口模糊,activeElement
将继续保持聚焦元素。
如果不希望这两种行为中的任何一种,请考虑基于CSS的方法:document.querySelector( ':focus' )
。
答案 6 :(得分: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);
答案 7 :(得分: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);
这样,只要在给定元素上调用了el.hasFocus()
,就可以检查元素是否具有焦点startFocusTracking()
。
答案 8 :(得分:7)
JQuery确实支持当前的:focus
伪类。如果您在JQuery文档中查找它,请在“选择器”下查看它指向W3C CSS docs的位置。我已经使用Chrome,FF和IE 7+进行了测试。请注意,要使其在IE中工作,html页面上必须存在<!DOCTYPE...
。这是一个假设您已为具有焦点的元素指定了id的示例:
$(":focus").each(function() {
alert($(this).attr("id") + " has focus!");
});
答案 9 :(得分:7)
如果要获取Element
实例的对象,则必须使用document.activeElement
,但如果要获取Text
实例的对象,则必须使用document.getSelection().focusNode
。
我希望有所帮助。
答案 10 :(得分:6)
使用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;
}
}
答案 11 :(得分: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
});
}
答案 12 :(得分:5)
如果您正在使用jQuery,则可以使用它来查明元素是否处于活动状态:
$("input#id").is(":active");
答案 13 :(得分:5)
在尝试确定哪个元素当前具有焦点时,我发现以下代码段非常有用。将以下内容复制到浏览器的控制台中,每秒都会打印出具有焦点的当前元素的详细信息。
[[True, False, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True, True],
[True, True, True, True, True, True, True, True, True]]
如果打印出整个元素无法帮助您精确定位元素,请随意修改setInterval(function() { console.log(document.querySelector(":focus")); }, 1000);
以注销不同的内容,以帮助您精确定位元素。
答案 14 :(得分:4)
使用dojo,您可以使用dijit.getFocus()
答案 15 :(得分:3)
只是把它放在这里给出我最终提出的解决方案。
我创建了一个名为document.activeInputArea的属性,并使用jQuery的HotKeys插件来捕获箭头键,tab和enter的键盘事件,并创建了一个用于单击输入元素的事件处理程序。
然后我每次改变焦点时调整了activeInputArea,所以我可以使用该属性来找出我的位置。
虽然很容易搞砸了,但是如果系统中有错误并且焦点不在你认为的位置,那么很难恢复正确的焦点。