使用 mat-date-range-input 但 JAWS reader 首先使用 JAWS-e 读取结束日期(下一个编辑框)
Using mat-date-range-input but the JAWS reader first reads the end date with JAWS-e (next edit box)
我有一个带有 mat-date-range-input 的组件。
我的客户使用 JAWS reader 并使用 JAWS-e(下一个编辑框)进行导航。
当他们这样做时,JAWS 首先读取 mat-date-range-input 的 'end date'。再次按下 JAWS-e 时会读取 'start date'。我原以为 'start date' 会先被阅读。
下面是 html 中带有 mat-date-range-input 的部分。
我首先觉得 aria-hidden=true 的跨度可能是问题的原因,但删除它并没有解决问题。
有没有人遇到过这种情况?有解决办法吗?
谢谢&问候,
内勒克
<div _ngcontent-ynn-c151="" class="ng-star-inserted" style="">
<mat-form-field _ngcontent-ynn-c151="" appearance="fill" class="mat-form-field date-picker ng-tns-c64-23 mat-primary mat-form-field-type-mat-date-range-input mat-form-field-appearance-fill mat-form-field-can-float mat-form-field-has-label mat-form-field-hide-placeholder ng-star-inserted">
<div class="mat-form-field-wrapper ng-tns-c64-23">
<div class="mat-form-field-flex ng-tns-c64-23">
<div class="mat-form-field-infix ng-tns-c64-23">
<mat-date-range-input _ngcontent-ynn-c151="" role="group" class="mat-date-range-input ng-tns-c64-23" aria-labelledby="mat-form-field-label-37" data-mat-calendar="mat-datepicker-2">
<div cdkmonitorsubtreefocus="" class="mat-date-range-input-container">
<div class="mat-date-range-input-start-wrapper">
<input _ngcontent-ynn-c151="" type="text" matstartdate="" name="startDate" class="mat-start-date mat-date-range-input-inner startDate ng-touched ng-pristine ng-valid" placeholder="startdatum" id="mat-date-range-input-0" aria-haspopup="dialog" min="1800-01-01T00:00:00+00:19" max="2022-03-02T00:00:00+01:00">
<span aria-hidden="true" class="mat-date-range-input-mirror">startdatum</span>
</div>
<span class="mat-date-range-input-separator mat-date-range-input-separator-hidden">–</span>
<div class="mat-date-range-input-end-wrapper">
<input _ngcontent-ynn-c151="" type="text" matenddate="" name="endDate" class="mat-end-date mat-date-range-input-inner endDate ng-touched ng-pristine ng-valid" placeholder="einddatum" aria-haspopup="dialog" min="1800-01-01T00:00:00+00:19" max="2022-03-02T00:00:00+01:00">
</div>
</div>
</mat-date-range-input>
<mat-date-range-picker _ngcontent-ynn-c151="" class="ng-tns-c64-23"></mat-date-range-picker>
<span class="mat-form-field-label-wrapper ng-tns-c64-23">
<label class="mat-form-field-label ng-tns-c64-23 mat-empty mat-form-field-empty ng-star-inserted" id="mat-form-field-label-37" for="mat-date-range-input-0" aria-owns="mat-date-range-input-0">
<mat-label _ngcontent-ynn-c151="" class="ng-tns-c64-23 ng-star-inserted">Datum (max 28 dagen)</mat-label>
</label>
</span>
</div>
<div class="mat-form-field-suffix ng-tns-c64-23 ng-star-inserted">
<mat-datepicker-toggle _ngcontent-ynn-c151="" matsuffix="" class="mat-datepicker-toggle ng-tns-c64-23" data-mat-calendar="mat-datepicker-2">
<button mat-icon-button="" type="button" class="mat-focus-indicator mat-icon-button mat-button-base" aria-haspopup="dialog" aria-label="Open calendar" tabindex="0">
<span class="mat-button-wrapper">
<mat-icon _ngcontent-ynn-c151="" role="img" matdatepickertoggleicon="" class="mat-icon notranslate material-icons mat-icon-no-color" aria-hidden="true" data-mat-icon-type="font">date_range</mat-icon>
</span>
<span matripple="" class="mat-ripple mat-button-ripple mat-button-ripple-round"></span>
<span class="mat-button-focus-overlay"></span>
</button>
</mat-datepicker-toggle>
</div>
</div>
<div class="mat-form-field-underline ng-tns-c64-23 ng-star-inserted">
<span class="mat-form-field-ripple ng-tns-c64-23">
</span>
</div>
<div class="mat-form-field-subscript-wrapper ng-tns-c64-23">
<div class="mat-form-field-hint-wrapper ng-tns-c64-23 ng-trigger ng-trigger-transitionMessages ng-star-inserted" style="opacity: 1; transform: translateY(0%);">
<div class="mat-form-field-hint-spacer ng-tns-c64-23"></div>
</div>
</div>
</div>
</mat-form-field>
</div>
无论您使用什么屏幕 reader,都会出现此问题,而不仅仅是 JAWS。
Angular Material就是mis-usingaria-owns attribute. You can test this on their "Date Range Selection”的例子。他们的代码基本上是这样的:
<input placeholder="Start date" id="startdate">
<input placeholder="End date">
<label for="startdate" aria-owns="startdate">Enter a date range</label>
和all ARIA attributes一样,aria-owns
只是对屏幕的提示reader。 ARIA 属性应该可以帮助屏幕 reader 理解页面的组织。 ARIA 属性不会影响页面的外观,也不会影响浏览器的行为。在这种特殊情况下,ARIA 属性不会影响浏览器的 Tab 键顺序。
因此无论 ARIA 属性是否存在,当您通过日期范围小部件 tab 时,tab 顺序(默认)与 DOM 顺序相同.在这种情况下,<input placeholder="Start date" id="startdate">
是第一个,因此它首先接收选项卡焦点。下一个 选项卡 转到下一个 DOM 元素,即 <input placeholder="End date">
。 <label>
不是制表位。
这一切都按预期工作。
如果您使用屏幕 reader 命令进行导航,就会变得奇怪。屏幕 reader 用户可以正常使用 tab 键,他们会按正确的顺序听到内容。但是,如果屏幕 reader 用户尝试导航 DOM(实际上是 AOM - 可访问性对象模型),无论是通过 E 键(通常是 INS+E) 或 downArrow 键,then aria-owns
会影响东西,因为ARIA属性会影响画面reader.
另一个需要理解的概念是 AOM。辅助功能对象模型类似于文档对象模型 (DOM),只是它本质上是 DOM 的 子集 。并非 DOM 上的所有内容都会出现在 AOM 中。当您使用屏幕 reader 命令时,屏幕 reader 会与 AOM 交互。
例如,如果您有一个带有 display:none
的元素,该元素仍然存在于 DOM 中。您仍然可以对其调用 getObjectByName()
。但是该元素将从 AOM 中删除,这样屏幕 reader 用户就不能再使用屏幕 reader 命令导航到该元素。
如 OP 中所述,aria-hidden
也发生了类似的事情。将 aria-hidden
设置为 true 将从 AOM 中 删除 该元素,因此屏幕 reader 不再认为它存在。
因此,如前所述,可以使用 downArrow 键(或专门用于输入字段的 E 键)来遍历 AOM .它让用户可以像浏览文本文档一样浏览 AOM。可以把它想象成在文本编辑器中阅读 HTML 文件,然后使用 向下箭头 键转到编辑器中的下一行。
aria-owns
更改 AOM 顺序而不实际更改 DOM。 aria-owns
可让您影响 AOM 中的 parent/child 关系并模仿一个元素 在 另一个元素之后,即使它实际上不在 HTML 中文件。
所以在这种情况下,即使 DOM 物理上看起来像这样:
<input placeholder="Start date" id="startdate">
<input placeholder="End date">
<label for="startdate" aria-owns="startdate">Enter a date range</label>
AOM 将如下所示:
<input placeholder="End date">
<label for="startdate" aria-owns="startdate">Enter a date range</label>
<input placeholder="Start date" id="startdate">
因为 <label>
上的 aria-owns="startdate"
导致开始日期元素 在 标签之后。
是的,这很复杂,但是一旦您了解了导致它的原因,它就有点简单了。
Is there a solution?
否 :-( 除了联系 google 让他们知道他们没有正确使用 aria-owns。
我有一个带有 mat-date-range-input 的组件。 我的客户使用 JAWS reader 并使用 JAWS-e(下一个编辑框)进行导航。 当他们这样做时,JAWS 首先读取 mat-date-range-input 的 'end date'。再次按下 JAWS-e 时会读取 'start date'。我原以为 'start date' 会先被阅读。
下面是 html 中带有 mat-date-range-input 的部分。 我首先觉得 aria-hidden=true 的跨度可能是问题的原因,但删除它并没有解决问题。
有没有人遇到过这种情况?有解决办法吗?
谢谢&问候, 内勒克
<div _ngcontent-ynn-c151="" class="ng-star-inserted" style="">
<mat-form-field _ngcontent-ynn-c151="" appearance="fill" class="mat-form-field date-picker ng-tns-c64-23 mat-primary mat-form-field-type-mat-date-range-input mat-form-field-appearance-fill mat-form-field-can-float mat-form-field-has-label mat-form-field-hide-placeholder ng-star-inserted">
<div class="mat-form-field-wrapper ng-tns-c64-23">
<div class="mat-form-field-flex ng-tns-c64-23">
<div class="mat-form-field-infix ng-tns-c64-23">
<mat-date-range-input _ngcontent-ynn-c151="" role="group" class="mat-date-range-input ng-tns-c64-23" aria-labelledby="mat-form-field-label-37" data-mat-calendar="mat-datepicker-2">
<div cdkmonitorsubtreefocus="" class="mat-date-range-input-container">
<div class="mat-date-range-input-start-wrapper">
<input _ngcontent-ynn-c151="" type="text" matstartdate="" name="startDate" class="mat-start-date mat-date-range-input-inner startDate ng-touched ng-pristine ng-valid" placeholder="startdatum" id="mat-date-range-input-0" aria-haspopup="dialog" min="1800-01-01T00:00:00+00:19" max="2022-03-02T00:00:00+01:00">
<span aria-hidden="true" class="mat-date-range-input-mirror">startdatum</span>
</div>
<span class="mat-date-range-input-separator mat-date-range-input-separator-hidden">–</span>
<div class="mat-date-range-input-end-wrapper">
<input _ngcontent-ynn-c151="" type="text" matenddate="" name="endDate" class="mat-end-date mat-date-range-input-inner endDate ng-touched ng-pristine ng-valid" placeholder="einddatum" aria-haspopup="dialog" min="1800-01-01T00:00:00+00:19" max="2022-03-02T00:00:00+01:00">
</div>
</div>
</mat-date-range-input>
<mat-date-range-picker _ngcontent-ynn-c151="" class="ng-tns-c64-23"></mat-date-range-picker>
<span class="mat-form-field-label-wrapper ng-tns-c64-23">
<label class="mat-form-field-label ng-tns-c64-23 mat-empty mat-form-field-empty ng-star-inserted" id="mat-form-field-label-37" for="mat-date-range-input-0" aria-owns="mat-date-range-input-0">
<mat-label _ngcontent-ynn-c151="" class="ng-tns-c64-23 ng-star-inserted">Datum (max 28 dagen)</mat-label>
</label>
</span>
</div>
<div class="mat-form-field-suffix ng-tns-c64-23 ng-star-inserted">
<mat-datepicker-toggle _ngcontent-ynn-c151="" matsuffix="" class="mat-datepicker-toggle ng-tns-c64-23" data-mat-calendar="mat-datepicker-2">
<button mat-icon-button="" type="button" class="mat-focus-indicator mat-icon-button mat-button-base" aria-haspopup="dialog" aria-label="Open calendar" tabindex="0">
<span class="mat-button-wrapper">
<mat-icon _ngcontent-ynn-c151="" role="img" matdatepickertoggleicon="" class="mat-icon notranslate material-icons mat-icon-no-color" aria-hidden="true" data-mat-icon-type="font">date_range</mat-icon>
</span>
<span matripple="" class="mat-ripple mat-button-ripple mat-button-ripple-round"></span>
<span class="mat-button-focus-overlay"></span>
</button>
</mat-datepicker-toggle>
</div>
</div>
<div class="mat-form-field-underline ng-tns-c64-23 ng-star-inserted">
<span class="mat-form-field-ripple ng-tns-c64-23">
</span>
</div>
<div class="mat-form-field-subscript-wrapper ng-tns-c64-23">
<div class="mat-form-field-hint-wrapper ng-tns-c64-23 ng-trigger ng-trigger-transitionMessages ng-star-inserted" style="opacity: 1; transform: translateY(0%);">
<div class="mat-form-field-hint-spacer ng-tns-c64-23"></div>
</div>
</div>
</div>
</mat-form-field>
</div>
无论您使用什么屏幕 reader,都会出现此问题,而不仅仅是 JAWS。
Angular Material就是mis-usingaria-owns attribute. You can test this on their "Date Range Selection”的例子。他们的代码基本上是这样的:
<input placeholder="Start date" id="startdate">
<input placeholder="End date">
<label for="startdate" aria-owns="startdate">Enter a date range</label>
和all ARIA attributes一样,aria-owns
只是对屏幕的提示reader。 ARIA 属性应该可以帮助屏幕 reader 理解页面的组织。 ARIA 属性不会影响页面的外观,也不会影响浏览器的行为。在这种特殊情况下,ARIA 属性不会影响浏览器的 Tab 键顺序。
因此无论 ARIA 属性是否存在,当您通过日期范围小部件 tab 时,tab 顺序(默认)与 DOM 顺序相同.在这种情况下,<input placeholder="Start date" id="startdate">
是第一个,因此它首先接收选项卡焦点。下一个 选项卡 转到下一个 DOM 元素,即 <input placeholder="End date">
。 <label>
不是制表位。
这一切都按预期工作。
如果您使用屏幕 reader 命令进行导航,就会变得奇怪。屏幕 reader 用户可以正常使用 tab 键,他们会按正确的顺序听到内容。但是,如果屏幕 reader 用户尝试导航 DOM(实际上是 AOM - 可访问性对象模型),无论是通过 E 键(通常是 INS+E) 或 downArrow 键,then aria-owns
会影响东西,因为ARIA属性会影响画面reader.
另一个需要理解的概念是 AOM。辅助功能对象模型类似于文档对象模型 (DOM),只是它本质上是 DOM 的 子集 。并非 DOM 上的所有内容都会出现在 AOM 中。当您使用屏幕 reader 命令时,屏幕 reader 会与 AOM 交互。
例如,如果您有一个带有 display:none
的元素,该元素仍然存在于 DOM 中。您仍然可以对其调用 getObjectByName()
。但是该元素将从 AOM 中删除,这样屏幕 reader 用户就不能再使用屏幕 reader 命令导航到该元素。
如 OP 中所述,aria-hidden
也发生了类似的事情。将 aria-hidden
设置为 true 将从 AOM 中 删除 该元素,因此屏幕 reader 不再认为它存在。
因此,如前所述,可以使用 downArrow 键(或专门用于输入字段的 E 键)来遍历 AOM .它让用户可以像浏览文本文档一样浏览 AOM。可以把它想象成在文本编辑器中阅读 HTML 文件,然后使用 向下箭头 键转到编辑器中的下一行。
aria-owns
更改 AOM 顺序而不实际更改 DOM。 aria-owns
可让您影响 AOM 中的 parent/child 关系并模仿一个元素 在 另一个元素之后,即使它实际上不在 HTML 中文件。
所以在这种情况下,即使 DOM 物理上看起来像这样:
<input placeholder="Start date" id="startdate">
<input placeholder="End date">
<label for="startdate" aria-owns="startdate">Enter a date range</label>
AOM 将如下所示:
<input placeholder="End date">
<label for="startdate" aria-owns="startdate">Enter a date range</label>
<input placeholder="Start date" id="startdate">
因为 <label>
上的 aria-owns="startdate"
导致开始日期元素 在 标签之后。
是的,这很复杂,但是一旦您了解了导致它的原因,它就有点简单了。
Is there a solution?
否 :-( 除了联系 google 让他们知道他们没有正确使用 aria-owns。