Skip to content

Instantly share code, notes, and snippets.

@danemacaulay
Last active March 15, 2020 10:33
Show Gist options
  • Save danemacaulay/7fe1a2a0074feb7a57b6bb7b039f673e to your computer and use it in GitHub Desktop.
Save danemacaulay/7fe1a2a0074feb7a57b6bb7b039f673e to your computer and use it in GitHub Desktop.
get unique css selector by element
'use strict';
function attributeIterator(node, extractorFunction) {
var selector = '';
var attributes = node.attributes;
for (var i = 0; i < attributes.length; i++) {
var attr = attributes[i];
var attrSelector = extractorFunction(attr);
if (attrSelector) {
selector += attrSelector;
}
}
return selector;
}
function getNthChild(node) {
var nthChild;
var siblings = node.parentElement.children;
for (var i = 0; i < siblings.length; i++) {
var sibling = siblings[i];
if (sibling.isEqualNode(node)) {
nthChild = i + 1;
}
}
return nthChild;
}
function getMaxDepth(node) {
var depth = 0;
while (!node.isEqualNode(document.body)) {
depth++;
node = node.parentElement;
}
return depth;
}
function byClass(node) {
return attributeIterator(node, function (attribute) {
if (attribute.name === 'class') {
return '.' + attribute.value.replace(' ', '.');
}
});
}
function byId(node) {
return attributeIterator(node, function (attribute) {
if (attribute.name === 'id') {
return '#' + attribute.value;
}
});
}
function byAttributes(node) {
return attributeIterator(node, function (attribute) {
if (attribute.name === 'id' || attribute.name === 'class' || attribute.name === 'href') {
return;
}
return '[' + attribute.name + '="' + attribute.value + '"]';
});
}
function byNthChild(node) {
if (node.parentElement) {
var nthChild = getNthChild(node);
return ':nth-child(' + nthChild + ')';
}
return '';
}
function byTag(node) {
return node.tagName;
}
function getSelectorByStrategies(node, strategies) {
var selector = '';
strategies.forEach(function (strategy) {
selector += strategy(node);
});
return selector;
}
function uniqueSelector(node, strategies, unusedStrategies, context = []) {
if (node === null) {
throw new Error('No node provided');
}
strategies = strategies || [byTag];
unusedStrategies = unusedStrategies || [
byId,
byClass,
byAttributes,
// byNthChild,
];
var selector = getSelectorByStrategies(node, strategies);
var fullSelector = context.length ? selector + ' ' + context.join(' ') : selector;
var results = document.querySelectorAll(fullSelector);
if (node.isEqualNode(document.body)) {
console.log('unable to get unique selector')
}
else if (results.length > 1 && unusedStrategies.length === 0 && node.parentElement) {
context.unshift(selector);
return uniqueSelector(node.parentElement, null, null, context);
}
else if (results.length > 1) {
strategies.push(unusedStrategies.shift());
return uniqueSelector(node, strategies, unusedStrategies, context);
}
else if (results.length === 0) {
throw new Error('unable to get unique selector');
}
return fullSelector;
}
document.addEventListener('click', function(e) {
e = e || window.event;
e.preventDefault();
var target = e.target || e.srcElement;
var text = target.textContent || text.innerText;
var selector = uniqueSelector(target);
console.log(text + '\n' + selector + '\n -------');
}, false);
@danemacaulay
Copy link
Author

paste this into the debugging console then click on elements on the current page to get their unique selector written out to the console

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment