CSS&JS/⚡Thinkers

custom Select - 이벤트 위임으로 좀 더 깔끔하게

arancia_ 2021. 4. 30. 23:47

aosceno.tistory.com/492

 

커스텀 셀렉트 박스 만들기 - HTML DOM에는 select만 작성하고 vaniila JS로 알아서 DIV 생성

HTML CSS JS 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64..

aosceno.tistory.com

이벤트 위임 방법에 대해 모르던 시절 구현한건 코드가 오질나게 길죠

이벤트 위임을 사용해서 좀 더 줄여봤습니다.

select가 실제로 값이 변경되는지 확인하기 위해서 display:none을 걸지 않은것뿐입니다~

HTML

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1.0"/>
    <title>커스텀 셀렉트 - 이벤트 위임</title>
<link href="custom_select.css" rel="stylesheet" type="text/css"/>
<script src="custom_select.js" defer></script>
</head>
<body>
    <div class="myDiv">
        <select>
            <option>test__01</option>
            <option>test__02</option>
            <option>test__03test__03test__03</option>
        </select>
        <!-- 
        <div class="sel__cont">
            <div class="sel__selected" data-select="result">test__01</div>
            <ul class="sel__ul off">
                <li data-select="item">test__01</li>
                <li data-select="item">test__02</li>
                <li data-select="item">test__03test__03test__03</li>
            </ul>
        </div>
        -->
    </div><!--  -->
    <div class="myDiv">
        <select>
            <option>hello__a</option>
            <option>hello__b</option>
            <option>hello__c</option>
        </select>
    </div><!--  -->
    <div class="myDiv">
        <select>
            <option>world__01</option>
            <option>world__02</option>
            <option>world__03</option>
        </select>
    </div><!--  -->
</body>
</html>
cs

CSS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
@charset "utf-8";
 
*{margin:0;padding:0;}
li{list-style-type:none;}
html,body{font-size:20px;}
 
/* select{display:none;} */
 
.myDiv{
    display:flex;flex-wrap:wrap;
    align-items:center;
    position:relative;
    width:90%;
    margin:1rem auto; padding:1rem;
    background:#eee;}
 
select{opacity:.5;font-family:inherit;font-size:inherit;color:inherit;}
 
.sel__cont{position:relative;}
 
.sel__selected{
    position:relative;
    padding:.5em 3em .5em 1em;
    background:#fff; border:1px solid rgb(42, 55, 112);
    font-weight:bold;color:rgb(21, 20, 46);
    cursor:pointer;}
 
.sel__selected::after{
    content:'';display:block;position:absolute;
    top:calc(50% - .3em);right:.8em;
    transform:rotate(45deg);
    width:.4em;height:.4em;
    border:2px solid #d2d2d2;border-width:0 4px 4px 0;}
 
.sel__ul{
    position:absolute; z-index:10;
    top:99%;left:0;
    border-top:1px solid #d2d2d2;}
.sel__ul.off{display:none;}
 
.sel__ul li{
    position:relative;
    padding:.5em 3em .5em 1em;
    background:#fff;
    border:1px solid #ccc;border-top:none;
    cursor:pointer;}
 
.sel__ul li:hover{
    background:rgb(42, 55, 112);color:#fff;}
cs

JS

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
const select_all = document.getElementsByTagName('SELECT');
 
/* 01.CUSTOM SELECT 자동 생성 */
let sel__cont, sel__selected, sel__ul, sel__li;
let opt_all;
 
 
for(let sel of select_all){ makeSelect(sel); }
 
function makeSelect(sel){
    sel__cont = document.createElement('DIV');
    sel__cont.classList.add('sel__cont');
    sel__cont.setAttribute('data-select''sect')
    
    sel__selected = document.createElement('DIV');
    sel__selected.classList.add('sel__selected');
    sel__selected.setAttribute('data-select','result');
 
    sel__ul = document.createElement('UL');
    sel__ul.classList.add('sel__ul');
    sel__ul.classList.add('off');
 
    opt_all = sel.getElementsByTagName('OPTION');
 
    sel__selected.innerHTML = opt_all[0].innerHTML;
 
    for(let opt of opt_all){
        sel__li = document.createElement('LI');
        sel__li.setAttribute('data-select','item')
        sel__li.innerHTML = opt.innerHTML;
        sel__ul.appendChild(sel__li);}
    
    sel__cont.appendChild(sel__selected);
    sel__cont.appendChild(sel__ul);
 
    sel.parentElement.appendChild(sel__cont);
}//makeSelect
 
/* 02. 이벤트 위임으로 클릭시 받아옴 */
 
const sect_cus = document.querySelectorAll("[data-select='sect']");
const result = document.querySelectorAll("[data-select='result']");
 
for(let sect of sect_cus){
    sect.addEventListener('click',e => startSelect(e));
}
 
function startSelect(e){
    const target = e.target;
    switch(target.dataset.select){
        case "result" : 
            target.nextElementSibling.classList.remove('off');
            break;
        case "item" :
            changeResult(target);
            realSelect(target);
            break;
    }
}//startSelect
 
function changeResult(tg){
    //custom select의 result 값 바꾸기
    const thisVal = tg.innerHTML;
    const thisResult = tg.parentElement.previousElementSibling;
    thisResult.innerHTML = thisVal;
    tg.parentElement.classList.add('off');
}//changeResult
 
function realSelect(tg){
    //찐 select 선택되게 하기
    const realSelect = tg.parentElement.parentElement.previousElementSibling;
    const realOption = realSelect.children;
    const thisIndex = Array.prototype.indexOf.call(tg.parentElement.children, tg);
    realOption[thisIndex].selected = true;
}//realSelect
cs

 

코드 자체는 한 6줄 정도 더 늘어났지만 개인적으로는 함수도 분리하고 그래서인지 더 알아보기 쉽다고 생각해욤

밑에는 소스코드 ^_^

custom_select_이벤트위임.zip
0.00MB