` (e.g. ` foo `);
- * **Or**, if the element does not have a visible label, provide a label using the `aria-label` attribute (e.g. `aria-label="Activities"`).
+Provide an accessible name for the element with the `accesskey` attribute using one of the following examples:
+ * `title` attribute (e.g., `Activity: This is a paragraph that users need to jump to.`)
+ * `` or `aria-labelledby` to designate visible text as the label
+ * ` ` embedded in a `` (e.g., ` Activity `)
+ * `aria-label` attribute if the element does not have a visible label (e.g., `aria-label="Activity"`)
@@ -69,12 +71,14 @@
### About this requirement
* [IBM 3.3.2 Labels and Instructions](https://www.ibm.com/able/requirements/requirements/#3_3_2)
-* [WebAIM - The accesskey attribute](https://webaim.org/techniques/keyboard/accesskey#spec)
-* [ARIA practices - Developing a Keyboard Interface](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/)
+* [WebAIM - The accesskey attribute](https://webaim.org/techniques/keyboard/accesskey/#spec)
+* [ARIA practices - Developing a Keyboard Interface](https://www.w3.org/WAI/ARIA/apg/practices/keyboard-interface/)
+* [ARIA practices - Providing Accessible Names and Descriptions](https://www.w3.org/WAI/ARIA/apg/practices/names-and-descriptions/)
+
### Who does this affect?
- * People using a screen reader, including blind, low vision and neurodivergent people
+ * People using a screen reader, including blind, low vision, and neurodivergent people
* People who physically cannot use a pointing device
* People with dexterity impairment using voice control
diff --git a/accessibility-checker-engine/src/v4/rules/element_accesskey_labelled.ts b/accessibility-checker-engine/src/v4/rules/element_accesskey_labelled.ts
index 0481b054d..353d1a359 100644
--- a/accessibility-checker-engine/src/v4/rules/element_accesskey_labelled.ts
+++ b/accessibility-checker-engine/src/v4/rules/element_accesskey_labelled.ts
@@ -11,10 +11,12 @@
limitations under the License.
*****************************************************************************/
-import { Rule, RuleResult, RuleFail, RuleContext, RulePotential, RuleManual, RulePass, RuleContextHierarchy } from "../api/IRule";
+import { Rule, RuleResult, RuleContext, RulePotential, RulePass, RuleContextHierarchy } from "../api/IRule";
import { eRulePolicy, eToolkitLevel } from "../api/IRule";
import { RPTUtil } from "../../v2/checker/accessibility/util/legacy";
-import { DOMWalker } from "../../v2/dom/DOMWalker";
+import { VisUtil } from "../../v2/dom/VisUtil";
+import { ARIADefinitions } from "../../v2/aria/ARIADefinitions";
+import { ARIAMapper } from "../../v2/aria/ARIAMapper";
export let element_accesskey_labelled: Rule = {
id: "element_accesskey_labelled",
@@ -34,8 +36,8 @@ export let element_accesskey_labelled: Rule = {
messages: {
"en-US": {
"Pass_0": "Rule Passed",
- "Potential_1": "The HTML element with an assigned 'accesskey' attribute does not have an associated label",
- "group": "An HTML element with an assigned 'accesskey' attribute must have an associated label"
+ "Potential_1": "The element with an assigned 'accesskey' attribute does not have an associated label",
+ "group": "An element with an assigned 'accesskey' attribute must have an associated label"
}
},
rulesets: [{
@@ -46,25 +48,36 @@ export let element_accesskey_labelled: Rule = {
}],
act: [],
run: (context: RuleContext, options?: {}, contextHierarchies?: RuleContextHierarchy): RuleResult | RuleResult[] => {
- const ruleContext = context["dom"].node as Element;
- let passed = false;
- if (RPTUtil.attributeNonEmpty(ruleContext, "title")) {
- passed = true;
- } else if (RPTUtil.attributeNonEmpty(ruleContext, "aria-label")) {
- passed = true;
- } else if (RPTUtil.getLabelForElementHidden(ruleContext, true)) { // ignore hidden
- passed = true;
- } else if (RPTUtil.attributeNonEmpty(ruleContext, "aria-labelledby")) {
- // assume the validity of the id (of aria-labelledby) is checked by a different rule
- passed = true;
- } else if (ruleContext.nodeName.toLowerCase() === "input"
- && DOMWalker.parentNode(ruleContext).nodeName.toLowerCase() === "label") {
- // assume the validity of the label, e.g. empty label, is checked by a different rule
- passed = true;
- }
+ const ruleContext = context["dom"].node as HTMLElement;
+ //skip the check if the element is hidden or disabled
+ if (!VisUtil.isNodeVisible(ruleContext) || RPTUtil.isNodeDisabled(ruleContext))
+ return;
+
+ //skip if the element is tabbable, it's covered by other rules
+ if (RPTUtil.isTabbable(ruleContext))
+ return;
+
+ let roles = RPTUtil.getRoles(ruleContext, true);
+ //skip the native element, mostly text elements
+ if (!roles || roles.length === 0) return;
+
+ let patterns = ARIADefinitions.designPatterns[roles[0]]
+ if (!patterns.nameFrom)
+ return;
+
+ // ignore if accessble name is required (checked in other rules) or prohibited (text element)
+ if (patterns.nameRequired || !patterns.nameFrom || patterns.nameFrom.includes("prohibited"))
+ return;
+
+ //special case: legend, as a child of a fieldset, delegate the accesskey command to the field of the fieldset which is covered by other rules
+ if (ruleContext.parentElement && ruleContext.parentElement.nodeName.toLowerCase() === 'fieldset')
+ return;
+
+ // check if accessible name exists
+ if (ARIAMapper.computeName(ruleContext).trim().length > 0)
+ return RulePass("Pass_0");
- if (passed) return RulePass("Pass_0");
- if (!passed) return RulePotential("Potential_1");
+ return RulePotential("Potential_1");
}
}
\ No newline at end of file
diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_accesskey_labelled_ruleunit/AssesskeyNeedsLabelHidden.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_accesskey_labelled_ruleunit/AssesskeyNeedsLabelHidden.html
index bff58d66c..eaa691026 100644
--- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_accesskey_labelled_ruleunit/AssesskeyNeedsLabelHidden.html
+++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_accesskey_labelled_ruleunit/AssesskeyNeedsLabelHidden.html
@@ -41,7 +41,7 @@
passedXpaths: [
],
failedXpaths: [
- "/html/body/p"
+
]
}
];
diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_accesskey_labelled_ruleunit/form_control_accesskey.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_accesskey_labelled_ruleunit/form_control_accesskey.html
new file mode 100755
index 000000000..e430776e4
--- /dev/null
+++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_accesskey_labelled_ruleunit/form_control_accesskey.html
@@ -0,0 +1,26 @@
+
+
+
+
+
+accessble key
+
+
+
+ Stress reliever
+
+ HTML
+ CSS
+
+
+
+
+
diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_accesskey_labelled_ruleunit/legend_accesskey.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_accesskey_labelled_ruleunit/legend_accesskey.html
new file mode 100755
index 000000000..fc3d5e837
--- /dev/null
+++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/element_accesskey_labelled_ruleunit/legend_accesskey.html
@@ -0,0 +1,29 @@
+
+
+
+
+
+word spacing
+
+
+
+
+ I want
+ pizza(s) with these toppings
+
+ Cheese
+ Ham
+ Pineapple
+
+
+
+
+