admin管理员组文章数量:1394133
I am trying to find a way to build the querySelector string of any given node. In other words - pick any node on a page - is it possible to walk up the DOM and build a string that would allow me to pass the generated string to document.querySelector and get back the node I chose?
From what I can tell querySelector has a bug where you can only use nth-child once in the string.
I have tried several times but so far have failed to find a solution. I want to do this in native JavaScript, not jQuery.Any suggestions?
I am trying to find a way to build the querySelector string of any given node. In other words - pick any node on a page - is it possible to walk up the DOM and build a string that would allow me to pass the generated string to document.querySelector and get back the node I chose?
From what I can tell querySelector has a bug where you can only use nth-child once in the string.
I have tried several times but so far have failed to find a solution. I want to do this in native JavaScript, not jQuery.Any suggestions?
Share Improve this question edited Apr 22, 2015 at 4:52 BoltClock 725k165 gold badges1.4k silver badges1.4k bronze badges asked Apr 22, 2015 at 4:48 Steve LloydSteve Lloyd 9592 gold badges20 silver badges39 bronze badges 13- 1 "From what I can tell querySelector has a bug where you can only use nth-child once in the string." I'm curious, where did you read this? Can you show us what you've tried? – BoltClock Commented Apr 22, 2015 at 4:50
-
2
If the element doesn't have an id already, then generate a unique ID for it, put the id on the object and then use that with
document.querySelector()
. What problem are you really trying to solve? You can always just save an actual reference to the DOM element itself if you just want to be able to get back to it. – jfriend00 Commented Apr 22, 2015 at 4:52 -
1
You can use xpath based node selection.
document.evaluate
in Chrome & FF anddocument.selectNodes
in IE – Vijay Commented Apr 22, 2015 at 4:55 - 2 @BoltClock: developer.mozilla/en/docs/Using_XPath#getXPathForElement – Amadan Commented Apr 22, 2015 at 5:03
-
2
@Steve Lloyd: I think you can simply pass
document
directly as the second argument to getXPathForElement. – BoltClock Commented Apr 22, 2015 at 18:10
2 Answers
Reset to default 6I see this question is from 2015 but I just dealt with this issue and had to build a custom function to do so.
I've made a snippet to test it, just click any element and the querySelector should display as a string in the bottom div.
function getQuerySelector(elem) {
var element = elem;
var str = "";
function loop(element) {
// stop here = element has ID
if(element.getAttribute("id")) {
str = str.replace(/^/, " #" + element.getAttribute("id"));
str = str.replace(/\s/, "");
str = str.replace(/\s/g, " > ");
return str;
}
// stop here = element is body
if(document.body === element) {
str = str.replace(/^/, " body");
str = str.replace(/\s/, "");
str = str.replace(/\s/g, " > ");
return str;
}
// concat all classes in "queryselector" style
if(element.getAttribute("class")) {
var elemClasses = ".";
elemClasses += element.getAttribute("class");
elemClasses = elemClasses.replace(/\s/g, ".");
elemClasses = elemClasses.replace(/^/g, " ");
var classNth = "";
// check if element class is the unique child
var childrens = element.parentNode.children;
if(childrens.length < 2) {
return;
}
var similarClasses = [];
for(var i = 0; i < childrens.length; i++) {
if(element.getAttribute("class") ==
childrens[i].getAttribute("class")) {
similarClasses.push(childrens[i]);
}
}
if(similarClasses.length > 1) {
for(var j = 0; j < similarClasses.length; j++) {
if(element === similarClasses[j]) {
j++;
classNth = ":nth-of-type(" + j + ")";
break;
}
}
}
str = str.replace(/^/, elemClasses + classNth);
}
else{
// get nodeType
var name = element.nodeName;
name = name.toLowerCase();
var nodeNth = "";
var childrens = element.parentNode.children;
if(childrens.length > 2) {
var similarNodes = [];
for(var i = 0; i < childrens.length; i++) {
if(element.nodeName == childrens[i].nodeName) {
similarNodes.push(childrens[i]);
}
}
if(similarNodes.length > 1) {
for(var j = 0; j < similarNodes.length; j++) {
if(element === similarNodes[j]) {
j++;
nodeNth = ":nth-of-type(" + j + ")";
break;
}
}
}
}
str = str.replace(/^/, " " + name + nodeNth);
}
if(element.parentNode) {
loop(element.parentNode);
}
else {
str = str.replace(/\s/g, " > ");
str = str.replace(/\s/, "");
return str;
}
}
loop(element);
return str;
}
https://jsfiddle/wm6goeyw/
This works as long as DOM structure remains same. Even little change in HTML code could result to incorrect (in terms of return value) result of this function. So, it is not intended for long storing of DOM reference to HTML element.
function createQuerySelector(element) {
if (element.id) {
return `#${element.id}`;
}
const path = [];
let currentElement = element;
let error = false;
while (currentElement.tagName !== 'BODY') {
const parent = currentElement.parentElement;
if (!parent) {
error = true;
break;
}
const childTagCount= {};
let nthChildFound = false;
for (const child of parent.children) {
const tag = child.tagName;
const count = childTagCount[tag] || 0;
childTagCount[tag] = count + 1;
if (child === currentElement) {
nthChildFound = true;
break;
}
}
if (!nthChildFound) {
error = true;
break;
}
const count = childTagCount[currentElement.tagName];
const tag = currentElement.tagName.toLowerCase();
const selector = `${tag}:nth-of-type(${count})`;
path.push(selector);
currentElement = parent;
}
if (error) {
console.error(element);
throw new Error('Unable to create query selector');
}
path.push('body');
const querySelector = path.reverse().join(' > ');
return querySelector;
}
本文标签: javascriptBuild the querySelector string value of any given node in the DOMStack Overflow
版权声明:本文标题:javascript - Build the querySelector string value of any given node in the DOM - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744598004a2614892.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论