Skip to content

Commit 493dd22

Browse files
authored
feat(closest): VirtualNode implementation of Element.closest. Deprecate commons.dom.findUp and commons.dom.findUpVirtual (#2139)
* feat(closest): VirtualNode implementation of Element.closest. Deprecate commons.dom.findUp and commons.dom.findUpVirtual * add shadow support
1 parent 8c92472 commit 493dd22

3 files changed

Lines changed: 81 additions & 0 deletions

File tree

lib/commons/dom/find-up.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* @method findUp
77
* @memberof axe.commons.dom
88
* @instance
9+
* @deprecated use axe.utils.closest
910
* @param {HTMLElement} element The starting HTMLElement
1011
* @param {String} target The selector for the HTMLElement
1112
* @return {HTMLElement|null} Either the matching HTMLElement or `null` if there was no match
@@ -21,6 +22,7 @@ dom.findUp = function(element, target) {
2122
* @method findUpVirtual
2223
* @memberof axe.commons.dom
2324
* @instance
25+
* @deprecated use axe.utils.closest
2426
* @param {VirtualNode} element The starting virtualNode
2527
* @param {String} target The selector for the HTMLElement
2628
* @return {HTMLElement|null} Either the matching HTMLElement or `null` if there was no match

lib/core/utils/closest.js

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/**
2+
* closest implementation that operates on a VirtualNode
3+
*
4+
* @method closest
5+
* @memberof axe.utils
6+
* @param {VirtualNode} vNode VirtualNode to match
7+
* @param {String} selector CSS selector string
8+
* @return {Boolean}
9+
*/
10+
axe.utils.closest = function closest(vNode, selector) {
11+
while (vNode) {
12+
if (axe.utils.matches(vNode, selector)) {
13+
return vNode;
14+
}
15+
16+
vNode = vNode.parent;
17+
}
18+
19+
return null;
20+
};

test/core/utils/closest.js

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
describe('utils.closest', function() {
2+
var closest = axe.utils.closest;
3+
var fixture = document.querySelector('#fixture');
4+
var queryFixture = axe.testUtils.queryFixture;
5+
var shadowSupported = axe.testUtils.shadowSupport.v1;
6+
7+
afterEach(function() {
8+
fixture.innerHTML = '';
9+
});
10+
11+
it('should find the current node', function() {
12+
var virtualNode = queryFixture(
13+
'<div id="parent"><div id="target">foo</div></div>'
14+
);
15+
var closestNode = closest(virtualNode, 'div');
16+
assert.equal(closestNode, virtualNode);
17+
});
18+
19+
it('should find a parent node', function() {
20+
var virtualNode = queryFixture(
21+
'<div id="parent"><span id="target">foo</span></div>'
22+
);
23+
var closestNode = closest(virtualNode, 'div');
24+
var parent = fixture.querySelector('#parent');
25+
assert.equal(closestNode, axe.utils.getNodeFromTree(parent));
26+
});
27+
28+
it('should find an ancestor node', function() {
29+
var virtualNode = queryFixture(
30+
'<div id="parent"><span><span><span><span id="target">foo</span></span></span></div>'
31+
);
32+
var closestNode = closest(virtualNode, 'div');
33+
var parent = fixture.querySelector('#parent');
34+
assert.equal(closestNode, axe.utils.getNodeFromTree(parent));
35+
});
36+
37+
it('should return null if no ancestor is found', function() {
38+
var virtualNode = queryFixture(
39+
'<div id="parent"><div id="target">foo</div></div>'
40+
);
41+
var closestNode = closest(virtualNode, 'h1');
42+
assert.isNull(closestNode);
43+
});
44+
45+
(shadowSupported ? it : xit)('should support shadow dom', function() {
46+
fixture.innerHTML = '<div id="parent"></div>';
47+
48+
var root = fixture.firstChild.attachShadow({ mode: 'open' });
49+
var slotted = document.createElement('span');
50+
slotted.innerHTML = '<span id="target">foo</span>';
51+
root.appendChild(slotted);
52+
axe.utils.getFlattenedTree(fixture.firstChild);
53+
54+
var virtualNode = axe.utils.getNodeFromTree(slotted.firstChild);
55+
var parent = fixture.querySelector('#parent');
56+
var closestNode = closest(virtualNode, 'div');
57+
assert.equal(closestNode, axe.utils.getNodeFromTree(parent));
58+
});
59+
});

0 commit comments

Comments
 (0)