在特定元素之前隐藏所有元素

时间:2018-05-28 18:37:24

标签: javascript

使用jQuery并在每个h1内的内容周围有一个包装容器,我可以很容易地隐藏它们。

但没有包装容器,怎么会这样做?

在下一个h1之前做一些隐藏所有事情的最佳方法是什么?

我没有使用jQuery,因为这是React应用程序的一部分。



h1 {
  border-bottom: solid 1px #000;
}

span {
  float: right;
}

<h1>h1 <span>x</span></h1>
<p>test 1</p>
<h2>h2</h2>
<p>test 2</p>

<h1>h1-1 <span>x</span></h1>
<p>test 3</p>
<h2>h2-2</h2>
<p>test 4</p>
&#13;
&#13;
&#13;

或在div标签中的下一个h1之后和之前包装所有内容?

6 个答案:

答案 0 :(得分:4)

我能用这个css做到这一点。只需添加课程&#34;开始&#34;从你想要开始折叠元素和类的h1到#34; upto&#34;到你希望元素崩溃的h1。

<强> CSS

.start ~ *:not(h1) {
   display: none;
}

.upto ~ * {
  display: block !important;
}

HTML

<h1 class='start'>h1 <span>x</span></h1>
 ...
<h1 class ='upto'>h1-1 <span>x</span></h1>

这里将隐藏start和upto之间的所有元素。您可以通过添加&#39; start&#39;来实现折叠效果。和&#39; upto&#39;相应的课程

将类添加到下一个h1也可以通过Javascript完成。所以,我可以有一个简单的js函数来设置&#39; start&#39;以及&#39; upto&#39;。

function collapse(startHeaderNumber, uptoHeaderNumber) {
    var allHeaders = document.getElementsByTagName("h1");
    var totalNoOfHeaders = allHeaders.length;

   if (startHeaderNumber > totalNoOfHeaders) {
       return;
   }

   var startHeader = allHeaders[startHeaderNumber - 1];
   startHeader.classList.add('start');

   if (uptoHeaderNumber <= totalNoOfHeaders) {
      var uptoHeader = allHeaders[uptoHeaderNumber - 1];
      uptoHeader.classList.add('upto');
   }

}

你可以简单地称之为

collapse(1 ,2)

它会折叠标题1和标题2之间的所有项目。或者,您可以将其称为

collapse(1)

会将第一个标题中的所有元素折叠到最后一个。

要获得完整演示,请参阅此fiddle

答案 1 :(得分:2)

sounds like you want something similar to jQuery's nextUntil() function. Here is a good guide to doing that in vanilla js. The code ends up looking like this:

var nextUntil = function (elem, selector, filter) {

    // Setup siblings array
    var siblings = [];

    // Get the next sibling element
    elem = elem.nextElementSibling;

    // As long as a sibling exists
    while (elem) {

        // If we've reached our match, bail
        if (elem.matches(selector)) break;

        // If filtering by a selector, check if the sibling matches
        if (filter && !elem.matches(filter)) {
            elem = elem.nextElementSibling;
            continue;
        }

        // Otherwise, push it to the siblings array
        siblings.push(elem);

        // Get the next sibling element
        elem = elem.nextElementSibling;

    }

    return siblings;

};

I obviously don't know the context behind what you are doing, but I reckon there's a better way around it by altering the HTML. This could potentially even let you do some of this with just css nth child selectors

答案 2 :(得分:1)

您可以递归使用previousElementSibling来获取h1元素的所有兄弟姐妹。以下是使用previousElementSibling

的工作示例

&#13;
&#13;
const elems = document.getElementsByTagName('h1');

for (let i = 0; i < elems.length; i++) hidePrev(elems[i]);

function hidePrev(elem)
{
    var pre = elem.previousElementSibling;
    if (!pre) return;
    pre.style.display = 'none';
    hidePrev(pre);
}
&#13;
h1 {
  border-bottom: solid 1px #000;
}

span {
  float: right;
}
&#13;
<h1>h1 <span>x</span></h1>
<p>test 1</p>
<h2>h2</h2>
<p>test 2</p>

<h1>h1-1 <span>x</span></h1>
<p>test 3</p>
<h2>h2-2</h2>
<p>test 4</p>
&#13;
&#13;
&#13;

答案 3 :(得分:1)

我评论了代码。我希望你能理解这里发生了什么,但如果没有,请在下面评论。

&#13;
&#13;
function hideUntilNextSiblingWithSameName(elementName) {
  /*
   * @Param {elementName: String} 
   * Hide all elements until the next one with the same name
   */
  var trackH1 = 0,
      element = document.getElementsByTagName(elementName)[0],
      node = element.parentNode.firstChild;

  do {
    // Keep truck of element with the same name.
    if (node.tagName === element.tagName) trackH1 += 1;

    // Stop if catch element with same name
    if (trackH1 == 2) break;

    // Do not hide link, script, style and text node
    if (node.nodeType === 3 || node.tagName === "LINK" || node.tagName === "SCRIPT" || node.tagName === "STYLE") continue;
    // Hide element
    else {
      node.style.visibility = "hidden";
    }
  } while (node = node.nextSibling)
}

hideUntilNextSiblingWithSameName("h1")
&#13;
<h1>h1 <span>x</span></h1>
<p>test 1</p>
<h2>h2</h2>
<p>test 2</p>

<h1>h1-1 <span>x</span></h1>
<p>test 3</p>
<h2>h2-2</h2>
<p>test 4</p>

<link rel="stylesheet" href="">
<script></script>
<style></style>
&#13;
&#13;
&#13;

https://codepen.io/anon/pen/QxGVNG

此刻,我隐藏了元素。但是,如果您甚至不想显示元素,请在else子句中使用 node.style.display = "none"; 而不是 node.style.visibility = "hidden";

答案 4 :(得分:0)

您可以通过以下更简单的方式执行此操作。我们的想法是在这种情况下找到节点的直接父节点body,并找到它的所有直接子节点。

然后,开始删除元素,直到我们找到所需的元素。在这个例子中,我试图隐藏元素,但你只需改变代码就可以删除它们。

以下是一个有效的演示:

const elems = document.querySelectorAll('body > *');
const elemBefore = document.querySelectorAll('h1')[1];

for (let i = 0; i < elems.length; i++) {
  let elem = elems[i];

  if (elem === elemBefore) {
    break;
  }

  elem.style.display = 'none';
}
h1 {
  border-bottom: solid 1px #000;
}

span {
  float: right;
}
<h1>h1 <span>x</span></h1>
<p>test 1</p>
<h2>h2</h2>
<p>test 2</p>

<h1>h1-1 <span>x</span></h1>
<p>test 3</p>
<h2>h2-2</h2>
<p>test 4</p>

答案 5 :(得分:0)

也许你可以使用一个技巧并通过css隐藏h1和h2后面的

&#13;
&#13;
const selector = document.querySelectorAll('h1, h2');
const clickH = function (event) {
   const h = event.target;
   const attr = h.getAttribute('class');
   if (attr === '') {
      h.setAttribute('class', 'closed')
      return undefined;
   }
   h.setAttribute('class', '')
}
selector.forEach((h) => {
    h.setAttribute('class', 'closed')
    h.addEventListener('click', clickH);
})
&#13;
h1, h2 {
  position: relative;
  border-bottom: solid 1px #000;
  background-color: #fff;
  height: 50px;
  border-bottom: solid 1px #000;
  display: block;
  z-index: 2;
  margin-bottom: 0;
}

.closed {
  margin-bottom: -50px;
}

p {
  height: 30px;
  
}

span {
  float: right;
}
&#13;
<h1>h1 <span>x</span></h1>
<p>test 1</p>
<h2>h2</h2>
<p>test 2</p>

<h1>h1-1 <span>x</span></h1>
<p>test 3</p>
<h2>h2-2</h2>
<p>test 4</p>
&#13;
&#13;
&#13;