如何在tabindex到达最后一个带有tabindex的元素后重新从1开始?

26

因此,例如,这是一个脚本:

<!-- Random content above this comment -->
<input type="text" tabindex="1" />
<input type="text" tabindex="2" />
<input type="text" tabindex="3" />
<input type="text" tabindex="4" />
<input type="text" tabindex="5" />
<input type="text" tabindex="6" />
<!-- Nothing underneath this comment -->

用户按TAB键,遍历六个文本框,到达最后一个文本框,然后按TAB键,它会跳转到第一个评论上面的内容,对吧?那么,我如何使它再次从tabindex="1"开始呢?


你可以为代码中“随机内容”部分的每个可聚焦元素设置tabindex="-1",以使其不属于制表符顺序。MSDN: tabindex(在MDN上找不到该页面)。 - Teemu
1
document.body.tabIndex = '0'; document.body.focus(); document.body.tabindex = '-1'。如果在HTML中正确排序,您也可以使用相同的tabindex。 - neaumusic
5个回答

26

很遗憾,如果没有启用 JavaScript,您无法这样做。 您可以监听最后一个元素上的 TAB (并确保不是 SHIFT+TAB)键按下事件,并在处理程序中手动将焦点设置为第一个元素。但是,将此逻辑绑定到键盘事件(即特定输入方法)并不通用,可能在使用以下情况时无法正常工作:

  • 移动浏览器
  • 某些其他娱乐设备(智能电视,游戏机等-它们通常使用D-Pad在可聚焦元素之间跳转)
  • 辅助功能服务

我建议采用更通用的方法,该方法不受焦点更改方式的影响。

想法是,您可以将要创建“tabindex循环”的表单元素包围在特殊的“焦点守卫”元素周围,这些元素也可以获得焦点(它们已分配tabindex)。 这是修改后的HTML:

<p>Some sample <a href="#" tabindex="0">content</a> here...</p>
<p>Like, another <input type="text" value="input" /> element or a <button>button</button>...</p>

<!-- Random content above this comment -->
<!-- Special "focus guard" elements around your
if you manually set tabindex for your form elements, you should set tabindex for the focus guards as well -->
<div class="focusguard" id="focusguard-1" tabindex="1"></div>
<input id="firstInput" type="text" tabindex="2" class="autofocus" />
<input type="text" tabindex="3" />
<input type="text" tabindex="4" />
<input type="text" tabindex="5" />
<input type="text" tabindex="6" />
<input id="lastInput" type="text" tabindex="7" />
<!-- focus guard in the end of the form -->
<div class="focusguard" id="focusguard-2" tabindex="8"></div>
<!-- Nothing underneath this comment -->

现在,你只需在这些守卫元素上监听 focus 事件,并手动将焦点更改为适当的字段(出于简单起见,使用 jQuery):

$('#focusguard-2').on('focus', function() {
  // "last" focus guard got focus: set focus to the first field
  $('#firstInput').focus();
});

$('#focusguard-1').on('focus', function() {
  // "first" focus guard got focus: set focus to the last field
  $('#lastInput').focus();
});

正如您所看到的,我还确保当焦点从第一个输入框向后移动(例如在第一个输入框上按下SHIFT+TAB)时,我们会回到最后一个输入框。 实例展示 请注意,“焦点守卫”也被分配了一个tabindex值,以确保在您的输入字段之前/之后立即关注它们。如果您没有手动设置输入的tabindex,则两个“焦点守卫”可以分别分配tabindex ="0" 当您的表单是动态生成的时,当然您也可以让所有这些都在动态环境中工作。只需找出您的可聚焦元素 (不太琐碎的任务),并将它们与相同的“焦点守卫”括起来。
希望这有所帮助,如果您有任何问题,请告诉我。
更新
正如nbro指出的那样,上述实现有一个不希望出现的效果,即在页面加载后按TAB键后选择最后一个元素(因为这会将焦点放在第一个可聚焦元素上,即#focusguard-1,这将触发聚焦到最后一个输入框)。为了缓解这个问题,您可以指定初始要聚焦的元素,并使用另一小段JavaScript将其聚焦。
$(function() { // can replace the onload function with any other even like showing of a dialog

  $('.autofocus').focus();
})

只需在您想要的任何元素上设置autofocus类,它会在页面加载时自动聚焦(或任何其他事件上监听)。


这种方法,如果我理解正确的话,会使焦点在页面加载后第一次单击选项卡按钮时转移到最后一个元素,这是不可取的... - nbro
@nbro 是的,这是一个不幸的副作用。但由于此实现无论如何都需要“javascript干预”,因此要求通过javascript设置初始焦点也是合理的。请参见更新的答案。 - Dmitry Pashkevich

10

以下是我的解决方案,您无需任何其他元素。正如您所看到的,元素将在<form>元素内循环。

$('form').each(function(){
    var list  = $(this).find('*[tabindex]').sort(function(a,b){ return a.tabIndex < b.tabIndex ? -1 : 1; }),
        first = list.first();
    list.last().on('keydown', function(e){
        if( e.keyCode === 9 ) {
            first.focus();
            return false;
        }
    });
});

请查看我回答的第一部分。 - Dmitry Pashkevich

2

以下是我考虑到第一个输入具有"autofocus"属性的解决方案:

在表单元素后添加以下代码(在HTML5中可以是任何标签):

<div tabindex="6" onFocus="document.querySelector('[autofocus]').focus()"></div>

这应该在事件'onFocusOut'上完成,而不是'onFocus',因为最后一个元素永远不会在选项卡上被选择。 - The mentalist Coder

1

是的,在通过输入进行制表后,它会跳转到没有指定制表顺序的合适元素。但是,在制表所有“可制表”元素之后,焦点将跳转到浏览器的UI元素(选项卡、菜单、书签等)之外的页面内容。

我认为最简单的方法是处理最后一个输入上的keyup事件,并拦截TAB使用(以及SHIFT+TAB)。


这是一个老话题,然而在今天的多设备世界中,这个问题变得更加相关了。keydown方法有一个缺点,在我的回答中我添加了更明确的说明。 - Dmitry Pashkevich

0
我建议您增加tabindex,即>100,并将tabIndex赋予您的“content”容器div,请注意,您的内容容器必须具有小于输入框的tabindex,例如99。
当您在最后一个输入框上按下tab键时,请使用JavaScript手动将焦点设置在您的内容div上(您可以使用tab键的keypress处理程序)。
document.getElementById("content").focus();

你必须给你的“内容”设置tabindex属性,以便将焦点设置到它上面。

现在,如果你按下Tab键,焦点将自动切换到第一个输入框。

希望这能帮到你。

谢谢。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接