简体   繁体   English

JS:隐藏除了一个(由id)以及它的所有降序子元素及其父元素之外的所有元素

[英]JS: Hide all elements except of one (by id) (and all of its descending child elements and its parents)

I try to select all elements on a page except of #content_container and all its descendent subelements and all of its parents. 我尝试选择页面上的所有元素,除了#content_container及其所有后代子元素及其所有父元素。 Later I want to hide all the selected elements. 后来我想隐藏所有选中的元素。

However I already fail with this: 但是我已经失败了:

var elems = document.querySelectorAll("body *:not(#content_container *)");

Browser console (chrome) returns: Failed to execute 'querySelectorAll' on 'Document': 'body *:not(#content_container *)' is not a valid selector. 浏览器控制台(chrome)返回:无法在'Document'上执行'querySelectorAll':'body *:not(#content_container *)'不是有效的选择器。

Whereas "body *:not(#content_container)" would not return an error. "body *:not(#content_container)"不会返回错误。

How can this be accomplished? 如何实现这一目标? note: cant use jQuery. 注意:不能使用jQuery。

Edit: Some of you wanted an example. 编辑:有些人想要一个例子。 The goal is to keep #content_container AND its content visible on the site, whereas all the other content will be hidden. 目标是保持#content_container及其内容在网站上可见,而所有其他内容将被隐藏。

<body>
<div class="hide">
    <div class="hide">

    </div>
</div>
<div>
    <div>
        <div class="hide">
            <div class="hide">

            </div>
        </div>
        <div id="content_container">
            <p>  ------- content_container div ------- </p>
            <div>
                    <div>
                            <div>

                            </div>
                    </div>
            </div>
            <div>

            </div>    
        </div>
    </div>
    <div class="hide">

    </div>
</div>
<div class="hide">
    <div class="hide">
        <div class="hide">
            <div class="hide">

            </div>
        </div>
    </div>
</div>
<div class="hide">
    <div class="hide">

    </div>
</div>

The only way I can see to do this is to get the subject node, then add all it's siblings to the "don't show" collection, then go up its parent nodes collecting and adding all siblings as you go, stopping at the body. 我可以看到这样做的唯一方法是获取主题节点,然后将其所有兄弟姐妹添加到“不显示”集合,然后上升其父节点收集并添加所有兄弟姐妹,停在身体。

The following only adds siblings and parent siblings, not the node itself or its immediate ancestors, stopping once the body child nodes are processed. 以下仅添加兄弟姐妹和父级兄弟,而不是节点本身或其直接祖先,一旦处理了正文子节点就停止。 It also only collects element nodes and ignores all others, so empty #text node siblings will still be there, but should not affect the layout. 它也只收集元素节点并忽略所有其他节点,因此空的#text节点兄弟节点仍然存在,但不应影响布局。 If you want to get rid of those, just delete them. 如果你想摆脱它们,只需删除它们。

Click the "Hide stuff" button. 单击“隐藏内容”按钮。

 function hideStuff(){ var el = document.querySelector('#content_container'); var node, nodes = []; do { var parent = el.parentNode; // Collect element children for (var i=0, iLen=parent.childNodes.length; i<iLen; i++) { node = parent.childNodes[i]; // Collect only sibling nodes that are elements and not the current element if (node.nodeType == 1 && node != el) { nodes.push(node); } } // Go up to parent el = parent; // Stop when processed the body's child nodes } while (el.tagName.toLowerCase() != 'body'); // Hide the collected nodes nodes.forEach(function(node){ node.style.display = 'none'; }); } 
 <body> <div class="hide">hide <div class="hide">hide </div> </div> <div> <div> <div class="hide">hide <div class="hide">hide </div> </div> <div id="content_container"> <p> ------- content_container div ------- </p> <button onclick="hideStuff()">Hide stuff</button> <div>don't hide <div>don't hide <div>don't hide </div> </div> </div> <div>don't hide </div> </div> </div> <div class="hide">hide </div> </div> <div class="hide">hide <div class="hide">hide <div class="hide">hide <div class="hide">hide </div> </div> </div> </div> <div class="hide">hide <div class="hide">hide </div> </div> </body> 

This selects then hides everything inside the <body> except #content_container , its children and its parents. 然后选择隐藏<body>内的所有内容,除了#content_container ,它的子#content_container及其父#content_container

class="hide" is added to the HTML purely to indicate which elements will be hidden, but isn't programmatically useful. class="hide"被添加到HTML中纯粹用于指示哪些元素被隐藏,但在编程上没有用处。

It works by applying the class="hidden" to every element within the <body> , unless it's #content_container or it contains #content_container . 它的工作原理是将class="hidden"应用于<body>每个元素,除非它是#content_container或它包含#content_container
An !important CSS rule then forces the children of #content_container to remain visible . 然后, !important CSS规则会强制#content_container的子项保持visible

For demonstration, I have added a 1 second delay before the hiding occurs. 为了演示,我在隐藏发生之前添加了1秒的延迟。

 setTimeout( () => { // for demo document.querySelectorAll( "body *:not( #content_container )" ) .forEach( ( v ) => { if ( !v.querySelector( "#content_container" ) ) { v.classList.add( "hidden" ); } } ); }, 1000 ); 
 body { padding: .5rem; background: lightgrey; } div { padding: inherit; border: 1px solid black; background: lightblue; } #content_container { background: lightgreen; visibility: visible !important; } /* to hide the children, remove this rule */ #content_container * { visibility: visible !important; } .hidden { visibility: hidden; } 
 <body> <div> <div class="hide"> <div class="hide"> <div class="hide"> <div class="hide"></div> </div> </div> </div> <div> <div> <div id="content_container"> <div> <div> <div></div> </div> </div> </div> <div class="hide"> <div class="hide"> <div class="hide"> <div class="hide"></div> </div> </div> </div> </div> </div> </div> </body> 

This solution doesn't maintain the visibility of #content_container 's parents. 此解决方案无法保持#content_container父母的visibility

If #content_container 's children should also be hidden, only a minor change to the CSS will fix it. 如果还应该隐藏#content_container的子项,只需对CSS进行一些小修改就可以解决问题。
I have highlighted the CSS that keeps the children visible. 我已经突出显示了让孩子们可见的CSS。

 setTimeout( () => { // for demo document.querySelectorAll( "body *:not( #content_container )" ) .forEach( ( v ) => { v.classList.add( "hidden" ); } ); }, 1000 ); 
 body { padding: .5rem; background: lightgrey; } div { padding: inherit; border: 1px solid black; background: lightblue; } #content_container { background: lightgreen; visibility: visible !important; } /* to hide the children, remove this rule */ #content_container * { visibility: visible !important; } .hidden { visibility: hidden; } 
 <body> <div> <div class="hide"> <div class="hide"> <div class="hide"> <div class="hide"></div> </div> </div> </div> <div> <div> <div id="content_container"> <div> <div> <div></div> </div> </div> </div> <div class="hide"> <div class="hide"> <div class="hide"> <div class="hide"></div> </div> </div> </div> </div> </div> </div> </body> 

A far more efficient and simpler alternative to the previous solution is to hide the <body> (and therefore everything else on the page) whilst forcing the visibility of #content_container and its children. 比以前的解决方案更有效和更简单的替代方法是隐藏<body> (以及页面上的所有其他内容),同时强制#content_container及其子项的可见性。

This is a more direct route, faster to apply and easier to reverse if required; 这是一种更直接的途径,应用更快,如果需要更容易逆转; my first solution sets a lot of redundant classes. 我的第一个解决方案设置了很多冗余类。

 setTimeout( () => { // for demo document.querySelector( "body" ).classList.add( "hidden" ); }, 1000 ); 
 body { padding: .5rem; background: lightgrey; } div { padding: inherit; border: 1px solid black; background: lightblue; } #content_container { background: lightgreen; visibility: visible !important; } .hidden { visibility: hidden; } 
 <body> <div> <div class="hide"> <div class="hide"> <div class="hide"> <div class="hide"></div> </div> </div> </div> <div> <div> <div id="content_container"> <div> <div> <div></div> </div> </div> </div> <div class="hide"> <div class="hide"> <div class="hide"> <div class="hide"></div> </div> </div> </div> </div> </div> </div> </body> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM