问题描述
我试图创建一个CSS选择器来选择给定父代中的所有子代;但只要路径上的任何元素具有某个类别,就排除它们。
上下文
我在Javascript中创建了一些materialization类,它将一些元素替换为它们的材质版本。这运行在顶级应用程序上。每个用户都可以创建自己的应用程序,并且我希望能够说一定数量的元素不应该经过这个过程。
示例
$ b
$ b 应该选择:
我试图创建一个CSS选择器来选择给定父代中的所有子代;但只要路径上的任何元素具有某个类别,就排除它们。
上下文
我在Javascript中创建了一些materialization类,它将一些元素替换为它们的材质版本。这运行在顶级应用程序上。每个用户都可以创建自己的应用程序,并且我希望能够说一定数量的元素不应该经过这个过程。
示例
$ b
$ b 应该选择:
注意:我已经想到了解决这个问题的其他方法,比如迭代名为'.no-material'的元素的所有子元素,如果可能的话,将'no-material'添加到所有类中,但是这是耗费资源的问题,我想从CSS选择器的角度解决这个问题。
谢谢
找到所有元素( all ),然后使用 no-material 对元素或其父元素( no ),然后从第一个元素中删除那些元素以找到那些元素(是)。
const difference =(a,b)=> a.filter(elt => b.indexOf(elt)=== -1); const all = document.querySelectorAll(input); const no = document.querySelectorAll(。no-material input,input.no-material); const yes = difference([... all],[... no]); console.log(yes.map(elt => elt.name));
< main style =display:none;> <! - 不可选 - > < div class =no-material> <输入名称=no-1> < / DIV> < DIV> < input name =no-2class =no-material> < / DIV> < DIV> < label class =no-material> <输入名称=no-3> < /标签> < / DIV> < DIV> < label class =no-material> <跨度> < input name =no-4> < /跨度> < /标签> < / DIV> < DIV> <标签> < span class =no-material> < input name =no-5> < /跨度> < /标签> < / DIV> <! - 可选 - > < DIV> < input name =yes-1> < / DIV> < DIV> < input name =yes-2> < / DIV> < DIV> <标签> < input name =yes-3> < /标签> < / DIV> < DIV> <标签> <跨度> <输入名称=是-4> < /跨度> < /标签> < / DIV> < DIV> <标签> <跨度> < input name =yes-5> < /跨度> < /标签> < / div>< / main>
What
I am trying to create a CSS selector which selects all children within a given parent; but excludes them as long as any element on the path has a certain class.
Context
I am creating some materialisation class in Javascript which replaces some elements into their material versions. This runs on a top-level app. Each user can create their own apps, and I want to be able to say that a certain group of elements should not go through this process.
Example
This should be selected:
<div> <input /> </div>
This should not be selected:
<div class="no-material"> <input /> </div>
The main challenge is that this label can be at any place. Example:
<main> <section class="no-material"> <form> <fieldset> <input /> </fieldset> </form> </section> </main>
Or it could be:
<main> <section> <form class="no-material"> <fieldset> <input /> </fieldset> </form> </section> </main>
Already tested
I tried a few attempts. The best scenario was:
div:not(.no-material) > input:not(.no-material), div:not(.no-material) *:not(.no-material) input:not(.no-material)
However, it stills gives some false positives. I could get more accurate by adding a lot of levels like:
div:not(.no-material) > input:not(.no-material), div:not(.no-material) > *:not(.no-material) > input:not(.no-material), div:not(.no-material) > *:not(.no-material) > *:not(.no-material) > input:not(.no-material)
And like that for 20-50 levels (or more?), but that's not very smart.
Live version
You can test your selectors by editing cssSelector in Javascript.
let cssSelector = [ // Independent selectors 'div:not(.no-material) > input:not(.no-material)', 'div:not(.no-material) *:not(.no-material) input:not(.no-material)' ].join(','); // This will get elements and run their names. We should get yes1-5, but not no1-5. let inputs = document.querySelectorAll(cssSelector); for (let input of inputs) console.log(input.getAttribute('name'));
<!-- Do not edit HTML, just the CSS selector --> <main style="display: none;"> <!-- Not selectable --> <div class="no-material"> <input name="no-1"> </div> <div> <input name="no-2" class="no-material"> </div> <div> <label class="no-material"> <input name="no-3"> </label> </div> <div> <label class="no-material"> <span> <input name="no-4"> </span> </label> </div> <div> <label> <span class="no-material"> <input name="no-5"> </span> </label> </div> <!-- Selectable --> <div> <input name="yes-1"> </div> <div> <input name="yes-2"> </div> <div> <label> <input name="yes-3"> </label> </div> <div> <label> <span> <input name="yes-4"> </span> </label> </div> <div> <label> <span> <input name="yes-5"> </span> </label> </div> </main> <!-- Do not edit HTML, just the CSS selector -->
Note: I already have thought of other ways of solving this like iterating all the children of an element called '.no-material' and add the class 'no-material' to all, but that is resource consuming and I want to solve this from a CSS selector standpoint if possible.
Thank you
Find all the elements (all), then the elements with no-material on the element or its parent (no), then remove those in the second from those in the first to find those that remain (yes).
const difference = (a, b) => a.filter(elt => b.indexOf(elt) === -1); const all = document.querySelectorAll("input"); const no = document.querySelectorAll(".no-material input, input.no-material"); const yes = difference([...all], [...no]); console.log(yes.map(elt => elt.name));
<main style="display: none;"> <!-- Not selectable --> <div class="no-material"> <input name="no-1"> </div> <div> <input name="no-2" class="no-material"> </div> <div> <label class="no-material"> <input name="no-3"> </label> </div> <div> <label class="no-material"> <span> <input name="no-4"> </span> </label> </div> <div> <label> <span class="no-material"> <input name="no-5"> </span> </label> </div> <!-- Selectable --> <div> <input name="yes-1"> </div> <div> <input name="yes-2"> </div> <div> <label> <input name="yes-3"> </label> </div> <div> <label> <span> <input name="yes-4"> </span> </label> </div> <div> <label> <span> <input name="yes-5"> </span> </label> </div> </main>
这篇关于CSS选择器排除任何级别的任何父级都有类的所有子级的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!