Skip to content

Commit

Permalink
feat: Add dom.getComposedParent function
Browse files Browse the repository at this point in the history
  • Loading branch information
WilcoFiers committed Jul 4, 2017
1 parent 99e8b73 commit aac57c0
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 6 deletions.
5 changes: 1 addition & 4 deletions lib/commons/dom/find-up.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,8 @@ dom.findUp = function (element, target) {
return null;
}

parent = (element.assignedSlot) ? element.assignedSlot : element.parentNode;
if (parent.nodeType === 11) {
parent = parent.host;
}
// recursively walk up the DOM, checking each parent node
parent = dom.getComposedParent(element);
while (parent && matches.indexOf(parent) === -1) {
parent = (parent.assignedSlot) ? parent.assignedSlot : parent.parentNode;
if (parent && parent.nodeType === 11) {
Expand Down
19 changes: 19 additions & 0 deletions lib/commons/dom/get-composed-parent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*global dom */
/**
* Get an element's parent in the composed tree
* @param DOMNode Element
* @return DOMNode Parent element
*/
dom.getComposedParent = function getComposedParent (element) {
if (element.assignedSlot) {
return element.assignedSlot; // content of a shadow DOM slot
} else if (element.parentNode) {
var parentNode = element.parentNode;
if (parentNode.nodeType === 1) {
return parentNode; // Regular node
} else if (parentNode.host) {
return parentNode.host; // Shadow root
}
}
return null; // Root node
};
3 changes: 1 addition & 2 deletions lib/commons/dom/is-visible.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,8 +64,7 @@ dom.isVisible = function (el, screenReader, recursed) {
return false;
}

parent = (el.assignedSlot) ? el.assignedSlot : el.parentNode;

parent = dom.getComposedParent(el);
if (parent) {
return dom.isVisible(parent, screenReader, true);
}
Expand Down
72 changes: 72 additions & 0 deletions test/commons/dom/get-composed-parent.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/* global xit */
describe('dom.getComposedParent', function () {
'use strict';
var getComposedParent = axe.commons.dom.getComposedParent;
var fixture = document.getElementById('fixture');
var shadowSupport = document.body && typeof document.body.attachShadow === 'function';

afterEach(function () {
fixture.innerHTML = '';
});

it('returns the parentNode normally', function () {
fixture.innerHTML = '<div id="parent"><div id="target"></div></div>';

var actual = getComposedParent(document.getElementById('target'));
assert.instanceOf(actual, Node);
assert.equal(actual, document.getElementById('parent'));
});

it('returns null from the documentElement', function () {
assert.isNull(
getComposedParent(document.documentElement)
);
});

(shadowSupport ? it : xit)('returns the slot node for slotted content', function () {
fixture.innerHTML = '<div id="shadow"><div id="target"></div></div>';
var shadowRoot = document.getElementById('shadow').attachShadow({ mode: 'open' });
shadowRoot.innerHTML = '<div id="grand-parent">' +
'<slot id="parent"></slot>' +
'</div>';

var actual = getComposedParent(fixture.querySelector('#target'));
assert.instanceOf(actual, Node);
assert.equal(actual, shadowRoot.querySelector('#parent'));
});

(shadowSupport ? it : xit)('returns explicitly slotted nodes', function () {
fixture.innerHTML = '<div id="shadow"><div id="target" slot="bar"></div></div>';
var shadowRoot = document.getElementById('shadow').attachShadow({ mode: 'open' });
shadowRoot.innerHTML = '<div id="grand-parent">' +
'<slot name="foo"></slot>' +
'<slot id="parent" name="bar"></slot>' +
'</div>';

var actual = getComposedParent(fixture.querySelector('#target'));
assert.instanceOf(actual, Node);
assert.equal(actual, shadowRoot.querySelector('#parent'));
});

(shadowSupport ? it : xit)('returns elements within a shadow tree', function () {
fixture.innerHTML = '<div id="shadow"> content </div>';
var shadowRoot = document.getElementById('shadow').attachShadow({ mode: 'open' });
shadowRoot.innerHTML = '<div id="parent">' +
'<slot id="target"></slot>' +
'</div>';

var actual = getComposedParent(shadowRoot.querySelector('#target'));
assert.instanceOf(actual, Node);
assert.equal(actual, shadowRoot.querySelector('#parent'));
});

(shadowSupport ? it : xit)('returns the host when it reaches the shadow root', function () {
fixture.innerHTML = '<div id="parent"> content </div>';
var shadowRoot = document.getElementById('parent').attachShadow({ mode: 'open' });
shadowRoot.innerHTML = '<div id="target"> <slot></slot> </div>';

var actual = getComposedParent(shadowRoot.querySelector('#target'));
assert.instanceOf(actual, Node);
assert.equal(actual, fixture.querySelector('#parent'));
});
});

0 comments on commit aac57c0

Please sign in to comment.