Reputation: 1904
I'm working on a live search function, but I need to hide any containers that do not have a match.
This is a sample of how the containers are populated if nothing is entered in the search bar. EDIT: This will be identical even if there is a string in the search bar. fadeOut()
hides the element, doesn't remove it.
<div id="Alabama_container" class="state-container">
<h1>Alabama</h1>
<div id="330_store-object" class="store-object" style="">
<h4>Store 330 - Birmingham</h4>
<p>(205) 981-1320</p>
<p>5201 US-280, Birmingham, AL 35242, USA</p>
<button id="330_store-object-link" class="button">View on Map</button><button id="330_store-object-floorPlan" class="button">Floorplans</button>
</div>
<div id="337_store-object" class="store-object" style="">
<h4>Store 337 - Dothan</h4>
<p>(334) 671-1370</p>
<p>4401 Montgomery Hwy #300, Dothan, AL 36303, USA</p>
<button id="337_store-object-link" class="button">View on Map</button><button id="337_store-object-floorPlan" class="button">Floorplans</button>
</div>
</div>
The state-container
elements are generated on the DOM first then store-object
elements are appended to the appropriately named state-container
.
Search Function Sample:
$(document).ready(function () {
$("#store-search").keyup(function () {
var filter = $(this).val(),
count = 0;
$(".store-object").each(function () {
// If the store object doesn't match, remove it
if ($(this).text().search(new RegExp(filter, "i")) < 0) {
$(this).fadeOut();
// Show the store objects that do match the query
} else {
$(this).show();
count++;
}
});
// Results counter for troubleshooting
var numberItems = count;
$("#filter-count").text(count + "Results Founds");
});
});
My search function simply uses filter to determine any matching strings within the store-object
elements and hides any that don't match. However, the matches still reside in their state-container
so what you end up with is a list of states without any results inside.
What I want to do is loop through state-container
elements and determine if it contains any store-object
children so I can handle it appropriately. What would I use to achieve this?
Upvotes: 0
Views: 532
Reputation: 85545
You can check if store-container has store-object and then only loop through them like:
$(".store-container").find(".store-object").length &&
$(".store-object").each(function () {
After your edit, I could say that you should check for visible length like:
$(".state-container").find(".store-object:visible").length &&
But, I would still say that you don't need to check anything because you're already checking for the condition that if it's visible then only fadeOut. That is, even if this is hidden, there's nothing problem using fadeOut. But what I can say is that you can pause the search execution:
setTimeout(()=>{
// your each function
}, 600);
Upvotes: 1
Reputation: 2658
There are several different ways to achieve what you want. One of which would be using the :visible
selector and then hiding the state-container on an empty set.
$('.state-container').each(function(){
if($(this).find('.store-object:visible').length === 0){
$(this).hide();
}
});
Keep in mind, you'll need to run that after all of the children's fadeOut animations have completed.
Another approach would be to keep a tally of the hidden elements as you go through the search, and if all children were hidden remove the parent.
$(document).ready(function () {
$('.state-container').each(function(){
$(this).data('total', $(this).find('.store-object').length);//set a count of total
});
$("#store-search").keyup(function () {
var filter = $(this).val(),
count = 0;
//reset the hidden count for the states
$('.state-container').each(function(){
$(this).data('hidden', 0);//initialize to 0
$(this).show();
});
$(".store-object").each(function () {
var parent = $(this).parent();
// If the store object doesn't match, remove it
if ($(this).text().search(new RegExp(filter, "i")) < 0) {
$(this).fadeOut();
parent.data('hidden', parent.data('hidden') + 1);//increment hidden count
// Show the store objects that do match the query
} else {
$(this).show();
count++;
}
if(parent.data('hidden') == parent.data('total')){
parent.hide();
}
});
// Results counter for troubleshooting
var numberItems = count;
$("#filter-count").text(count + "Results Founds");
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id='store-search' />
<div id="Alabama_container" class="state-container">
<h1>Alabama</h1>
<div id="330_store-object" class="store-object" style="">
<h4>Store 330 - Birmingham</h4>
<p>(205) 981-1320</p>
<p>5201 US-280, Birmingham, AL 35242, USA</p>
<button id="330_store-object-link" class="button">View on Map</button><button id="330_store-object-floorPlan" class="button">Floorplans</button>
</div>
<div id="337_store-object" class="store-object" style="">
<h4>Store 337 - Dothan</h4>
<p>(334) 671-1370</p>
<p>4401 Montgomery Hwy #300, Dothan, AL 36303, USA</p>
<button id="337_store-object-link" class="button">View on Map</button><button id="337_store-object-floorPlan" class="button">Floorplans</button>
</div>
</div>
Upvotes: 3