개발자/프로그래머스

[JavaScript] 표 헤더 정렬구현 및 필터 구현

푸루닉 2023. 1. 25. 21:15

보통의 웹페이지는 자바스크립트를 이용해 정렬과 필터를 구현한다.

여러곳에서  자바스크립트를 통한 정렬과 필터를 구현했을 때 장점은

1. 페이지 이동없이 이용가능하다.

2. DB의 부담을 최소화 할 수 있다

  • 보통의 경우 DB까지 접근하기 위해 Dispatcher Survelt을 통해 Controller => Service 등등을 거쳐 DB로 도달하는 과정을 거친다. DB로 정렬을 쉽게 구현할 수 있으나, 그만큼 서버의 부담이 많아지기에 자바스크립트를 통해 처리하는 것이 좋다.

구현 CSS

구현 영상

bandicam 2023-01-25 21-07-33-343.mp4
3.09MB


<html>

<!DOCTYPE html>
<html lang="en">
 <head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>김진형11A</title>
    <link href="김진형11A.css" rel="stylesheet">
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Jua&display=swap" rel="stylesheet">
    <style> 
        body{
            font-family: 'Jua', sans-serif;
            transform : rotate(0.04deg); 
        }     
    </style>
</head>
<body>
  <h1>김진형11A</h1>
  <hr>
      <div id="root">
        <div class="wrap">
            <div class="left">
                <div id="teamFilter">
                    <fieldset>
                       <legend>Team</legend>
                        <p><label><input type="checkbox" name="teamFilter" value="블루"><span>블루</span></label></p>
                        <p><label><input type="checkbox" name="teamFilter" value="레드"><span>레드</span></label></p>
                    </fieldset>
               </div>
                <div id="killDeath">
                    <fieldset>
                       <legend>킬 데스 평균</legend>
                       <div id="killAvg"> 
                        <p><label><input type="checkbox" name="killGraphe"><span>킬 평균이상</span></label></p>
                       </div>
                       <div id="deathAvg" >
                        <p><label><input type="checkbox" name="killGraphe"><span>데스 평균미만</span></label></p>
                       </div>
                    </fieldset>
               </div>
            </div>    
            <div class="right">
                <div id="column">     
                    <div class="item">
                        <div class="team">팀</div>
                        <div class="champion">챔피언</div>
                        <div class="user">유저명</div>
                        <div class="kill">킬</div>
                        <div class="death">데스</div>
                        <div class="assist">어시</div>
                        <div class="damage">피해량</div>
                        <div class="cs">CS</div>
                    </div>
                </div>
                <div id="items"></div>
            </div>
        </div>
    </div>
  
    
</body>
</html>

<JavaScript>

<script type="text/javascript" src="20.js"></script>
    <script>
        const items = document.getElementById('items')
        const item = document.getElementsByClassName('item')

        dataList.forEach(data => {
            const item = `
            <div class="item">
                <div class="team">${data.team}</div>
                <div class="champion">${data.champion}</div>
                <div class="user">${data.user}</div>
                <div class="kill">${data.kill}</div>
                <div class="death">${data.death}</div>
                <div class="assist">${data.assist}</div>
                <div class="damage">${data.damage}</div>
                <div class="cs">${data.cs}</div>
            </div>`
            items.innerHTML += item
        })
        
        const itemArray = Array.from(document.querySelectorAll('#items > .item'))
        
        itemArray.forEach(dto => {
            if(dto.innerHTML.includes('레드')){
               dto.classList.add("red")
               }
            else if(dto.innerHTML.includes('블루')){
                    dto.classList.add("blue")
            }
        })
    </script>
    
<!-- 정렬 -->
    <script>
        const headerLists = document.querySelectorAll('.right > #column > .item > div')
        const dataLists = Array.from(document.querySelectorAll('.right > #items > .item'))
        
        headerLists.forEach(div => div.setAttribute('asc', 1))
        
        function handler(event) {
            const order = event.target.className
            console.log(order)
            
            const asc = +event.target.getAttribute('asc')
            event.target.setAttribute('asc', -asc)
            
            dataLists.sort((a, b) => {
                const aa = a.querySelector('.' + order).innerText
                const bb = b.querySelector('.' + order).innerText
                console.log(aa)
                
                const flag = (order == 'champion' || order == 'team' || order == 'user') ? (aa > bb) : (+aa > +bb)
                const ret = flag ? 1 : -1
                return ret * asc
            })
            dataLists.forEach(data => items.appendChild(data))
            
        }
        
        headerLists.forEach(e => e.onclick = handler)
     </script>
<!-- 블루 레드 필터 -->
     <script>
        const itemList = Array.from(document.querySelectorAll('#items > .item'))
        const boxList = document.querySelectorAll('#teamFilter input[type="checkbox"]')
        
        function handler(event) {
            document.querySelectorAll('input[name="killGraphe"]').forEach(e => e.checked = '')
            const checkBoxArray = Array.from(document.querySelectorAll('#teamFilter input[type="checkbox"]:checked')).map(e => e.value)
            console.log(checkBoxArray)
            
            const result = itemList.filter(data => checkBoxArray.includes(data.querySelector('.team').innerText) == false)
            
            console.log(result.map(e => e.querySelector('.champion').innerText))
            
            
            itemList.forEach(data => data.classList.remove('hidden'))
            
            if(result.length == itemList.length) {
                return
            }
            result.forEach(data => data.classList.add('hidden'))
        }
     
     
        boxList.forEach(box => box.onchange = handler)
    </script>
<!-- 킬 데스 평균 -->
    <script>
        const arrayList = Array.from(document.querySelectorAll('#items > .item'))
        
        const killList = document.querySelectorAll('#killAvg input[type="checkbox"]')
        // 에러 방지를 위한 초기값지정
        let kill = []
        kill = arrayList.map(data => data.querySelector('.kill').innerText)
        // 킬 배열
        const killNum = kill.map((e) => Number(e)) 
        
        // 킬 합계
        const killSum = killNum.reduce(function add(sum, currValue) {
            return sum + currValue
        })
        
        // 킬 평균(반올림)
        const killAvg = Math.round(killSum / killNum.length )
        
        document.querySelector('#killAvg input[type="checkbox"]').value = killAvg
        
        const deathList = document.querySelectorAll('#deathAvg input[type="checkbox"]')
        // 데스평균 시작
        // 에러 방지를 위한 초기값지정
        let death = []
        death = arrayList.map(data => data.querySelector('.death').innerText)
        
        // 데스 배열
        const deathNum = death.map((e) => Number(e))
        
        // 데스 합계
        const deathSum = deathNum.reduce(function add(sum, currValues) {
            return sum + currValues
        })
        
        // 데스 평균
        const deathAvg = Math.round(deathSum / deathNum.length)
        // 벨류값으로 삽입
        document.querySelector('#deathAvg input[type="checkbox"]').value = deathAvg

        // 핸들러
        function handler2(event) {
            document.querySelectorAll('input[name="teamFilter"]').forEach(e => e.checked = '')
            // kill 체크박스 체크여부
            let docKill = document.querySelector('#killAvg input[type="checkbox"]:checked')
            // death 체크박스 체크여부
            let docDeath = document.querySelector('#deathAvg input[type="checkbox"]:checked')
            // kill 평균값
            const killAvgs = killAvg
            let result = []
            let killFilter = []
            
            // 사망평균값
            const deathAvgs = deathAvg
            let result2 = []
            let deathFilter = []
            // 체크됐으면 벨류값 저장
            if(docKill != null){
                killFilter =docKill.value
            }
            if(docDeath != null) {
                deathFilter =docDeath.value
            }
            
            if(docKill != null){
                result = arrayList.filter(data => (data.querySelector('.kill').innerText) <= +killFilter)
            }
            
            if(docDeath != null){
                result2 = arrayList.filter(data => (data.querySelector('.death').innerText) >= +deathFilter)
            }
            // 히든 클래스 제거
            arrayList.forEach(data => data.classList.remove('hidden'))
            
            // 체크안됐으면 원래값 반환
            if(docKill == null && docDeath == null) {
                return
            }
            
            // 담아주기
            if(docKill != null){
                result.forEach(data => data.classList.add('hidden'))
            }
            if(docDeath != null){
                result2.forEach(data => data.classList.add('hidden'))
            }
        }

        killList.forEach(kill => kill.onchange = handler2)
        deathList.forEach(death => death.onchange = handler2)
    </script>

<Css>

@charset "UTF-8"; 
        .wrap {
            display: flex;
            margin: auto;
        }
        .left {
            flex: 1;
            padding: 10px;
            overflow: hidden;
            font-size: 20px;
            text-align: center;
        }
        .left p label {
            user-select: none;
        }
        .left p input[type="checkbox"] {
            margin-right: 20px;
        }
        .right {
            flex: 4;
            padding: 10px;
        }
        #column {
            background-color: #7b7a8e;
            font-weight: bold;
            text-align: center;
        }
        #items {
            height: 80vh;
            overflow-x: hidden;
            overflow-y: scroll;
            text-align: center;
        }
        ::-webkit-scrollbar {
            display: none;
        }
        .item {
            display: flex;
            word-break: break-all;
        }
        #items > .item:hover {
            background-color: #eee;
            cursor: pointer;
        }
        .item > div {
            flex: 1;
            padding: 5px 10px;
            border: 1px solid black;
        }
        .item > div:first-child {
            flex: 0.5;
        }
        .item > div:nth-child(n+3):nth-child(-n+3) {
            flex: 2;
        }
        .item > div:nth-child(n+4):nth-child(-n+6) {
            flex: 0.5;
        }
        #column > .item > div:hover {
            background-color: #eee;
            cursor: pointer;
        }
        .blue {
            background-color: skyblue;
        }
        .red {
            background-color: lightpink;
        }
        .hidden {
            display: none;
        }

        #teamFilter {
            margin-bottom: 37px;
        }

<데이터>

const dataList = [
    {
        user: 'TrynMst',
        champion: '퀸',
        team: '블루',
        kill: 7,
        death: 7,
        assist: 7,
        damage: 27176,
        cs: 173,
    },
    {
        user: '강승우의 제발PLZ',
        champion: '마오카이',
        team: '블루',
        kill: 4,
        death: 6,
        assist: 17,
        damage: 22744,
        cs: 144,
    },
    {
        user: 'Hide on bush',
        champion: '신드라',
        team: '블루',
        kill: 8,
        death: 3,
        assist: 10,
        damage: 42702,
        cs: 274,
    },
    {
        user: '128482031',
        champion: '바루스',
        team: '블루',
        kill: 14,
        death: 5,
        assist: 8,
        damage: 31350,
        cs: 277,
    },
    {
        user: '남궁성훈',
        champion: '카르마',
        team: '블루',
        kill: 0,
        death: 4,
        assist: 27,
        damage: 17341,
        cs: 40,
    },
     {
        user: '망나니박진수',
        champion: '말파이트',
        team: '레드',
        kill: 5,
        death: 4,
        assist: 9,
        damage: 14605,
        cs: 205,
    },
    {
        user: '스물다섯번째밤',
        champion: '그라가스',
        team: '레드',
        kill: 10,
        death: 6,
        assist: 8,
        damage: 24502,
        cs: 184,
    },
    {
        user: 'HIYEON',
        champion: '세트',
        team: '레드',
        kill: 2,
        death: 9,
        assist: 3,
        damage: 8344,
        cs: 115,
    },
    {
        user: 'Every Sec0nd',
        champion: '제리',
        team: '레드',
        kill: 7,
        death: 7,
        assist: 8,
        damage: 20191,
        cs: 296,
    },
    {
        user: '귀여워서 죄송합니다',
        champion: '하이머딩거',
        team: '레드',
        kill: 0,
        death: 7,
        assist: 11,
        damage: 16797,
        cs: 26,
    },
]

백엔드 개발자를 지향하더라도 기본적인 javaScript는 필수적이다.