Andriy Stolyar
Andriy Stolyar

Reputation: 615

How to build a CSS Selector from event object in JS?

I created a simple event listener for clicks:

window.addEventListener("click", function (event) {
  console.log(event);
});

From what I see, the event object contains a lot of useful data about the parent elements, HTML and CSS data of the clicked element.

Is there a way to build a CSS-selector (hopefully unique) from these event objects? If yes, are there any open-source solutions you can think of?

Upvotes: 1

Views: 1731

Answers (1)

T.J. Crowder
T.J. Crowder

Reputation: 1074168

Yes, it's entirely possible to build a unique CSS selector for any element in the DOM, because of the pseudo-class :nth-child which lets us differentiate between two elements with the same characteristics in the same parent.

Here's a simple example, which builds a selector using the tag name and its position relative to other elements within its parent. This example builds and shows the selector, then uses it a quarter second later to add a 'clicked' class to the element (which shows it in bold green):

// Find the index of the given element in its parent
function indexOf(element) {
    var parent = element.parentNode;
    var child, index = 1;
    for (child = parent.firstElementChild;
         child;
         child = child.nextElementSibling) {
        if (child === element) {
            return index;
        }
        ++index;
    }
    return -1;
}
document.addEventListener("click", function(e) {
    // Starting from this element, build a tagname:nth-child(x) selector
    // for it, then prepend one for each of its parents up to BODY
    var element = e.target;
    var selector = element.tagName + ":nth-child(" + indexOf(element) + ")";
    while ((element = element.parentElement) != null) {
        if (element.tagName === "BODY") {
            selector = "BODY > " + selector;
            break;
        }
        selector = element.tagName + ":nth-child(" + indexOf(element) + ") > " + selector;
    }
    show(selector);
});
function show(selector) {
    console.log(selector);
    setTimeout(function() {
        document.querySelector(selector).classList.add("clicked");
    }, 250);
}
#container, #container div {
  border: 1px solid #ddd;
}
.clicked {
  color: green;
  font-weight: bold;
}
<div id="container">
  <div>
    <span>one</span>
    <span>two</span>
    <span>three</span>
    <span>four</span>
  </div>
  <div>
    <span>one</span>
    <span>two</span>
    <span>three</span>
    <span>four</span>
  </div>
</div>

Upvotes: 3

Related Questions