是否有一个jQuery选择器来获取所有可以获得焦点的元素?

这个答案告诉哪些HTML元素可以获得焦点。 是否有一个与这些元素完全匹配的jQuery选择器?

现在我只是使用$('input,select,textarea,a') ,但我想知道是否有更精确的东西。

来自OP提到的另一个SO回答 :

今天的浏览器在HTMLElement上定义了focus(),…

因此,这意味着测试focus作为元素的一个成员是无效的,因为所有元素都会拥有它,无论它们是否真正接受焦点。

…但是除非是下列之一,否则元素实际上不会成为焦点:

  • 带有href * HTMLInputElement / HTMLSelectElement / HTMLTextAreaElement / HTMLButtonElement的HTMLAnchorElement / HTMLAreaElement但没有disabled (如果你尝试,IE实际上会给你一个错误),并且出于安全原因,文件上传有exception行为
  • HTMLIFrameElement(虽然它集中在它没有做任何有用的事情)。 其他嵌入元素也许,我还没有测试过它们。
  • 具有tabindex任何元素

那么,在jQuery Selector中明确命名所有这些呢?

 $('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]') 

更新#1

我在这里更新了你的jsFiddle 。 它似乎工作。

我还在上面的列表中添加了属性contenteditable元素。


更新#2

正如@ jfriend00指出的那样,“根据用途,人们可能想要过滤掉不可见的元素”。 要完成此操作,只需将.filter(’:visible’)应用于从上面的选择器生成的集合。


更新#3

正如Xavin指出的那样 :jQuery UI现在有一个执行此function的选择器:focusable 。 如果您已经在使用jQuery UI,那么这可能就是您的选择。 如果没有,那么你可能想看看jQuery UI如何做到这一点 。 在任何情况下,jQuery UI的页面上的描述:focusable是有帮助的:

如果未禁用以下类型的元素,则可以对其进行聚焦:输入,选择,文本区域,按钮和对象。 如果锚具有href或tabindex属性,则它们是可聚焦的。 如果区域元素位于命名地图内,具有href属性,并且使用地图存在可见图像,则它们是可聚焦的。 所有其他元素都可以根据其tabindex属性和可见性进行聚焦。

所以,我上面提出的选择器很接近,但它没有考虑到一些细微差别。

这是从jQuery UI中删除的function,通过微小的调整使其自包含。 (改编是未经测试的,但应该有效):

 function focusable( element ) { var map, mapName, img, nodeName = element.nodeName.toLowerCase(), isTabIndexNotNaN = !isNaN( $.attr( element, "tabindex" ) ); if ( "area" === nodeName ) { map = element.parentNode; mapName = map.name; if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) { return false; } img = $( "img[usemap=#" + mapName + "]" )[0]; return !!img && visible( img ); } return ( /input|select|textarea|button|object/.test( nodeName ) ? !element.disabled : "a" === nodeName ? element.href || isTabIndexNotNaN : isTabIndexNotNaN) && // the element and all of its ancestors must be visible visible( element ); function visible( element ) { return $.expr.filters.visible( element ) && !$( element ).parents().addBack().filter(function() { return $.css( this, "visibility" ) === "hidden"; }).length; } } 

注意:上面的函数仍然依赖于jQuery,但不应该需要jQuery UI。

您可以检查具有focus()函数的元素:

 $('*').each(function() { if(typeof this.focus == 'function') { // Do something with this element } }) ; 

编辑思考一点,将*:visible而不仅仅*作为大多数应用程序的选择器可能是有意义的。

另一个简单但完整的jQuery选择器可能是这样的:

 $('a[href], area[href], input, select, textarea, button, iframe, object, embed, *[tabindex], *[contenteditable]') .not('[tabindex=-1], [disabled], :hidden') 

我有一个相对简单的解决方案,它以Tab键顺序返回所有tabbable子节点,而不使用jQuery。

 function tabbable(el) { return [].map.call(el.querySelectorAll([ 'input', 'select', 'a[href]', 'textarea', 'button', '[tabindex]' ]), function(el, i) { return { el, i } }). filter(function(e) { return e.el.tabIndex >= 0 && !e.el.disabled && e.el.offsetParent; }). sort(function(a,b) { return a.el.tabIndex === b.el.tabIndex ? ai - bi : (a.el.tabIndex || 9E9) - (b.el.tabIndex || 9E9); }); } 

对于IE,请考虑实现与e.el.offsetParent不同的可见性检查。 jQuery可以在这里帮助你。

如果您不需要排序的元素,请忽略对sort()的调用。

在jQuery中不存在你正在寻找的选择器。

如果您已经在使用jQueryUI,则可以使用: focusable selector。

http://api.jqueryui.com/focusable-selector/

您可能希望尝试在捕获焦点事件的body元素上设置焦点处理程序,而不是获取可聚焦元素的列表。

 $(document.body).on("focus", "*", function(e) { //Scroll to e.target }); 

知道元素是否支持特定类型的侦听器的一般测试是查看它是否具有相关属性,例如,为了测试对焦点事件的支持,请使用:

 if ('focus' in element) { // element supports the focus event } 

但是,也有一些例外。 请参阅如何以编程方式确定HTML对象可以侦听哪些事件的答案? 。