Hello,

kok nae-ga ha-myun an-dweneun MAGIC...🧚

웹 프로그래밍/공부일지

[ JavaScript ] Select박스를 검색가능하게 만들어보자 :P

✿도담도담 2021. 3. 29. 18:33

예전에 업무를 하면서 Vue를 이용해 우선 만들었던 기능을
순수 JavaScript로 만들 기회가 또 생겨 확장성을 더 생각해서 구현해 보았다.
jQuery에 익숙해져있다가 순수 JavaScript로만 하려니 생각보다 힘들었다😥

 

내가 만들고자 한건 우리가 일반적으로 쓰는 select box를 사용하면

아래와 같이 검색 선택 박스로 바뀌는 것이다.

마우스 이벤트로도 구현을 했고

아래, 위 키를 눌러서 엔터를 누르면 선택 되도록 키이벤트도 구현했다!

결과물🥰

 


코드 리뷰
function setCustomSelect (instance, list, width){
  
  var box = document.createElement("span");
  var input = document.createElement("input");
  var ul = document.createElement("ul");  
  
  input.type = "text";
  input.value = instance.options[instance.selectedIndex].text; // set init value
  input.style.width = width + "px";
  input.addEventListener('click', function() { event.stopPropagation(); showSearchList(ul, true); });
  input.addEventListener('keyup', function(e) { searchSearchList(e, ul); });
  
  ul.style.width = width + "px";
  for (var i=0; i<list.length; i++) {
    // add search list item    
    var item = list[i];
    var li = document.createElement("li");
    li.innerText = list[i].name;
    li.dataset.id = list[i].id;
    li.addEventListener('click', function() { event.stopPropagation(); selectSearchList(this); });
    ul.appendChild(li);
  }
  
  box.appendChild(input);
  box.appendChild(ul);
  box.className = "custom-box";
  instance.style.display = "none";
  instance.parentNode.insertBefore(box, instance);
}

몇몇 코드만 설명하고 다른부분들은 깃헙을 참고바란다.
우선 함수 setCustomSelect에서 select박스를 input태그와 ul로 변경해 주는 작업을 한다.

기존에 selected 되어있던 option의 텍스트를 초기 값으로 넣어주도록 되어있다. (line 7)

태그들을 만들어주고 이벤트 등록 해주는 코드라 보시는데 크게 어려울 것 없다 생각하고 넘어가겠다 :)

 

function searchSearchList (e, instance) {
	
	let keycode = e.code;	
	var keywords = e.target.value.split(" ");
	var options  = instance.getElementsByTagName("li");	
	var changedText = "<i>$&</i>";	

	if (keycode == 'ArrowDown' || keycode == 'ArrowUp') {
		setFocusCustomItem(keycode, instance);
		return;
	}
	else if (keycode == 'Enter') {
		selectSearchList(instance.getElementsByClassName("focus")[0]);
		return;
	}
		
	for (var i=0; i<options.length; i++) {
		
		var count = 0;
		var option_name = options[i].innerText;
		for (var j=0; j<keywords.length; j++) {
			
			var keyword = keywords[j];
			if (keyword == "") {
				count++;
				continue;
			}


			if( option_name.match(new RegExp(keyword, "i")) ){
				count++;
			}
		}
		
		if (count == keywords.length) {
			// show
			var regEx = new RegExp( keywords.join('|'), "gi" );
			options[i].innerHTML = option_name.replace(regEx, changedText);
			options[i].className = "";			
		} else {
			// hide
			options[i].className = "off";
		}
	}
}

input태그의 keydown이벤트 부분이다.

화살표 키를 누르면 검색리스트에서 아이템을 focus해주도록,

엔터키를 누르면 리스트를 선택해주는 이벤트와 같은 함수로 넘어간다.

이 외의 키를 입력했다면 검색되어 필터링된 아이템을 표시해준다.

 

function selectSearchList (instance) {
	
	var id = instance.dataset.id;
	var name = instance.innerText;
	var inp = focus_select.parentNode.getElementsByTagName("input")[0];
	var select = focus_select.parentNode.nextSibling;
	
	select.value = id;
	inp.value = name;	
	focus_select.className = '';
	focus_select.parentNode.nextSibling.onchange();
}

선택 했을때의 이벤트이다.

input태그에 해당 값의 text를 표시해주고,

기존 select박스에 value값을 변경한 뒤에 select박스의 onchange이벤트를 실행시킨다.

 

하기전엔 언제 다하나 했는데 막상 해보니 크게 또 어려운 부분은 없어서...

코드를 보다 보면 이해 되리라 생각한다 😀

 

깃헙 : github.com/hyeonmin-dev/search-select