1

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?

4
  • 1
    "Is there a way to build a CSS-selector (hopefully unique) from these event objects?" Yes, you can build a unique CSS selector for any element if you start with a reference to the element (such as event.target). That selector is not likely to be useful, however. Without knowing what you want to do with it, we can't reasonably answer this question. Commented Oct 18, 2017 at 14:15
  • 1
    I want to record user actions on my website using eventListenters, and then replay these actions using Selenium(browser automation). I was going to use CSS-selectors of elements to find them and click(there's a function in Selenium called find_element_by_css_selector()). Commented Oct 18, 2017 at 14:20
  • You can walk the DOM up to the top and create a selector such as body div:nth-child(44) span:nth-child(3). Commented Oct 18, 2017 at 14:34
  • You could save the x/y of the event then dispatch a click event at that x/y coordinate Commented Oct 18, 2017 at 14:37

1 Answer 1

3

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>

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.