Skip to content

Commit

Permalink
Merge pull request #1734 from IBMa/dev-1675
Browse files Browse the repository at this point in the history
newrule(`draggable_alternative_exists`): WCAG 2.2: 2.5.7 Dragging Movements
  • Loading branch information
ErickRenteria authored Nov 9, 2023
2 parents bc32ebb + a3e9e36 commit 6dc7dbc
Show file tree
Hide file tree
Showing 8 changed files with 374 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<!--
/******************************************************************************
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.
*****************************************************************************/
-->
<!-- Title and messages generated at build time -->
<link rel="icon" href="https://ibm.com/able/favicon-32x32.png" type="image/png">
<link rel="icon" href="https://ibm.com/able/favicon.svg" type="image/svg+xml">
<link rel="stylesheet" href="../common/help.css" />
<script type="module">
import "https://1.www.s81c.com/common/carbon/web-components/tag/latest/code-snippet.min.js";
import "https://1.www.s81c.com/common/carbon/web-components/tag/latest/list.min.js";
</script>
<script src="https://cdn.jsdelivr.net/npm/marked/marked.min.js"></script>
<script src="../common/help.js"></script>
</head>
<body>
<div class="bx--grid toolHelp">
<div class="bx--row">
<div class="bx--col-sm-4 bx--col-md-8 bx--col-lg-16 toolHead">
<!-- Group message injected here -->
<h3 id="ruleMessage"></h3>
<!-- Severity level injected here -->
<div id="locLevel"></div>
<!-- Rule specific message injected here -->
<p id="groupLabel"></p>
</div>
</div>
<div class="bx--row">
<div class="bx--col-sm-4 bx--col-md-5 bx--col-lg-8 toolMain">
<!-- Start main panel -->
<mark-down><script type="text/plain">

### Why is this important?

Some people cannot use a mouse, pen, or touch to drag items.
Examples of draggable elements include list items, text, and images.
The design should not rely on dragging as the only means for the user’s actions.

- **_Draggable_**: an operation where the pointer (mouse, pen, or touch) engages with an element on the [down-event](https://www.w3.org/WAI/WCAG22/Understanding/dragging-movements.html#dfn-down-event) and the element (or a representation of its position) follows the pointer until an [up-event](https://www.w3.org/WAI/WCAG22/Understanding/dragging-movements.html#dfn-up-event).
- **_Single-pointer_**: one or several pointer inputs that operate with _one point of contact with the screen_, including single taps and clicks, double-taps and double-clicks, and long presses.
- **_Path-based gesture_**: involves a pointer interaction where not just the endpoints matter.
- **_Exceptions and additional terms_**: are defined at [Understanding Dragging Movements](https://www.w3.org/WAI/WCAG22/Understanding/dragging-movements.html#key-terms).

**Note**: This requirement is separate from keyboard accessibility.
However, providing a text input can be an acceptable _single-pointer_ alternative to dragging.
For example, a text input beside a slider could allow any user to enter a precise value for the slider.
In such a situation, the on-screen keyboard for touch users offers a _single-pointer_ means of entering an alphanumeric value.

<!-- This is where the code snippet is injected -->
<div id="locSnippet"></div>

### What to do

For any action that involves dragging with a mouse, pen, or touch:
- Provide a _single-pointer_ alternative, such as including single taps and clicks, double-taps and double-clicks, and long presses as alternatives to the dragging
- **Or**, provide a text input alternative

</script></mark-down>
<!-- End main panel -->
<!-- This is where the rule id is injected -->
<div id="ruleInfo"></div>
</div>
<div class="bx--col-sm-4 bx--col-md-3 bx--col-lg-4 toolSide">
<!-- Start side panel -->
<mark-down><script type="text/plain">

### About this requirement

- [WCAG 2.5.7 Dragging Movements](https://www.w3.org/WAI/WCAG22/Understanding/dragging-movements.html)
- [WCAG technique G219: Ensuring that an alternative is available for dragging movements that operate on content](https://www.w3.org/WAI/WCAG22/Techniques/general/G219)
- [WCAG Failure F108: Failure due to not providing a _single-pointer_ method for the user to operate a function that uses a dragging movement](https://www.w3.org/WAI/WCAG22/Techniques/failures/F108)

### Who does this affect?

- People who struggle with performing dragging movements
- People with tremors or other movement disorders using a mouse, stylus, or touch input
- People using a device in environments where they are exposed to shaking such as public transportation
- Many older adults

</script></mark-down>
<!-- End side panel -->
</div>
</div>
</div>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
1 change: 1 addition & 0 deletions accessibility-checker-engine/src/v4/rules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
1 change: 1 addition & 0 deletions accessibility-checker-engine/src/v4/rulesets.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
Expand Down
12 changes: 12 additions & 0 deletions accessibility-checker-engine/src/v4/sc-urls.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<!--
/******************************************************************************
Copyright:: 2020- 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.
*****************************************************************************/
-->

<html lang="en">

<head>
<title>RPT Test Suite</title>
<script>
const draggableElement = document.querySelector('p[draggable="true"]');
console.log("dragstart: "+ draggableElement);
draggableElement.addEventListener("dragstart", (event) => { console.log("dragstart");
event.dataTransfer.setData("text/plain", "This text may be dragged");
});
</script>
</head>

<body>

<p>no draggable defined: This text <strong>may</strong> be dragged by selection.</p>

<p draggable="false">draggable false: This text <strong>may</strong> be selected and dragged.</p>

<p draggable="">draggable undefined:This text <strong>may</strong> be selected and dragged.</p>

<p draggable="true">draggable true: This text <strong>may</strong> be dragged.</p>

<img id="drag1" src="https://ibm.com/able/favicon-32x32.png" alt=""/>

<script>
UnitTest = {
ruleIds: ["draggable_alternative_exists"],
results: [
{
"ruleId": "draggable_alternative_exists",
"value": [
"INFORMATION",
"PASS"
],
"path": {
"dom": "/html[1]/body[1]/p[2]",
"aria": "/document[1]/paragraph[2]"
},
"reasonId": "pass_undraggable",
"message": "The element \"p\" is not draggable",
"messageArgs": [
"p"
],
"apiArgs": [],
"category": "Accessibility"
},
{
"ruleId": "draggable_alternative_exists",
"value": [
"INFORMATION",
"POTENTIAL"
],
"path": {
"dom": "/html[1]/body[1]/p[4]",
"aria": "/document[1]/paragraph[4]"
},
"reasonId": "potential_alternative",
"message": "Ensure the draggable element \"p\" has a \"single pointer\" alternative",
"messageArgs": [
"p"
],
"apiArgs": [],
"category": "Accessibility"
}
]
}
</script>
</body>

</html>
Loading

0 comments on commit 6dc7dbc

Please sign in to comment.