在两个元素之间选择CSS兄弟姐妹

发布于 2025-01-20 19:34:33 字数 2159 浏览 6 评论 0原文

我正在看的HTML看起来像这样:

document.querySelectorAll('h4#unique_id  ~ h5 ~p +p +h5').forEach(title => console.log(title))
<body>
  <h4 id="unique_id"> foo bing bar </h4>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <!-- selection should start here -->
    <h5>title text 1</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <h5>title text 2</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <h5>title text 3</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
  <!-- and end here -->
  <h4 id="randome_id_234353">title text</h4>
  <p>some text I don't want</p>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
</body>

我想抓住所有h5元素,如果可能的话,p元素。

我有document.queryselectorall('h4#unique_id〜h5〜p +p +p +p +h5')到目前为止,但它错过了第一个h5我想要并抓住了最后一个i不想要。我无法找出兄弟姐妹选择器或如何使用:不或类似于我找到另一个H4时停止。

这个问题选择CSS Selector的两个已知元素之间的所有元素依赖我无法访问的jQuery, Select elect两个定义的元素依赖于知道元素的数量和位置,而我不知道。

只有CSS选择器可能会做到这一点吗?

The html I'm looking at looks like this:

document.querySelectorAll('h4#unique_id  ~ h5 ~p +p +h5').forEach(title => console.log(title))
<body>
  <h4 id="unique_id"> foo bing bar </h4>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <!-- selection should start here -->
    <h5>title text 1</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <h5>title text 2</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <h5>title text 3</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
  <!-- and end here -->
  <h4 id="randome_id_234353">title text</h4>
  <p>some text I don't want</p>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
</body>

I want to grab all the h5 elements, and if possible the p elements as well.

I have document.querySelectorAll('h4#unique_id ~ h5 ~p +p +h5') so far but that misses the first h5 I want and grabs the last one I don't want. I can't figure out sibling selectors or how to use :not or similar to stop when I find another h4.

This question Select all elements between two known elements by CSS selector relies on jquery which I don't have access to, and Select elements between two defined elements relies on knowning the number and position of elements, which I don't.

Is this possible with just css selectors?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

淡写薰衣草的香 2025-01-27 19:34:34

好的,您可以使用同级选择器的混合物,而不是:

选择器是:

#unique_id~p:not(#unique_id~h4~p) /* any p following the unique id but not a p following another h4 after the unique id */

然后,您为H5s重复此选择器,结果是:

document.querySelectorAll('#unique_id~p:not(#unique_id~h4~p),#unique_id~h5:not(#unique_id~h4~h5)').forEach(title => title.style.color = 'red');
<h4 id="unique_id"> foo bing bar </h4>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h5>title text 1</h5>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h5>title text 2</h5>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h5>title text 3</h5>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h4 id="randome_id_234353">title text</h4>
<p>some text I don't want</p>
<p>some text I don't want</p>
<h5>title text I don't want</h5>
<p>some text I don't want</p>
<h5>title text I don't want</h5>
<p>some text I don't want</p>
<h5>title text I don't want</h5>
<p>some text I don't want</p>

根据您的编辑 - 在第一个H5之前不要包括P(从Alohci的评论中稍作修改选择器):

document.querySelectorAll('#unique_id~:is(h5, h5~p):not(#unique_id ~ h4 ~ *)').forEach(title => title.style.color = 'red');
<h4 id="unique_id"> foo bing bar </h4>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h5>title text 1</h5>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h5>title text 2</h5>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h5>title text 3</h5>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h4 id="randome_id_234353">title text</h4>
<p>some text I don't want</p>
<p>some text I don't want</p>
<h5>title text I don't want</h5>
<p>some text I don't want</p>
<h5>title text I don't want</h5>
<p>some text I don't want</p>
<h5>title text I don't want</h5>
<p>some text I don't want</p>

Ok you can use a mixture of sibling selector and not:

The selector is:

#unique_id~p:not(#unique_id~h4~p) /* any p following the unique id but not a p following another h4 after the unique id */

you then repeat this selector for your h5s and the result is:

document.querySelectorAll('#unique_id~p:not(#unique_id~h4~p),#unique_id~h5:not(#unique_id~h4~h5)').forEach(title => title.style.color = 'red');
<h4 id="unique_id"> foo bing bar </h4>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h5>title text 1</h5>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h5>title text 2</h5>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h5>title text 3</h5>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h4 id="randome_id_234353">title text</h4>
<p>some text I don't want</p>
<p>some text I don't want</p>
<h5>title text I don't want</h5>
<p>some text I don't want</p>
<h5>title text I don't want</h5>
<p>some text I don't want</p>
<h5>title text I don't want</h5>
<p>some text I don't want</p>

As per your edit - not to include the p before the first h5 (selector is slightly modified from Alohci's comment):

document.querySelectorAll('#unique_id~:is(h5, h5~p):not(#unique_id ~ h4 ~ *)').forEach(title => title.style.color = 'red');
<h4 id="unique_id"> foo bing bar </h4>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h5>title text 1</h5>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h5>title text 2</h5>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h5>title text 3</h5>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<p>some text</p>
<h4 id="randome_id_234353">title text</h4>
<p>some text I don't want</p>
<p>some text I don't want</p>
<h5>title text I don't want</h5>
<p>some text I don't want</p>
<h5>title text I don't want</h5>
<p>some text I don't want</p>
<h5>title text I don't want</h5>
<p>some text I don't want</p>

柏林苍穹下 2025-01-27 19:34:34

有趣的问题。如果我正确理解您的问题,您想记录所有不包含的元素,这些文本我不需要h5 - elements。

如果您有父元素,则可以将&gt;与父元素结合使用,以选择其所有孩子使用* -Selector选择其所有孩子。

您可以在语句中应用多个:not() - 选择器。在下面,我刚刚选择了所有ph4 - 元素,该元素是h4#h4#randome_id_234353 - element,例如So:

document.querySelectorAll('.container > *:not(h4#randome_id_234353 ~ p):not(h4#randome_id_234353 ~ h5):not(h4)').forEach(title => console.log(title))
<body>
<div class="container">
  <h4 id="unique_id"> foo bing bar </h4>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 1</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 2</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 3</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h4 id="randome_id_234353">title text</h4>
  <p>some text I don't want</p>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
</div>
</body>

如果没有容器,则可以使用相同的逻辑到log 不是 preceed h4#randome_id_234353的所有内容。

document.querySelectorAll('h4#unique_id ~ *:not(h4#randome_id_234353 ~ *):not(h4#randome_id_234353)').forEach(title => console.log(title))
<body>
  <h4 id="unique_id"> foo bing bar </h4>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 1</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 2</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 3</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h4 id="randome_id_234353">title text</h4>
  <p>some text I don't want</p>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
</body>

Interesting question. If I understand your problem correctly, you want to log all of the elements that are not containing some text I don't want and the h5-elements.

If you have a parent element, you can use the > to selector in combination with the parent element to select all of its children with the *-selector.

You can apply multiple :not()-selectors to a statement. Below I just selected all p and h4-elements that are preceded by the h4#randome_id_234353-element, like so:

document.querySelectorAll('.container > *:not(h4#randome_id_234353 ~ p):not(h4#randome_id_234353 ~ h5):not(h4)').forEach(title => console.log(title))
<body>
<div class="container">
  <h4 id="unique_id"> foo bing bar </h4>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 1</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 2</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 3</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h4 id="randome_id_234353">title text</h4>
  <p>some text I don't want</p>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
</div>
</body>

If you don't have a container, you can use the same logic to log everything that does not preceed h4#randome_id_234353.

document.querySelectorAll('h4#unique_id ~ *:not(h4#randome_id_234353 ~ *):not(h4#randome_id_234353)').forEach(title => console.log(title))
<body>
  <h4 id="unique_id"> foo bing bar </h4>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 1</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 2</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h5>title text 3</h5>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <h4 id="randome_id_234353">title text</h4>
  <p>some text I don't want</p>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
</body>

不寐倦长更 2025-01-27 19:34:34

只有少数数组方法适用于类似数组的对象,因此我经常发现转换 NodeList (这是一个可迭代的、类似数组的对象)很有用,但是,至关重要的是,将不是数组)转换为数组,这样我就可以用它做更多事情。

在这种情况下,通过将 NodeList 转换为 array 我可以使用 javascript 方法 .filter() 这正是我需要删除不需要的内容集合末尾的元素。


NodeList 转换为数组

如何将此静态NodeList:转换

let myClassElements = document.querySelectorAll('.myclass');

数组

通过将扩展语法...)与数组文字[])相结合:

let myClassElements = [... document.querySelectorAll('.myclass')];

在此基础上,我可以创建一个包含我需要的所有元素(加上一些不必要的元素)的 array

[...document.querySelectorAll('h4#unique_id ~ h5, h4#unique_id ~ p')]

以及另一个包含所有不必要元素的数组:

[...document.querySelectorAll('h4:not(#unique_id) ~ h5, h4:not(#unique_id) ~ p')]

然后我可以 .filter()从前者中取出后者:

const rawListOfElements = [...document.querySelectorAll('h4#unique_id ~ h5, h4#unique_id ~ p')];

const elementsToRemove = [...document.querySelectorAll('h4:not(#unique_id) ~ h5, h4:not(#unique_id) ~ p')];

const mySelectedElements = rawListOfElements.filter((element) => elementsToRemove.includes(element) === false).forEach(title => console.log(title));

工作示例:

const rawListOfElements = [...document.querySelectorAll('h4#unique_id ~ h5, h4#unique_id ~ p')];

const elementsToRemove = [...document.querySelectorAll('h4:not(#unique_id) ~ h5, h4:not(#unique_id) ~ p')];

const mySelectedElements = rawListOfElements.filter((element) => elementsToRemove.includes(element) === false).forEach(title => console.log(title));
<body>
  <h4 id="unique_id"> foo bing bar </h4>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <!-- selection should start here -->
    <h5>title text 1</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <h5>title text 2</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <h5>title text 3</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
  <!-- and end here -->
  <h4 id="randome_id_234353">title text</h4>
  <p>some text I don't want</p>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
</body>

Only a small number of array methods work with array-like objects, so I often find it useful to turn a NodeList (which is an iterable, array-like object but, crucially, not an array) into an array, so that I can do many more things with it.

In this case by turning NodeList into an array I can use the javascript method .filter() which is exactly what I need to remove the unwanted elements from the end of the collection.


Turning a NodeList into an array:

How can I turn this static NodeList:

let myClassElements = document.querySelectorAll('.myclass');

into an array?

By combining spread syntax (...) with an array literal ([]):

let myClassElements = [... document.querySelectorAll('.myclass')];

On that basis, I can create an array of all the elements I do need (plus a few unnecessary ones):

[...document.querySelectorAll('h4#unique_id ~ h5, h4#unique_id ~ p')]

and also another array of all the unnecessary elements:

[...document.querySelectorAll('h4:not(#unique_id) ~ h5, h4:not(#unique_id) ~ p')]

And then I can .filter() out the latter from the former:

const rawListOfElements = [...document.querySelectorAll('h4#unique_id ~ h5, h4#unique_id ~ p')];

const elementsToRemove = [...document.querySelectorAll('h4:not(#unique_id) ~ h5, h4:not(#unique_id) ~ p')];

const mySelectedElements = rawListOfElements.filter((element) => elementsToRemove.includes(element) === false).forEach(title => console.log(title));

Working Example:

const rawListOfElements = [...document.querySelectorAll('h4#unique_id ~ h5, h4#unique_id ~ p')];

const elementsToRemove = [...document.querySelectorAll('h4:not(#unique_id) ~ h5, h4:not(#unique_id) ~ p')];

const mySelectedElements = rawListOfElements.filter((element) => elementsToRemove.includes(element) === false).forEach(title => console.log(title));
<body>
  <h4 id="unique_id"> foo bing bar </h4>
  <p>some text</p>
  <p>some text</p>
  <p>some text</p>
  <!-- selection should start here -->
    <h5>title text 1</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <h5>title text 2</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <h5>title text 3</h5>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
    <p>some text</p>
  <!-- and end here -->
  <h4 id="randome_id_234353">title text</h4>
  <p>some text I don't want</p>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
  <h5>title text I don't want</h5>
  <p>some text I don't want</p>
</body>

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文