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

时间:2017-07-03 00:32:51

标签: javascript css-selectors

我尝试选择页面上的所有元素,除了#content_container及其所有后代子元素及其所有父元素。后来我想要隐藏所有选中的元素。

但是我已经失败了:

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

浏览器控制台(chrome)返回:无法在'Document'上执行'querySelectorAll':'body *:not(#content_container *)'不是有效的选择器。

"body *:not(#content_container)"不会返回错误。

如何实现这一目标? 注意:不能使用jQuery。

编辑: 有些人想要一个例子。目标是保持#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>

2 个答案:

答案 0 :(得分:2)

我能看到这样做的唯一方法是获取主题节点,然后将其所有兄弟姐妹添加到“不显示”集合中,然后上升其父节点收集并添加所有兄弟姐妹,停止身体。

以下只会添加兄弟姐妹和父级兄弟,而不是节点本身或其直接祖先,一旦处理了正文子节点,就会停止。它也只收集元素节点并忽略所有其他节点,因此空的#text节点兄弟节点仍然存在,但不应影响布局。如果你想摆脱它们,只需删除它们。

点击“隐藏内容”按钮。

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>

答案 1 :(得分:1)

然后选择隐藏<body>内的所有内容,#content_container除了class="hide",其子项及其父项。

class="hidden"仅添加到HTML中,以指示隐藏哪些 元素,但在编程方面没有用处。

通过将<body>应用于#content_container中的每个元素,除非它是#content_container或包含!important。 然后,#content_container CSS规则会强制visible的孩子保持setTimeout( () => { // for demo document.querySelectorAll( "body *:not( #content_container )" ) .forEach( ( v ) => { if ( !v.querySelector( "#content_container" ) ) { v.classList.add( "hidden" ); } } ); }, 1000 );

为了演示,我在隐藏发生之前添加了1秒延迟。

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>
visibility

此解决方案无法保留#content_container父母的#content_container

如果setTimeout( () => { // for demo document.querySelectorAll( "body *:not( #content_container )" ) .forEach( ( v ) => { v.classList.add( "hidden" ); } ); }, 1000 );的孩子也应该被隐藏,只需对CSS进行一些小改动即可解决问题 我已经突出显示了让孩子们可见的CSS。

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>
<body>

比以前的解决方案更有效,更简单的替代方法是隐藏#content_container(以及页面上的其他所有内容),同时强制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>
width: 120%
<div class="container>
// Your regular content here
</div>

//In this grey block, make it width 100% and add the content you want
<div class="grey-block">
//So the content inside will still be aligned with the rest of the page
<div class="container">
</div>
</div>

//Continue with the rest of the page
<div class="container>
</div>