获取元素的 CSS 选择器(当它没有 id 时)
Posted
技术标签:
【中文标题】获取元素的 CSS 选择器(当它没有 id 时)【英文标题】:Get element's CSS selector (when it doesn't have an id) 【发布时间】:2011-06-03 01:16:55 【问题描述】:我正在尝试通过 javascript/CSS 修改页面(很像 Stylish 或 Greasemonkey 所做的)。这是一个非常复杂的页面(我没有构建,或者无法修改预渲染),这使得构建 CSS 选择器变得很困难(手动查看文档结构)。我怎样才能做到这一点?
【问题讨论】:
抱歉,您如何识别元素?还是您的意思是构建完整的 DOM 树? 我的最终目的是为对象创建一个 css 选择器。我可以查看页面代码并通过查看文档来推断此路径(来自 gmail.com “div.nH.T4.pp + div.pp + div.nH.pp.ps.TZ”的示例选择器),我想要一种方法来帮助我构建选择器。 嘿,rcphq,你找到解决这个问题的任何方法了吗?我也在寻找同样的东西。 为什么不使用它的 id 如果它有一个,或者如果它没有一个就分配一个新的 id? 这是一个比看起来更复杂的问题,有good libraries that solve it。此外,它是 Getting a jQuery selector for an element 的副本。 【参考方案1】:如果元素是 div 表或 body..etc 中的第一个子元素,则可以用于 css first-child 伪类
你可以使用 jquery 的第 n 个 child() 函数。
http://api.jquery.com/nth-child-selector/
来自 jquery.com 的示例
<!DOCTYPE html>
<html>
<head>
<style>
div float:left;
span color:blue;
</style>
<script src="http://code.jquery.com/jquery-1.4.4.js"></script>
</head>
<body>
<div><ul>
<li>John</li>
<li>Karl</li>
<li>Brandon</li>
</ul></div>
<div><ul>
<li>Sam</li>
</ul></div>
<div><ul>
<li>Glen</li>
<li>Tane</li>
<li>Ralph</li>
<li>David</li>
</ul></div>
<script>$("ul li:nth-child(2)").append("<span> - 2nd!</span>");</script>
</body>
</html>
如果我正确理解了这个问题,我的 2 美分。
【讨论】:
这可行,但我在我没有建立的页面上执行此操作,因此 id 需要以某种方式获得它是什么“nth-child”。这是我的主要问题。【参考方案2】:function fullPath(el)
var names = [];
while (el.parentNode)
if (el.id)
names.unshift('#'+el.id);
break;
else
if (el==el.ownerDocument.documentElement) names.unshift(el.tagName);
else
for (var c=1,e=el;e.previousElementSibling;e=e.previousElementSibling,c++);
names.unshift(el.tagName+":nth-child("+c+")");
el=el.parentNode;
return names.join(" > ");
console.log( fullPath( $('input')[0] ) );
// "#search > DIV:nth-child(1) > INPUT:nth-child(1)"
这似乎是您要求的,但您可能会意识到这并不能保证唯一标识一个元素。 (对于上面的示例,所有同级输入也将匹配。)
编辑:将代码更改为使用 nth-child
而不是 CSS 类来正确消除单个孩子的歧义。
【讨论】:
漂亮简洁的纯 js 函数 :) 请注意, :nth-child 在应用于 HTML 标记时将不起作用......或者至少我无法让它在 Firefox 或Chrome...我想这可能是由于 没有父级。 没问题,我也不会考虑这个问题:) 我已经提交了一个微妙的编辑,在你的新版本中将“HTML”更改为“html”......由于 .toLowerCase( ) 方法。 请注意,由于 CSS 选择器不允许选择 DOM 文本节点,因此此代码在这种情况下会产生错误的结果(el.tagName 将给出 undefined)。 不错...可能想将它打包到一个库中,或者可能改进 one 的 10+ ones 做同样的事情。 这将很好地工作,直到他们预先添加另一个孩子,这是nth-child()
选择器的固有问题。我会使用特异性派生一个选择器。【参考方案3】:
使用安装了 FireBug 的 FireFox。
右键单击任何元素 选择“检查元素” 右键单击 HTML 树中的元素 选择“复制 XPath”或“复制 CSS 路径”此答案的永久链接的输出 (XPath):
/html/body/div[4]/div[2]/div[2]/div[2]/div[3]/table/tbody/tr/td[2]/table/tbody/tr/ td/div/a
CSS 路径:
html body.question-page div.container div#content div#mainbar div#answers div#answer-4588287.answer table tbody tr td table.fw tbody tr td.vt div.post-menu a
但是关于这条评论:
我的最终目的是创建一个 CSS 对象的选择器...
如果这是您的意图,可能有更简单的 JavaScript 方法:
var uniquePrefix = 'isThisUniqueEnough_';
var counterIndex = 0;
function addCssToElement(elem, cssText)
var domId;
if(elem.id)domId=elem.id;
else
domId = uniquePrefix + (++counterIndex);
elem.id = domId;
document.styleSheets[0].insertRule("#"+domId+""+cssText+"");
最后一行可能需要针对不同的浏览器进行不同的实现。没有测试。
【讨论】:
谢谢,我使用的是 chrome 的 firebug (lite) 版本,但找不到这个选项。像魅力一样工作。【参考方案4】:我发现我实际上可以使用this code from chrome devtools source 来解决这个问题,而无需进行太多修改。
在将 WebInspector.DOMPresentationUtils
中的相关方法添加到新命名空间并修复一些差异后,我简单地这样称呼它:
> UTILS.cssPath(node)
实现示例see css_path.js
【讨论】:
这是迄今为止我找到的最好的解决方案。为方便起见,我将其发布在 npm 上:npmjs.com/package/cssman @Macks:你愿意publish the source on GitHub吗? 其实Chromium code produces a lot of non-unique selectors。 如果非唯一意味着生成的选择器应返回 1 且仅返回 1 个元素,则操作从未明确要求它。但是应该很容易修改代码以检查同级并获取索引或其他不同的属性 为什么会产生非唯一的?我以为它做了第 n 个孩子的事情?【参考方案5】:检查这个 CSS 选择器生成器库@medv/finder
生成最短选择器 每页的唯一选择器 稳定而健壮的选择器 2.9 kB gzip 并缩小大小生成选择器示例:
.blog > article:nth-child(3) .add-comment
【讨论】:
【参考方案6】:function getCssSelector(el)
names = [];
do
index = 0;
var cursorElement = el;
while (cursorElement !== null)
++index;
cursorElement = cursorElement.previousElementSibling;
;
names.unshift(el.tagName + ":nth-child(" + index + ")");
el = el.parentElement;
while (el !== null);
return names.join(" > ");
【讨论】:
以上是关于获取元素的 CSS 选择器(当它没有 id 时)的主要内容,如果未能解决你的问题,请参考以下文章