【问题标题】:Obtain an ordered list of DOM's focus order获取DOM的焦点顺序的有序列表
【发布时间】:2020-12-09 09:07:05
【问题描述】:

我很欣赏 DOM 有时是动态的野兽。但是,我想知道是否有一个简单的调用可以在任何给定时间获取 DOM 的可聚焦元素/节点的有序列表?这显然会包括所有具有tabindex 声明但不是-1 的节点,以及默认情况下可聚焦的任何节点。

TY.

【问题讨论】:

  • 没有开箱即用的功能,您当然可以编写自己的功能来过滤您需要的所有元素。你试过这样做吗?
  • 我还没有尝试过,因为我在等着看是否有一种开箱即用的方法来做到这一点(或者至少是非常类似于开箱即用的方法) -the-box 解决方案)。如果答案是我需要创建自定义逻辑,我想显而易见的解决方案是递归查询 DOM 树,查找 tab-index 属性,以及默认情况下已知可聚焦的特定标签,然后重新排序元素tab-indexes 基于它们的数值(因为它会影响优先顺序)?
  • 是的,这是如何实现的。
  • 干杯。感谢您回复并最终回答我的问题:)

标签: javascript html dom keyboard accessibility


【解决方案1】:

没有执行此操作的内置函数,但我相信以下内容会按预期工作。

正如您所看到的,这并不完全直截了当,因为您必须考虑在其上设置了 visibility:hiddendisplay: none 的父元素。我还必须为 contenteditable 添加一个解决方法,因为它是可聚焦的,但在 JavaScript 中显示为 tabindex="-1",即使没有设置 tabindex,这破坏了我检查事物的方式。

我实际上做的是使用 CSS 选择器 focusableItems 抓取所有可聚焦的元素。

然后我将这些项目变成一个数组,同时删除带有tabindex="-1" 的任何项目以及任何隐藏的项目。

最后,我们以正数 tabindex 开头的项目数组排序,然后按 DOM 顺序对所有其他项目进行排序。

它的边缘有点粗糙,但似乎通过了我能想到的所有测试。遗憾的是,getComputedStyle 是我能想到的在父项上解释 visibility: hidden 的唯一方法,因为这是最难解决的情况。

var focusableItems = 'a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), [tabindex]:not([disabled]), [contenteditable=true]:not([disabled])';

var items = document.querySelectorAll(focusableItems);


var itemsList=[];
for (var i=0;i<items.length;i++) {
  //don't add items with a negative tabindex. Also because "contenteditable" reveals itself as tabindex="-1" in chrome had to add a little workaround.
  if(items[i].tabIndex != "-1" || (items[i].hasAttribute("contenteditable") && !items[i].hasAttribute("tabIndex"))){
    //warning this is a bit slow on thousands of elements but is needed to pick up "visibility: hidden" and "display: none" correctly.
    var style = window.getComputedStyle(items[i]); 
    //check if the item is visible.
    if(items[i].offsetWidth > 0 && items[i].offsetHeight > 0 && items[i].offsetParent && style.display != "none" && style.visibility != "hidden"){
       itemsList.push(items[i]);
    }
  }
}


//anything with a tabindex needs to be first in the list but also from smallest to largest.
itemsList.sort(function(a, b){
   var aVal = 999999999999999;
   var bVal = 999999999999999;
   if(a.hasAttribute("tabIndex") && parseInt(a.tabIndex) > 0){
      aVal = parseInt(a.tabIndex);
   }
   if(b.hasAttribute("tabIndex") && parseInt(b.tabIndex) > 0){
      bVal = parseInt(b.tabIndex);
   }
   return aVal - bVal
});





console.log(itemsList);
.none{
    display:none;
}
.hidden{
   visibility: hidden;
}
<div>
    <button tabindex="1">focus me first so you can check tab order against console as you go</button>
    <div contenteditable="true" tabindex="0">editable</div>
    <h1>Here is some stuff</h1>
    <p>The <span contenteditable="true" tabindex="2">quick (second tab)</span> brown fox <span contenteditable="true">jumped (editable)</span> over the lazy dog.</p>
    <input name="vis" value="visible"/>
    <input name="dis" disabled value="disabled"/>
    <input name="notabindex" tabindex="-1" value="negative tabindex"/>
    <button tabindex="4">Ok (fourth)</button>
    <button tabindex="3">Cancel (third)</button>
    <p tabindex="0">(This last content is tabbable.)</p>
    <div class="none" tabindex="0">display: none</div>
    <div class="none">
        <div tabindex="0">display: none nested</div>
    </div>
    <div class="hidden" tabindex="0">visibility: hidden</div>
    <div class="hidden">
        <div tabindex="0">visibility: hidden nested</div>
    </div>
    <button>end button - last item</button>
</div>

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多