NVDA屏幕阅读器不能可预测地切换到焦点模式

3
我有一段简单的代码,我正在尝试在使用NVDA屏幕阅读器时使其可访问。具体来说,我有一个带有“button”角色的div,其中嵌套了另一个带有“button”角色的div。每个div都有不同的onkeydown事件,当用户切换到该div并按下“enter”键时触发。当我没有打开NVDA屏幕阅读器时,这种键盘功能都可以正常工作。然而,当我打开屏幕阅读器时,嵌套的keydown事件不再触发。相反,即使嵌套事件具有焦点,只有父事件会触发。但是,如果我手动将NVDA从“浏览模式”更改为“焦点模式”(通过按下NVDA键+空格键),则键事件再次按预期工作。不幸的是,我不能指望使用NVDA的人知道如何手动切换到“焦点模式”。它需要自动切换到“焦点模式”,或者需要在“浏览模式”下工作。以下是代码:
<div role="button" 
   tabindex="1" 
   onkeydown="keyEvent(event, outerDivAction)"
   class="outerDiv">
   Outer Div

   <div role="button" 
     tabindex="1"
     onkeydown="keyEvent(event, innerDivAction)"
     class="innderDiv">
     Inner Div</div>
   </div>

<div class="result"></div>

JavaScript:

function outerDivAction(event) {
  event.stopPropagation();
  console.log('outer div');
   $('.result').html('<p>outer div!</p>');
}

function innerDivAction(event) {
  event.stopPropagation();
  console.log('inner div')
  $('.result').html('<p>inner div!</p>');
}

function keyEvent(event, callback) {
  event.stopPropagation();
  if (event.which === 13) {
    callback(event);
  }
}

$('.outerDiv').click(outerDivAction);

$('.innderDiv').click(innerDivAction);

您可以在此处查看Codepen:http://codepen.io/jennEDVT/pen/Yprova 如果有任何人能提供帮助,将不胜感激! p.s. 我知道,如果我将嵌套的div移到它不再是嵌套的,而是第一个div的同级元素,则一切都会按预期工作。 不幸的是,这不是一个选项。 这个div需要被嵌套。
2个回答

6

这不是NVDA的错误。

首先,您不能有嵌套的可点击元素。具体来说,您不能有嵌套的交互内容。您不能嵌套链接和按钮。您不能在按钮中嵌套链接,也不能在链接中嵌套按钮。还有其他一些值得参考的交互式内容

您可能会发现,您的代码技术上是有效的,但这只是因为您所编写的是一个谎言。

您选择在<div>上放置role=button,而不是使用正确的元素(<button>)。HTML验证器将通过您的代码,因为嵌套<div>是有效的。

但是,通过为它们每个都指定role=button,您已经指示用户代理将它们视为<button>(减去所有附带的好处,如可访问性、键处理程序、语义等)。

现在让我们回到并将该代码作为用户代理看到的内容(作为嵌套的<button>)进行验证。 W3C Nu HTML检查器将失败(我知道,因为我运行了一个测试):

错误:看到开始标记button,但已经打开了相同类型的元素。

我的建议是:

  • 不要嵌套它们,
  • 将它们转换为<button>
  • 删除无效的tabindex=1(您不需要),
  • 删除键码检查,因为<button>可以免费提供它(包括字符32),
  • 将您的<div class="result">变成ARIA实时区域(这里有一些提示),
  • 并在按钮周围放置包装器,以获得所需的视觉效果。

样例重构代码:

 <div class="wrapper">
   <button class="outerDiv">
     Outer Div
   </button>
   <button class="innderDiv">
     Inner Div
   </button>
 </div>

 <div class="result" role="alert" aria-live="assertive"></div>

感谢您花时间提供如此全面的说明。不幸的是,由于我正在开发的实际规格是带有一些关联下拉菜单项目的导航,然后下拉菜单项目有一个附加的子菜单显示为弹出菜单。而且这些项目中的每一个有时都可以是按钮(打开子菜单)或链接,所以目前我使用JavaScript动态地将它们从role =“ button”更改为role =“ link”。元素嵌套的原因是子菜单是父项的子级。 - jennEDVT
为了避免嵌套按钮,您可以重构代码,使用包含按钮的嵌套子列表的列表。这需要一些额外的工作来根据列表项的焦点(或按钮切换)控制可见性,但它避免了@aardrian提到的嵌套交互内容。这是一个CodePen示例,以说明我的意思:http://codepen.io/anon/pen/KNyZYm - Skerrvy
@jennEDVT,你可能别无选择,只能进行重构,因为你总会遇到辅助技术方面的问题。Skerrvy有一个很好的快速演示,你可以尝试一下。此外,寻找现有的模式并进行修改也是一个不错的选择。例如,Adobe有一个复杂的超级菜单,虽然对于大多数网站来说过于繁琐,但可能适合你的需求?http://adobe-accessibility.github.io/Accessible-Mega-Menu/ - aardrian
感谢所有的建议和提供的资源。听起来需要进行重构。 - jennEDVT

1
如果您感兴趣,WAI-ARIA Authoring Practices(APG)提供了有关如何使各种设计模式可访问的指南。它还包括一个关于您所描述的内容:菜单或菜单栏,其中包含带有子菜单的菜单的代码示例。

请在您的答案中编辑一些代码,以帮助原帖作者。通常不赞成仅提供链接的答案(即将解决方案本身作为链接呈现而不在帖子本身中解释,即使存在其他非链接文本),因为它们可能会失效如果链接失效,并且过去曾用于自我推广。 - Justin Time - Reinstate Monica
感谢提供资源! - jennEDVT

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