Reputation: 17
Problem: I need a way in jQuery to hide a parent div if all the children in a list contained within said div are hidden.
Context: I'm working on an employee portal that allows an admin to upload PDFs. When they upload the PDF, they can attach it to a category and they can also add tags to it. The purpose of the tags is for an inline filtering feature that will only show files associated with a particular tag if they select it from the menu. A simplified example of my markup:
<!-- Filtering Menu -->
<ul class="resource-filters">
<li class="all">All</li>
<li class="filter-example">Filter #1</li>
<li class="filter-example">Filter #2</li>
<li class="filter-example">Filter #3</li>
</ul>
<!-- Category #1 -->
<div class="resources-files-container">
<h3>Category #1</h3>
<ul class="attachment-list">
<li class="filter-example-1">
<a href="#">PDF Example #1</a>
</li>
<li class="filter-example-3">
<a href="#">PDF Example #3</a>
</li>
</ul>
</div>
<!-- Category #2 -->
<div class="resources-files-container">
<h3>Category #2</h3>
<ul class="attachment-list">
<li class="filter-example-2 hidden">
<a href="#">PDF Example #2</a>
</li>
<li class="filter-example-2 hidden">
<a href="#">PDF Example #2</a>
</li>
</ul>
</div>
The problem I am having is, say I select "Filter #1" from the menu. All list items that don't have the class of .filter-example-1
will be set to display: none
(the hidden class). In the example markup above, that would mean that Category #2 now has zero items to show. I want the entire div of .resources-files-container
to hide (until they select another filter that is appropriate).
I've been trying to solve this problem for a couple of hours now and have done plenty of searching (I've found some solutions that fit part of my criteria, but not this specific case). I've got the entire app figured out except for this particular portion. The following jQuery isn't particularly relevant for this specific problem I'm having, but just to give you some context:
// only run if we're in the portal
if ($("#portal-container").length) {
// get the unique list of classnames
var classes = {};
$('.attachment-list li').each(function() {
$($(this).attr('class').split(' ')).each(function() {
if (this !== '') {
classes[this] = this;
}
});
});
//build the list items
class_list = '';
for (class_name in classes) {
class_list += '<li class="'+class_name+'">'+class_name+'</li>';
};
// append the resulting list to the page
$(class_list).appendTo('#resource-filter ul');
// sorting functionality
$('#portal-page').on('click', '#resource-filter li', function() {
// set the current filter
var filterVal = $(this).attr('class');
// add current state to filter button
$('#resource-filter li.current').removeClass('current');
$(this).addClass('current');
// filtering function
if(filterVal == 'filter-all') {
$('.attachment-list li.hidden').fadeIn('slow').removeClass('hidden');
} else {
$('.attachment-list li').each(function() {
if(!$(this).hasClass(filterVal)) {
$(this).fadeOut('normal').addClass('hidden');
} else {
$(this).fadeIn('slow').removeClass('hidden');
}
});
}
});
}
I highly appreciate any advice.
Upvotes: 0
Views: 3717
Reputation: 163
Also include an else to toggle the visibility back on if the selection is changed:
function toggleContainersByChildren() {
$('.resources-files-container').each(function () {
if ($(this).find('li:visible').length === 0) { // note the three = signs
$(this).hide(); //hides the container if no children are visible
} else {
$(this).show(); //shows it again if the children are turned back on
}
});
}
toggleContainersByChildren(); //call this function to check your containers for visible children every time the filter is changed
Edit: Calling attention to the === equality sign...
Upvotes: 1
Reputation: 16831
If I understand you correctly, you want to check if all the li
inside a div .resources-files-container
don't have the .filter-example-1
class...
So, it would be something like this:
//Select all div with this class, and iterate through them
$('.resources-files-container').each(function() {
//Checks if the number of li's with the specified class inside this div is "0"
if($(this).find('li.filter-example-1').length == 0) {
//Hides the div, because there's no visible li in it.
$(this).hide();
}
});
Upvotes: 0
Reputation: 78650
$(".resources-files-container")
.filter(function(){
return $(this).find("li:visible").length == 0;
})
.hide();
Filter the list of .resources-files-container
elements to just those with no visible li
elements and then hide that filtered set.
Upvotes: 2