当关注后代交互元素时,jQuery keydown()不触发

要使应用程序符合W3C feed pattern,我必须创建键盘命令,以帮助屏幕阅读器用户浏览通过无限滚动加载的内容。参见工作示例here

在示例页面上,专注于列表中的一项,然后按PAGE_DOWN / PAGE_UP。看到?这样一来,您就可以浏览列表项,同时跳过每一项的内容。

如果您将重点放在其中一个项目中的按钮上并尝试从那里导航,则该按钮仍将在文章之间正确导航。 这就是我希望我的应用程序运行的方式,但事实并非如此。

我的代码与示例中的代码基本相同。 <article>中有多个<section role="feed">元素。使用jQuery,我将'keydown'事件附加到该<section>,称为#product-grid

$('#product-grid').keydown(function(event) {
  // Detect which key was pressed and execute appropriate action
});

HTML结构:

<section id="product-grid" role="feed">
  <article tabindex="-1">
    <a href="#"> having focus on this element prevents the 'keydown' event from firing
      <img src="..."/>
      <p>some text</p>
    </a>
    <div>
      if you click on this non-interactive section instead,the event fires correctly
    </div>
  </article>

  (...) many other <article> elements

</section>

在我的文章中,有一些锚点。如果您专注于它们并按某个键,则不会触发“ keydown”事件 。如果您将重点放在本文的其他任何地方,都可以。

据我了解,当后代项具有焦点时,父项(在这种情况下为#product-grid)也会成为焦点。我说得对吗?

我尝试过的事情:

  • 委托事件,使用on()捕获#product-grid中某些元素(包括锚元素)的keydown事件。
  • 将keydown事件处理程序直接附加到<article>中的锚点。当我专注于它并按一个键时,什么也没有发生。根据我在SO上搜索得到的结果,这应该可以工作。

这是一个小提琴,您可以在其中重现问题: https://jsfiddle.net/fgzom4kw/

重现该问题:

  1. 单击任何项​​目的灰色背景(而不是锚点)。红色轮廓将表明它已聚焦。
  2. 使用PAGE UP和PAGE DOWN来浏览项目。
  3. 按TAB键,将焦点放在锚点之一上。
  4. 焦点对准锚点后,尝试使用PAGE UP和PAGE DOWN键再次导航。

将此行为与W3C example的行为进行比较。


问题已解决。有两种解决方案:

我的方式:https://stackoverflow.com/a/59449938/9811172

<matrixRef> 还是公路! </matrixRef>

Twisty的方式:https://stackoverflow.com/a/59448891/9811172

检查注释是否有任何警告。

etric520 回答:当关注后代交互元素时,jQuery keydown()不触发

我无法复制您所说的问题。也就是说,您需要一个更广泛的选择器。基本上,如果用户专注于选择器后代的任何项目,则希望绑定keydown回调。请考虑以下内容。

$(function() {
  $("#product-grid").children().keydown(function(e) {
    var el = $(e.target);
    var ch = e.which;
    console.log("Event:",e.type,"HTML Target:",el.prop("nodeName"),"Char:",ch);
  });
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<section id="product-grid" role="feed">
  <article tabindex="-1">
    <a href="#"> having focus on this element prevents the 'keydown' event from firing
      <img src="..."/>
      <p>some text</p>
    </a>
    <div>
      if you click on this non-interactive section instead,the event fires correctly
    </div>
  </article>
  <article tabindex="-1">
    <a href="#"> having focus on this element prevents the 'keydown' event from firing
      <img src="..."/>
      <p>some text</p>
    </a>
    <div>
      if you click on this non-interactive section instead,the event fires correctly
    </div>
  </article>
</section>

使用$("#product-grid").children()作为选择器将获取所有子元素。然后,您可以根据需要绑定回调。

更新

根本问题是使用可Tabable元素时的当前焦点。看一个新的例子:https://jsfiddle.net/Twisty/m1w2b7rv/39/

JavaScript

$(function() {
  function setFocus(i) {
    $("[aria-posinset='" + i + "']").focus();
  }

  function navFocus(c,i,a) {
    switch (c) {
      case 33: // PAGE_UP
        if (i > 1) {
          setFocus(--i);
        }
        break;
      case 34: // PAGE_DOWN
        if (i < a) {
          setFocus(++i);
        }
        break;
      case 35: // END
        if (event.ctrlKey) {
          if (i !== a) {
            setFocus(a);
          }
        }
        break;
      case 36: // HOME
        if (event.ctrlKey) {
          if (i !== 1) {
            setFocus(1);
          }
        }
        break;
    }
  }

  $("#product-grid").on("keydown",function(event) {
    var el = $(event.target);
    if (el.prop("nodeName") == "A") {
      el = el.closest("article");
      el.focus();
    }
    var itemIndex = el.attr('aria-posinset');
    var itemCount = el.attr('aria-setsize');
    navFocus(event.which,itemIndex,itemCount);
  });
});

keydown事件正在冒泡并被触发,但是当前文章没有focus,因此没有一种很好的方法来获取文章的正确索引。因此,如果焦点位于链接上,我们必须首先将焦点重新设置为article元素。

,

我知道了。 enter image description here

答案在W3C示例的JavaScript代码中,就在这里:And so did Twisty

var focusedArticle =
  aria.Utils.matches(event.target,'[role="article"]') ?
    event.target :
    aria.Utils.getAncestorBySelector(event.target,'[role="article"]');

它试图找出按键时焦点所在的元素。

  1. 如果event.target<article>或(如示例中的)<div role="article">,它将使用该元素。
  2. 如果event.target不是文章,它将尝试检索其可以找到的“最近”文章。

这意味着,如果在按下一个键盘命令时文章中的交互式窗口小部件具有焦点,则将使用包含该窗口小部件的文章来代替。 article元素之所以特别,是因为它们包含我的事件处理程序(和屏幕阅读器)中使用的元数据(aria-posinset,aria-setsize)。诀窍在于该getAncestorBySelector方法。

这是现在的工作方式:

$('#product-grid').keydown(function(event) {
  var $focusedItem = $(event.target);

  // if focused element is not <article>,find the closest <article>
  if ($focusedItem.is(':not(article)')) {
    $focusedItem = $focusedItem.closest('article');
  }

  var itemIndex = $focusedItem.attr('aria-posinset');
  var itemCount = $focusedItem.attr('aria-setsize');

  (...)

..并且解决了问题:D


提出我的解决方案: https://www.w3.org/TR/wai-aria-practices-1.1/examples/feed/js/feed.js

本文链接:https://www.f2er.com/2876348.html

大家都在问