在JavaScript中,如何确定匹配给定CSS选择器的所有元素是否与另一个给定的CSS选择器匹配?

时间:2014-03-17 01:31:09

标签: javascript html css css-selectors

规范

此功能的输入将是两个选择器。这意味着没有预先存在的DOM元素,这是此问题中的一个重要约束。函数应该回答的问题是"所有与Needle匹配的元素是否会被Haystack匹配?"换句话说,我试图确定Needle匹配的元素集是否代表Haystack匹配的元素集的子集。下面的示例表应阐明规范:

Needle           | Haystack         | Matches? | Explanation / Counterexample
-----------------+------------------+----------+--------------------------------
div              | *                | yes      | Any div is something.
div              | div              | yes      | Any div is a div.
div              | div:not(.classy) | no       | <div class="classy">
div              | .classy          | no       | <div>
div.classy       | div              | yes      | Any classy div is a div.
div.classy       | div.classy       | yes      | Any classy div is a classy div.
div.classy       | div:not(.classy) | no       | <div class="classy">
div.classy       | .classy          | yes      | Any classy div is classy.
div:not(.classy) | div              | yes      | Any non-classy div is a div.
.classy          | div              | no       | <span>
.classy          | div.classy       | no       | <div>
:not(.classy)    | div              | no       | <span>
div div          | div              | yes      | Any nested div is a div.
div              | div div          | no       | Not all divs are nested.

一个天真的解决方案会根据Needle创建一个临时DOM元素,并以Haystack作为参数调用document.querySelector()。解决方案将迭代列表并返回true,如果它找到生成的元素。注意事项:

  • 仅仅因为匹配针的一个元素恰好与Haystack匹配并不意味着匹配针的所有可能的元素将匹配Haystack。很难使代表性元素尽可能通用。
  • 很难生成与non-simple selector匹配的元素,因为必须重新创建直到该元素的整个树才能容纳它。
  • 将临时元素插入DOM并且未正确清理它们可能会干扰网站逻辑。

完整的解决方案应避免创建临时DOM元素。该解决方案理想地依赖于渲染引擎的内置CSS匹配机制。如果解决方案使用特定于供应商的功能,那么这些功能应该可以在其他浏览器的当前版本的纯JavaScript中进行重新编程(其中IE10可以被认为是&#34;当前&#34; IE)


动机

该函数的目的是查询文档样式表以查找适用于与给定选择器匹配的元素的所有规则。例如,给定以下CSS:

* {
    color: yellow;
}

div {
    background-color: black;
}

.classy {
    margin: 5px;
}

人们会期待以下情况:

Selector   | Matched rules
-----------+-----------------------------------------------------
div.classy | color: yellow; background-color: black; margin: 5px;
div        | color: yellow; background-color: black;
.classy    | color: yellow; margin: 5px;

一个天真的解决方案将逐块迭代文档样式表,并在选择器上执行精确的字符串匹配。这些将产生比em引擎计算的更少的规则。完整的解决方案需要上一节中描述的功能。


类似问题

我相信this asker想要一个类似的解决方案,但问题没有被理解。


感谢您的时间!

1 个答案:

答案 0 :(得分:2)

如果没有一份文件可以为seletors提供一些上下文,我认为这是不可能的。很容易看出“div”是“*”的子集。但是,对于像“div”和“.classy”这样的其他选择器来说,这并不容易。如果每个div都有一个经典类而没有其他元素具有该类,它们可能会返回完全相同的元素集。

同样,如果没有div具有一类优等,“div”和“div:not(.classy)”可能会返回完全相同的集合。

因此,在一般情况下,不可能确定一个选择器是否在没有文档的情况下返回另一个选择器的子集,尽管可以针对一组非常有限的(平凡的?)案例(例如span.someClass是子集)跨度)。