diff --git a/accessibility-checker-engine/src/v4/util/AriaUtil.ts b/accessibility-checker-engine/src/v4/util/AriaUtil.ts index 84ab61049..6b5d0a90c 100644 --- a/accessibility-checker-engine/src/v4/util/AriaUtil.ts +++ b/accessibility-checker-engine/src/v4/util/AriaUtil.ts @@ -751,6 +751,32 @@ export class AriaUtil { return roles; } + /** + * return the roles with given role type. + * + * @parm {element} element - The element to start the node walk on to find parent node + * @parm {array} roleTyples - role types, such as 'widget', 'structure' etc. + * + * @return {array} roles - A parent node of the element passed in, which has the provided role + * + * @memberOf AriaUtil + */ + public static isWidget(element) { + if (!element) return false; + + const widget = CacheUtil.getCache(element.ownerDocument, "is_element_widget", null); + if (widget === null) { + let ret = false; + const role = AriaUtil.getResolvedRole(element); + if (role && ARIADefinitions.designPatterns[role].roleType === 'widget') + ret = true; + + CacheUtil.setCache(element.ownerDocument, "is_element_widget", ret); + return ret; + } + return widget; + } + /** * This function is responsible for finding a node which matches the role and is a sibling of the * provided element. diff --git a/accessibility-checker-engine/src/v4/util/CommonUtil.ts b/accessibility-checker-engine/src/v4/util/CommonUtil.ts index 52ce6d4ab..ace859285 100644 --- a/accessibility-checker-engine/src/v4/util/CommonUtil.ts +++ b/accessibility-checker-engine/src/v4/util/CommonUtil.ts @@ -55,9 +55,9 @@ export class CommonUtil { return !element.hasAttribute("disabled"); }, "textarea": true, - "div": function (element) { + /**"div": function (element) { return element.hasAttribute("contenteditable"); - }, + },*/ "a": function (element) { // xlink:href?? see svg return element.hasAttribute("href"); @@ -109,6 +109,7 @@ export class CommonUtil { } return retVal; } else { + if (element.hasAttribute("contenteditable")) return true; return false; } } @@ -123,6 +124,29 @@ export class CommonUtil { return CommonUtil.isTabbable(ele); } + /** + * Note that this only detects if the element itself is interactive, but not onclick event. + */ + public static isClickable(element) { + if (!VisUtil.isNodeVisible(element)) return false; + + // native focusable element + let nodeName = element.nodeName.toLowerCase(); + if (nodeName in CommonUtil.tabTagMap) { + let retVal = CommonUtil.tabTagMap[nodeName]; + if (typeof (retVal) === "function") { + retVal = retVal(element); + } + return retVal; + } else { + //custom widget + if (AriaUtil.isWidget(element) && element.hasAttribute("tabindex")) { + return true; + } + } + return false; + } + /* * get conflict Aria and Html attributes * return: a list of Aria and Html attribute pairs that are conflict @@ -457,15 +481,15 @@ export class CommonUtil { * a target is en element that accept a pointer action (click or touch) * */ - public static isTarget(element) { + public static isTarget(element) { if (!element || element.nodeType !== 1 || ["html", "body"].includes(element.nodeName.toLowerCase()) || CommonUtil.getAncestor(element, ["svg", "pre", "code", "script", "meta", 'head']) !== null || !VisUtil.isNodeVisible(element) || VisUtil.isNodeVisuallyHidden(element) || CommonUtil.isNodeDisabled(element) || VisUtil.isElementOffscreen(element)) return false; - - if (element.hasAttribute("tabindex") || CommonUtil.isTabbable(element)) + + if (CommonUtil.isClickable(element)) return true; const role = AriaUtil.getResolvedRole(element); diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/target_spacing_sufficient_ruleunit/block_overlaid_hidden_default.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/target_spacing_sufficient_ruleunit/block_overlaid_hidden_default.html index 41b41b9fc..b4d715048 100755 --- a/accessibility-checker-engine/test/v2/checker/accessibility/rules/target_spacing_sufficient_ruleunit/block_overlaid_hidden_default.html +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/target_spacing_sufficient_ruleunit/block_overlaid_hidden_default.html @@ -52,8 +52,8 @@ -
1
-
2
+
1
+
2