Skip to content

Commit beccabe

Browse files
Merge pull request #140 from browserstack/AXE-1598-form-element-visible-label
Fix: AXE-1598 form element visible label
2 parents fd6b33f + 4562db3 commit beccabe

File tree

3 files changed

+106
-2
lines changed

3 files changed

+106
-2
lines changed
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
import { getNodeFromTree, memoize } from '../../core/utils';
2+
import { sanitize } from '../text';
3+
import { getIntersectionRect, getRectCenter, isPointInRect } from '../math';
4+
import getOverflowHiddenAncestors from './get-overflow-hidden-ancestors';
5+
import cache from '../../core/base/cache';
6+
7+
/**
8+
* Get the visible text client rects of a node.
9+
* @method getVisibleChildTextRect
10+
* @memberof axe.commons.dom
11+
* @instance
12+
* @param {Element} node
13+
*/
14+
const getVisibleChildTextRect = memoize(
15+
function getVisibleChildTextRectMemoized(node) {
16+
const vNode = getNodeFromTree(node);
17+
const nodeRect = vNode.boundingClientRect;
18+
const clientRects = [];
19+
const overflowHiddenNodes = getOverflowHiddenAncestors(vNode);
20+
21+
node.childNodes.forEach(textNode => {
22+
if (textNode.nodeType !== 3 || sanitize(textNode.nodeValue) === '') {
23+
return;
24+
}
25+
26+
const contentRects = getContentRects(textNode);
27+
if (isOutsideNodeBounds(contentRects, nodeRect) && !cache.get('ruleId')) {
28+
return;
29+
}
30+
31+
clientRects.push(...filterHiddenRects(contentRects, overflowHiddenNodes));
32+
});
33+
34+
// a11y-engine-domforge change
35+
if (clientRects.length <= 0) {
36+
return [];
37+
}
38+
/**
39+
* if all text rects are larger than the bounds of the node,
40+
* or goes outside of the bounds of the node, we need to use
41+
* the nodes bounding rect so we stay within the bounds of the
42+
* element.
43+
*
44+
* @see https://github.com/dequelabs/axe-core/issues/2178
45+
* @see https://github.com/dequelabs/axe-core/issues/2483
46+
* @see https://github.com/dequelabs/axe-core/issues/2681
47+
*
48+
* also need to resize the nodeRect to fit within the bounds of any overflow: hidden ancestors.
49+
*
50+
* @see https://github.com/dequelabs/axe-core/issues/4253
51+
*/
52+
return clientRects.length
53+
? clientRects
54+
: filterHiddenRects([nodeRect], overflowHiddenNodes);
55+
}
56+
);
57+
export default getVisibleChildTextRect;
58+
59+
function getContentRects(node) {
60+
const range = document.createRange();
61+
range.selectNodeContents(node);
62+
return Array.from(range.getClientRects());
63+
}
64+
65+
/**
66+
* Check to see if the text rect size is outside the of the
67+
* nodes bounding rect. Since we use the midpoint of the element
68+
* when determining the rect stack we will also use the midpoint
69+
* of the text rect to determine out of bounds
70+
*/
71+
function isOutsideNodeBounds(rects, nodeRect) {
72+
return rects.some(rect => {
73+
const centerPoint = getRectCenter(rect);
74+
return !isPointInRect(centerPoint, nodeRect);
75+
});
76+
}
77+
78+
/**
79+
* Filter out 0 width and height rects (newline characters) and
80+
* any rects that are outside the bounds of overflow hidden
81+
* ancestors
82+
*/
83+
function filterHiddenRects(contentRects, overflowHiddenNodes) {
84+
const visibleRects = [];
85+
contentRects.forEach(contentRect => {
86+
// ie11 has newline characters return 0.00998, so we'll say if the
87+
// line is < 1 it shouldn't be counted
88+
if (contentRect.width < 1 || contentRect.height < 1) {
89+
return;
90+
}
91+
92+
// update the rect size to fit inside the bounds of all overflow
93+
// hidden ancestors
94+
const visibleRect = overflowHiddenNodes.reduce((rect, overflowNode) => {
95+
return rect && getIntersectionRect(rect, overflowNode.boundingClientRect);
96+
}, contentRect);
97+
98+
if (visibleRect) {
99+
visibleRects.push(visibleRect);
100+
}
101+
});
102+
103+
return visibleRects;
104+
}

lib/commons/dom/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ export { default as getTargetSize } from './get-target-size';
2222
export { default as getTextElementStack } from './get-text-element-stack';
2323
export { default as getViewportSize } from './get-viewport-size';
2424
export { default as getVisibleChildTextRects } from './get-visible-child-text-rects';
25+
export { default as getVisibleChildTextRect } from './get-visible-child-text-rect';
2526
export { default as hasContentVirtual } from './has-content-virtual';
2627
export { default as hasContent } from './has-content';
2728
export { default as hasLangText } from './has-lang-text';

lib/rules/autocomplete-valid.json

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@
99
"EN-301-549",
1010
"EN-9.1.3.5",
1111
"ACT",
12-
"a11y-engine",
13-
"a11y-engine-experimental"
12+
"a11y-engine"
1413
],
1514
"actIds": ["73f2c2"],
1615
"metadata": {

0 commit comments

Comments
 (0)