[英]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.