★최종 결과물
0. 작업 개요
특정 리스트에서 버튼을 누를 시,
해당 버튼 카테고리에 맞는 리스트아이템만 노출되는 필터기능을 이용한 메뉴판 만들기.
라이브러리 형식으로 자바스크립트를 잘몰라도 간편하게 사용 할 수 있게 만들어보자.
ex) 메뉴와 리스트 아이템에 data-filter 속성을 추가 한 뒤,
클릭 시 클릭된 메뉴의 data-filter 속성과 매치되는 list-item만 노출 되게끔 작업 진행 예정
1. HTML
HTML을 작성하면서 JS 구조를 잠깐 생각해봤는데, filter-list가 같은 페이지 내에
여러개가 있을 경우 조금 꼬이거나 할것 같아서 전체를 감싸는 container에 data-filter-id를 추가해줬다.
<div class="menu_container" data-filter-id="asian_food">
<div class="menu_header">Asian Food</div>
<div class="menu_button_area">
<ul>
<li><button type="button" data-filter="all" class="active">All</button></li>
<li><button type="button" data-filter="kor">Korea</button></li>
<li><button type="button" data-filter="jp">Japan</button></li>
<li><button type="button" data-filter="ch">China</button></li>
</ul>
</div>
<div class="menu_list">
<ul>
<li data-filter="kor">Bibimbab</li>
<li data-filter="jp">Sushi</li>
<li data-filter="ch">Dimsum</li>
<li data-filter="kor">Samgyeopsal</li>
<li data-filter="jp">Sashimi</li>
<li data-filter="ch">Spring Roll</li>
<li data-filter="kor">Japchae</li>
<li data-filter="jp">Ramen</li>
<li data-filter="ch">Wonton</li>
<li data-filter="kor">Kimchi</li>
<li data-filter="jp">Soba</li>
<li data-filter="ch">Tangbao</li>
<li data-filter="kor">Tteokbokki</li>
<li data-filter="jp">Yakitori</li>
<li data-filter="ch">Dumpling</li>
<li data-filter="kor">Jajangmyeon</li>
<li data-filter="jp">Tempura</li>
<li data-filter="ch">Chow Mein</li>
<li data-filter="kor">Haemul Pajeon</li>
</ul>
</div>
</div>
2. CSS
.menu_container {
background-color: #fff;
width: 500px;
height: 500px;
padding: 20px;
box-sizing: border-box;
box-shadow: 3px 3px 6px rgba(0,0,0, 0.5);
border-radius: 10px;
display: flex;
flex-direction: column;
justify-content: flex-start;
align-items: center;
}
.menu_header {
font-size: 24px;
font-weight: 600;
color: #222;
margin: 0;
padding: 0;
}
.menu_list,
.menu_button_area {
width: 100%;
}
.menu_list ul,
.menu_button_area ul {
display: flex;
width: 100%;
margin: 0;
padding: 0 20px;
box-sizing: border-box;
flex-wrap: wrap;
}
.menu_list ul li {
width: 50%;
}
.menu_button_area {
margin: 20px 0;
}
.menu_button_area ul{
display: flex;
justify-content: center;
}
.menu_button_area ul li {
list-style: none;
margin: 0 5px;
}
.menu_button_area ul li button {
background-color: transparent;
border: none;
background: #eee;
padding: 5px 15px;
border-radius: 100px;
cursor: pointer;
}
.menu_button_area ul li button.active {
background: #222;
color: #fff;
}
3. JS
const filterMenuInit = () => {
const filters = document.querySelectorAll('[data-filter-id]');
filters.forEach(filter => {
const filterBtns = [...filter.querySelectorAll('[data-filter]')].filter(el => el.nodeName === 'BUTTON');
const filterLists = [...filter.querySelectorAll('[data-filter]')].filter(el => el.nodeName === 'LI');
filterBtns.forEach(btn => {
btn.addEventListener('click', () => {
const filterType = btn.getAttribute('data-filter');
filterBtns.forEach(btn => btn.classList.remove('active'));
btn.classList.add('active');
filterLists.forEach(list => {
if (filterType === 'all'){
list.style.display = 'list-item';
return;
}
list.style.display = list.getAttribute('data-filter') === filterType ? 'list-item' : 'none';
})
});
})
})
};
filterMenuInit();
filterMenuInit()
1. document에서 "data-filter-id" 속성을 가진 모든 dom을 filters에 저장.
2. forEach 매서드를 이용하여 각각의 filters를 순회하며 해당 filter내에서 [data-fitler] 속성을 가진것중 button, 그리고 li 들을 따로따로 fitlerBtns, 그리고 filterLists 로 저장한다.
3. forEach 매서드로 filterBtns를 순회하며 이벤트리스너를 등록해준다.
4. filterType을 따로 변수로 할당 해준다.
5. filterBtns에 한번더 forEach 매서드로 active class를 제거해준 뒤, 현재 forEach문의 버튼에 active를 붙여준다.
6. filterLists를 forEach 매서드로 순회하며 filterType이 all이 아닐경우 위에서 지정한 filterType과 getAttribute('data-fitler')값이 같은지 확인 후 같으면 display 속성을 list-item으로, 같지 않으면 none으로 바꿔준다.
all일 경우 list아이템의 display 속성을 list-item으로 변경 후 리턴한다. ( 전부 노출 )