Skip to content

Instantly share code, notes, and snippets.

@totherik
Last active April 7, 2016 15:50
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save totherik/bf729dab469cde69a52d383caa00bce0 to your computer and use it in GitHub Desktop.
Save totherik/bf729dab469cde69a52d383caa00bce0 to your computer and use it in GitHub Desktop.
/**
* A simple (and I assume fairly slow) function for generating a unique selector for a given element.
* @param element
* @returns {string}
*/
function generateSelector(element) {
let selector = [];
let root = document.body.parentElement;
while (element && element !== root && !element.id) {
let name = element.tagName.toLowerCase();
let nodeSelector = [ name ].concat(Array.from(element.classList)).join('.');
let parent = element.parentElement;
let twins = (parent && Array.from(parent.querySelectorAll(`:scope > ${nodeSelector}`))) || [];
let children = (parent && Array.from(parent.children)) || [];
if (twins.length > 1) {
// There are more elements identical to current element, so isolate with nth-child.
// These would be elements with no id, identical names, and either identical classes or no classes.
selector.unshift(`${name}:nth-child(${children.indexOf(element) + 1})`);
} else {
let snowflake = (parent && parent.querySelectorAll(`:scope > ${name}`)) || [];
if (snowflake.length === 1) {
// No identical elements, and no elements of the same name, so we have found a
// beautiful and unique snowflake...just using node name is safe.
selector.unshift(name);
} else {
if (children.length === 1) {
// No siblings from which to disambiguate.
selector.unshift(name);
} else {
// No identical elements, but elements of the same name, so disambiguate.
selector.unshift(nodeSelector);
}
}
}
element = element.parentElement;
}
// If we found the ID, prepend it.
if (element && element.id) {
selector.unshift(`#${element.id}`);
}
return selector.join(' > ');
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment