Skip to content

Instantly share code, notes, and snippets.

@eliascotto
Last active July 18, 2021 06:28
Show Gist options
  • Save eliascotto/1de5f191b02ac41f2eea3a41ad45e728 to your computer and use it in GitHub Desktop.
Save eliascotto/1de5f191b02ac41f2eea3a41ad45e728 to your computer and use it in GitHub Desktop.
DOM Element selector
/**
* UI to select any element on the webpage using the mouse,
* and print to console the exact selector of the DOM element.
*
* Inspired by Firefox Screenshot
*
* Live Version:
* https://codesandbox.io/s/dom-element-selector-dsm69
*/
(function () {
let attached = false;
let overlayEl = null;
let elementBg = null;
function addBackgroundOverlay() {
overlayEl = document.createElement("div");
overlayEl.dataset.overlaySelector = true;
overlayEl.style.position = "absolute";
overlayEl.style.display = "block";
overlayEl.style.top = 0;
overlayEl.style.left = 0;
overlayEl.style.width = "100%";
overlayEl.style.height = "100%";
overlayEl.style.zIndex = 998;
overlayEl.style.background = "rgba(0, 0, 0, 0.75)";
document.body.append(overlayEl);
}
function addBackgroundMouseEl(el) {
elementBg = document.createElement("div");
elementBg.dataset.mouseElementSelector = true;
elementBg.style.position = "absolute";
elementBg.style.display = "block";
elementBg.style.top = 0;
elementBg.style.left = 0;
elementBg.style.width = 0;
elementBg.style.height = 0;
elementBg.style.zIndex = 999;
elementBg.style.background = "rgba(255, 255, 255, 0.3)";
elementBg.style.border = "2px dashed #ccc";
elementBg.style.boxSizing = "border-box";
elementBg.addEventListener("click", mouseClickHander);
overlayEl.append(elementBg);
}
function getSelector(el) {
// Common attributes for create a selector
const attributes = ["title", "href", "disabled", "for", "src"];
// Change delimiter for capture similar elements
const delimiter = " > "
let selectors = [];
let element = el;
while (element) {
if (typeof element.hasAttribute === "function") {
attributes.forEach((attr) => {
if (element.hasAttribute(attr)) {
selectors.unshift(`[${attr}="${element.getAttribute(attr)}"]`);
}
});
}
if (element.className) {
element.classList.forEach((cl) => {
selectors.unshift("." + cl);
});
}
if (element.id && !/\s/.test(element.id)) {
selectors.unshift("#" + element.id);
}
selectors.unshift(element.tagName);
selectors.unshift(delimiter);
element = element.parentNode;
}
return selectors.join("");
}
function getElementUnderCursor(e) {
const elementsFromPoint = document.elementsFromPoint(e.x, e.y);
return elementsFromPoint.find(
(el) =>
!el.hasAttribute("data-overlay-selector") &&
!el.hasAttribute("data-mouse-element-selector")
);
}
function mouseMoveHandler(e) {
const elUnderCursor = getElementUnderCursor(e);
const elPosSize = elUnderCursor.getBoundingClientRect();
elementBg.style.top = `${elPosSize.top}px`;
elementBg.style.left = `${elPosSize.left}px`;
elementBg.style.width = `${elPosSize.width}px`;
elementBg.style.height = `${elPosSize.height}px`;
}
function mouseClickHander(e) {
const elUnderCursor = getElementUnderCursor(e);
const elSelector = getSelector(elUnderCursor);
console.log(elSelector);
}
function attachMouseMoveEvent() {
if (!attached) {
document.addEventListener("mousemove", mouseMoveHandler);
attached = true;
}
}
function detachMouseMoveEvent() {
if (attached) {
overlayEl.remove();
elementBg.removeEventListener("click", mouseClickHander);
elementBg.remove();
document.removeEventListener("mousemove", mouseMoveHandler);
attached = false;
}
}
document.getElementById("select").addEventListener("click", (e) => {
e.preventDefault();
e.stopPropagation();
addBackgroundOverlay();
addBackgroundMouseEl();
attachMouseMoveEvent();
});
document.addEventListener("keyup", (e) => {
if (e.key === "Escape") {
detachMouseMoveEvent();
}
});
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment