Filter elements if child element of elements has a certain class

Asked

Viewed 156 times

3

The title of the question is already very self-explanatory. I’m trying to filter elements (div) depending on whether their child elements have determined(s) class(s).

I found the simple code below that filters very well, but not exactly the way I need it - it filters Divs according to their own classes, see:

var $boxs = $("#divs > .tr");
var $btns = $(".btn").on("click", function() {

  var active = 
    $btns.removeClass("active")
      .filter(this)
      .addClass("active")
      .data("filter");

  $boxs
    .hide()
    .filter( "." + active )
    .fadeIn(450);

});
* {
  box-sizing: border-box;
}
body {
  background: #ecf0f1;
  font-family: helvetica, sans-serif;
  font-weight: 200;
}
.btn {
  border: none;
  background: linear-gradient(to bottom, #3498db, #2980b9);
  border-radius: 3px;
  font-family: Arial;
  color: #ffffff;
  padding: 5px 10px 5px 10px;
  text-decoration: none;
  margin: 5px;
}

.active {
  background: linear-gradient(to bottom, #3cb0fd, #3498db);
  text-decoration: none;
}
.tr {
  background-image: linear-gradient(to bottom, #3498db, #2980b9);
  padding: 10px;
  margin: 3px;
  text-align: center;
  border-radius: 3px;
  color: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="active btn" data-filter="tr">Show All</button>
<button class="btn" data-filter="a">Show A</button>
<button class="btn" data-filter="b">Show B</button>
<button class="btn" data-filter="c">Show C</button>
<button class="btn" data-filter="d">Show D</button>

<div id="divs">
<div class="tr"><div class="a b">A e B</div></div>
<div class="tr a">A</div>
<div class="tr b">B</div>
<div class="tr c a">C e A</div>
<div class="tr c">C</div>
<div class="tr d">D</div>
</div>

As you can see from the lines

<div id="divs">
    <div class="tr"><div class="a b">A e B</div></div>

... then I want you to div-mother (.tr) is filtered depending on the classes of your daughters (.a .b), and not her own.

Any idea?

From now on I am grateful.

1 answer

2


Use the method .has(), searching for elements that have child elements that match the specified selector.

The line .filter( "." + active ) searches for Ivs that have a class, then switching to:

.filter( function(){ return $(this).hasClass(active) || $("." + active, this).length } )

You will also find Ivs that have children with the class. callback function returns the elements that have the class (.hasClass()) or that have some child element with the same class. The code $("." + active, this).length counts the child elements with the specified class and returns 0 (if they do not exist) or greater than 0 (if they exist). That is, one of the two conditions separated by || must be true.

var $boxs = $("#divs > .tr");
var $btns = $(".btn").on("click", function() {

  var active = 
    $btns.removeClass("active")
      .filter(this)
      .addClass("active")
      .data("filter");

  $boxs
    .hide()
    .filter( function(){ return $(this).hasClass(active) || $("." + active, this).length } )
    .fadeIn(450);

});
* {
  box-sizing: border-box;
}
body {
  background: #ecf0f1;
  font-family: helvetica, sans-serif;
  font-weight: 200;
}
.btn {
  border: none;
  background: linear-gradient(to bottom, #3498db, #2980b9);
  border-radius: 3px;
  font-family: Arial;
  color: #ffffff;
  padding: 5px 10px 5px 10px;
  text-decoration: none;
  margin: 5px;
}

.active {
  background: linear-gradient(to bottom, #3cb0fd, #3498db);
  text-decoration: none;
}
.tr {
  background-image: linear-gradient(to bottom, #3498db, #2980b9);
  padding: 10px;
  margin: 3px;
  text-align: center;
  border-radius: 3px;
  color: #fff;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<button class="active btn" data-filter="tr">Show All</button>
<button class="btn" data-filter="a">Show A</button>
<button class="btn" data-filter="b">Show B</button>
<button class="btn" data-filter="c">Show C</button>
<button class="btn" data-filter="d">Show D</button>

<div id="divs">
<div class="tr"><div class="a b">A e B</div></div>
<div class="tr a">A</div>
<div class="tr b">B</div>
<div class="tr c a">C e A</div>
<div class="tr c">C</div>
<div class="tr d">D</div>
</div>

  • The form it has at present only shows those who have descendants with the chosen class, but not the very elements that have the class as well. That is when you click on "Show A" you should show "A and B" as well as "A" and "C and A"

  • But you didn’t mention the question

  • In the question you say you want to filter by the children and not by the main div

  • I’m not the AP! What I interpreted by the example is that he wanted to filter for himself and his children, but the best thing is to let the AP pronounce.

  • Thank you very much Sam, perfect! @Isac is not the author of the answer, if that’s what you implied.

  • The @Isac is right rsrs, that’s exactly what I meant. But I marked it as correct because in the meantime I found an alternative solution. Anyway, thank you both!!

  • @Thiagosoubra Blz! I edited the answer. Abs!

Show 2 more comments

Browser other questions tagged

You are not signed in. Login or sign up in order to post.