在日期选择器网格上移动时,屏幕阅读器不会读取单元格值

问题描述 投票:0回答:1

我有以下日期选择器。问题是,当运行屏幕阅读器(NVDA)时,当使用 keyboard 将日期选择器网格上的选择移动到不同的单元格时,屏幕阅读器只会显示“空白”。 (但是,如果我用鼠标悬停在单元格上,它确实会正确读取当天的数字。)

$(document).ready(function () {
    $('#ui-datepicker-div').addClass("month-calendar-widget");
    $(".month-calendar input").datepicker({
        showOtherMonths: true,
        minDate: 0,
        beforeShow: function () {
          $('#ui-datepicker-div').addClass("month-calendar-widget");
        }
    }).datepicker("setDate", convertDateToUTC(new Date()));
});

我希望通过使用

aria-label
beforeShowDay
属性添加到网格的每个单元格来解决此问题,如下所示:

  beforeShowDay: function(date) {
    var dateString = $.datepicker.formatDate('MM d, yy', date);
    return [true, '', dateString + "" + 'aria-label="' + dateString + '" role="gridcell" aria-selected="false"'];
  }

但是,这会导致以下错误的 html:

<td class=" " data-event="click" data-handler="selectDay" data-month="1" data-year="2024" title="February 16, 2024aria-label=&quot;February 16, 2024&quot; role=&quot;gridcell&quot; aria-selected=&quot;false&quot;">
    <a class="ui-state-default" href="#">16</a>
</td>

我错过了什么?

更新1: 为了进一步澄清,这是我的目标:

  • 运行 NVDA(只需 google
    nvda download
    并下载并运行它)
  • 例如,导航到迭戈在下面的答案中提供的日期选择器,然后使用 keyboard 移动到网格中的不同单元格:
  • 我期待 NVDA 说出日期,但它只是说“空白”。
jquery jquery-ui-datepicker screen-readers
1个回答
1
投票

由于 beforeShowDay 仅支持创建

title
属性的值,并且由于关闭引用以添加更多属性的技巧可能还不够,因为它是针对 td 而不是交互式元素,因此您可以只使用不同的策略来填充实际锚点上的
aria-label
属性。

您可以依赖选项

beforeShow
,它将运行在日期选择器实际显示之前一刻给出的函数:

https://api.jqueryui.com/datepicker/#option-beforeShow

演出前 类型:函数(元素输入,对象安装)

一个接受输入字段和当前日期选择器实例的函数 并返回一个选项对象来更新日期选择器。这是 在显示日期选择器之前调用。

这样的函数将迭代日历中包含用户可以选择的每一天(锚元素)的每个交互元素,并向其添加一个

aria-label
属性,其值来自其父单元格上的
title
属性(设置像你一样通过
beforeShowDay
)。

这是正在处理的日单元格的示例:

<td
  class="ui-datepicker-days-cell-over ui-datepicker-current-day ui-datepicker-today"
  title="February 9, 2024"
  data-handler="selectDay"
  data-event="click"
  data-month="1"
  data-year="2024">
    <a
      class="ui-state-default ui-state-highlight ui-state-active" href="#"
      aria-label="February 9, 2024">9</a>
</td>

可以选择通过像这样从每个组件中挑选零件来制作日期,但这有点过分了:

const year = parentCell.attr('data-year');
const month = parentCell.attr('data-month');
const day = $(this).text();

const paddedMonth =
  (parseInt(month, 10) + 1).toString().padStart(2, '0'); 
const paddedDay = day.padStart(2, '0'); 

//previously grab day info and format the correponding date
const formattedDate = `${paddedDay}/${paddedMonth}/${year}`;

//populate the day anchor with the aria-label containing dd/mm/yyyy
$(this).attr('aria-label', formattedDate);

作为进一步的操作,我还处理了

onSelect
事件,一旦在日期选择器中选择了日期,该事件就会将
aria-label
属性添加到输入元素中。可能不需要它,因为屏幕阅读器可能已经可以读取输入元素的值。

请使用屏幕阅读器提供反馈,以便我们了解

aria-label
是否足够或是否需要采取进一步措施。顺便说一句,样板现在已经非常成熟,可以处理添加更多信息,我们只需要了解哪些信息即可。

$(document).ready(function () {
  $(".month-calendar input").datepicker({
    showOtherMonths: true,
    minDate: 0,
    
    //on date selected
    onSelect: function(dateText, inst) {
      const value = "Selected date: " + dateText;
      //set the aria-label of the input element with the date picked
      $(this).attr("aria-label", value);
    },
    
    //before showing each day in the datepicker grid
    beforeShowDay: function(date) {
      //return a value used to populate the title attr of the day td
      const dateString = $.datepicker.formatDate('MM d, yy', date);
      return [true, '', dateString];
    },
    
    //before showing the days grid
    beforeShow: function(input, inst){
      //set timeout is to wait for the ui to be rendered
      setTimeout(function() {
        //select the calendar element
        const daysGrid = $('#ui-datepicker-div .ui-datepicker-calendar');
        //fetch all the anchors being interactive days
        const interactiveDays = $(daysGrid).find('td a');
        
        //for each one of them
        interactiveDays.each(function(){
          const parentCell = $(this).closest('td');                                    
          //set the aria-label as the same value on the title attr of its parent
          $(this).attr('aria-label', $(parentCell).attr('title'));
          
          //...other aria attributes could be set at this point...
        });
      }); 
    }

  }).datepicker("setDate", new Date());
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<link rel="stylesheet" href="https://code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<div class="month-calendar">
  <input type="text" id="datepicker">
</div>

© www.soinside.com 2019 - 2024. All rights reserved.