如何使用JavaScript全局禁用页面中除所有表单之外的tab键?

如何使用JavaScript全局禁用页面中除所有表单之外的tab键?,javascript,Javascript,我正在制作一个单页应用程序,将于下周发布,面向一个相当大的客户,并将在一个相当大的活动中上线,在那之前还有很多事情要完成 有100多个“页面”都加载在一个700px 600px的窗口中,我不久前就知道你可以在页面/部分中使用tab键,这反过来会破坏应用程序,因为它会将焦点转移到隐藏的屏幕外元素,因此,我禁用了整个应用程序的tab键 但现在有几个地方,我们有一个表单,其中有一些输入字段,您在填写表单时无法通过制表符进行切换。这真是个麻烦事 我需要这样做,以便您可以通过制表符通过表单字段,但只有表单

我正在制作一个单页应用程序,将于下周发布,面向一个相当大的客户,并将在一个相当大的活动中上线,在那之前还有很多事情要完成

有100多个“页面”都加载在一个700px 600px的窗口中,我不久前就知道你可以在页面/部分中使用tab键,这反过来会破坏应用程序,因为它会将焦点转移到隐藏的屏幕外元素,因此,我禁用了整个应用程序的tab键

但现在有几个地方,我们有一个表单,其中有一些输入字段,您在填写表单时无法通过制表符进行切换。这真是个麻烦事

我需要这样做,以便您可以通过制表符通过表单字段,但只有表单字段。我为表单设置了tabindex属性,并尝试启用“输入”选项卡,但在不导致应用程序跳转到隐藏部分的情况下无法使其工作

这是我需要更改的函数,它将禁用tab键,表单中的输入到输入字段除外

window.onkeydown = function(e) {
    if (e.keyCode === tab) {
        return false;
    }
}
我试着这么做,但是obv不起作用,哈哈

$('input').keydown(function(e) {
    if (e.keyCode === tab) {
        return true;
    }
});

谢谢:)

您是否尝试过在所有您不想使用tab键的元素上设置
tabIndex=“-1”
?我认为这是一个更好的解决方案

否则,在密钥处理程序函数中,测试
event.target
(或IE中的
event.srcmelement
),查看事件是否源自表单元素。您似乎正在使用jQuery,因此可以将“allowTab”类仅分配给表单中的字段,然后执行以下操作:

$(document).keydown(function(e) {
   if (!$(e.target).hasClass("allowTab"))
      return false;
});


我们要做的是确定下一行是什么输入,然后跳到它

可能需要一些优化,但它可以工作。这原本是为了跳过非表单元素。如果愿意,您可以添加选择器以不跳过。此外,您可以为
Shift+Tab
行为添加逻辑(可能在Tab逻辑之前)



显然,它仍将根据某些元素在源代码中的显示方式来遍历这些元素。但是,为什么不从DOM中删除这些隐藏的元素,而是使用。这样,你就不会有在屏幕外元素之间来回循环的痛苦。

我对@Joseph发布的答案做了一些修正,可以在表单的输入中移动+制表符,这样你就可以反转方向。以前,当我第一次必须找到一种方法来做这件事时,这对我来说是一件非常烦人的事情,直到现在,我都没有时间再浪费在寻找一个完整的解决方案上。给你

$(function() {
    // gather all inputs of selected types
    var inputs = $('input, textarea, select, button'), inputTo;

    // bind on keydown
    inputs.on('keydown', function(e) {

        // if we pressed the tab
        if (e.keyCode == 9 || e.which == 9) {
            // prevent default tab action
            e.preventDefault();

            if (e.shiftKey) {
                // get previous input based on the current input
                inputTo = inputs.get(inputs.index(this) - 1);
            } else {
                // get next input based on the current input
                inputTo = inputs.get(inputs.index(this) + 1);
            }

            // move focus to inputTo, otherwise focus first input
            if (inputTo) {
                inputTo.focus();
            } else {
                inputs[0].focus();
            }
        }
    });
});

演示它的工作情况

我希望OP只需要为当前“屏幕”中的字段设置一个
tabIndex
>-1,并且应该是可导航的,其他所有内容都应该是-1。@RobG-当然。这就是我第一句话的意思。当“屏幕”改变时,很容易(特别是因为他似乎正在使用jQuery)更改选项卡索引。我的主要观点是使用
tabIndex
,而不是试图取消tab键。有几十个元素需要tabIndex=-1。我还应该提到这样一个事实:我们正在根据您所导航到的上下文在容器中克隆和交换html代码的整个部分。这是一件非常复杂的事情,但它会产生一个问题,即在任何给定上下文中,只要元素位于DOM中,就需要该代码可用。这并不总是一个案例,可以运行时,它的工作…对不起,我想我只是不明白你的页面结构。我认为,由于您使用的是jQuery,因此可以使用一行代码轻松地为所有(适当的)元素设置tabindex。然后,当然,当您显示表单时,您知道可以将其元素的tabindex设置回0?nnnnnn-我不认为能够只显示一两行是问题所在。可能只需按一次键/按下文档上的任何侦听器即可。如果按tab键来自应允许它的元素,请允许它。否则取消它。支持所需的只是一个元素列表(ID、类、数组成员等),这些元素应该允许当前页面“上下文”的选项卡导航。这不会跳过隐藏的输入,或问题中提到的设置屏幕外的输入,并且它会跳过链接,这样,如果您不(或不能)使用该页面,您就无法使用该页面使用鼠标或其他定点设备,同时(虽然很容易修复),它只向前循环,打破了默认的shift tab行为。如果要重用这些元素,为什么不删除这些屏幕外元素,或者至少使用DOM片段或克隆来存储对它的一些引用呢,到目前为止,在应用程序的每个上下文中使用表单字段时(在包含表单的面板设置函数中),这些字段应该是可选项卡的。代码需要存在于所有包含表单的设置函数中,因为在函数运行之前,它们不存在于DOM中,并且当上下文更改时,它们会从DOM中删除,因此有必要将其放在包含表单的上下文中。谢谢:)我发现虽然这种方法有效,但它不能处理通过字段shift+tab的反向tab。如果不是因为我不得不不断地测试和重新测试,我做了很多次这种形式的东西,它最终肯定会出现在我身上。所以,一旦我写了这个shift+tab部分来真正模拟tab键,我会把它贴在这里。你还打算按照你在评论中的指示发布你的解决方案吗?实际上我从来没有找到过解决方案。但是,刚才看到了这条评论,并提出了一个完整的解决方案,用于在表单上进行tabbing和shift+tabbing,并将其发布在下面。
$(document).ready(function() {

    //gather all inputs of selected types
    var inputs = $('input, textarea, select, button');

    //bind on keydown
    inputs.on('keydown', function(e) {

        //if we pressed the tab
        if (e.keyCode == 9 || e.which == 9) {

            //prevent default tab action
            e.preventDefault();

            //get next input based on the current input we left off
            var nextInput = inputs.get(inputs.index(this) + 1);

            //if we have a next input, go to it. or go back
            if (nextInput) {
                nextInput.focus();
            }
            else{
                inputs[0].focus();
            }
        }
    });
});​
$(function() {
    // gather all inputs of selected types
    var inputs = $('input, textarea, select, button'), inputTo;

    // bind on keydown
    inputs.on('keydown', function(e) {

        // if we pressed the tab
        if (e.keyCode == 9 || e.which == 9) {
            // prevent default tab action
            e.preventDefault();

            if (e.shiftKey) {
                // get previous input based on the current input
                inputTo = inputs.get(inputs.index(this) - 1);
            } else {
                // get next input based on the current input
                inputTo = inputs.get(inputs.index(this) + 1);
            }

            // move focus to inputTo, otherwise focus first input
            if (inputTo) {
                inputTo.focus();
            } else {
                inputs[0].focus();
            }
        }
    });
});