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

时间:2011-10-05 22:31:54

标签: javascript jquery

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

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

8 个答案:

答案 0 :(得分:30)

来自other SO answer referred to by the OP

  

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

所以,这意味着测试focus作为元素的成员是有效,因为所有元素将拥有它,无论它们是否实际是否接受焦点。

  

...但是除非是下列之一,否则元素实际上不会聚焦:

     
      
  • 带有href的HTMLAnchorElement / HTMLAreaElement   *   HTMLInputElement / HTMLSelectElement / HTMLTextAreaElement / HTMLButtonElement   但不是disabled(如果你尝试,IE实际上会给你一个错误),   出于安全原因,文件上传有异常行为
  •   
  • 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

updated your jsFiddle here。它似乎有用。

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


更新#2

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


更新#3

作为Xavin pointed out:jQuery UI现在有一个执行此功能的选择器:focusable。如果您已经在使用jQuery UI,那么这可能就是您的选择。如果没有,那么您可能想要check out how jQuery UI does it。在任何情况下,:focusable的jQuery UI页面上的描述都很有用:

  
    

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

  

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

这是从jQuery UI中删除的功能,只需稍作调整即可使其自包含。 (改编是未经测试的,但应该有效):

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。

答案 1 :(得分:5)

您可以检查具有focus()功能的元素:

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

修改的 再考虑一下,将*:visible而不仅仅*作为大多数应用程序的选择器可能是有意义的。

答案 2 :(得分:4)

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

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

答案 3 :(得分:2)

我有一个相对简单的解决方案,它以Tab键顺序返回所有可列表的子节点,而不使用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 ? a.i - b.i : (a.el.tabIndex || 9E9) - (b.el.tabIndex || 9E9); });
}

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

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

答案 4 :(得分:1)

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

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

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

答案 5 :(得分:0)

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

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

但是,也有一些例外。请参阅How do you programmatically determine to which events an HTML object can listen for?的答案。

答案 6 :(得分:0)

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

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

答案 7 :(得分:0)

var allElementsThatCanBeFocused = $(':focusable');