Javascript 获取被点击的 <a> 的 DOM 路径
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5728558/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Get the DOM path of the clicked <a>
提问by Tomkay
HTML
HTML
<body>
<div class="lol">
<a class="rightArrow" href="javascriptVoid:(0);" title"Next image">
</div>
</body>
Pseudo Code
伪代码
$(".rightArrow").click(function() {
rightArrowParents = this.dom(); //.dom(); is the pseudo function ... it should show the whole
alert(rightArrowParents);
});
Alert message would be:
警报消息将是:
body div.lol a.rightArrow
body div.lol a.rightArrow
How can I get this with javascript/jquery?
我怎样才能用 javascript/jquery 得到这个?
回答by Michael Connor
Here is a native JS version that returns a jQuery path. I'm also adding IDs for elements if they have them. This would give you the opportunity to do the shortest path if you see an id in the array.
这是一个返回 jQuery 路径的原生 JS 版本。如果元素有 ID,我还会为它们添加 ID。如果您在数组中看到一个 id,这将使您有机会执行最短路径。
var path = getDomPath(element);
console.log(path.join(' > '));
Outputs
输出
body > section:eq(0) > div:eq(3) > section#content > section#firehose > div#firehoselist > article#firehose-46813651 > header > h2 > span#title-46813651
Here is the function.
这是功能。
function getDomPath(el) {
var stack = [];
while ( el.parentNode != null ) {
console.log(el.nodeName);
var sibCount = 0;
var sibIndex = 0;
for ( var i = 0; i < el.parentNode.childNodes.length; i++ ) {
var sib = el.parentNode.childNodes[i];
if ( sib.nodeName == el.nodeName ) {
if ( sib === el ) {
sibIndex = sibCount;
}
sibCount++;
}
}
if ( el.hasAttribute('id') && el.id != '' ) {
stack.unshift(el.nodeName.toLowerCase() + '#' + el.id);
} else if ( sibCount > 1 ) {
stack.unshift(el.nodeName.toLowerCase() + ':eq(' + sibIndex + ')');
} else {
stack.unshift(el.nodeName.toLowerCase());
}
el = el.parentNode;
}
return stack.slice(1); // removes the html element
}
回答by T.J. Crowder
Using jQuery, like this (followed by a solution that doesn't use jQuery except for the event; lots fewer function calls, if that's important):
使用 jQuery,就像这样(接下来是一个除了事件之外不使用 jQuery 的解决方案;如果这很重要,函数调用就会少很多):
$(".rightArrow").click(function() {
var rightArrowParents = [];
$(this).parents().addBack().not('html').each(function() {
var entry = this.tagName.toLowerCase();
if (this.className) {
entry += "." + this.className.replace(/ /g, '.');
}
rightArrowParents.push(entry);
});
alert(rightArrowParents.join(" "));
return false;
});
Live example:
现场示例:
$(".rightArrow").click(function() {
var rightArrowParents = [];
$(this).parents().addBack().not('html').each(function() {
var entry = this.tagName.toLowerCase();
if (this.className) {
entry += "." + this.className.replace(/ /g, '.');
}
rightArrowParents.push(entry);
});
alert(rightArrowParents.join(" "));
return false;
});
<div class="lol multi">
<a href="#" class="rightArrow" title="Next image">Click here</a>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
(In the live examples, I've updated the class
attribute on the div
to be lol multi
to demonstrate handling multiple classes.)
(在实时示例中,我更新class
了div
to be上的属性lol multi
以演示处理多个类。)
That uses parents
to get the ancestors of the element that was clicked, removes the html
element from that via not
(since you started at body
), then loops through creating entries for each parent and pushing them on an array. Then we use addBack
to add the a
back into the set, which also changes the order of the set to what you wanted (parents
is special, it gives you the parents in the reverse of the order you wanted, but then addBAck
puts it back in DOM order). Then it uses Array#join
to create the space-delimited string.
这用于parents
获取被单击元素的祖先,html
从该 via 中删除元素not
(因为您从 开始body
),然后循环为每个父元素创建条目并将它们推送到数组上。然后我们使用addBack
将a
back添加到 set 中,这也将 set 的顺序更改为您想要的(parents
很特别,它以与您想要的顺序相反的顺序为您提供父母,然后addBAck
将其放回 DOM 顺序) . 然后它用于Array#join
创建以空格分隔的字符串。
When creating the entry, if there's anything on className
we replace spaces with .
to support elements that have more than one class (<p class='foo bar'>
has className
= "foo bar"
, so that entry ends up being p.foo.bar
).
创建条目时,如果有任何内容,className
我们将替换空格.
以支持具有多个类的元素(<p class='foo bar'>
has className
= "foo bar"
,因此条目最终为p.foo.bar
)。
Just for completeness, this is one of those places where jQuery may be overkill, you can readily do this just by walking up the DOM:
为了完整起见,这是 jQuery 可能过度使用的地方之一,您只需走 DOM 就可以轻松做到这一点:
$(".rightArrow").click(function() {
var rightArrowParents = [],
elm,
entry;
for (elm = this; elm; elm = elm.parentNode) {
entry = elm.tagName.toLowerCase();
if (entry === "html") {
break;
}
if (elm.className) {
entry += "." + elm.className.replace(/ /g, '.');
}
rightArrowParents.push(entry);
}
rightArrowParents.reverse();
alert(rightArrowParents.join(" "));
return false;
});
Live example:
现场示例:
$(".rightArrow").click(function() {
var rightArrowParents = [],
elm,
entry;
for (elm = this; elm; elm = elm.parentNode) {
entry = elm.tagName.toLowerCase();
if (entry === "html") {
break;
}
if (elm.className) {
entry += "." + elm.className.replace(/ /g, '.');
}
rightArrowParents.push(entry);
}
rightArrowParents.reverse();
alert(rightArrowParents.join(" "));
return false;
});
<div class="lol multi">
<a href="#" class="rightArrow" title="Next image">Click here</a>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
There we just use the standard parentNode
propertyof the element repeatedly to walk up the tree until either we run out of parents or we see the html
element. Then we reverse our array (since it's backward to the output you wanted), and join it, and we're good to go.
在那里,我们只是重复使用元素的标准parentNode
属性沿着树向上走,直到我们用完父html
元素或我们看到元素。然后我们反转我们的数组(因为它向后返回到您想要的输出),并加入它,我们很高兴。
回答by Aleksandar Totic
I needed a native JS version, that returns CSS standard path (not jQuery), and deals with ShadowDOM. This code is a minor update on Michael Connor's answer, just in case someone else needs it:
我需要一个原生 JS 版本,它返回 CSS 标准路径(不是 jQuery),并处理 ShadowDOM。此代码是 Michael Connor 答案的一个小更新,以防万一其他人需要它:
function getDomPath(el) {
if (!el) {
return;
}
var stack = [];
var isShadow = false;
while (el.parentNode != null) {
// console.log(el.nodeName);
var sibCount = 0;
var sibIndex = 0;
// get sibling indexes
for ( var i = 0; i < el.parentNode.childNodes.length; i++ ) {
var sib = el.parentNode.childNodes[i];
if ( sib.nodeName == el.nodeName ) {
if ( sib === el ) {
sibIndex = sibCount;
}
sibCount++;
}
}
// if ( el.hasAttribute('id') && el.id != '' ) { no id shortcuts, ids are not unique in shadowDom
// stack.unshift(el.nodeName.toLowerCase() + '#' + el.id);
// } else
var nodeName = el.nodeName.toLowerCase();
if (isShadow) {
nodeName += "::shadow";
isShadow = false;
}
if ( sibCount > 1 ) {
stack.unshift(nodeName + ':nth-of-type(' + (sibIndex + 1) + ')');
} else {
stack.unshift(nodeName);
}
el = el.parentNode;
if (el.nodeType === 11) { // for shadow dom, we
isShadow = true;
el = el.host;
}
}
stack.splice(0,1); // removes the html element
return stack.join(' > ');
}
回答by Gabriele Petrioli
Here is a solution for exact matching of an element.
这是一个元素精确匹配的解决方案。
It is important to understand that the selector(it is not a real one) that the chrome tools show do not uniquely identify an element in the DOM. (for example it will not distinguish between a list of consecutive span
elements. there is no positioning/indexing info)
重要的是要了解chrome 工具显示的选择器(它不是真正的选择器)不能唯一标识 DOM 中的元素。(例如它不会区分连续span
元素的列表。没有定位/索引信息)
An adaptation from a similar (about xpath) answer
$.fn.fullSelector = function () {
var path = this.parents().addBack();
var quickCss = path.get().map(function (item) {
var self = $(item),
id = item.id ? '#' + item.id : '',
clss = item.classList.length ? item.classList.toString().split(' ').map(function (c) {
return '.' + c;
}).join('') : '',
name = item.nodeName.toLowerCase(),
index = self.siblings(name).length ? ':nth-child(' + (self.index() + 1) + ')' : '';
if (name === 'html' || name === 'body') {
return name;
}
return name + index + id + clss;
}).join(' > ');
return quickCss;
};
And you can use it like this
你可以像这样使用它
console.log( $('some-selector').fullSelector() );
回答by darthmatch
I moved the snippet from T.J. Crowder to a tiny jQuery Plugin. I used the jQuery version of him even if he's right that this is totally unnecessary overhead, but i only use it for debugging purpose so i don't care.
我将代码片段从 TJ Crowder 移到了一个很小的 jQuery 插件中。我使用了他的 jQuery 版本,即使他是对的,这完全是不必要的开销,但我只将它用于调试目的,所以我不在乎。
Usage:
用法:
Html
html
<html>
<body>
<!-- Two spans, the first will be chosen -->
<div>
<span>Nested span</span>
</div>
<span>Simple span</span>
<!-- Pre element -->
<pre>Pre</pre>
</body>
</html>
Javascript
Javascript
// result (array): ["body", "div.sampleClass"]
$('span').getDomPath(false)
// result (string): body > div.sampleClass
$('span').getDomPath()
// result (array): ["body", "div#test"]
$('pre').getDomPath(false)
// result (string): body > div#test
$('pre').getDomPath()
Repository
存储库
回答by sv_in
$(".rightArrow")
.parents()
.map(function () {
var value = this.tagName.toLowerCase();
if (this.className) {
value += '.' + this.className.replace(' ', '.', 'g');
}
return value;
})
.get().reverse().join(", ");
回答by Jayram Prajapati
hello this function solve the bug related to current element not show in the path
你好这个功能解决了当前元素没有显示在路径中的问题
check this now
现在检查这个
$j(".wrapper").click(function(event) {
selectedElement=$j(event.target);
var rightArrowParents = [];
$j(event.target).parents().not('html,body').each(function() {
var entry = this.tagName.toLowerCase();
if (this.className) {
entry += "." + this.className.replace(/ /g, '.');
}else if(this.id){
entry += "#" + this.id;
}
entry=replaceAll(entry,'..','.');
rightArrowParents.push(entry);
});
rightArrowParents.reverse();
//if(event.target.nodeName.toLowerCase()=="a" || event.target.nodeName.toLowerCase()=="h1"){
var entry = event.target.nodeName.toLowerCase();
if (event.target.className) {
entry += "." + event.target.className.replace(/ /g, '.');
}else if(event.target.id){
entry += "#" + event.target.id;
}
rightArrowParents.push(entry);
// }
where $j
= jQuery Variable
where $j
= jQuery 变量
also solve the issue with .. in class name
也用 .. 在类名中解决问题
here is replace function :
这是替换功能:
function escapeRegExp(str) {
return str.replace(/([.*+?^=!:${}()|\[\]\/\])/g, "\");
}
function replaceAll(str, find, replace) {
return str.replace(new RegExp(escapeRegExp(find), 'g'), replace);
}
Thanks
谢谢
回答by Haradzieniec
var obj = $('#show-editor-button'),
path = '';
while (typeof obj.prop('tagName') != "undefined"){
if (obj.attr('class')){
path = '.'+obj.attr('class').replace(/\s/g , ".") + path;
}
if (obj.attr('id')){
path = '#'+obj.attr('id') + path;
}
path = ' ' +obj.prop('tagName').toLowerCase() + path;
obj = obj.parent();
}
console.log(path);