仅通过特定元素的可聚焦后代进行制表的最简单方法是什么?

时间:2011-10-24 01:25:02

标签: javascript html focus tabindex

假设我有一个充满焦点元素的文档,要么是因为它们天生具有焦点(如<input type="text">),要么因为它们有tabindex="0"等。

现在让我们说我的文档中有一部分要显示为模式对话框,我不希望用户被对话框外的任何内容分散注意力。我想tab键只能通过对话框的容器元素内的可聚焦元素循环。最简单的方法是什么?

如果可能的话,我正在寻找一种解决方案,它不关心对话框或页面其他部分的内容,也不会尝试修改它们。也就是说,我不想让对话框之外的元素不可聚焦。首先,这需要做出可逆的改变并跟踪状态。其次,这需要了解元素可以聚焦的所有可能方式。这让我觉得凌乱,脆弱,不易退缩。

我的第一次尝试看起来像这样,但只能向前方向(按Tab键)。它不能反向工作(按Shift + Tab键)。

<div>Focusable stuff outside the dialog.</div>
<div class="dialog" tabindex="0">
  <!-- Focus should be trapped inside this dialog while it's open -->
  <div class="content">
    Form contents and focusable stuff here.
  </div>
  <div class="last-focus" tabindex="0" onfocus="this.parentNode.focus()"></div>
</div>
<div>More focusable stuff outside the dialog.</div>

我宁愿看到纯JavaScript解决方案。如果有一种方法可以使用jQuery这样的库来执行此操作,我更喜欢指向执行此操作的库代码的链接。

3 个答案:

答案 0 :(得分:12)

为了完整起见,我正在接受@Domenic提供的jQuery UI dialog链接并填写详细信息。

要以jQuery方式实现这一点需要两件事:

  1. 收听TabShift+Tab(在keydown上)了解应该捕获焦点的模态元素。这是通过键盘移动焦点的唯一方法。 (如果你想阻止鼠标与文档的其余部分进行交互,那么通过用一个元素覆盖它来解决它是一个单独的问题,以防止任何鼠标事件通过。)

  2. 查找模态元素中的所有tabbable元素。这些是所有可聚焦元素的子集,不包括具有tabindex="-1"

  3. 的元素

    Tab继续前进。 Shift+Tab倒退了。在模式元素中的最后一个tabbable元素被聚焦时按下任何时间Tab,第一个应该获得焦点。同样,在第一个tabbable元素被聚焦时按下任何时间Shift+Tab,最后一个应该获得焦点。这将使焦点保持在模态元素内。

    困难的部分是知道哪些元素是可以列表的。由于tabbable元素都是没有tabindex="-1"的可聚焦元素,因此我们需要知道哪些元素是可聚焦的。由于没有确定元素是否可聚焦的属性,jQuery按hard-coding the following cases执行:

    • inputselecttextareabuttonobject元素未被禁用。
    • aarea元素,其hreftabindex设置的数值。
    • 具有tabindex设置数值的任何元素。

    检查这三种情况是不够的。 jQuery继续确保元素可见。这意味着以下两个都必须为真:

    • 它的祖先都不是display: none
    • visibility的计算值为visible。这意味着设置visibility的最近祖先必须具有值visible。如果没有祖先设置visibility,则计算值为visible

    应该注意jQuery's :visible selector对于此实现看起来不正确,因为它表示“带有visibility: hidden的元素...被认为是可见的”,但它们无法集中精力。

答案 1 :(得分:1)

The jQuery UI dialog通过捕获keydown事件,检查它们是否用于TAB,然后手动聚焦正确的元素来实现此目的。

答案 2 :(得分:0)

jqModal jQuery插件通过将modal选项设置为true来实现此功能。此页面上带有表单的示例应该显示它。我记得通过代码看看发生了什么,你可以用简单的JS很容易地做到这一点。

相关问题