Created
September 25, 2018 19:13
-
-
Save anechunaev/800c6bc5e29ccc17118b55c971f9bb0c to your computer and use it in GitHub Desktop.
Get element path in DOM (including correct shadow DOM path resolving).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* Return string that represent element position in DOM (usually valid CSS selector). Position is relative to document.body. | |
* | |
* ATTENTION! | |
* If you use shadow DOM on the page, this function will not return valid CSS selector. | |
*/ | |
export function getPath(element: Element) { | |
const stack = []; | |
let el = element; | |
while (!!el.parentNode) { | |
let sibCount = 0; | |
let sibIndex = 0; | |
for (let i = 0; i < el.parentNode.childNodes.length; i++) { | |
const sib = el.parentNode.childNodes[i]; | |
if (sib.nodeName === el.nodeName) { | |
if (sib === el) { | |
sibIndex = sibCount; | |
} | |
sibCount++; | |
} | |
} | |
if (el.hasAttribute('id') && el.id !== '') { | |
stack.unshift(el.nodeName.toLowerCase() + '#' + el.id); | |
} else if (sibCount > 1) { | |
stack.unshift(el.nodeName.toLowerCase() + ':nth-of-type(' + (sibIndex + 1) + ')'); | |
} else { | |
stack.unshift(el.nodeName.toLowerCase()); | |
} | |
el = el.parentNode as Element; | |
if (!el.parentNode) { | |
if (typeof (el as any).host !== 'undefined') { | |
stack.unshift(':shadow'); | |
el = (el as any).host; | |
} else { | |
el = { parentNode: null } as Element; | |
} | |
} | |
} | |
return stack.slice(2, stack.length).join(' '); | |
} | |
/** | |
* Return element by path string that is generated by function above. | |
*/ | |
export function getElementByPath(path: string, source: any = document.body) { | |
const parts = path.split(':shadow'); | |
let parent = source; | |
let result; | |
for (let i = 0; i < parts.length; i++) { | |
const fragment = parent.querySelector(parts[i]); | |
if (i + 1 < parts.length) { | |
parent = fragment.shadowRoot; | |
} else { | |
result = fragment; | |
} | |
} | |
return result; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment