首页 > 解决方案 > 如何检查 div .has() 2 是否在 div 中处于同一级别的元素

问题描述

我对 jQuery 有点挑战......

我想检查一个包装器 div 是否包含 2 个特定元素,每个元素都有一个特定的类,所以我可以在它前面隐藏包装器div.basic-questiondiv.clearfix。但是我怎样才能让它工作呢?

我知道 .has() 方法,但我无法让它在我想要的用例中工作,因为 2 个标准处于同一级别而不是嵌套。

我要隐藏的部分必须同时包含div.basic-answers-for-sliderul.basic-answers-results,如上所述,它们都在同一级别...

这是简化的html结构:

/* FIRST POLL, answered and showing results */
/* this div-section needs to remain visible */
<div class="basic-question basic-question-text-vertical">      
  <ul class="basic-answers"></ul>    
  <ul class="basic-answers-results basic-answers"></ul>
</div>

/* these 2 div-section needs to be HIDDEN by the jQuery code */
<div class="clearfix"></div>
<div class="basic-question"> 
  <div class="basic-answers-for-slider"></div> 
  <ul class="basic-answers-results basic-answers"></ul>
</div>

/* these 2 div-section needs to be HIDDEN by the jQuery code */
<div class="clearfix"></div>
<div class="basic-question"> 
  <div class="basic-answers-for-slider"></div> 
  <ul class="basic-answers-results basic-answers"></ul>
</div>

/* SECOND POLL, not yet answered so no results visible yet */
/* this div-section needs to remain visible */
<div class="basic-question basic-question-text-vertical">      
  <ul class="basic-answers"></ul>    
</div>

/* these 2 div-section needs to remain visible as there is no ul.basic-answers-results */
<div class="clearfix"></div>
<div class="basic-question"> 
  <div class="basic-answers-for-slider"></div> 
</div>

我简单的大脑会说我需要做类似的事情:

jQuery(document).ready(function($) {
  $('div.basic-question').has('div.basic-answers-for-slider') ** && has('ul.basic-answers-results') ** .hide();
  $('div.basic-question').has('div.basic-answers-for-slider') ** && has('ul.basic-answers-results') ** .prev('div.clearfix').hide();
});

但是**之间的那部分显然不起作用......而且我似乎无法在网上找到正确的提示。

有没有人对我应该采取的方法有什么建议?

标签: javascripthtmljquerycss

解决方案


我能想到的最简单的方法如下:

// here we select `ul.basic-answers-results` that is an
// adjacent-sibling of the `div.basic-answers-for-slider
// element both of which are the immediate children of a
// `.basic-question` element:
$('.basic-question > div.basic-answers-for-slider + ul.basic-answers-results')
  // we then navigate from the child (`ul.basic-answers-results`)
  // element back to the parent, using the `parent()` method:
  .parent()
  // and then we add a class-name - here 'hide' - which is
  // used to hide the element (in the demo this adjusts
  // opacity to 0.2, to demonstrate how it works, but in
  // production this could be adjusted to `display: none;`:
  .addClass('hide');
/* almost none of the CSS is relevant to the demo, and
   and is just for some aesthetics: */
*,
 ::before,
 ::after {
  box-sizing: border-box;
  font-family: Calibri, Ubuntu, Helvetica, Arial, sans-serif;
  font-size: 1rem;
  line-height: 1.5;
  margin: 0;
  padding: 0;
}

div,
ul,
p {
  border: 1px solid #000;
  margin: 0.5em auto;
  width: 80%;
}

/* Not relevant to the demo, but here we use the :is()
   CSS psuedo-class function to shorten as an alternative
   to:
   .basic-question div::before,
   .basic-question ul::before */
.basic-question :is(div, ul)::before {
  content: attr(class);
  font-style: italic;
}

p {
  border: 0 none transparent;
}

code {
  background-color: #cca;
  font-family: mono;
  padding: 0 0.3em;
}

/* the utility class used to hide the element(s),
   for proof-of-concept I reduced the opacity,
   but "display: none;" could easily be substituted: */
.hide {
  opacity: 0.2;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p class="problem-description">The sections I want to hide must contain both <code>div.basic-answers-for-slider</code> and <code>ul.basic-answers-results</code></p>
<!-- FIRST POLL, answered and showing results
     this div-section needs to remain visible -->
<div class="basic-question basic-question-text-vertical">
  <ul class="basic-answers"></ul>
  <ul class="basic-answers-results basic-answers"></ul>
</div>

<!-- these 2 div-section needs to be HIDDEN by the jQuery code -->
<div class="clearfix"></div>
<div class="basic-question">
  <div class="basic-answers-for-slider"></div>
  <ul class="basic-answers-results basic-answers"></ul>
</div>

<!-- these 2 div-section needs to be HIDDEN by the jQuery code -->
<div class="clearfix"></div>
<div class="basic-question">
  <div class="basic-answers-for-slider"></div>
  <ul class="basic-answers-results basic-answers"></ul>
</div>

<!-- SECOND POLL, not yet answered so no results visible yet
     this div-section needs to remain visible  -->
<div class="basic-question basic-question-text-vertical">
  <ul class="basic-answers"></ul>
</div>

<!-- these 2 div-section needs to remain visible as there is no
     ul.basic-answers-results -->
<div class="clearfix"></div>
<div class="basic-question">
  <div class="basic-answers-for-slider"></div>
</div>

当然,使用 jQuery 完成的任何事情也可以使用纯 JavaScript 来实现:

// here we use document.querySelectorAll() to retrieve a NodeList
// of - as before - the `ul.basic-answers-results` elements which
// are the siblings of `div.basic-answers-for-slider` elements,
// both of which are the immediate child elements of a `.basic-question`
// element:
document.querySelectorAll(
  '.basic-question > div.basic-answers-for-slider + ul.basic-answers-results'
  // we then use NodeList.prototype.forEach() to iterate over each node in the
  // set returned by document.querySelectorAll():
).forEach(
  // using an Arrow function (since we don't need to use 'this'), to pass
  // the current Node (el) of the NodeList over which we're iterating
  // into the function, in which we navigate to the element's parentNode
  // and add the class 'hide' to handle the hiding:
  (el) => el.parentNode.classList.add('hide')
);
/* almost none of the CSS is relevant to the demo, and
   and is just for some aesthetics: */

*,
 ::before,
 ::after {
  box-sizing: border-box;
  font-family: Calibri, Ubuntu, Helvetica, Arial, sans-serif;
  font-size: 1rem;
  line-height: 1.5;
  margin: 0;
  padding: 0;
}

div,
ul,
p {
  border: 1px solid #000;
  margin: 0.5em auto;
  width: 80%;
}


/* Not relevant to the demo, but here we use the :is()
   CSS psuedo-class function to shorten as an alternative
   to:
   .basic-question div::before,
   .basic-question ul::before */

.basic-question :is(div, ul)::before {
  content: attr(class);
  font-style: italic;
}

p {
  border: 0 none transparent;
}

code {
  background-color: #cca;
  font-family: mono;
  padding: 0 0.3em;
}


/* the utility class used to hide the element(s),
   for proof-of-concept I reduced the opacity,
   but "display: none;" could easily be substituted: */

.hide {
  opacity: 0.2;
}
<p class="problem-description">The sections I want to hide must contain both <code>div.basic-answers-for-slider</code> and <code>ul.basic-answers-results</code></p>
<!-- FIRST POLL, answered and showing results
     this div-section needs to remain visible -->
<div class="basic-question basic-question-text-vertical">
  <ul class="basic-answers"></ul>
  <ul class="basic-answers-results basic-answers"></ul>
</div>

<!-- these 2 div-section needs to be HIDDEN by the jQuery code -->
<div class="clearfix"></div>
<div class="basic-question">
  <div class="basic-answers-for-slider"></div>
  <ul class="basic-answers-results basic-answers"></ul>
</div>

<!-- these 2 div-section needs to be HIDDEN by the jQuery code -->
<div class="clearfix"></div>
<div class="basic-question">
  <div class="basic-answers-for-slider"></div>
  <ul class="basic-answers-results basic-answers"></ul>
</div>

<!-- SECOND POLL, not yet answered so no results visible yet
     this div-section needs to remain visible  -->
<div class="basic-question basic-question-text-vertical">
  <ul class="basic-answers"></ul>
</div>

<!-- these 2 div-section needs to remain visible as there is no
     ul.basic-answers-results -->
<div class="clearfix"></div>
<div class="basic-question">
  <div class="basic-answers-for-slider"></div>
</div>

参考:


推荐阅读