JavaScript

[javascript] classList를 사용한 커스텀 select 메뉴 만들기

teamnova 2023. 1. 10. 21:02
728x90

안녕하세요. 오늘은 classList를 select 메뉴를 커스텀해서 아래와 같이 만들어보겠습니다. 

 

커스텀 메뉴 완성본

우선 만들고자 하는 커스텀 내용은

1.option들을 클릭시에 볼 수있도록 하게 만들고

2. option 선택 시 선택된 내용이 select에 적용되고(1,2 classList 사용)

3.select 메뉴를 만드는데 내용이 많아 option이 한없이 길어지는 경우, 검색을 통해 찾을 수 있게 만든다.

입니다. 오늘은 이 중 1,2번까지 진행해보겠습니다.

 

우선 classList에 대해 알아봅시다. classList의 add,remove,replace,toggle을 통해 클래스 값을 수정할 수 있습니다. 사용예제는 아래에 첨부하였으니 자세한 내용은 아래 링크를 통해 참고바랍니다.

https://developer.mozilla.org/en-US/docs/Web/API/Element/classList

 

Element.classList - Web APIs | MDN

The Element.classList is a read-only property that returns a live DOMTokenList collection of the class attributes of the element. This can then be used to manipulate the class list.

developer.mozilla.org

//출처 https://developer.mozilla.org/en-US/docs/Web/API/Element/classList

const div = document.createElement("div");//div태그 생성.
div.className = "foo";
//생성된 div 태그에 clasName 부여.
// our starting state: <div class="foo"></div>

div.classList.remove("foo");//div태그의 클래스"foo"삭제
div.classList.add("anotherclass");
//div태그에 새로운 클래스 추가.
// <div class="anotherclass"></div>

div.classList.add("foo", "bar", "baz");
div.classList.remove("foo", "bar", "baz");
//여러개의 태그명을 추가 또는 삭제할 수 있음.

// toggle을 사용하면 클래스명 추가삭제를 on off처럼 적용할 수 있다.
div.classList.toggle("visible");

// add/remove visible, depending on test conditional, i less than 10
//횟수를 지정할 수 있음.
div.classList.toggle("visible", i < 10);

//contains를 사용해 특정 클래스명이 있는지 확인할 수 있음.
console.log(div.classList.contains("foo"));

// add or remove multiple classes using spread syntax
// spread syntax(전개구문)을 사용해서 배열형태로 클래스명을 추가 또는 삭제할 수 있음.
const cls = ["foo", "bar"];
div.classList.add(...cls);
div.classList.remove(...cls);

//특정 클래스명을 지정하는 클래스명으로 변경. foo => bar
div.classList.replace("foo", "bar");

 

 

그럼이제 classList를 사용하여 위 gif와 같이 커스텀 select 메뉴를 만들어보겠습니다. 

 

custom_menu.html 

<div class="wrapper">
  <div class="select">
    <span>나라를 선택해주세요</span>
    <span class="material-icons">expand_more</span>
  </div><!--select-->
  <div class="content">
    <div class="search-box">
      <span class="material-icons">search</span>     
      <input class="filter" type="text" placeholder="검색">
    </div><!--search box-->
    <ul class="options">
    </ul>
  </div><!--content-->
</div><!--wrapper-->
  <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">

custom_menu.css

*{
  margin:0;
  padding:0;
  box-sizing: border-box;
}

.wrapper{
  width: 360px;
  margin:20px auto 0;
}
.select, .options li{
  display:flex;
  cursor:pointer;
  align-items:center;
}
.select{
  height:60px;
  padding:0 20px;
  background:#4285f4;
  border-radius:10px;
  color:#ffffff;
  justify-content:space-between;
}
.content{
  display:none;/*원래 안보이도록 설정*/
  background:#ffffff;
  margin-top:5px;
  padding:15px;
  border-radius:10px;
}

.active .content {/*wrapper에 active클래스가 추가되면 보이도록하기*/
  display:block;
}

.content .search-box{
  position: relative;
}
.search-box .material-icons{
  left:15px;
  line-height:53px;
  position: absolute;
}
.search-box input{
  height:53px;
  width:100%;
  outline:none;
  font-size:17px;
  padding:0 10px 0 43px;
  border: 1px solid #aabb;
  border-radius:10px;
}
.content .options{
  margin-top:10px;
  max-height:250px;
  overflow-y:auto;
}
.options::-webkit-scrollbar-track{
  backgound:#f1f1f1;
  border-radius:25px;
}

.options::-webkit-scrollbar-thumb{
  backgound:#ccc;
  border-radius:25px;
}

.options li{
  height:50px;
  padding:0 13px;
  border-radius:7px;
}
.options li:hover{
   background:#f2f2f2;
}

custom_menu.js

const wrapper = document.querySelector('.wrapper');//전체 frame
const select = document.querySelector('.select');//선택영역

let countries = 
["가나","가봉","감비아","과테말라","그레나다","그리스","기니","네덜란드","대한민국"];
//위 countries를 li에 세팅

select.addEventListener('click',function(){//선택영역 클릭시
  wrapper.classList.toggle('active');
  //classList api로 클래스명 추가/삭제 반복.
  //css클래스 설정을 통해 클래스 추가,삭제될 때마다 보이고 안보이고가 결정됨.
});

addLi();

function addLi(){ //ul내부에 countries 배열에 있는 모든 국가들 추가하기.
  countries.forEach(country=> {
    let li = `<li onclick="changeClickedName(this)">${country}</li>`;
    options.insertAdjacentHTML("beforeend",li);
  })
}

완성되면 아래와 같이 클릭시 option들을 보여주는 것을 확인할 수 있습니다.

 

 

자세한 내용은 아래 링크 추가적으로 참고 바랍니다.

https://developer.mozilla.org/ko/docs/Web/API/Element/insertAdjacentHTML

 

Element.insertAdjacentHTML() - Web API | MDN

insertAdjacentHTML() 메서드는 HTML or XML 같은 특정 텍스트를 파싱하고, 특정 위치에 DOM tree 안에 원하는 node들을 추가 한다. 이미 사용중인 element 는 다시 파싱하지 않는다. 그러므로 element 안에 존재하

developer.mozilla.org

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

 

Array.prototype.forEach() - JavaScript | MDN

forEach() 메서드는 주어진 함수를 배열 요소 각각에 대해 실행합니다.

developer.mozilla.org