I’ve got a group of items that each have one or more data attributes (in an array). Above them, there’s a group of tabs each with a data attribute that is the same as it’s label. When I click a tab, I’d like to hide all the items that don’t have the same data attribute. This would be easy if each item had only one data attribute, but some have multiple and need to be shown if they match at all. I’m getting a little bogged down in the JS, but I feel like I’m close. Anyone see what I’m doing wrong?
Thank you
(function($) {
$(document).ready(function() {
$(".main .tabs .tab").click(function() {
let currentTab;
currentTab = $(this).data('dept');
$(".main .tabs .tab").removeClass('active');
$(this).addClass('active');
// loop through all members and match those of currentTab
$(".member-container .member").each(function(i, member) {
if (currentTab == 'all') {
$(member).removeClass('hide');
} else {
$(member).removeClass('hide');
let memberDepts = $(member).data('dept');
$(memberDepts).each(function(j, dept) {
if ($(member).data('dept') != dept) {
$(member).addClass('hide')
}
})
}
})
})
});
})(jQuery);
body {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.tabs {
display: flex;
column-gap: 15px;
padding-top: 100px;
justify-content: center;
}
.tabs .tab {
padding: 20px;
border: 2px solid green;
cursor: pointer;
}
.tabs .tab.active {
background-color: green;
color: #fff;
}
.member-container {
display: flex;
width: 90%;
padding-top: 100px;
margin: 0 auto;
flex-wrap: wrap;
column-gap: 20px;
row-gap: 20px;
}
.member-container .member {
width: 30%;
border: 2px solid red;
height: 100px;
display: flex;
align-items: center;
justify-content: center;
font-size: 25px;
}
.member-container .member.hide {
display: none;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<main class="main">
<div class="tabs">
<div data-dept="all" class="tab">All</div>
<div data-dept="finance" class="tab">Finance</div>
<div data-dept="adminisration" class="tab">Admin</div>
<div data-dept="marketing" class="tab">Marketing</div>
<div data-dept="executive" class="tab">Executive</div>
<div data-dept="senior" class="tab">Senior</div>
<div data-dept="organization" class="tab">Org</div>
</div>
<div class="member-container">
<div data-dept="["finance"]" class="member">John Doe</div>
<div data-dept="["finance", "marketing"]" class="member">Jane Doe</div>
<div data-dept="["senior"]" class="member">Billy Bob</div>
<div data-dept="["adminisration", "senior"]" class="member">Suzy Q</div>
<div data-dept="["executive"]" class="member">Random Name</div>
<div data-dept="["marketing"]" class="member">Another Name</div>
<div data-dept="["organization","executive","marketing"]" class="member">Foo Bar</div>
<div data-dept="["adminisration"]" class="member">Does it Matter?</div>
</div>
</main>
I’ve got a link to codepen too : https://codepen.io/paul-molnar/pen/QWzazKq
4
Answers
Try this out. Essentially your problem was around this code:
memberDepts
is an array of strings, a list of the departments. You are then trying to select it as a jQuery object like it was an HTML element and loop over it. Within that loop you were trying to see if each member is contained or not.Since we already have the currently selected deparment as a string, and we have an array of strings, we can just use
.includes()
to greatly simplify this and correct the issue.I’ve also made a few other changes, mostly around selecting eleemnts as few times as possible. If you call
$(member)
3 times in a loop of 10 items, that’s 30 calls to select elements! It only needs to happen once.Use the array
.includes()
method to test if the selected tab is inside the array in thedata
attribute.Try this. I just used spaces as delimiters between the depts. If you have dept. names with spaces, you could choose a different char as the delimiter or use a dash to represent a space.
You can replace the .show() and .hide() with add/remove class. I just used those as a example.
Split your depts dataset by space, and use Array.prototype.includes()