【问题标题】:Multiple forms on one HTML page: how to restrict tabbing to a single form?一个 HTML 页面上的多个表单:如何将选项卡限制为单个表单?
【发布时间】:2011-03-30 09:29:29
【问题描述】:

我目前正在构建的网站与常规网站略有不同。所有网站内容都在一个 index.php 文件中,而不是有多个单独的页面,并且使用绝对定位和 javascript,用户在网站上从一个页面“平移”到另一个页面。

页面中也有几种不同的形式。有人告诉我不要担心为禁用 Javascript 的人提供服务,因此我们为页面上的所有表单选择了 jQuery 和 JSON 网络服务。这一切现在都可以完美运行,但存在一个轻微的可用性问题:制表符。

由于有多个表单,从一个输入字段切换到下一个输入字段可能会导致用户在到达表单末尾并再次切换时突然跳转到站点的完全不同部分。这在 Firefox 和 Safari 中尤其烦人,因为在选项卡时按钮和单选按钮会被忽略。

所以这是我的问题:有人知道将用户的焦点限制在单个表单元素上的方法吗?

【问题讨论】:

  • 在切换时 Firefox 忽略收音机?在我看来不是...
  • 嗯,现在我在 Mac 上的 Firefox 4 上也没有看到。但有人告诉我 3.6 做到了。
  • 从可访问性的角度来看,这可能是一个问题:键盘用户如何选择第二种形式?似乎他们会卡在第一种形式中,无法超越。

标签: javascript html accessibility


【解决方案1】:
我目前正在建设的网站与常规网站略有不同。所有网站内容都在一个 index.php 文件中,而不是拥有多个单独的页面,并且使用绝对定位和 javascript,用户在网站上从一个页面“平移”到另一个页面。

这是一种替代方法,可以回避这个问题,最终可能更容易获得。

我假设您在该页面上有一些元素用于触发从一个子页面到另一个子页面的平移?

如果是这样,这里的基本想法是,当任何页面“滚动”时,使用 display:none 或 visibility:hidden 隐藏那个“子页面”(可能是某个容器 DIV)。

这里的关键问题是,使用这两种方法中的任何一种隐藏的内容都是不可选项卡的,因此用户不会意外地使用选项卡进入这些隐藏的页面。同样重要的是,从可访问性的角度来看,屏幕阅读器知道会忽略以这种方式标记的内容,因此他们只会阅读当前页面(这与有视力的用户所看到的一致),而不是整个页面。

【讨论】:

  • 这就像一个魅力,并且在可访问性方面要好得多,因为现在 tab 键只在屏幕上的元素和浏览器的 UI 之间循环。谢谢!
  • 聪明人!给你加一个,先生。我遇到了与 OP 类似的问题 - 这是一个很好的解决方案。
【解决方案2】:

为什么不将每个表单的 tabindex 增加 100?

所以表格 1 的 tabindeces 范围为 100-112,表格 2 的 tabindex 范围为 200-234,表格 3 的 tabindex 范围为 300-314...

【讨论】:

    【解决方案3】:

    好的,我决定编写自己的解决方案,它适用于所有主要浏览器(Safari 除外,稍后会详细介绍)。基本上,它的工作原理是为表单中的最后一个“可选项卡”元素分配一个类,该元素通常是提交按钮,称为“lastInForm”。简单的 HTML 如下所示:

    <form action="action.php">
    <fieldset><input id="input1" name="input1" type="text" placeholder="text here" /></fieldset>
    <fieldset><input id="input2" name="input2" type="text" placeholder="text here" /></fieldset>
    <fieldset><input id="input3" name="input3" type="text" placeholder="text here" /></fieldset>
    
    <button class="lastInForm" type="submit">I'm last</button>
    </form>
    

    使用最新版本的 jQuery,我监听那个 .lastInForm 元素的 keydown 事件并检查对应于 tab 键的 keyCode 9。当我收到该事件时,我查找最近的表单元素,查找所述表单中的第一个输入元素,并将焦点应用于它。

    像这样:

    $(document).ready(function(evt){
    
    $('.lastInForm').live('keydown', function(evt){
        if(evt.keyCode === 9){
            evt.preventDefault();
    
            var form = $(this).closest('form');
            var input = $('input:first', form);
    
            if(input !== undefined){
                input.focus();
            }
        }
    });
    });
    

    ... 这会巧妙地形成一个表单,您可以使用 tab 键循环遍历元素。

    现在我之前提到它适用于除 Safari 之外的所有主要浏览器。这样做的原因是 Safari 默认情况下不允许您使用选项卡切换到除文本字段之外的任何元素。要启用此行为,您必须检查:

    Preferences > Advanced > Universal Access: Press Tab to highlight each item on a webpage.
    

    为什么 Apple 选择默认禁用这种有用的辅助功能,我无法理解,但我所知道的是,如果用户启用此设置,我的脚本也适用于他们。

    【讨论】:

    • 现在,我意识到对于 99% 的网站并不完全推荐强制这种非默认行为,但对于这个极端情况,我正在研究它就像一种魅力。希望有人能从中受益。
    • 可能的缺点:在大多数浏览器中(IE、Chrome、Firefox、Safari - Opera 处理选项卡的方式不同...),当您跳到页面末尾时,再次点击选项卡会将您带到浏览器 UI - 通常是地址栏,然后从那里返回页面。这将对此产生干扰。 (用户仍然可以点击一些浏览器热键直接进入地址栏,因此它们并没有完全被困住。)您可能需要考虑的其他事项:shift-tab 向相反方向移动,所以你需要以类似但互补的方式处理第一个字段。 (更多在下一条评论)
    • 另外,如果用户确实直接转到地址栏(某些 Chrome/Firefox 中的 Ctrl-L,IE 中的 F4)并从那里进入 doc(使用 tab 或 shift-tab),则没有保证浏览器将返回到最后聚焦的元素;一些浏览器从顶部开始。其他表单在不使用时是否对用户可见?如果它们不可见,那么在这些表单上使用 display:none 或 visibility:false 将隐藏它们并将它们完全从 Tab 键顺序中移除,从而使所有这些边缘情况变得毫无意义。
    • 我也不确定这是否适用于移动设备,使用“下一个/上一个”按钮。
    【解决方案4】:

    在您的 (X)HTML 中使用 tabindex

    这在 Seamonkey 2.0.11 和 Chrome 10.0 中完美运行

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
        "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
    
    <head>
        <title>untitled</title>
        <meta http-equiv="content-type" content="text/html;charset=utf-8" />
        <style type="text/css">
            /* absolute positioning */
            #form1 { position: absolute; bottom: 0; right: 0; width: 40%; }
            #form2 { position: absolute; top: 100px; left: 30px; width: 40%; }
           /* floats
            #form1 {float: right; width: 40%; }
            #form2 {float: left; width: 40%; } */
        </style>
    </head>
    
    <body>
    
    <form id="form1" action="#" method="get">
    <fieldset>
    <legend>Form 1</legend>
    <div><label for="t1">T1</label><input type="text" id="t1" name="t1" tabindex="1" /></div>
    <div><label for="t3">T3</label><input type="text" id="t3" name="t3" tabindex="3" /></div>
    <div><label for="t2">T2</label><input type="text" id="t2" name="t2" tabindex="2" /></div>
    <input type="submit" tabindex="4" />
    </fieldset>
    </form>
    
    <form id="form2" action="#" method="get">
    <fieldset>
    <legend>Form 2</legend>
    <div><label for="t6">T6</label><input type="text" id="t6" name="t6" tabindex="6" /></div>
    <div><label for="t5">T5</label><input type="text" id="t5" name="t5" tabindex="5" /></div>
    <input type="submit" tabindex="7" />
    </fieldset>
    </form>
    
    </body>
    
    </html>
    

    【讨论】:

    • 那行不通。阅读我的问题:同一页面上有多个表单。如果我在每个表单中使用相同的 tabindices(即第一个输入获取 tabindex 1,第二个输入 tabindex 2,等等),用户会不断在每个表单之间切换,这会更糟。如果我使用顺序 tabindices,结果与我根本没有使用 tabindex 一样。
    • 我读了你的问题.. 你当然应该重复索引,标准的兼容浏览器应该遵循 w3c 所说的索引。我会在测试页面上试试。
    • @gillesv:添加了测试页面,如果这在您的页面中不起作用,则可能是由于您的 (X)HTML 中的错误
    • 结果保持不变:我从 T1 到 T2 到 T3 到 T4 再到 T5。它不应该让我从 T4 切换到 T5,因为 T5 的形式不同。如果我原来的问题不清楚,我很抱歉。我在 Chrome 9 和 Firefox 4 上都试过了。不过感谢您的努力。
    • 因为 T5 在页面的另一侧是 2000 像素,并且不小心切换到不相关的表单完全改变了用户所处的上下文。我意识到这个网站听起来像是一个可访问性的噩梦,但它是为了广告活动和仅键盘导航不是优先事项。我只需要 tabindex 在同一个表单中循环,而不是跳转到不同的表单。
    猜你喜欢
    • 1970-01-01
    • 2011-01-27
    • 1970-01-01
    • 2012-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多