Reputation: 975
I was able to put together a javascript-only filter, but am now stuck, and could use some help.
Essentially it is broken down into "days" and "events".
If the user clicks a day or multiple days it shows the events for those days.
To further filter it down, they can click the events and it only shows those particular events for the selected days.
I have gotten that to work, but cannot make it work the other way round. If they have only selected the event(s), it will not show anything unless a day is selected.
Also, I am trying to figure out how to implement a "show all" checkbox that would uncheck the other boxes, yet show all dates/events.
function change() {
let results = Array.from(document.querySelectorAll('.result > div')),
dayChecked = document.querySelectorAll('.filter input.day:checked'),
eventChecked = document.querySelectorAll('.filter input.event:checked');
// Hide all results
results.forEach(function(result) {
result.style.display = 'none';
});
// Filter results to only those that meet ALL requirements:
filterdayOrevent(dayChecked);
if (eventChecked.length != 0) {
filterdayOrevent(eventChecked);
}
function filterdayOrevent(dayOreventChecked) {
results = Array.from(dayOreventChecked).reduce(function(sum, input) {
const attrib = input.getAttribute('rel');
return sum.concat(results.filter(function(result) {
return result.classList.contains(attrib);
}));
}, []);
}
// Show those filtered results:
results.forEach(function(result) {
result.style.display = 'block';
});
}
change();
<div class="filter">
<div class="checkbox">
<label><input type="checkbox" rel="" class="" onchange="change()" />Show All</label>
</div>
<h1>Select day</h1>
<div class="checkbox">
<label><input type="checkbox" rel="friday" class="day" onchange="change()" />Friday</label>
</div>
<div class="checkbox">
<label><input type="checkbox" rel="saturday" class="day" onchange="change()" />Saturday</label>
</div>
<div class="checkbox">
<label><input type="checkbox" rel="sunday" class="day" onchange="change()" />Sunday</label>
</div>
<h1>Select event</h1>
<div class="checkbox">
<label><input type="checkbox" rel="screening" class="event" onchange="change()" />Screening</label>
</div>
<div class="checkbox">
<label><input type="checkbox" rel="seminar" class="event" onchange="change()" />Seminar</label>
</div>
<div class="checkbox">
<label><input type="checkbox" rel="social" class="event" onchange="change()" />Social</label>
</div>
</div>
<P></P>
<div class="result">
<div class="friday screening">Friday / Screening</div>
<div class="friday seminar">Friday / Seminar</div>
<div class="friday social">Friday / Social</div>
<div class="saturday screening">Saturday / Screening</div>
<div class="saturday seminar">Saturday / Seminar</div>
<div class="saturday social">Saturday / Social</div>
<div class="sunday screening">Sunday / Screening</div>
<div class="sunday seminar">Sunday / Seminar</div>
<div class="sunday social">Sunday / Social</div>
</div>
Upvotes: 1
Views: 65
Reputation: 4050
You should only filter by day if at least one day has been checked, much the same way you added a check for the Events. Without this everything fails the day check and the event check starts filtering an empty array.
if(dayChecked.length != 0){
filterdayOrevent(dayChecked);
}
To handle the Show All checkbox I would make it call its own function and handle the things it needs to do there. Once you have prepared (uncheck all other filters) simply call the change function.
function showAll() {
let isChecked = document.getElementById('showAllCheck').checked;
//if Show All is checked, uncheck everything else then call change()
if(isChecked){
let filters = document.querySelectorAll('.filter input');
Array.from(filters).forEach(function(filter) {
filter.checked = false;
});
}
change();
}
function change() {
let results = Array.from(document.querySelectorAll('.result > div')),
dayChecked = document.querySelectorAll('.filter input.day:checked'),
eventChecked = document.querySelectorAll('.filter input.event:checked');
// Hide all results
results.forEach(function(result) {
result.style.display = 'none';
});
// Filter results to only those that meet ALL requirements:
if(dayChecked.length != 0){
filterdayOrevent(dayChecked);
}
if (eventChecked.length != 0) {
filterdayOrevent(eventChecked);
}
function filterdayOrevent(dayOreventChecked) {
results = Array.from(dayOreventChecked).reduce(function(sum, input) {
const attrib = input.getAttribute('rel');
return sum.concat(results.filter(function(result) {
return result.classList.contains(attrib);
}));
}, []);
}
// Show those filtered results:
results.forEach(function(result) {
result.style.display = 'block';
});
}
change();
<div class="checkbox">
<label><input type="checkbox" id="showAllCheck" rel="" class="" onchange="showAll()" />Show All</label>
</div>
<div class="filter">
<h1>Select day</h1>
<div class="checkbox">
<label><input type="checkbox" rel="friday" class="day" onchange="change()" />Friday</label>
</div>
<div class="checkbox">
<label><input type="checkbox" rel="saturday" class="day" onchange="change()" />Saturday</label>
</div>
<div class="checkbox">
<label><input type="checkbox" rel="sunday" class="day" onchange="change()" />Sunday</label>
</div>
<h1>Select event</h1>
<div class="checkbox">
<label><input type="checkbox" rel="screening" class="event" onchange="change()" />Screening</label>
</div>
<div class="checkbox">
<label><input type="checkbox" rel="seminar" class="event" onchange="change()" />Seminar</label>
</div>
<div class="checkbox">
<label><input type="checkbox" rel="social" class="event" onchange="change()" />Social</label>
</div>
</div>
<P></P>
<div class="result">
<div class="friday screening">Friday / Screening</div>
<div class="friday seminar">Friday / Seminar</div>
<div class="friday social">Friday / Social</div>
<div class="saturday screening">Saturday / Screening</div>
<div class="saturday seminar">Saturday / Seminar</div>
<div class="saturday social">Saturday / Social</div>
<div class="sunday screening">Sunday / Screening</div>
<div class="sunday seminar">Sunday / Seminar</div>
<div class="sunday social">Sunday / Social</div>
</div>
Upvotes: 1