Skip to content

Commit 9cfbe8d

Browse files
committed
feat: considerations for elements within ShadowRoot
1 parent 1111cc6 commit 9cfbe8d

File tree

3 files changed

+56
-2
lines changed

3 files changed

+56
-2
lines changed

src/index.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,11 @@ export default function unique( el, options={} ) {
248248
if (isUniqueSelector) {
249249
return maybeUniqueSelector
250250
}
251-
currentElement = currentElement.parentNode
251+
252+
// Using parentElement here (rather than parentNode) to
253+
// filter out any document/document fragment nodes that may
254+
// be ancestors to elements within Shadow DOM trees.
255+
currentElement = currentElement.parentElement
252256
}
253257

254258
return null;

src/isUnique.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,11 @@ export function isUnique( el, selector )
88
{
99
if( !Boolean( selector ) ) return false;
1010
try {
11-
var elems = el.ownerDocument.querySelectorAll(selector);
11+
// Using getRootNode here to scope checks to any parent
12+
// ShadowRoot. getRootNode will otherwise return the
13+
// document associated to the elements page/frame (like
14+
// the ownerDocument property would).
15+
var elems = el.getRootNode().querySelectorAll(selector);
1216
return elems.length === 1 && elems[0] === el;
1317
} catch (e) {
1418
return false

test/unique-selector.js

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -299,4 +299,50 @@ describe( 'Unique Selector Tests', () =>
299299
expect( uniqueSelector ).to.equal( 'span' );
300300
})
301301
})
302+
303+
describe('shadow dom', () => {
304+
it( 'builds expected selector inside and outside shadow context', () => {
305+
$( 'body' ).append( '<div id="shadow-host" class="shadow-host-class"></div>' );
306+
307+
const hostNode = $( '#shadow-host' ).get( 0 );
308+
309+
const shadowRoot = hostNode.attachShadow({ mode: "open" })
310+
const shadowElement = hostNode.ownerDocument.createElement('div')
311+
shadowElement.innerHTML = `
312+
<div id="inner-shadow-container">
313+
<button id="shadow-button" class="shadow-button-class">Click Me</button>
314+
</div>
315+
`
316+
shadowRoot.appendChild(shadowElement);
317+
318+
const uniqueSelectorForHost = unique( hostNode );
319+
expect( uniqueSelectorForHost ).to.equal( '#shadow-host' );
320+
321+
const uniqueSelectorForShadowContent = unique ( shadowElement.querySelector('#shadow-button') )
322+
expect( uniqueSelectorForShadowContent ).to.equal( '#shadow-button' );
323+
})
324+
325+
it( 'builds unique selector scoped to shadow root', () => {
326+
$( 'body' ).append( '<div id="shadow-host" class="shadow-host-class"></div>' );
327+
$( 'body' ).append( '<button class="shadow-button-class">Click Me Third</button>' );
328+
329+
const hostNode = $( '#shadow-host' ).get( 0 );
330+
331+
const shadowRoot = hostNode.attachShadow({ mode: "open" })
332+
const shadowElement = hostNode.ownerDocument.createElement('div')
333+
shadowElement.innerHTML = `
334+
<div id="inner-shadow-container">
335+
<button class="shadow-button-class">Click Me First</button>
336+
<button class="shadow-button-class">Click Me Second</button>
337+
</div>
338+
`
339+
shadowRoot.appendChild(shadowElement);
340+
341+
const uniqueSelectorInRootDocument = unique( $( 'body' ).find( '.shadow-button-class' ).get( 0 ) );
342+
expect( uniqueSelectorInRootDocument ).to.equal( '.shadow-button-class' );
343+
344+
const uniqueSelectorForShadowContent = unique ( shadowElement.querySelectorAll('.shadow-button-class')[0] )
345+
expect( uniqueSelectorForShadowContent ).to.equal( '#inner-shadow-container > :nth-child(1)' );
346+
})
347+
})
302348
} );

0 commit comments

Comments
 (0)