Javascript NVDA屏幕阅读器未按预期切换到聚焦模式

Javascript NVDA屏幕阅读器未按预期切换到聚焦模式,javascript,accessibility,nvda,Javascript,Accessibility,Nvda,我有一个简单的代码块,在使用NVDA屏幕阅读器时,我试图让键盘可以访问 具体来说,我有一个角色为“button”的div,另一个角色为“button”的div嵌套在其中。每个div都有一个不同的onkeydown事件,当用户点击该div并按下“enter”时,该事件将被触发 当我没有打开NVDA屏幕阅读器时,这个键盘功能可以正常工作 但是,当我打开屏幕阅读器时,嵌套的keydown事件不再触发。相反,即使嵌套事件具有焦点,也只会激发父事件 但是,如果我手动将NVDA从“浏览模式”更改为“焦点模式

我有一个简单的代码块,在使用NVDA屏幕阅读器时,我试图让键盘可以访问

具体来说,我有一个角色为“button”的div,另一个角色为“button”的div嵌套在其中。每个div都有一个不同的onkeydown事件,当用户点击该div并按下“enter”时,该事件将被触发

当我没有打开NVDA屏幕阅读器时,这个键盘功能可以正常工作

但是,当我打开屏幕阅读器时,嵌套的keydown事件不再触发。相反,即使嵌套事件具有焦点,也只会激发父事件

但是,如果我手动将NVDA从“浏览模式”更改为“焦点模式”(通过按NVDA键+空格键),则按键事件将再次按需要工作

不幸的是,我不能期望使用NVDA的人知道手动切换到“聚焦模式”。它要么需要自动切换到“焦点模式”,要么需要在“浏览模式”下工作

代码如下:

HTML:


外分区
内分区
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);
功能输出(事件){
event.stopPropagation();
控制台日志(“外部分区”);
$('.result').html('outerdiv!

'); } 函数innerDivAction(事件){ event.stopPropagation(); console.log('internaldiv') $('.result').html('内部div!

'); } 函数keyEvent(事件,回调){ event.stopPropagation(); if(event.which==13){ 回调(事件); } } $('.outerDiv')。单击(outerDivAction); $('.innderDiv')。单击(innerDivAction);
您也可以在此处查看代码笔:

任何人能提供的任何帮助都将不胜感激

p、 美国。
我知道,如果我取下嵌套的div并将其移动,使其不再嵌套,而是成为第一个div的兄弟,那么一切都会按预期工作。不幸的是,这不是一个选择。div需要嵌套。

这不是NVDA中的错误

首先,不能有嵌套的可单击元素。明确地不能嵌套链接和按钮。不能在按钮中嵌套链接,也不能在链接中嵌套按钮。还有其他类型的值得研究,以供将来参考

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

您没有使用正确的元素(
),而是选择将
角色=按钮
置于
上。HTML验证器将传递您的代码,因为它可以有效地嵌套

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

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

错误:已看到开始标记
按钮
,但相同类型的元素已打开

我的建议是:

  • 为了不让它们筑巢
  • 将它们转换为
    s
  • 删除无效的
    tabindex=1
    (您不需要)
  • 取消对密钥代码的检查,因为
    免费提供密钥代码(包括字符32)
  • 把你的
    变成一个(有)
  • 并在按钮周围放置一个包装,以提供所需的视觉效果
重新编译的代码示例:

 <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>

外分区
内分区

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

感谢您花时间提供如此全面的解释。不幸的是,这将很难实现,因为我正在开发的实际规范是一个导航,其中一些项具有与其关联的下拉菜单,然后这些下拉项具有一个显示为弹出菜单的附加子菜单。这些项目中的每一项有时都可以是按钮(打开子菜单)或链接,因此目前我使用JavaScript将它们从role=“button”动态更改为role=“link”。元素嵌套的原因是因为子菜单是父项的子项。为了避免嵌套按钮,您是否可以重新构造代码以使用带有嵌套子列表(包含按钮)的列表?根据列表项的焦点(或按钮切换)控制可见性需要更多的努力,但它避免了@aardrian提到的嵌套交互内容。这里有一个代码笔来说明我的意思:@jennEDVT,你可能除了重构之外别无选择,因为你总是会遇到辅助技术的问题。Skerrvy提供了一个很好的快速演示,展示了您可以尝试的功能。另外,寻找可以修改的现有模式。例如,Adobe有一个复杂的大菜单,虽然对大多数网站来说太多了,但可能是一个合适的选择?感谢所有的建议和资源。听起来重构已经准备好了。请编辑一些代码,以帮助OP理解您的答案。只有链接的答案(指解决方案本身作为链接呈现,而不在帖子中解释的任何答案,即使存在其他非链接文本)通常不受欢迎,因为如果链接断开,这些答案可能会失效,并且在过去被用于自我推广。感谢您提供的资源!
 <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>