Javascript:选择元素的下一个兄弟并通过单击更改其类(不使用ID)

时间:2016-09-26 12:27:21

标签: javascript css nextsibling

我想在单击它后立即将CSS类名添加到元素的下一个兄弟中以获得简单的显示/隐藏效果

我有以下html输出,我没有元素ID。

<div class="news-message">
  <div class="message-head"> Headline of Message 1 </div>
  <div class="message-content"> Here comes the content of message 1 </div>
</div>
<div class="news-message">
  <div class="message-head"> Headline of Message 2 </div>
  <div class="message-content"> Here comes the content of message 2 </div>
</div>
<div class="news-message">
  <div class="message-head"> Headline of Message 3 </div>
  <div class="message-content"> Here comes the content of message 3 </div>
</div>

    

现在我想要隐藏消息内容并只显示标题(通过display: none轻松实现)。

只要点击标题,我就希望显示该特定邮件的内容。

所以我的想法是在CSS“消息内容”中添加DIV类“可见”,点击消息头并再次点击删除它。

所以我在“pm-head”元素和以下javascript中添加了“onClick =”changeClass()“

function changeClass() {
  var hidecontent = document.querySelectorAll('.message-content');
  var i;
  for (i = 0; i < hidecontent.length; i++) {
    hidecontent[i].classList.toggle('visible');      }    }

但是这会在该页面上添加对所有“message-content”div可见的类,而我只需将它添加到我点击的“pm-head”元素的下一个兄弟中。

我不能在这个上使用jquery或其他框架/库。

抱歉,我是javascript的新手,可能是一个容易回答的问题。

由于 约翰

3 个答案:

答案 0 :(得分:3)

nextSibling是您寻求的答案。 没有自己测试,但这应该适合你:

function changeClass(e) {
    e.target.nextSibling.classList.toggle("visible");
}

答案 1 :(得分:1)

您可以使用此代码,这需要定义额外的类hidden,并将其添加到每个消息内容代码的HTML中:

Array.from(document.querySelectorAll('.news-message'), function (elem) {
    elem.addEventListener('click', function hideContent(e) {
        e.currentTarget.querySelector('.message-content').classList.toggle('hidden');
    });
});

Array.from(document.querySelectorAll('.news-message'), function (elem) {
    elem.addEventListener('click', function hideContent(e) {
        e.currentTarget.querySelector('.message-content').classList.toggle('hidden');
    });
});
.hidden { display:none; }
<div class="news-message">
  <div class="message-head">
    Headline of Message 1
    </div>
   <div class="message-content hidden">
    Here comes the content of message 1
   </div>
</div>

<div class="news-message">
  <div class="message-head">
    Headline of Message 2
    </div>
   <div class="message-content hidden">
    Here comes the content of message 2
   </div>
</div>

<div class="news-message">
  <div class="message-head">
    Headline of Message 3
    </div>
   <div class="message-content hidden">
    Here comes the content of message 3
   </div>
</div>

请注意,虽然您可以使用nextSibling,但这会使用另一种方法:它捕获news-message元素(父项)上的点击,然后找到message-content元素,最后切换隐藏的课程。

通过捕获父级别的点击事件,您还可以通过单击内容本身来切换内容的显示。这可能很有用。如果您不想要此行为,请将代码更改为:

Array.from(document.querySelectorAll('.message-head'), function (elem) {
    elem.addEventListener('click', function hideContent(e) {
        e.currentTarget.parentNode.querySelector('.message-content')
                       .classList.toggle('hidden');
    });
});

Array.from(document.querySelectorAll('.message-head'), function (elem) {
    elem.addEventListener('click', function hideContent(e) {
        e.currentTarget.parentNode.querySelector('.message-content')
                       .classList.toggle('hidden');
    });
});
.hidden { display:none; }
<div class="news-message">
  <div class="message-head">
    Headline of Message 1
    </div>
   <div class="message-content hidden">
    Here comes the content of message 1
   </div>
</div>

<div class="news-message">
  <div class="message-head">
    Headline of Message 2
    </div>
   <div class="message-content hidden">
    Here comes the content of message 2
   </div>
</div>

<div class="news-message">
  <div class="message-head">
    Headline of Message 3
    </div>
   <div class="message-content hidden">
    Here comes the content of message 3
   </div>
</div>

此变体只会处理标题上的点击,转到其父节点,然后像以前一样从那里开始。

答案 2 :(得分:0)

我建议,如果你能使用ES6:

// a named function to handle the toggling of visibility:
function toggleNextSibling(event) {

  // event.target is the element/node that triggered
  // the event:
  event.target
    // the nextElementSibling finds the next element
    // sibling of the clicked node:
    .nextElementSibling
    // we use Element.classList.toggle to add the
    // supplied class-name if it's not present, or
    // remove the supplied class-name if it is
    // present:
    .classList.toggle('shown');
}

// here we document.querySelectorAll() to retrieve a (non-live)
// NodeList of the elements of the document that match the
// supplied CSS selector, this NodeList is then passed to
// Array.from() to convert the Array-like NodeList into an
// Array:
Array.from(document.querySelectorAll('.message-head'))

  // as we have an Array we can then use Array.prototype.forEach()
  // to iterate over each element of the Array to perform actions
  // upon them:
  .forEach(

    // 'head' is a reference to the Array element of the Array
    // over which we're iterating, and upon each of those
    // Array elements we're then using addEventListener() to
    // bind a function (toggleNextSibling()) as the event-
    // handler for the 'click' event (but note the deliberate 
    // absence of parentheses following the function name):
    head => head.addEventListener('click', toggleNextSibling)
  );

function toggleNextSibling(event) {
  event.target.nextElementSibling.classList.toggle('shown');
}

Array.from(document.querySelectorAll('.message-head'))
  .forEach(head => head.addEventListener('click', toggleNextSibling));
.message-head {
  cursor: pointer;
  margin: 0.5em 0 0 0;
}
.news-message:first-child.message-head {
  margin-top: 0;
}
.message-content {
  display: none;
  text-indent: 1em;
  color: rebeccapurple;
}
.message-content.shown {
  display: block;
}
<div class="news-message">
  <div class="message-head">
    Headline of Message 1
  </div>
  <div class="message-content">
    Here comes the content of message 1
  </div>
</div>

<div class="news-message">
  <div class="message-head">
    Headline of Message 2
  </div>
  <div class="message-content">
    Here comes the content of message 2
  </div>
</div>

<div class="news-message">
  <div class="message-head">
    Headline of Message 3
  </div>
  <div class="message-content">
    Here comes the content of message 3
  </div>
</div>

如果没有ES6,上面的内容可以翻译成以下内容(尽管函数本身不需要更改):

// here we use Function.prototype.call(), to enable us to
// pass the NodeList to Array.prototype.slice(), which converts
// the NodeList to an Array:
Array.prototype.slice.call(document.querySelectorAll('.message-head'))

  // again, having an Array allows us to use Array methods, but
  // here we cannot use Arrow function expressions (as they were
  // not available until ES6), so instead we use a function expression:
  .forEach(function(head) {

    // 'head' refers to the current Array element of the Array
    // over which we're iterating, and we again use addEventListener
    // to bind the named function to the 'click' event:
    head.addEventListener('click', toggleNextSibling)
  });

function toggleNextSibling(event) {
  event.target.nextElementSibling.classList.toggle('shown');
}

Array.prototype.slice.call(document.querySelectorAll('.message-head'))
  .forEach(function(head) {
    head.addEventListener('click', toggleNextSibling)
  });
.message-head {
  cursor: pointer;
  margin: 0.5em 0 0 0;
}
.news-message:first-child.message-head {
  margin-top: 0;
}
.message-content {
  display: none;
  text-indent: 1em;
  color: rebeccapurple;
}
.message-content.shown {
  display: block;
}
<div class="news-message">
  <div class="message-head">
    Headline of Message 1
  </div>
  <div class="message-content">
    Here comes the content of message 1
  </div>
</div>

<div class="news-message">
  <div class="message-head">
    Headline of Message 2
  </div>
  <div class="message-content">
    Here comes the content of message 2
  </div>
</div>

<div class="news-message">
  <div class="message-head">
    Headline of Message 3
  </div>
  <div class="message-content">
    Here comes the content of message 3
  </div>
</div>