获取元素的 CSS 选择器(当它没有 id 时)

IT技术 javascript dom css-selectors
2021-01-17 23:57:11

我正在尝试通过 JavaScript/CSS 修改页面(很像 Stylish 或 Greasemonkey 所做的)。这是一个非常复杂的页面(我没有构建,或者无法修改预渲染),这使得构建 CSS 选择器变得困难(手动查看文档结构)。我怎样才能做到这一点?

6个回答
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 类来正确消除单个孩子的歧义。

没问题,这也不是我会想到的 :) 由于 .toLowerCase() 方法,我已经提交了一个微妙的编辑,在您的新修订版中将“HTML”更改为“html”。
2021-03-19 23:57:11
请注意,由于 CSS 选择器不允许选择 DOM 文本节点,因此在这种情况下,此代码将产生错误的结果(el.tagName 将给出 undefined)。
2021-03-30 23:57:11
这将很好地工作,直到他们预先添加另一个孩子,这是nth-child()选择器的固有问题我会使用特异性来派生一个选择器。
2021-03-30 23:57:11
不坏...可能需要将其打包成一个库,或者可能提高一个对的10+的人做同样的事情。
2021-04-04 23:57:11
漂亮简洁的纯 js 函数 :) 稍微注意一下,当应用于 HTML 标签时,:nth-child 将不起作用……或者至少我无法在 Firefox 或 Chrome 中使用它……我想这可能是由于 <html> 没有父级这一事实。
2021-04-13 23:57:11

我发现我实际上可以使用来自 chrome devtools 源的这段代码来解决这个问题,而无需进行那么多修改。

WebInspector.DOMPresentationUtils从新命名空间添加相关方法并修复一些差异后,我简单地这样称呼它:

> UTILS.cssPath(node)

实现示例 css_path.js

这是迄今为止我找到的最好的解决方案。为方便起见,我将其发布在 npm 上:npmjs.com/package/cssman
2021-03-16 23:57:11
@Macks:您是否愿意在 GitHub 上发布源代码
2021-03-25 23:57:11
为什么它会产生非唯一性?我以为它做了第 n 个孩子的事情?
2021-03-25 23:57:11
如果非唯一是指生成的选择器应返回 1 个且仅返回 1 个元素,则 op 从未明确要求它。但是应该很容易修改代码以检查兄弟姐妹并获取索引或其他不同的属性
2021-03-27 23:57:11
2021-04-10 23:57:11

使用安装了 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 /一个

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) 版本,但找不到这个选项。像魅力一样工作。
2021-04-08 23:57:11

检查这个 CSS 选择器生成器库@medv/finder

  • 生成最短选择器
  • 每页唯一的选择器
  • 稳定稳健的选择器
  • 2.9 kB gzip 并缩小大小

生成的选择器示例:

.blog > article:nth-child(3) .add-comment

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(" > ");
}