不包含blockquote的节点的查询选择器

时间:2013-11-11 16:03:48

标签: javascript css-selectors selectors-api

我正在试图找出以下标记的选择器。我想要除了包含blockquote 的节点之外的所有节点<blockquote>将永远是<div>的直接孩子,它将成为<body>代码的直接子女。

示例HTML:

<ul>
    <!-- Lots of HTML -->
</ul>
<div>
    <p>
        <!-- Lots of other HTML -->
    </p>
</div>
<div>
    <blockquote>Some text I don't care about</blockquote>
</div>

预期结果:

<ul><!-- Lots of HTML --></ul>
<div><p><!-- Lots of other HTML --></p></div>

尝试选择器:

document.querySelectorAll("body > :not(div > blockquote)")

我尝试了以上操作,但是我无法在:not()选择器中放置一个直接的子选择器。尝试失败的Here is a fiddle

我目前不在,也不能使用jQuery。

1 个答案:

答案 0 :(得分:4)

你不能原生地这样做。在任何当前的选择器规范中,无法通过子节点过滤元素。 (但是,这可能会出现在未来的选择器规范中。)

因此,您需要自己进行过滤。这并不是特别困难。一种方法是选择所有相关元素,然后过滤掉你不想要的元素:

Array.prototype.slice.call(document.querySelectorAll("body > *"))
    .filter(function(el) {
        return !el.querySelector(':scope > blockquote');
    })

(jsFiddle)

这会将选择变为数组,然后使用Array#filter方法去掉所有包含blockquote元素的方法。

显然,这比原生选择器的性能差得多,但它是在当前JS中做你想要的唯一方法。

正如BoltClock正确指出的那样,:scope还不是官方标准。由于Chrome 支持它,我被一种虚假的安全感所迷惑:其他浏览器还没有。如果要在任何级别排除包含blockquote元素的任何顶级元素,最好的方法是:

return !el.querySelector('blockquote');