Skip to content

Instantly share code, notes, and snippets.

@Eseperio
Created April 17, 2023 14:59
Show Gist options
  • Save Eseperio/9545e9d8a540dd79a4f6eed6ff2d4ada to your computer and use it in GitHub Desktop.
Save Eseperio/9545e9d8a540dd79a4f6eed6ff2d4ada to your computer and use it in GitHub Desktop.

Css unique selector generator

The css-unique-selector class is a JavaScript utility that generates a unique CSS selector for a given DOM element. The selector is generated in a way that it can be used to select only that element on a page, without affecting other elements.

The utility uses a combination of the element's tag name, classes, IDs, and the parent elements' classes and IDs to generate the selector. If a selector cannot be found that uniquely identifies the element, the utility will return the shortest selector that still identifies the element.

The utility is useful for developers who need to manipulate or style a specific element on a webpage but do not have direct access to the HTML source code. By using the unique selector, developers can easily target the desired element without affecting other elements on the page.

class UniqueSelector {
static getElementSelector(element) {
if (element.id) {
return `#${element.id}`;
}
if (element.tagName === 'BODY') {
return 'body';
}
let selector = element.tagName.toLowerCase();
if (element.className) {
selector += `.${element.className.replace(/ /g, '.')}`;
}
let siblings = Array.from(element.parentNode.children);
let index = siblings.indexOf(element) + 1;
if (siblings.length > 1) {
selector += `:nth-child(${index})`;
}
return selector;
}
static getUniqueSelector(element) {
let selector = this.getElementSelector(element);
let elements = document.querySelectorAll(selector);
if (elements.length === 1) {
return selector;
}
let bestSelector = selector;
let bestCount = elements.length;
// Try with parents' ids
let parent = element.parentElement;
while (parent) {
if (parent.id) {
let parentSelector = `#${parent.id} ${selector}`;
elements = document.querySelectorAll(parentSelector);
if (elements.length === 1) {
return parentSelector;
}
if (elements.length < bestCount) {
bestSelector = parentSelector;
bestCount = elements.length;
}
}
parent = parent.parentElement;
}
// Try with parents' classes
let parentClasses = [];
parent = element.parentElement;
while (parent && parent.tagName !== 'BODY') {
let classes = Array.from(parent.classList).filter(c => !parentClasses.includes(c));
for (let i = 0; i < classes.length; i++) {
let parentSelector = `.${classes[i]} ${selector}`;
elements = document.querySelectorAll(parentSelector);
if (elements.length === 1) {
return parentSelector;
}
if (elements.length < bestCount) {
bestSelector = parentSelector;
bestCount = elements.length;
}
parentClasses.push(classes[i]);
}
parent = parent.parentElement;
}
// Try with all parents
parent = element.parentElement;
let selectors = [selector];
while (parent && parent.tagName !== 'BODY') {
let newSelectors = [];
for (let i = 0; i < selectors.length; i++) {
let newSelector = `${parent.tagName.toLowerCase()} ${selectors[i]}`;
newSelectors.push(newSelector);
elements = document.querySelectorAll(newSelector);
if (elements.length === 1) {
return newSelector;
}
if (elements.length < bestCount) {
bestSelector = newSelector;
bestCount = elements.length;
}
}
selectors = newSelectors;
parent = parent.parentElement;
}
// Show alert and return best selector
alert('No se ha podido encontrar un selector único.');
return bestSelector;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment