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> </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?
Advertisement
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> </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>