Get Unique Selector of Element in Jquery

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



Leave a reply



Submit