Making a filter to show/hide the elements

yotube
0

Issue

I use a filtering function in my webpage. When a button is clicked, it hides the associated elements and fades itself. Once it's clicked again, it brings those elements back and restores its color.

What I want to do is to add two additional buttons: "Show all" and "Hide all". I want them to show/hide all elements and also fade/restore all the button colors upon click.

First I made an onclick event handler for these two buttons, but it didn't work properly. I think I have to combine everything in the same onload event, and that's where I got stuck. Could you please help me to modify my js to achieve my goal?

Snippet:



for (let button of document.querySelectorAll(".filterbutton")) {
button.addEventListener("click", filter);
}

let filters = new Set;

function toggleDisplay(selector, display) {
let elems = document.querySelectorAll(selector);
for (let elem of elems) {
elem.style.display = display;
}
}

function filter() {
let filterSelector = this.dataset.filter;
let show = filters.delete(filterSelector);
this.style.color = show ? "" : "rgb(200,200,200)";
if (!show) {
filters.add(filterSelector); // toggle this filter
} else {
toggleDisplay(filterSelector, "");
}
if (filters.size) {
toggleDisplay([...filters].join(","), "none");
}
}

.filterbutton,
.showallbutton,
.hideallbutton {
border: 1px solid;
display: inline-block;
background: lightblue;
padding: 5px;
cursor: pointer
}

.group a {
display: block;
}

<div class="filter">
<div class="filterbutton" data-filter=".filter01">Filter 01</div>
<div class="filterbutton" data-filter=".filter02">Filter 02</div>
<div class="filterbutton" data-filter=".filter03">Filter 03</div>
</div>

<div class="group">
<a class="filter01 filter02 filter03">This element has filter01, filter02 and filter03</a>
<a class="filter01 filter02">This element has filter01 and filter02</a>
<a class="filter01 filter03">This element has filter01 and filter03</a>
<a class="filter02 filter03">This element has filter02 and filter03</a>
<a class="filter01">This element has filter01 only</a>
<a class="filter02">This element has filter02 only</a>
<a class="filter03">This element has filter03 only</a>
</div>

<div class="show-hide">
<div class="showallbutton">Show all</div>
<div class="hideallbutton">Hide all</div>
</div>




Solution

I always delegate

Here I delegate from document; if you can find a closer container, use that instead

I also removed the dot from the data-filter=". <<<

Lastly I made the color change a class.

the code to detect the show/hide buttons can be simpler if you give both a common class

Here is the solution based on a PEN you showed me



window.addEventListener("DOMContentLoaded", function() {
const filtered = document.querySelectorAll(".group a");
const buttons = document.querySelectorAll(".filter-button");
const toggleContent = () => {
let filterSelector = [...buttons] // the buttons
.filter(btn => btn.matches(".inactive")) // that are grey
.map(btn => btn.dataset.filter); // get their data-filter
console.log(filterSelector)

filtered.forEach(anc => { // Hide the links whose classes are are in the filterSelector
const hide = filterSelector.length > 0 &&
filterSelector.some(filter => [...anc.classList].includes(filter))
anc.style.display = hide ? "none" : "inline-block";
});
}
const filter = e => {
const tgt = e.target; // what was clicked?
if (tgt.matches(".filter-button")) { // a button?
tgt.classList.toggle("inactive"); // toggle it
toggleContent(); // toggle the links
} else if (tgt.closest(".toggleall")) { // or if (!tgt.matches("toggleButton")) return if you give the buttons a class
const show = tgt.matches(".toggleall-show"); // show all?
const hide = tgt.matches(".toggleall-hide"); // hide all?
if (!show && !hide) return; // something else was clicked
buttons.forEach(btn => btn.classList[show ? "remove" : "add"]("inactive")); // if show, remove all inactive if not, addd all inacctive
toggleContent(); // toggle the links
}
};

document.addEventListener("click", filter);
});

@charset "utf-8";
.container {
width: calc(100% - 56px);
padding: 18px;
padding-bottom: 2px;
margin: 10px;
float: left;
overflow: hidden;
border-radius: 10px;
box-shadow: 0 0 1px rgb(0, 0, 0);
}

.toggleall {
margin-bottom: 16px;
display: block;
font-family: Arial, Helvetica, sans-serif;
color: rgb(70, 70, 70);
}

.toggleall-show,
.toggleall-hide {
width: 70px;
padding: 5px;
margin: 2px;
font-family: Arial, Helvetica, sans-serif;
color: rgb(70, 70, 70);
font-weight: bold;
font-size: 12px;
text-align: center;
cursor: pointer;
display: inline-block;
border-radius: 5px;
box-shadow: inset 0 0 0 1px rgb(200, 200, 200);
transition: all 0.5s ease;
}

.toggleall-show:hover,
.toggleall-hide:hover {
text-decoration: underline;
transition: all 0.1s ease;
}

.filter {
margin-bottom: 16px;
display: block;
font-family: Arial, Helvetica, sans-serif;
color: rgb(70, 70, 70);
}

.filter-title,
.filter-button {
padding: 5px;
margin: 2px;
font-family: Arial, Helvetica, sans-serif;
color: rgb(70, 70, 70);
font-weight: bold;
font-size: 12px;
text-align: center;
display: inline-block;
border-radius: 5px;
}

.filter-button {
cursor: pointer;
box-shadow: inset 0 0 0 1px rgb(200, 200, 200);
}

.filter-button:hover {
text-decoration: underline;
}

.inactive {
color: rgb(200, 200, 200);
}

.group {
width: calc(100% - 60px);
padding: 20px;
padding-bottom: 40px;
margin: 10px;
display: grid;
grid-template-columns: repeat(5, 1fr);
grid-auto-rows: 200px;
grid-gap: 20px;
grid-auto-flow: dense;
counter-reset: div;
float: left;
overflow: hidden;
border-radius: 10px;
box-shadow: 0 0 1px rgb(0, 0, 0);
}

.group a {
height: 200px;
display: inline-flex;
position: relative;
overflow: hidden;
background: rgb(255, 255, 255);
transition: all 0.5s ease, height 0s;
}

<div class="platform-controller">
<div class="filter">
<div class="filter-title">Filter List 1:</div>
<div class="filter-button" data-filter="filter0a">Item A</div>
<div class="filter-button" data-filter="filter0b">Item B</div>
<div class="filter-button" data-filter="filter0c">Item C</div>
</div>
<div class="filter">
<div class="filter-title">Filter List 2:</div>
<div class="filter-button" data-filter="filter01">Item 1</div>
<div class="filter-button" data-filter="filter02">Item 2</div>
<div class="filter-button" data-filter="filter03">Item 3</div>
</div>
<div class="toggleall">
<div class="toggleall-show">Show all</div>
<div class="toggleall-hide">Hide all</div>
</div>
</div>
<div class="group">
<a class="filter0a filter01" href="www.google.com">Image 1</a>
<a class="filter0b filter02" href="www.google.com">Image 2</a>
<a class="filter0c filter03" href="www.google.com">Image 3</a>
</div>





Answered By - mplungjan

Post a Comment

0Comments
Post a Comment (0)

#buttons=(Accept !) #days=(20)

Our website uses cookies to enhance your experience. Learn More
Accept !
To Top