如何使用 WAI-ARIA 创建完全可访问的嵌套下拉列表



几天前,我开始在互联网上搜索有关WAI-ARIA的教程和文档,以获取任何类型的AJAX请求。

我习惯于使用 jQuery 和 AJAX 编写嵌套下拉列表。它运行良好,但无法本机访问。例如,我们需要使用 WAI-ARIA 特定的标签来"启用"各种动态内容的可访问性,例如 AJAX。

我的要求之一如下:

  • 假设我有一个状态下拉列表,该下拉列表使用 onchange 事件更新区域下拉列表。如何使用 WAI-ARIA 和 jQuery 与屏幕阅读器交互,以告知用户区域下拉列表已更新?

我的2c是咏叹调控制可能更适合这里。

您在此处描述的 UI 听起来与您在线购买产品时经常发现的国家/州选择非常相似。这些的典型模式是:

<label for="country">Country:</label>
<select id="country" aria-controls="state">
    <option value="">Select a country...</option>
    <option value="Andorra">Andorra</option>
    <option value="Belgium">Belgium</option>
    ...
</select>
<br>
<label for="state">State:</label>
<select id="state">
    <option value="">(Select a country first)</option>
    ... options here populated when country changes ...
</select>

这里有几点需要注意:

  • 我在每次选择的开头使用"占位符"选项条目。这有两个好处。首先,它提供了关于用户应该如何使用 UI 的强化文档 - 如果他们以某种方式最终首先查看第二个字段,它会将他们定向到第一个字段。其次,它避免了用户意外选择默认值:您的代码可以检查默认的"选择..."。是提交的一个,并提醒用户选择一个实际值。此外,它还隐藏了内容选项正在从用户更改的事实。

  • 不过,这里最主要的是,这两个选择之间的关系应该从表单或页面的上下文中清楚。无论是否看到,遇到此类表单的用户都不需要明确告知状态选择的内容已更改,因为他们会期望从表单设计和上下文中更改。人们知道州是特定于一个国家的(例如,德国没有"加利福尼亚"),与县类似,因此已经对这些工作方式有了期望。

使用aria-live在这里感觉不合适。它实际上是为异步更新的页面区域设计的,否则用户将不得不不断轮询,来回阅读以扫描更改。聊天面板可能是典型的例子:当另一端的某人出现消息时,您希望屏幕阅读器在消息出现时读出消息,而不必手动搜索它。相比之下,此处的 UI 更加同步;当国家/地区发生变化时,州将在那里填充,然后(*),这是预期行为。

ARIA确实有一个aria-controls="ids..."属性,这似乎更适合:规范说当一个控件影响另一个控件的可见性或内容时,它用于,这似乎描述了这里发生的事情。我不知道是否有任何屏幕阅读器支持这一点,或者当它出现时他们会读出什么 - 我可能会研究这个并在以后更新这个答案。但无论如何,前面的要点适用,无论如何,表单的行为和语义应该是显而易见的。

--

(*) 仍然存在一个问题,即如果您异步更新内容 - 例如。 通过 Ajax 而不是从页面上已加载的数组获取县列表,那么在选择国家/地区和结果可用于下一个选择之间可能存在延迟。 Aria-Live 在这里感觉又不是正确的解决方案, 由于您不想读出新内容,因此您只想让用户知道选择现在可供使用。

对于这个用例,我会添加aria-livearia-atomic属性,示例代码:

<select id="foo" aria-live="assertive" aria-atomic="true">
    <option value="nw">Northwest</option>
    <option value="ne">Northeast</option>
    <option value="se">Southeast</option>
    <option value="sw">Southwest</option>
</select>

我认为assertivearia-live 属性的正确值,但polite可能是合适的。aria-atomic属性用于告诉浏览器/AT,当发生更改时,该区域必须作为一个整体呈现。您还可以考虑最初对选择使用aria-disabled: true,然后在使用与 State 选择关联的值更新它之前将其切换到 false

编辑

好的,我已经使用NVDA,IE9和Firefox 13.01做了一些测试。我目前没有可用的 JAWS,所以如果有人可以使用 JAWS 测试页面,那就太好了。据我所知,VoiceOver 尚不支持aria属性刚刚在 10.7(Lion)上使用 Chrome + Voiceover 进行了测试,并且 Voiceover 似乎确实支持 aria-live .

此处提供测试页面。

我使用了一个简单的脚本来模拟将数据加载到区域选择中(使用对象):

var options = [],
    regions = {
    'nw': 'Northwest',
    'ne': 'Northeast',
    'se': 'Southeast',
    'sw': 'Southwest'
}
$(document).ready(function() {
    $.each(regions, function(key, value) {
        options.push('<option value="'+ key +'">'+ value +'</option>');
    });
    $('.block').on('change, focusout', '.states', function() {
        $(this).parent().children('.regions')
            .attr({'disabled': false, 'aria-disabled': false})
            .html(options.join(''));
    });
    window.setTimeout(
        function() {
            $('#speak').text('assertive!');
        },
        3000
    );
});

了一下后的一些观察(在屏幕阅读器方面,我当然不是专家,所以如果我错过了什么,请告诉我)......

  • 不建议使用 HTML disabled 属性,因为您确实不希望在状态选择聚焦之前加载区域数据,并且由于在聚焦时禁用了关联的区域选择,因此在按 Tab 键转到下一个控件时会跳过它(您可以在下面的录音中听到这一点。奇怪的是,Firefox 会宣布区域选择的值,即使它没有集中它。

  • 我认为 politeassertive 之间的行为没有区别,或者在没有 aria-live 属性的示例中。我以为FF13和IE9都支持aria-live,但从最后的代码($('#speak')...)来看,IE9似乎不支持?

  • 也许通过 AJAX 模拟加载的延迟是一件好事。

您可以收听录音:IE9,Firefox 13

最新更新