[英]How can i get all elements with a selector attribute with VanillaJS?
[英]Is there a jQuery selector to get all elements that can get focus?
这个答案告诉了哪些 HTML 元素可以接收焦点。 是否有与这些元素完全匹配的 jQuery 选择器?
现在我只是使用$('input,select,textarea,a')
,但我想知道是否有更精确的东西。
今天的浏览器在 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 :
我在这里更新了你的 jsFiddle 。 它似乎有效。
我还在上面的列表中添加了具有contenteditable
属性的元素。
更新#2 :
正如@jfriend00 指出的那样,“根据使用情况,人们可能希望过滤掉不可见的元素”。 要实现这一点,只需将.filter(':visible')应用于从上述选择器生成的集合。
更新 #3 :
正如Xavin 指出的那样:jQuery UI 现在有一个选择器, :focusable ,可以执行此功能。 如果您已经在使用 jQuery UI,那么这可能是您要走的路。 如果没有,那么您可能想看看 jQuery UI 是如何做到的。 无论如何,jQuery UI 页面上关于:focusable
的描述很有帮助:
如果未禁用以下类型的元素,则它们是可聚焦的:输入、选择、文本区域、按钮和对象。 如果锚具有 href 或 tabindex 属性,则它们是可聚焦的。 如果 area 元素位于命名地图内、具有 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。
另一个简单但完整的 jQuery 选择器可能是这样的:
$('a[href], area[href], input, select, textarea, button, iframe, object, embed, *[tabindex], *[contenteditable]')
.not('[tabindex=-1], [disabled], :hidden')
您可以检查具有focus()
函数的元素:
$('*').each(function() {
if(typeof this.focus == 'function') {
// Do something with this element
}
}) ;
再想一想,将*:visible
而不仅仅是*
作为大多数应用程序的选择器可能更有意义。
我有一个相对简单的解决方案,它在不使用 jQuery 的情况下,按 Tab 键顺序返回所有可制表的子项。
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()
的调用。
在 jQuery 中不存在您正在查找的选择器。
如果您已经在使用 jQueryUI,则可以使用: focusable 选择器。
您可能想要尝试在捕获焦点事件的body
元素上设置一个焦点处理程序,而不是获取可聚焦元素的列表。
$(document.body).on("focus", "*", function(e) {
//Scroll to e.target
});
var allElementsThatCanBeFocused = $(':focusable');
了解元素是否支持特定类型侦听器的一般测试是查看它是否具有相关属性,例如测试是否支持焦点事件,请使用:
if ('focus' in element) {
// element supports the focus event
}
但是,也有一些例外。 请参阅如何以编程方式确定 HTML 对象可以侦听哪些事件的答案? .
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.