Get unique selector of element in Jquery
I'll answer this myself, because i found a solution which i had to modify. The following script is working and is based on a script of Blixt:
jQuery.fn.extend({
getPath: function () {
var path, node = this;
while (node.length) {
var realNode = node[0], name = realNode.name;
if (!name) break;
name = name.toLowerCase();
var parent = node.parent();
var sameTagSiblings = parent.children(name);
if (sameTagSiblings.length > 1) {
var allSiblings = parent.children();
var index = allSiblings.index(realNode) + 1;
if (index > 1) {
name += ':nth-child(' + index + ')';
}
}
path = name + (path ? '>' + path : '');
node = parent;
}
return path;
}
});
How to get the unique selector of elements
What about something like this ?
var getUniquePath = function( node ) {
var parts = [ ];
$( node ).parents().each( function( index, element ) {
parts .push( element.tagName + '[' + $(element).index() + ']' );
});
return parts.join( '', parts.reverse() );
}
javascript get element unique selector
Keep in mind that this will not necessarily uniquely identify elements. But, you can construct that type of selector by traversing upwards from the node and prepending the element you're at. You could potentially do something like this
var generateQuerySelector = function(el) { if (el.tagName.toLowerCase() == "html") return "HTML"; var str = el.tagName; str += (el.id != "") ? "#" + el.id : ""; if (el.className) { var classes = el.className.split(/\s/); for (var i = 0; i < classes.length; i++) { str += "." + classes[i] } } return generateQuerySelector(el.parentNode) + " > " + str;}
var qStr = generateQuerySelector(document.querySelector("div.moo"));alert(qStr);
body<div class="outer"> div.outer <div class="inner" id="foo"> div#foo.inner <div class="moo man"> div.moo.man </div> </div></div>
Get unique selector jQuery
Another approach might be to wander up the dom tree and create a path to the element, which you can save and use it later as a selector again, although that might not be bulletproof, but maybe its a point where you can start off.
Edit: Updated the Answer with your suggestion in the comment, now it returns the id if available
Just visit the example on JSBin And click the document
twice.
but notice what gets highlighted..
jQuery.fn.getPath = function () {
if (this.length != 1) throw 'Requires one element.';
var path, node = this;
if (node[0].id) return "#" + node[0].id;
while (node.length) {
var realNode = node[0],
name = realNode.localName;
if (!name) break;
name = name.toLowerCase();
var parent = node.parent();
var siblings = parent.children(name);
if (siblings.length > 1) {
name += ':eq(' + siblings.index(realNode) + ')';
}
path = name + (path ? '>' + path : '');
node = parent;
}
return path;
};
var sel;
$(document)
.click(function (e, a) {
if (!sel) {
sel = $("#comment-21702402")
.getPath();
alert("Path is: " + sel + ", hiding the Element -> Click again to highlight");
} else {
$(sel)
.css("background-color", "yellow");
}
});
Jquery get unique css selector on rightclick menu item or click a dom element
Putting the answer of @jeka5555 together with a library such as css-selector-generator.js, and using MDN's xpath generator you can do this:
<html>
<head>
<script src="./css-selector-generator.js"></script>
<script>
function getXPathForElement(el, xml) {
var xpath = '';
var pos, tempitem2;
while(el !== xml.documentElement) {
pos = 0;
tempitem2 = el;
while(tempitem2) {
if (tempitem2.nodeType === 1 && tempitem2.nodeName === el.nodeName) { // If it is ELEMENT_NODE of the same name
pos += 1;
}
tempitem2 = tempitem2.previousSibling;
}
xpath = "*[name()='"+el.nodeName+"' and namespace-uri()='"+(el.namespaceURI===null?'':el.namespaceURI)+"']["+pos+']'+'/'+xpath;
el = el.parentNode;
}
xpath = '/*'+"[name()='"+xml.documentElement.nodeName+"' and namespace-uri()='"+(el.namespaceURI===null?'':el.namespaceURI)+"']"+'/'+xpath;
xpath = xpath.replace(/\/$/, '');
return xpath;
}
</script>
<script>
function context(event) {
event.preventDefault();
console.log(event.target);
var sel_gen = new CssSelectorGenerator();
var sel = sel_gen.getSelector(event.target);
var xpath = getXPathForElement(event.target, document);
alert("sel: " + sel + "; xpath: " + xpath);
}
</script>
</head>
<body>
<div class=myclass>
<div>
<p oncontextmenu="context(event)">Right click me</p>
<p>Clicking me won't help</p>
</div>
</div>
</body>
</html>
This particular case alerts:
sel: .myclass > div > :nth-child(1); xpath: /*[name()='HTML' and namespace-uri()='http://www.w3.org/1999/xhtml']/*[name()='BODY' and namespace-uri()='http://www.w3.org/1999/xhtml'][1]/*[name()='DIV' and namespace-uri()='http://www.w3.org/1999/xhtml'][1]/*[name()='DIV' and namespace-uri()='http://www.w3.org/1999/xhtml'][1]/*[name()='P' and namespace-uri()='http://www.w3.org/1999/xhtml'][1]
I would trust the library to get it right much more than I would trust myself!
And try this jsfiddle.
Also this jsfiddle modifies the Mozilla function to give a simpler xpath.
There are other libraries available for the css selector, see this answer to a similar question.
How to get unique selector on jQuery
You can do it either like this:
const data = $($('.row').get(1)).find('table tr').map(function() {
const a = $(this).find('td:first-child a');
const td = $(this).find('td:last-child');
return {
version: a.text(),
href: a.attr('href'),
date: td.text()
}
}).get();
Or like this:
const data = $(document.getElementsByClassName('row')[1]).find('table tr').map(function() {
const a = $(this).find('td:first-child a');
const td = $(this).find('td:last-child');
return {
version: a.text(),
href: a.attr('href'),
date: td.text()
}
}).get();
const data = $($('.row').get(1)).find('table tr').map(function() { const a = $(this).find('td:first-child a'); const td = $(this).find('td:last-child');
return { version: a.text(), href: a.attr('href'), date: td.text() }}).get();console.log(data)
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script><div class="row" style="margin-left: 2%; margin-right: 2%;"> <table class="striped" style="margin-left: auto; margin-right: auto;"> <tbody> <tr> <td>App Download Version</td> <td><span>1.12</span></td> </tr> <tr> <td>Last Updated</td> <td><span>April 8, 2018</span></td> </tr> <tr> <td>Apk Size</td> <td><span>3.0M</span></td> </tr> <tr> <td>App by</td> <td><span>Free Music - lt;/span></td> </tr> <tr> <td>Category</td> <td><a title="Download Music & Audio apps apks" href="/category/music-audio/1/"><span>Free</span><span> Music & Audio</span> App</a></td> </tr> <tr> <td>Content Rating</td> <td>Teen</td> </tr> <tr> <td>Support Android Version</td> <td><span>Android 15 and above</span></td> </tr> <tr> <td>App Package</td> <td class="hide-on-small-only">com.musicstreaming.freemusic</td> <td class="hide-on-med-and-up">com.musicstr...</td> </tr> </tbody> </table>
<!-- Second Part -->
<div class="row" style="margin-left: 2%; margin-right: 2%;"> <table class="striped" style="margin-left: auto; margin-right: auto;"> <tbody> <tr> <td><a title="download Free Music 1.12 apk " onclick="ga('send', 'event', 'button', 'download_ver', 'com.musicstreaming.freemusic_2018-04-08.apk');" href="/download-app/com.musicstreaming.freemusic/4_com.musicstreaming.freemusic_2018-04-08.apk/">1.12</a></td> <td>April 8, 2018</td> </tr> </tbody> </table>
Getting a jQuery selector for an element
I see now that a plugin existed (with the same name I thought of too), but here's just some quick JavaScript I wrote. It takes no consideration to the ids or classes of elements – only the structure (and adds :eq(x)
where a node name is ambiguous).
jQuery.fn.getPath = function () {
if (this.length != 1) throw 'Requires one element.';
var path, node = this;
while (node.length) {
var realNode = node[0], name = realNode.name;
if (!name) break;
name = name.toLowerCase();
var parent = node.parent();
var siblings = parent.children(name);
if (siblings.length > 1) {
name += ':eq(' + siblings.index(realNode) + ')';
}
path = name + (path ? '>' + path : '');
node = parent;
}
return path;
};
(License: MIT)
Reveal a unique selector inside jQuery each()
If I understand your question correctly, you could use a jQuery extension (like the one listed here) when looping through you .each
function.
JSFiddle Demo
$(function () {
var selectors = [];
$('#abc, .xyz').each(function () {
var uniqueSelectorForThis = $(this).getPath();
selectors.push(uniqueSelectorForThis);
});
// Will log this based on your HTML:
// ["html>body>div", "html>body>div:nth-child(2)", "html>body>div:nth-child(3)", "html>body>div:nth-child(4)"]
console.log(selectors);
});
Related Topics
Memory Leak Risk in JavaScript Closures
Can JavaScript Connect with MySQL
Foreach on Queryselectorall Not Working in Recent Microsoft Browsers
How to Determine Which Submit Button Was Pressed, Form Onsubmit Event, Without Jquery
Getelementsbyname() Not Working
Scroll with Anchor Without # in Url
Making a Chrome Extension Download a File
Ignore Mouse Interaction on Overlay Image
Why Does Jquery Only Affect the First Div Element
How to Check If an HTML Element Is Empty Using Jquery
Why Is Value Undefined at .Then() Chained to Promise
How to Get Image from Canvas Element and Use It in Img Src Tag
Setting CSS Value Limits of the Window Scrolling Animation
How to Export HTML Table to Excel Using JavaScript