我想用JavaScript找出当前关注的元素。我一直在浏览DOM,但尚未找到我需要的东西。有办法做到这一点吗?
我寻找这个的原因:
我正在尝试制作箭头之类的键并enter
浏览输入元素表。选项卡现在可以使用,但是可以输入,默认情况下,箭头没有显示。我已经设置了关键处理部分,但是现在我需要弄清楚如何在事件处理功能中转移焦点。
find-focused-element
软件包:npmjs.com/package/find-focused-element
我想用JavaScript找出当前关注的元素。我一直在浏览DOM,但尚未找到我需要的东西。有办法做到这一点吗?
我寻找这个的原因:
我正在尝试制作箭头之类的键并enter
浏览输入元素表。选项卡现在可以使用,但是可以输入,默认情况下,箭头没有显示。我已经设置了关键处理部分,但是现在我需要弄清楚如何在事件处理功能中转移焦点。
find-focused-element
软件包:npmjs.com/package/find-focused-element
Answers:
使用document.activeElement
,所有主要浏览器均支持。
以前,如果您试图找出哪个表单字段具有焦点,则无法。要在旧版浏览器中模拟检测,请将“焦点”事件处理程序添加到所有字段,并将最后关注的字段记录在变量中。添加一个“模糊”处理程序,以在发生模糊事件时针对最后关注的字段清除变量。
如果需要删除,activeElement
可以使用模糊;document.activeElement.blur()
。它将更改activeElement
为body
。
相关链接:
activeElement
实际上不返回聚焦元素。任何元素都可以具有焦点。如果文档具有4个“ scrolldivs”,则这些div中的0或1可通过箭头键滚动。如果单击一个,则该div将被聚焦。如果单击全部,则身体将聚焦。你如何找出哪个scrolldiv是重点?jsfiddle.net/rudiedirkx/bC5ke/show(检查控制台)
div
是Firefox 17,并且只能通过制表到该浏览器。所有主要浏览器通过document.activeElement
其返回的元素类型仅限于与输入相关的元素。如果没有此类元素具有焦点,则所有主要浏览器都会返回该body
元素-IE 9除外,IE 9将返回该html
元素。
document.activeElement
应该包装在中,try catch
因为在某些情况下它可能引发异常(而不仅仅是IE9 AFAIK)。参见bugs.jquery.com/ticket/13393和bugs.jqueryui.com/ticket/8443
正如JW所说,您至少无法以浏览器无关的方式找不到当前关注的元素。但是,如果您的应用程序仅是IE(有些是...),则可以通过以下方式找到它:
document.activeElement
编辑:看来IE毕竟没有错,这是HTML5草案的一部分,并且至少受最新版本的Chrome,Safari和Firefox支持。
return elem === document.activeElement && (!document.hasFocus || document.hasFocus()) && !!(elem.type || elem.href || ~elem.tabIndex);
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
没有重点关注时。
它不考虑<body>
(或也许<html>
)是否具有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
<body>
如果没有可聚焦元素,则默认为。此外,如果某个元素已聚焦并且浏览器窗口模糊,activeElement
将继续保留该聚焦的元素。
如果这两种行为都不理想,请考虑使用基于CSS的方法:document.querySelector( ':focus' )
。
querySelector
:stackoverflow.com/a/40873560/2624876
我喜欢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);
$("*:focus")
吗?
我在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中运行,<!DOCTYPE...
必须在html页面上存在。这是一个示例,假设您已为具有焦点的元素分配了ID:
$(":focus").each(function() {
alert($(this).attr("id") + " has focus!");
});
this.id
代替$(this).attr('id')
,或者至少(当您已经拥有jQuery对象时)使用$(this)[0].id
。此级别的本地Javascript更快,更高效。在这种情况下可能不会引起注意,但是在整个系统中,您会发现有所不同。
如果要获得作为的实例的对象,则Element
必须使用document.activeElement
,但如果要获得作为的实例的对象,则Text
必须使用document.getSelection().focusNode
。
希望对您有所帮助。
document.getSelection().focusNode.parentElement
然后点击Enter。在那之后,过去document.activeElement
并做同样的事情。;)
document.activeElement
给出了<textarea>
而document.getSelection().focusNode
给<td>
包含<textarea>
(并document.getSelection().focusNode.parentElement
给出了<tr>
含<td>
)
Element
必须使用document.activeElement
,但是如果要获取作为的实例的对象,则Text
必须使用document.getSelection().focusNode
。请再次测试。希望我能帮上忙。
focusNode
也不保证它是文本节点。
使用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;
}
}
document.activeElement
:内部<div>
元素实际上无法获得焦点,因为您可以通过将:focus
伪类设置为可见的东西来直观地看到(例如:jsfiddle.net/4gasa1t2/1)。您要说的是内部<div>
的哪个包含选择或插入符号,这是一个单独的问题。
我发现以下代码段在尝试确定当前具有焦点的元素时很有用。将以下内容复制到浏览器的控制台中,然后每秒将打印出具有焦点的当前元素的详细信息。
setInterval(function() { console.log(document.querySelector(":focus")); }, 1000);
console.log
如果打印出整个元素不能帮助您确定元素,则可以随意修改来注销其他内容,以帮助您确定确切的元素。
阅读其他答案并尝试一下自己,似乎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
});
}