2011-10-05 32 views
23

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

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

+0

可能不是。也许试试[':input'](http://api.jquery.com/input-selector/)选择器? – Bojangles

+0

一旦你有可聚焦元素的列表,你想做什么? – Dennis

+0

@丹尼斯 - 向下滚动以确保它们在聚焦时可见。 http://stackoverflow.com/questions/7650892/how-to-scroll-down-the-page-when-a-covered-input-box-is-focused – ripper234

回答

5

你可以检查该有focus()功能要素:

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

编辑 思考多一点,它可能会很有意义的*:visible而不仅仅是*的选择对于大多数应用这个。

+0

绝对要走的路。因为jQuery选择器是建立在http://sizzlejs.com上的,所以我认为就显式选择器而言,这是不可能的。 – ifightcrime

+0

除了,如果你阅读链接在OP中的帖子,它说:“只有具有focus()方法的元素是HTMLInputElement,HTMLSelectElement,HTMLTextAreaElement和HTMLAnchorElement。这明显地省略了HTMLButtonElement和HTMLAreaElement.'所以测试'.focus()'不会(明显地)执行它。 – Lee

+0

DOM元素是主机对象,它们不需要符合ECMAScript的规则,因此它们对* typeof *运算符的响应可以是任何内容,包括抛出错误。在IE 8中,'typeof element.focus'在文本输入上返回* object *,所以上面的测试在大约1:5的浏览器中使用时会失败,可能更多。 – RobG

28

other SO answer referred to by the OP

今天的浏览器定义焦点()在HTML元素,...

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

...但一个元素不会采取实际的重点,除非它的一个:

  • HTMLAnchorElement/HTMLAreaElement带有href * 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用户界面现在有一个选择器,: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的。

+0

根据使用情况,可能需要过滤掉不可见的元素。 – jfriend00

+0

也许没有更好的办法,但这种类型的代码的问题是它很脆弱。每当有新类型的可编辑元素或使某些可编辑元素变为可用的新属性时,都必须对其进行维护。 – jfriend00

+0

@ jfriend00 - 好点。我更新了我的答案,以包含您的建议。 – Lee

0

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

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

除了我们已经证明检查'this.focus'的类型不起作用。 – jfriend00

4

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

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

'[tabindex]'前面的'*'是不必要的 – Omu

+0

是的,你是对的! – tzi

0

我有一个相对简单的解决方案,它返回所有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 ? a.i - b.i : (a.el.tabIndex || 9E9) - (b.el.tabIndex || 9E9); }); 
} 

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

如果您不需要排序元素,请拨打电话sort()

相关问题