[JavaScript] 중복으로 열리지 않는 dropdown

Yeonsu Summer·2022년 8월 6일
1

JavaScript

목록 보기
1/13
post-thumbnail

요즘 내가 진행하고 있는 프로젝트에 여러 개의 조건을 받아 정보를 필터링하는 기능이 들어있다.

조건을 받기 위한 dropdown을 만들었는데 한 가지 문제점이 보였다.

dropdown이 중복으로 열리면 사용자가 보기에 불편할 것이다.

그래서 1개의 dropdown이 열려있는 상태에서 다른 dropdown을 클릭하면 이미 열려있는 것은 닫히는 기능을 코드로 짜보았다.


HTML

<div class="filter-group">
  <div class="filter">
    <button class="filter-toggle">종류</button>
    
    <ul class="filter-menu">
      <li class="filter-option">한식</li>
      <li class="filter-option">중식</li>
      <li class="filter-option">일식</li>
    </ul>
  </div>
  
  <div class="filter">
    <button class="filter-toggle">인원</button>
    
    <ul class="filter-menu">
      <li class="filter-option">1명</li>
      <li class="filter-option">2명</li>
      <li class="filter-option">3명</li>
    </ul>
  </div>
  
  <div class="filter">
    <button class="filter-toggle">기타</button>
    
    <ul class="filter-menu">
      <li class="filter-option">비건</li>
      <li class="filter-option">스타쉐프</li>
      <li class="filter-option">방송출연</li>
    </ul>
  </div>
</div>

3개의 dropdown form을 만들어줍니다.

  • filter-group: filter들의 집합

  • filter: 하나의 dropdown 기능을 구현하는 form

  • filter-toggle: 클릭 시 filter-menu toggle

  • filter-menu: filter-option이라는 선택사항을 갖고있는 dropdown


CSS

  * {
      padding: 0;
      margin: 0;
    }
    .filter-group {
      display: flex;
      justify-content: start;
      align-items: start;
      margin: 20px;
    }
    .filter {
      position: relative;  // ☆
      margin-right: 8px;
    }
    .filter-toggle {
      display: flex;
      justify-content: center;
      align-items: center;
      padding: 4px 16px;
      background-color: #eeeeee;
      border-radius: 30px;
      border: none;
    }
    .filter-toggle:hover {
      background-color: pink;
    }
    .filter-menu {
      visibility: hidden;  // ★
      position: absolute;  // ☆
      left: 0;  // ☆
      top: 40px;  // ☆
      padding: 8px 0;
      width: 240px;
      max-height: 400px;
      border-radius: 8px;
      background-color: #fff;
      opacity: 0;  // ★
      overflow-y: auto;
      transform: translate3d(0, -20px, 0);  // ★
      transition: all 200ms ease-in-out;  // ★
      box-shadow: 0 4px 20px rgba(63, 65, 80, 0.3);
      list-style-type: none;
    }
    .filter.is-open .filter-menu {
      visibility: visible;  // ★
      transform: translate3d(0, 0, 0);  // ★
      opacity: 1;  // ★
    }
    .filter-option {
      padding: 16px 24px;
    }
  • 여기서 가장 중요한 부분은 ★로 주석된 속성들이다.

    filter-menu가 보이지 않도록 처리한 후,
    filteris-open이 추가되었을 때 filter-menu를 보이게 만드는 것이다.
    transition 속성을 사용해 부드럽게 toggling 할 수 있게 된다.

  • ☆로 주석된 부분은 filter-menu를 적절하게 위치시킨 것이다.

  • 나머지는 원하는 스타일에 맞게 바꿀 수 있다.


JavaScript


// 1번째
const filterButtonList = document.querySelectorAll(".filter-toggle");


// 3번째
function toggleFilterMenu() {
  const filter = this.parentNode;
  const filterOpened = document.querySelector(".filter.is-open");
  
  // 3-1
  if (filterOpened) {
    console.log(1);  // 1번 동작 확인
    filterOpened.classList.remove("is-open");
  }
  
  // 3-2
  if (filter != filterOpened) {
    console.log(2);  // 2번 동작 확인
    filter.classList.add("is-open");
  }
}
 

// 2번째
filterButtonList.forEach(function (button) {
  button.addEventListener("click", toggleFilterMenu);
});
  
  1. filterButtonListfilter-toggle을 미리 선언한다.

  2. filterButtonList를 클릭하면 toggleFilterMenu 함수를 실행시킨다.

foreach는 배열을 하나씩 실행하는 것이다.

filterButtonListquerySelectorAll를 사용해 선언되었으므로, 이것은 Array(배열)이다.

  1. filterthis(=filterButtonList =filter-toggle)의 부모 요소를 선언한다.
    filteris-open을 toggle 할 예정

3-1. 이미 is-open상태인 filter가 있는 경우, is-open을 삭제한다.

3-2. filteris-open상태가 아닌 경우, is-open을 추가한다.


결과

X➡클릭동일한 버튼 클릭다른 버튼 클릭
2번 동작1번동작1번동작➡2번동작

이 기능은 dropdown 뿐만 아니라 radio-box와 같이 여러 선택지 중 하나만 골라야 하는 경우에도 쓰일 수 있다.

profile
🍀 an evenful day, life, journey

0개의 댓글