Skip to content

Getting all elements on a page and hiding them upon filter

I have something that filters groups of cards on a page that works well, until I try to add section headers to each group. Ideally, I’d like all the section headers to disappear when my “no results” block is displayed.

var $filterCheckboxes = $('input[type="checkbox"]');
$filterCheckboxes.on("change", function () {
  $(".card-grid").show();
  var selectedFilters = {};
  $filterCheckboxes.filter(":checked").each(function () {
    if (!selectedFilters.hasOwnProperty(this.name)) {
      selectedFilters[this.name] = [];
    }
    selectedFilters[this.name].push(this.value);
  });
  var $filteredResults = $(".card");
  $.each(selectedFilters, function (name, filterValues) {
    $filteredResults = $filteredResults.filter(function () {
      var matched = false,
        currentFilterValues = $(this).data("category").split(" ");
      $.each(currentFilterValues, function (_, currentFilterValue) {
        if ($.inArray(currentFilterValue, filterValues) != -1) {
          matched = true;
          return false;
        }
      });
      return matched;
    });
  });
  $(".card").hide().filter($filteredResults).show();
  var all_hidden = true;
  $(".card").each(function (index) {
    if ($(this).is(":visible")) {
      all_hidden = false;
      document.getElementsByClassName("no-results")[0].style.display = "none";
      document.getElementsByClassName("section-header")[0].style.display =
        "block";
    }
  });
  if (all_hidden) {
    $(".card-grid").hide();
    document.getElementsByClassName("no-results")[0].style.display = "block";
    document.getElementsByClassName("section-header")[0].style.display = "none";
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="filter-container">
  <ul class="filters">
    <li><input type="checkbox" name="topic" id="topic1" value="topic1"><label for="topic1">Topic 1
    </li>
    <li><input type="checkbox" name="topic" id="topic2" value="topic2"><label for="topic2">Topic 2</li>
    <li><input type="checkbox" name="topic" id="topic3" value="topic3"><label for="topic3">Topic 3
    </li>
  </ul>
</div>

<div class="filter-section-content">
  <div class="filter-container">
    <ul class="filters">
      <li><input type="checkbox" name="content-type" id="subfilter1" value="reads"><label for="subfilter1">subfilter1</label></li>
      <li><input type="checkbox" name="content-type" id="subfilter2" value="linkedin"><label for="subfilter2">subfilter2</label></li>
      <li><input type="checkbox" name="content-type" id="subfilter3" value="subfilter3"><label for="subfilter3">subfilter3</label>
      </li>
    </ul>
  </div>
</div>

<p>&nbsp;</p>

<!--Cards-->
<!--Topic 1-->
<p class="section-header">Topic 1</p>
<div class="card-grid">
  <!--New Card-->
  <div class="card" data-category="topic1 subfilter1">
    <div class="card-front-wrap">
      <div class="card-front">
        <p class="label">Topic 1</p>
        <h1>Title</h1>
      </div>
    </div>
    <div class="card-overlay">
      <h5>More Info <i class="far fa-arrow-alt-circle-down fa-lg"></i></h5>
      <div class="card-body">
      </div>
    </div>
  </div>
  <!--New Card-->
  <div class="card" data-category="topic1 subfilter3">
    <div class="card-front-wrap">
      <div class="card-front">
        <p class="label">Topic 1</p>
        <h1>Title</h1>
      </div>
    </div>
    <div class="card-overlay">
      <h5>More Info <i class="far fa-arrow-alt-circle-down fa-lg"></i></h5>
      <div class="card-body">
      </div>
    </div>
  </div>
</div>
<!--Topic 2-->
<p class="section-header">Topic 2</p>
<div class="card-grid">
  <!--New Card-->
  <div class="card" data-category="topic2 subfilter1">
    <div class="card-front-wrap">
      <div class="card-front">
        <p class="label">Topic 2</p>
        <h1>Title</h1>
      </div>
    </div>
    <div class="card-overlay">
      <h5>More Info <i class="far fa-arrow-alt-circle-down fa-lg"></i></h5>
      <div class="card-body"></div>
    </div>
  </div>
</div>

<div class="no-results">
  No Results
</div>

I know that the [0] after the line that gets the class name for the section headers is only pulling in the first, but when I remove that then I get a “style is undefined” error. Shouldn’t it be getting every element with the specified class name?

Answer

I use $(this).parent().prev(".section-header") to find out the header to set it show/hide when $(".card").each(function (index).

And by default, we should hide "no-results". Just show it if all_hidden = true.

So basically, I updated your codes into the below codes:

var all_hidden = true;
$(".card").each(function(index) {
    if ($(this).is(":visible")) {
        all_hidden = false;
        // Show header if the card is visible
        $(this).parent().prev(".section-header").show();
    } else {
        // Hide header if the card is invisible
        $(this).parent().prev(".section-header").hide();
    }
});
if (all_hidden) {
    document.getElementsByClassName("no-results")[0].style.display = "block";
} else {
    document.getElementsByClassName("no-results")[0].style.display = "none";
}

You can see full of demo here:

var $filterCheckboxes = $('input[type="checkbox"]');
$filterCheckboxes.on("change", function () {
  $(".card-grid").show();
  var selectedFilters = {};
  $filterCheckboxes.filter(":checked").each(function () {
    if (!selectedFilters.hasOwnProperty(this.name)) {
      selectedFilters[this.name] = [];
    }
    selectedFilters[this.name].push(this.value);
  });
  var $filteredResults = $(".card");
  $.each(selectedFilters, function (name, filterValues) {
    $filteredResults = $filteredResults.filter(function () {
      var matched = false,
        currentFilterValues = $(this).data("category").split(" ");
      $.each(currentFilterValues, function (_, currentFilterValue) {
        if ($.inArray(currentFilterValue, filterValues) != -1) {
          matched = true;
          return false;
        }
      });
      return matched;
    });
  });
  $(".card").hide().filter($filteredResults).show();
  var all_hidden = true;
  $(".card").each(function (index) {
    if ($(this).is(":visible")) {
      all_hidden = false;
      // Show header if the card is visible
      $(this).parent().prev(".section-header").show();
    } else {
      // Hide header if the card is invisible
      $(this).parent().prev(".section-header").hide();
    }
  });
  if (all_hidden) {
    document.getElementsByClassName("no-results")[0].style.display = "block";
  } else {
    document.getElementsByClassName("no-results")[0].style.display = "none";
  }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="filter-container">
  <ul class="filters">
    <li><input type="checkbox" name="topic" id="topic1" value="topic1"><label for="topic1">Topic 1
    </li>
    <li><input type="checkbox" name="topic" id="topic2" value="topic2"><label for="topic2">Topic 2</li>
    <li><input type="checkbox" name="topic" id="topic3" value="topic3"><label for="topic3">Topic 3
    </li>
  </ul>
</div>

<div class="filter-section-content">
  <div class="filter-container">
    <ul class="filters">
      <li><input type="checkbox" name="content-type" id="subfilter1" value="reads"><label for="subfilter1">subfilter1</label></li>
      <li><input type="checkbox" name="content-type" id="subfilter2" value="linkedin"><label for="subfilter2">subfilter2</label></li>
      <li><input type="checkbox" name="content-type" id="subfilter3" value="subfilter3"><label for="subfilter3">subfilter3</label>
      </li>
    </ul>
  </div>
</div>

<p>&nbsp;</p>

<!--Cards-->
<!--Topic 1-->
<p class="section-header">Topic 1</p>
<div class="card-grid">
  <!--New Card-->
  <div class="card" data-category="topic1 subfilter1">
    <div class="card-front-wrap">
      <div class="card-front">
        <p class="label">Topic 1</p>
        <h1>Title</h1>
      </div>
    </div>
    <div class="card-overlay">
      <h5>More Info <i class="far fa-arrow-alt-circle-down fa-lg"></i></h5>
      <div class="card-body">
      </div>
    </div>
  </div>
  <!--New Card-->
  <div class="card" data-category="topic1 subfilter3">
    <div class="card-front-wrap">
      <div class="card-front">
        <p class="label">Topic 1</p>
        <h1>Title</h1>
      </div>
    </div>
    <div class="card-overlay">
      <h5>More Info <i class="far fa-arrow-alt-circle-down fa-lg"></i></h5>
      <div class="card-body">
      </div>
    </div>
  </div>
</div>
<!--Topic 2-->
<p class="section-header">Topic 2</p>
<div class="card-grid">
  <!--New Card-->
  <div class="card" data-category="topic2 subfilter1">
    <div class="card-front-wrap">
      <div class="card-front">
        <p class="label">Topic 2</p>
        <h1>Title</h1>
      </div>
    </div>
    <div class="card-overlay">
      <h5>More Info <i class="far fa-arrow-alt-circle-down fa-lg"></i></h5>
      <div class="card-body"></div>
    </div>
  </div>
</div>
<!-- default hide no results -->
<div class="no-results" style="display: none">
  No Results
</div>