+
+
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.