聚焦元素阻止 role="alert" 内容被公布

Focusing Element Prevents role="alert" Content From Being Announced

$(document).ready(function() {
  $('#submitButton').click(function (){
    $('#password').focus();
    loadSRValidationMessages('#alertContainer', '.adhocError');
  });
});


function loadSRValidationMessages(n, t) {
    $(n).empty();
    var content = "";
    $(t).each(function() {
        var t = $(this).text();
        if (t.length > 0) {
          content += "<p>" + t + "<\/p>";
        }
    })
    $(n).append('<div id="alerts" role="alert" aria-atomic="true">' + content + '</div>');
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>

<div id="alertContainer">

</div>

<form id="loginForm">
  <input type="password" id="password" required><br/>
  <label class="adhocError">An example error.</label>
  <button type="button" id="submitButton">Submit</button>
</form>

我想提出的是一个问题,在这个问题中,似乎专注于某个元素会中断,或者可能会阻止屏幕 reader (NVDA) 宣布新的 role="alert" 内容。我进行了一些研究并查看了一些现有的类似问题,但尚未找到解决方案(理想情况下,让屏幕 reader 宣布新的警报内容并关注一个元素)。

我有一个使用 jQuery 的简单场景。代码是缩写的。如果您发现任何其他需要的信息,请告诉我。

我同意格雷厄姆的观点,如果焦点事件发生在设置role="alert"之后,那么警报将被中断。交换顺序 - 首先将焦点放在无效字段上,然后设置 role="alert".

在无效字段上同时使用aria-invalid="true",以及link使用aria-describedby字段的特定错误消息,它将在字段标签和值之后宣布错误. (我不建议 aria-labelledby 将错误消息 link 发送到字段,因为该属性用于对字段标签进行编程,而不是描述,如果您使用aria-labelledby 用于错误消息)。

<div class="sr-only" id="errorList" role="alert" aria-atomic="true"></div>

<form id="frmlogin">
// Add aria-invalid, aria-labelledby, aria-describedby attributes to the field
<input type="text" id="name" aria-invalid="false" aria-labelledby="somelabel" aria-describedby="errorList"/>
<button id="submitButton">Submit</button>
</form>

<script>
$('#submitButton').click(function () {
    if ($('#frmlogin').valid()) {
        $('#frmlogin').submit();
    }
    else {
        // Swap order of focus event and validation message so focus happens first
        var validator = $("#frmlogin").validate();
        validator.focusInvalid();
        // Set the aria-invalid attribute to the field that has the error
        $("#frmlogin").setAttribute("aria-invalid", "true");
        // Load the validation messages
        loadSRValidationMessages('#errorList', '.field-validation-error');
    }
});
</script>

由于 role="alert" 元素在某些浏览器/屏幕 reader 组合中的工作方式,更可靠的方法是添加完整的警报消息 及其容器 到页面,而不是更新容器内的文本。

如果您需要发出多个警报,您应该只向页面添加多个警报容器(并最终删除旧的警报容器,通过关闭/关闭按钮或当警报不再相关时)。

如果您想向页面添加多个更新,更好的策略是在页面上放置一个 aria-live="assertive" 区域并在其中添加/更新内容。

我发现在 Web 应用程序中处理屏幕 reader 更新的最佳方法是在页面上有一个 aria-live="assertive" 区域并在 [=32] 中有一个中央消息队列=] (JS),每条消息之间有延迟。

如果您有类似聊天应用程序之类的东西或您不想打断屏幕的不“紧急”东西 reader 可以添加具有第二个 aria-live="polite" 区域的用户(使用由 JS 处理的第二个消息队列)。

这样你最终会得到两个简单的队列来将消息添加到 messages.assertivemessages.polite 并且你将消除与许多 aria-live 区域相关的大量问题(包括role="alert" 个地区)。