How to create a unique CSS selector for a DOM element?

I need to create a unique css selector for elements.
In particular, I have an onclick event handler that needs to remember which target element was clicked and sent this information to my server. Is there a way to do this without modifying the DOM?

PS my javascript code should be running on different sites of 3-party websites, so I can not make any assumptions about html.

+8
javascript dom css-selectors
source share
5 answers

let's say you have a list of links for simplicity: you can simply pass the index of the triggering element to the collection of all elements

<a href="#">...</a> <a href="#">...</a> <a href="#">...</a> 

js (jQuery 1.7+, I used .on() otherwise use bind() ), the function may be

 var triggers = $('a'); triggers.on('click', function(e) { e.preventDefault(); var index = triggers.index($(this)); /* ajax call passing index value */ }); 

so if you click on the passed index value of the third element, there will be 2. (index based on 0); Of course, this is true if the code (DOM) does not change. Later you can use this index to create a CSS rule for this element, for example. using :nth-child

Otherwise, if each of your elements has a different attribute (e.g. id), you can pass this attribute

example on JsFiddle: http://jsfiddle.net/t7J8T/

+1
source share

Yes, you could do it. But with a few caveats. To be able to guarantee the uniqueness of selectors, you need to use :nth-child() , which is not universally supported. If you want to put these CSS selectors in CSS files, this will not work in all browsers.

I would do it with something like this:

 function () { if (this.id) { return sendToServer('#' + this.id); } var parent = this.parentNode; var selector = '>' + this.nodeName + ':nth-child(' + getChildNumber(this) ')'; while (!parent.id && parent.nodeName.toLowerCase() !== 'body') { selector = '>' + this.nodeName + ':nth-child(' + getChildNumber(parent) + ')' + selector; parent = parent.parentNode; } if (parent.nodeName === 'body') { selector = 'body' + selector; } else { selector = '#' + parent.id + selector; } return sendToServer(selector); } 

Then add this to your click handler for each item you want to simulate. I will leave you to implement getChildNumber() .

Edit: Just looked at your comment that it is third-party code ... so you can add an event argument, replace all instances of this with event.target , and then just insert the window function to click the event, if that is easier.

+3
source share

Perhaps you can traverse the DOM tree from node back to the body element to create a selector.

Firebug has a function for this, both with XPath and with CSS selectors.

See this answer

+1
source share
 "use strict"; function getSelector(_context){ var index, localName,pathSelector, that = _context, node; if(that =='null') throw 'not an dom reference'; index = getIndex(that); while(that.tagName){ pathSelector = that.localName+(pathSelector?'>'+pathSelector :''); that = that.parentNode; } pathSelector = pathSelector+':nth-of-type('+index+')'; return pathSelector; } function getIndex(node){ var i=1; var tagName = node.tagName; while(node.previousSibling){ node = node.previousSibling; if(node.nodeType === 1 && (tagName.toLowerCase() == node.tagName.toLowerCase())){ i++; } } return i; } document.addEventListener('DOMContentLoaded', function(){ document.body.addEventListener('mouseover', function(e){ var c = getSelector(e.target); var element = document.querySelector(c); //console.log(element); console.log(c); //element.style.color = "red" }); }); 

you can try this. without using jquery.

+1
source share

Check out this library of CSS @ medv / finder selector generators

Build status

  • Generating Shortest Selectors
  • Unique page selectors
  • Stable and reliable selectors
  • 2.9 kB gzip and minify size

An example of a generated selector:

 .blog > article:nth-child(3) .add-comment 
+1
source share

All Articles