diff --git a/accessibility-checker-engine/help-v4/en-US/draggable_alternative_exists.html b/accessibility-checker-engine/help-v4/en-US/draggable_alternative_exists.html new file mode 100644 index 000000000..46e09059d --- /dev/null +++ b/accessibility-checker-engine/help-v4/en-US/draggable_alternative_exists.html @@ -0,0 +1,99 @@ + + + + + + + + + + + + + +
+
+
+ +

+ +
+ +

+
+
+
+
+ + + + +
+
+
+ + + +
+
+
+ + diff --git a/accessibility-checker-engine/src/v4/rules/draggable_alternative_exists.ts b/accessibility-checker-engine/src/v4/rules/draggable_alternative_exists.ts new file mode 100644 index 000000000..b209b5bf8 --- /dev/null +++ b/accessibility-checker-engine/src/v4/rules/draggable_alternative_exists.ts @@ -0,0 +1,65 @@ +/****************************************************************************** + Copyright:: 2022- IBM, Inc + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + http://www.apache.org/licenses/LICENSE-2.0 + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + *****************************************************************************/ + +import { RPTUtil } from "../../v2/checker/accessibility/util/legacy"; +import { Rule, RuleResult, RuleContext, RulePass, RuleContextHierarchy, RulePotential } from "../api/IRule"; +import { eRulePolicy, eToolkitLevel } from "../api/IRule"; +import { VisUtil } from "../../v2/dom/VisUtil"; + +export let draggable_alternative_exists: Rule = { + id: "draggable_alternative_exists", + context: "dom:*[draggable]", + dependencies: [], + help: { + "en-US": { + "group": "draggable_alternative_exists.html", + "pass_alternative": "draggable_alternative_exists.html", + "pass_undraggable": "draggable_alternative_exists.html", + "potential_alternative": "draggable_alternative_exists.html" + } + }, + messages: { + "en-US": { + "group": "A draggable element must have a \"single pointer\" alternative", + "pass_alternative": "The draggable element \"{0}\" has a \"single pointer\" alternative", + "pass_undraggable": "The element \"{0}\" is not draggable", + "potential_alternative": "Ensure the draggable element \"{0}\" has a \"single pointer\" alternative" + } + }, + rulesets: [{ + id: ["WCAG_2_2"], + num: ["2.5.7"], + level: eRulePolicy.VIOLATION, + toolkitLevel: eToolkitLevel.LEVEL_THREE + }], + act: [], + run: (context: RuleContext, options?: {}, contextHierarchies?: RuleContextHierarchy): RuleResult | RuleResult[] => { + const ruleContext = context["dom"].node as HTMLElement; + if (!VisUtil.isNodeVisible(ruleContext)) + return null; + + const nodeName = ruleContext.nodeName.toLocaleLowerCase(); + + //ignore certain elements + if (RPTUtil.getAncestor(ruleContext, ["pre", "code", "script", "meta"]) !== null + || nodeName === "body" || nodeName === "html" ) + return null; + + if (ruleContext.getAttribute("draggable") === 'true') + return RulePotential("potential_alternative", [nodeName]); + else if (ruleContext.getAttribute("draggable") === 'false') + return RulePass("pass_undraggable", [nodeName]); + else + return null; + } +} diff --git a/accessibility-checker-engine/src/v4/rules/element_tabbable_unobscured.ts b/accessibility-checker-engine/src/v4/rules/element_tabbable_unobscured.ts index 7d6057c6b..d84272253 100644 --- a/accessibility-checker-engine/src/v4/rules/element_tabbable_unobscured.ts +++ b/accessibility-checker-engine/src/v4/rules/element_tabbable_unobscured.ts @@ -16,7 +16,6 @@ import { Rule, RuleResult, RuleContext, RulePass, RuleContextHierarchy, RulePote import { eRulePolicy, eToolkitLevel } from "../api/IRule"; import { VisUtil } from "../../v2/dom/VisUtil"; import { DOMMapper } from "../../v2/dom/DOMMapper"; -import { DOMUtil } from "../../v2/dom/DOMUtil"; export let element_tabbable_unobscured: Rule = { id: "element_tabbable_unobscured", diff --git a/accessibility-checker-engine/src/v4/rules/index.ts b/accessibility-checker-engine/src/v4/rules/index.ts index f9430b5e7..2bb42749f 100644 --- a/accessibility-checker-engine/src/v4/rules/index.ts +++ b/accessibility-checker-engine/src/v4/rules/index.ts @@ -80,6 +80,7 @@ export * from "./debug_paths" export * from "./detector_tabbable" export * from "./dir_attribute_valid" export * from "./download_keyboard_controllable" +export * from "./draggable_alternative_exists" export * from "./element_accesskey_labelled" export * from "./element_accesskey_unique" export * from "./element_attribute_deprecated" diff --git a/accessibility-checker-engine/src/v4/rulesets.ts b/accessibility-checker-engine/src/v4/rulesets.ts index f5a4eea58..b46ec0a5c 100644 --- a/accessibility-checker-engine/src/v4/rulesets.ts +++ b/accessibility-checker-engine/src/v4/rulesets.ts @@ -61,6 +61,7 @@ const summaries = { "2.5.2": "For functionality that can be operated using a single pointer, completion of the function is on the up-event with an ability to abort, undo or reverse the outcome.", "2.5.3": "For user interface components with labels that include text or images of text, the accessible name contains the text that is presented visually.", "2.5.4": "Functionality that can be operated by motion can also be operated by user interface components, and the motion trigger can be disabled.", + "2.5.7": "All functionality that uses a dragging movement for operation can be achieved by a single pointer without dragging.", "3.1.1": "The default human language of Web pages, non-Web documents, or software can be programmatically determined.", "3.1.2": "The human language of each passage or phrase in the content can be programmatically determined.", "3.2.1": "When any component receives focus, it does not initiate a change of context.", diff --git a/accessibility-checker-engine/src/v4/sc-urls.json b/accessibility-checker-engine/src/v4/sc-urls.json index a84f4603c..93183bb16 100644 --- a/accessibility-checker-engine/src/v4/sc-urls.json +++ b/accessibility-checker-engine/src/v4/sc-urls.json @@ -707,6 +707,18 @@ "level": "AAA", "wcagType": "2.1" }, + "2.5.7": { + "num": "2.5.7", + "url": "https://www.w3.org/TR/WCAG22/#dragging-movements", + "scId": "WCAG2:dragging-movement", + "scAltId": ["dragging-movement"], + "test": "WCAG2:WCAG2:dragging-movement", + "howToMeetUrl": "https://www.w3.org/WAI/WCAG22/Understanding/dragging-movements.html", + "understandingUrl": "https://www.w3.org/WAI/WCAG22/Understanding/dragging-movements.html", + "handle": "Dragging Movement", + "level": "AA", + "wcagType": "2.2" + }, "3.1.1": { "num": "3.1.1", "url": "https://www.w3.org/TR/WCAG21/#language-of-page", diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/draggable_alternative_exists_ruleunit/element_draggable.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/draggable_alternative_exists_ruleunit/element_draggable.html new file mode 100755 index 000000000..d1651bc4c --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/draggable_alternative_exists_ruleunit/element_draggable.html @@ -0,0 +1,91 @@ + + + + + + + + RPT Test Suite + + + + + +

no draggable defined: This text may be dragged by selection.

+ +

draggable false: This text may be selected and dragged.

+ +

draggable undefined:This text may be selected and dragged.

+ +

draggable true: This text may be dragged.

+ + + + + + + diff --git a/accessibility-checker-engine/test/v2/checker/accessibility/rules/draggable_alternative_exists_ruleunit/element_dropstop.html b/accessibility-checker-engine/test/v2/checker/accessibility/rules/draggable_alternative_exists_ruleunit/element_dropstop.html new file mode 100755 index 000000000..031b8bb30 --- /dev/null +++ b/accessibility-checker-engine/test/v2/checker/accessibility/rules/draggable_alternative_exists_ruleunit/element_dropstop.html @@ -0,0 +1,105 @@ + + + + + + + + RPT Test Suite + + + + + + +

Drag or move the image into the rectangle:

+ +
+
+ +
+
+ + + + +