Javascript 仅通过特定元素的可聚焦子体进行制表的最简单方法?
假设我有一个充满可聚焦元素的文档,要么因为它们是天生可聚焦的(比如Javascript 仅通过特定元素的可聚焦子体进行制表的最简单方法?,javascript,html,focus,tabindex,Javascript,Html,Focus,Tabindex,假设我有一个充满可聚焦元素的文档,要么因为它们是天生可聚焦的(比如),要么因为它们有tabindex=“0”等等 现在让我们假设我的文档中有一部分我想显示为一个模式对话框,我不想让用户被对话框之外的任何东西分心。我希望tab键只在对话框的容器元素内的可聚焦元素之间循环。最简单的方法是什么 如果可能的话,我正在寻找一种解决方案,它不关心对话框或页面其余部分的内容,也不试图修改它们。也就是说,例如,我不想使对话框外部的元素不可聚焦。首先,这需要做出可逆的改变并跟踪状态。其次,这需要了解使元素可聚焦的
),要么因为它们有tabindex=“0”
等等
现在让我们假设我的文档中有一部分我想显示为一个模式对话框,我不想让用户被对话框之外的任何东西分心。我希望tab键只在对话框的容器元素内的可聚焦元素之间循环。最简单的方法是什么
如果可能的话,我正在寻找一种解决方案,它不关心对话框或页面其余部分的内容,也不试图修改它们。也就是说,例如,我不想使对话框外部的元素不可聚焦。首先,这需要做出可逆的改变并跟踪状态。其次,这需要了解使元素可聚焦的所有可能方式。这让我感觉凌乱、脆弱、无法缩放
我的第一次尝试看起来像这样,但仅在前进方向上有效(按Tab键)。它在相反方向上不工作(按Shift+Tab)
对话框外的可聚焦内容。
在这里形成内容和可聚焦的内容。
在对话框之外有更多可聚焦的东西。
我宁愿看到纯JavaScript解决方案。如果有一种方法可以在jQuery这样的库中实现这一点,我更希望有一个指向实现这一点的库代码的链接。jQuery插件通过将
modal
选项设置为true来实现这一点。本页上的示例和表单应能说明这一点。我记得我仔细阅读了代码,看看发生了什么,你可以用简单的JS轻松地完成 通过捕获keydown
事件,检查它们是否用于TAB,然后手动聚焦正确的元素来实现这一点。为了完整性,我将获取提供的@Domenic链接并填写详细信息
要以jQuery方式实现这一点,需要两件事:
选项卡
或Shift+Tab
(在键下
)。这是通过键盘移动焦点的唯一方法。(如果要防止鼠标与文档的其余部分交互,这是一个单独的问题,可以通过使用元素覆盖它来解决,以防止任何鼠标事件通过。)tabindex=“-1”
的元素选项卡向前移动<代码>Shift+Tab
向后移动。当模态元素中的最后一个tabbable元素被聚焦时,任何时候按下Tab
,第一个应接收聚焦。类似地,当第一个tabbable元素被聚焦时,按下Shift+Tab时,最后一个应接收聚焦。这将在模态元素内保持焦点
困难的部分是知道哪些元素是可标记的。因为tabbable元素都是可聚焦的元素,没有tabindex=“-1”
,所以我们需要知道哪些元素是可聚焦的。由于没有属性来确定元素是否可聚焦,jQuery通过以下方式来确定:
,输入
,选择
,文本区
,以及未禁用的按钮
元素对象
和a
元素,这些元素具有区域
或href
集的数值选项卡索引
- 具有
集合数值的任何元素tabindex
- 它的祖先都不是
display:None
的计算值为可见性
。这意味着要设置可见
的最近祖先的值必须为可见性
。如果没有祖先设置了可见
,则计算值为可见性
可见
应该注意的是,这个实现看起来不正确,因为它说“具有
可见性的元素:隐藏的…被认为是可见的”,但它们不可聚焦。谢谢,Moin。它看起来像示例4,试图在对话框中捕获焦点,但并不完全有效(有一个获取焦点的“JavaScript”链接)。尽管如此,它看起来很有希望,但我不确定它是如何实现这一目标的。你能告诉我处理这个部分的来源吗?在插件中搜索大写字母“L”。它们似乎是keypress
、keydown
和mousedown
事件。最简单的方法是将“focusin”事件绑定到文档。在事件处理程序中,检查当前焦点是否在对话框中。如果没有,则将焦点重新应用于对话框中的某个元素。对话框关闭后,别忘了删除文档上的事件绑定。@Bjorn,听起来您需要使用计时器来聚焦与聚焦事件中的目标元素不同的元素。虽然这样做的代码较少,但如果没有把握好时间,听起来可能有问题。如果你让它工作起来,你应该发布一个单独的答案。你不需要定时器,你只需要响应聚焦事件。我已经让它工作了,但是我的代码依赖于jQuery/Backbone/marionete,所以如果您使用不同的框架,就没有一个明确的答案。
<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>