If you call a ShadowRoot’s toString() method, it will return "[object ShadowRoot]". According to this fact, here’s my approach:
function isInShadow(node) {
var parent = (node && node.parentNode);
while(parent) {
if(parent.toString() === "[object ShadowRoot]") {
return true;
}
parent = parent.parentNode;
}
return false;
}
EDIT
Jeremy Banks suggests an approach in another style of looping. This approach is a little different from mine: it also checks the passed node itself, which I didn’t do.
function isInShadow(node) {
for (; node; node = node.parentNode) {
if (node.toString() === "[object ShadowRoot]") {
return true;
}
}
return false;
}
function isInShadow(node) {
for (; node; node = node.parentNode) {
if (node.toString() === "[object ShadowRoot]") {
return true;
}
}
return false;
}
console.group('Testing');
var lightElement = document.querySelector('div');
console.assert(isInShadow(lightElement) === false);
var shadowChild = document.createElement('div');
lightElement.createShadowRoot().appendChild(shadowChild);
console.assert(isInShadow(shadowChild) === true);
var orphanedElement = document.createElement('div');
console.assert(isInShadow(orphanedElement) === false);
var orphanedShadowChild = document.createElement('div');
orphanedElement.createShadowRoot().appendChild(orphanedShadowChild);
console.assert(isInShadow(orphanedShadowChild) === true);
var fragmentChild = document.createElement('div');
document.createDocumentFragment().appendChild(fragmentChild);
console.assert(isInShadow(fragmentChild) === false);
console.log('Complete.');
console.groupEnd();
<div></div>