A Developing Developer

07-2. 이벤트 활용 본문

내일배움캠프 4기/[Javascript]혼자 공부하는 자바스크립트

07-2. 이벤트 활용

H-JJOO 2022. 11. 12. 18:30

  • 이벤트 모델 : 이벤트를 연결하는 방법을 의미
// 이벤트 모델 : 이벤트를 연결하는 방법

// 표준 이벤트 모델 <<-- 이거 쓰면 된다.
document.addEventListener('keyup', () => {

})

// 고전 이벤트 모델
document.body.onkeyup = (e) => {

}

// 인라인 이벤트 모델
const listener = (e) => {

}
  • 이벤트 객체 : 이벤트 리스너의 첫 번째 매개변수로 이벤트와 관련된 정보가 들어있다.

- 키보드 이벤트

 

1. keydown  : 키가 눌릴 때 실행, 꾹 누르고 있을 때도, 입력될 때도 실행
2. keypress : 키가 입력되어있을 때 실행, 웹 브라우저에 따라서 아시아권 문자를 제대로 처리 못할 때 있음
3. keyup    : 키보드에서 키가 떨어질 때 실행, 일반적으로 이거 사용

 

- 남은 글자 수 출력하기

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>남은 글자 수 출력하기</title>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const textarea = document.querySelector('textarea')
            const h1 = document.querySelector('h1')

            textarea.addEventListener('keyup', (e) => {
                const length = textarea.value.length
                h1.textContent = `글자 수: ${length}`
            })
        })
    </script>
</head>
<body>
    <h1></h1>
    <textarea></textarea>
</body>
</html>

textarea 박스에 글자를 타이핑하면
타이핑한 그자수를 알려줌

- 키보드 키 코드 사용하기

         이벤트 속성 이름            설명
              code                입력한 키
              keyCode       입력한 키를 나타내는 숫자
              altKey           Alt 키를 눌렀는지
              ctrlKey         Ctrl 키를 눌렀는지
              shiftKey        Shift 키를 눌렀는지

 

- 키보드 이벤트와 관련된 이벤트 속성

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>키보드 이벤트와 관련된 이벹트 속성</title>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const h1 = document.querySelector('h1')
            const print = (e) => {
                let output = ''
                output += `alt: ${e.altKey}<br>`
                output += `ctrl: ${e.ctrlKey}<br>`
                output += `shift: ${e.shiftKey}<br>`
                output += `code: ${typeof(e.code) != 'undefined' ? e.code : e.keyCode}<br>` // e.code 가 있으면 e.code 를 출력, undefined 라면 e.keyCode 를 출력
                h1.innerHTML = output
            }

            document.addEventListener('keydown', print) // -> 키가 눌릴 때 출력
            document.addEventListener('keyup', print) // -> 키가 떨어질 때 출력
        })
    </script>
</head>
<body>
    <h1></h1>
</body>
</html>

최초에 아무것도 없음
숫자 키 1 누르면 code 에 누른 키 알려줌
왼쪽 alt 키를 누르고 있으면, alt : true, code: AltLeft, 키를 때면 바로 false 로 바뀐다.

- 키로 하트 움직이기

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>키로 하트 움직이기</title>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            // 하트 초기 설정
            const heart = document.querySelector('h1')
            heart.style.position = 'absolute' // style 속성 조작하여 position 값 설정

            // 하트의 이동을 출력하는 기능
            let [x, y] = [0, 0]
            const block = 20
            const print = () => {
                heart.style.left = `${x * block}px`
                heart.style.top = `${y * block}px`
            }
            print()

            // 하트를 이동하는 기능
            const [left, up, right, down] = [37, 38, 39, 40] // 방향키 keycode(키코드) 를 쉽게 사용할 수 있게 변수 사용
            document.body.addEventListener('keydown', (e) => {
                switch (e.keyCode) { // 우짜지
                    case left:
                        x -= 1
                        break
                    case up:
                        y -= 1
                        break
                    case right:
                        x += 1
                        break
                    case down:
                        y += 1
                        break
                }
                print()
            })
        })
    </script>
</head>
<body>
    <h1>❤</h1>
</body>
</html>

최초에 하트가
키보드 방향키로 이동

  • 이벤트 발생 객체 : 이벤트를 발생시킨 객체를 의미. 이벤트 객체의 currentTarget 속석을 활용해서 확인 가능

- 이벤트 발생 객체, 이벤트 리스너를 외부로 빼낸 경우 

// 첫번째 
event.currentTarget // 속성을 사용
// 두번째
this // 키워드를 사용

- 글자 입력 양식 이벤트

// 입력 양식(form) : 사용자로부터 어떠한 입력을 받을 때 사용하는 요소 (input, textarea, button, select, 등등)

- 입력 양식을 기반으로 inch 를 cm 단위로 변환하는 프로그램

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>입력 양식을 기반으로 inch 를 cm 단위로 변환하는 프로그램</title>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const input = document.querySelector('input')
            const button  = document.querySelector('button')
            const p = document.querySelector('p')

            button.addEventListener('click', () => {
                // 입력을 숫자로 변환
                const inch = Number(input.value)

                // 숫자가 아니면 바로 리턴
                if (isNaN(inch)) {
                    p.textContent = '숫자를 입력하세요.'
                    return
                }

                // 변환해서 출력
                const cm = inch * 2.54
                p.textContent = `${cm} cm`
            })
        })
    </script>
</head>
<body>
    <input type="text">inch<br>
    <button>계산</button>
    <p></p>
</body>
</html>

빈칸에 숫자 입력

 

계산 버튼 클릭시 아래에 cm 변환

- 이메일 형식 확인하기

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>이메일 형식 확인하기</title>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const input = document.querySelector('input')
            const p = document.querySelector('p')
            const isEmail = (value) => {
                // 골뱅이를 갖고 있고 && 골뱅이 뒤에 점이 있다면
                return (value.indexOf('@') > 1) && (value.split('@')[1].indexOf('.') > 1)
            }

            input.addEventListener('keyup', (e) => {
                const value = e.currentTarget.value
                if (isEmail(value)) {
                    p.style.color = 'green'
                    p.textContent = `이메일 형식입니다: ${value}`
                } else {
                    p.style.color = 'red'
                    p.textContent = `이메일 형식이 아닙니다: ${value}`
                }
            })
        })
    </script>
</head>
<body>
    <input type="text">
    <p></p>
</body>
</html>

아무거나 입력하면 빨간색
abc@def.ghi 이메일 형식으로 입력시 초록색

- 드롭다운 목록 활용하기, select 태그

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>기본 select 태그</title>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const select = document.querySelector('select')
            const p = document.querySelector('p')

            select.addEventListener('change', (e) => {
                const options = e.currentTarget.options
                const index = e.currentTarget.options.selectedIndex

                p.textContent = `선택: ${options[index].textContent}` // 선택한 option 태그를 추출
            })
        })
    </script>
</head>
<body>
    <select>
        <option>-----</option>
        <option>떡볶이</option>
        <option>순대</option>
        <option>오뎅</option>
        <option>튀김</option>
    </select>
    <p>선택: -----</p>
</body>
</html>

최초
드롭다운 형식 클릭하면 목록나오고 클릭!
선택한 결과

- multiple select 태그

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>multiple select 태그</title>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const select = document.querySelector('select')
            const p = document.querySelector('p')

            select.addEventListener('change', (e) => {
                const options = e.currentTarget.options
                const list = []
                for (const option of options) { // options 속성에는 forEach() 메소드가 없어서 이런식으로 반복문 돌려야함
                    if (option.selected) {
                        list.push(option.textContent)
                    }
                }
                p.textContent = `선택: ${list.join(',')}` // 선택한 option 태그를 추출
            })
        })
    </script>
</head>
<body>
    <select multiple>
        <option>떡볶이</option>
        <option>순대</option>
        <option>오뎅</option>
        <option>튀김</option>
    </select>
    <p></p>
</body>
</html>

최초
하나만 클릭
Ctrl 키 눌러서 중복 선택

- cm 단위를 여러 단위로 변환하는 프로그램

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>cm 단위를 여러 단위로 변환하는 프로그램</title>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            let 현재값
            let 변환상수 = 10

            const select = document.querySelector('select')
            const input = document.querySelector('input')
            const span = document.querySelector('span')

            const calculate = () => {
                span.textContent = (현재값 * 변환상수).toFixed(2) // toFixed(n) : 소숫점 n 번째 까지 출력
            }

            select.addEventListener('change', (e) => {
                const options = e.currentTarget.options
                const index = e.currentTarget.options.selectedIndex
                변환상수 = Number(options[index].value) // 선택시 항목의 value 속성 추출
                calculate()
            })

            input.addEventListener('keyup', (e) => {
                현재값 = Number(e.currentTarget.value) // 값을 입력하면 현재 값을 추출
                calculate()
            })
        })
    </script>
</head>
<body>
    <input type="text"> cm =
    <span></span>
    <select>
        <option value="10">mm</option>
        <option value="0.01">m</option>
        <option value="0.393701">inch</option>
    </select>
</body>
</html>

최초
숫자 입력
왼쪽 드롭다운 클릭 후 원하는 단위 클릭

- 체크 박스 활용하기, checked 활용, 체크 상태일 때만 타이머를 증가시키는 프로그램

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>체크 박스 활용하기 (체크 상태일 때만 타이머를 증가시키는 프로그램)</title>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            let [timer, timerId] = [0, 0]
            const h1 = document.querySelector('h1')
            const checkbox = document.querySelector('input')

            checkbox.addEventListener('change', (e) => {
                if (e.currentTarget.checked) {
                    // 체크 상태
                    timerId = setInterval(() => {
                        timer += 1
                        h1.textContent = `${timer}초`
                    }, 1 * 1000)
                } else {
                    // 체크 해제 상태
                    clearInterval(timerId)
                }

            })
        })
    </script>
</head>
<body>
    <input type="checkbox">
    <span>타이머 활성화</span>
    <h1></h1>
</body>
</html>
// change 이벤트가 발생했을 때 체크 박스의 체크 상태를 확인하고 setInterval() 함수 또는 clearInterval() 함수를 실행

최초
체크 박스 클릭시 타이머 가동

- 라디오 버튼 활용하기

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>라디오 버튼 사용해보기</title>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            // 문서 객체 추출하기
            const output = document.querySelector('#output')
            const radios = document.querySelectorAll('[name=fruit]')

            // 모든 라디오 버튼에
            radios.forEach((radio) => {
                // 이벤트 연결
                radio.addEventListener('change', (e) => {
                    const current = e.currentTarget
                    if (current.value === '기타') {
                        output.textContent = `좋아하는 과일은 무엇인가요?`
                    } else if (current.checked) {
                        output.textContent = `좋아하는 과일은 ${current.value}이시군요!`
                    }
                })
            })
        })
    </script>
</head>
<body>
    <h3># 좋아하는 과일을 선택해 주세요</h3>
    <label>
        <input type="radio" name="fruit" value="사과">
        <span>사과</span>
    </label>
    <label>
        <input type="radio" name="fruit" value="바나나">
        <span>바나나</span>
    </label>
    <label>
        <input type="radio" name="fruit" value="귤">
        <span>귤</span>
    </label>
    <label>
        <input type="radio" name="fruit" value="딸기">
        <span>딸기</span>
    </label>
    <label>
        <input type="radio" name="fruit" value="기타">
        <span>기타</span>
    </label>
    <hr>
    <h3 id="output"></h3>
</body>
</html>

최초
과일 클릭시 멘트
기타 클릭시 멘트

- 기본 이벤트 막기, 이미지 마우스 오른쪽 버튼 클릭 막기(불펌 방지)

 preventDefault()
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>이미지 마우스 오른쪽 버튼 클릭 막기</title>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const imgs = document.querySelectorAll('img')

            imgs.forEach((img) => {
                img.addEventListener('contextmenu', (e) => {
                    e.preventDefault() // 컨텍스트 메뉴를 출력하는 기본 이벤트 제거
                })
            })
        })
    </script>
</head>
<body>
    <img src="http://placekitten.com/300/300" alt="">
</body>
</html>

사진에 마우스 오른쪽 이벤트 막힘

- 체크 때만 링크 활성화하기

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>체크 때만 링크 활성화하기</title>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            let status = false

            const checkbox = document.querySelector('input')
            checkbox.addEventListener('change', (e) => {
                status = e.currentTarget.checked
            })

            const link = document.querySelector('a')
            link.addEventListener('click', (e) => {
                if (!status) {
                    e.preventDefault()
                }
            })
        })
    </script>
</head>
<body>
    <label>
        <input type="checkbox">
        <span>링크 활성화</span>
    </label>
    <br>
    <a href="https://icepri3535.tistory.com/">개발일지</a>
</body>
</html>

체크 하지 않고 클릭하면 이동X
체크하고 클릭하면
해당 링크 이동

- 할 일 목록 만들기

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>할 일 목록 만들기</title>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            // 문서 객체 가져오기
            const input = document.querySelector('#todo')
            const todoList = document.querySelector('#todo-list')
            const addButtuon = document.querySelector('#add-button')

            // 변수 선언
            let keyCount = 0 // 제거하기 쉽게 만든 변수

            // 함수 선언
            const addTodo = () => {
                // 입력 양식에 내용입 없으면 추가 X
                if (input.value.trim() === '') {
                    alert('할 일을 입력해주세요.')
                    return
                }

                // 문서 객체 설정
                const item = document.createElement('div')
                const checkbox = document.createElement('input')
                const text = document.createElement('span')
                const button = document.createElement('button')

                // 문서 객체를 식별할 키 생성
                const key = keyCount // removeTodo() 함수에서 문서 객체를 쉽게 제거하기 위한 용도로 만든 변수
                keyCount += 1

                // item 객체를 조작하고 추가
                item.setAttribute('data-key', key)
                item.appendChild(checkbox)
                item.appendChild(text)
                item.appendChild(button)
                todoList.appendChild(item)

                // checkbox 객체를 조작
                checkbox.type = 'checkbox'
                checkbox.addEventListener('change', (e) => {
                    item.style.textDecoration = e.target.checked ? 'line-through' : ''
                })

                // text 객체를 조작
                text.textContent = input.value // span 형태를 구성

                // button 객체를 조작
                button.textContent = '제거하기'
                button.addEventListener('click', () => {
                    removeTodo(key)
                })

                // 입력 양식의 내용을 비운다.
                input.value = ''
            }

            const removeTodo = (key) => {
                // 식별 키로 문서 객체를 제거
                const item = document.querySelector(`[data-key="${key}"]`) // 위에서 지정한 <div data-key="숫자">를 기반으로 요소를 찾고 제거
                todoList.removeChild(item)
            }

            // 이벤트 연결
            addButtuon.addEventListener('click', addTodo)
            input.addEventListener('keyup', (e) => {
                // 입력 양식에서 Enter 키를 누르면 바로 addTodo() 함수를 호출
                const ENTER = 13
                if (e.keyCode === ENTER) {
                    addTodo()
                }
            })
        })
    </script>
</head>
<body>
    <h1>할 일 목록</h1>
    <input id="todo">
    <button id="add-button">추가하기</button>
    <div id="todo-list"></div>
</body>
</html>

최초
할일 타이핑
추가하기 버튼 누르면 등록
마무리 하고 체크 누르면 삭(제)선
제거하기 버튼 누르면 제거

- 타이머로 구현한 남은 글자 수 세기

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>글자 수 출력하기</title>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const textarea = document.querySelector('textarea')
            const h1 = document.querySelector('h1')
            let timerId

            textarea.addEventListener('focus', (e) => { // focus : 입력 양식 활성화
                timerId = setInterval(() => {
                    const length = textarea.value.length
                    h1.textContent = `글자 수 : ${length}`
                }, 50)
            })
            textarea.addEventListener('blur', (e) => { // blur : 입력 양식 비활성화
                clearInterval(timerId)
            })
        })
    </script>
</head>
<body>
    <h1></h1>
    <textarea></textarea>
</body>
</html>

최초
타이핑

결과는 '남은 글자 수 출력하기' 와 다르지 않지만, focus 이벤트와  blur 이벤트를 활용해서 작성!

 

- focus, blur 이벤트 : 입력 양식에 초점을 맞춘 경우(활성화 상태)와 초점을 해제한 경우(비활성화 상태)에 발생하는 이벤트

 

- localStorage 객체? : 웹 브라우저에 데이터를 저장하는 객체

  • localStorage.getItem(키) : 저장된 값을 추룰, 없으면 undefined 나옴, 객체의 속성을 추출하는 일반적인 형태로 localStorage.키 또는 localStorage[키] 형태로 사용
  • localStorage.setITem(키, 값) : 값을 저장, 전과 마찬가지로 객체에 속성을 저장하는 일반적인 형태 사용 가능
  • localStorage.removeItem(키) : 특정 키의 값을 제거
  • localStorage.clear() : 저장된 모든 값을 제거


- 웹 브라우저에 데이터를 저장하는 localStorage 객체 활용하기

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>웹 브러우저에 데이터를 저장하는 localStorage 객체와 활용하기</title>
    <script>
        document.addEventListener('DOMContentLoaded', () => {
            const p = document.querySelector('p')
            const input = document.querySelector('input')
            const button = document.querySelector('button')

            const saveValue = localStorage.getItem('input') // 값을 읽을 때
            // localStorage.input 도 가능
            if (saveValue) {
                input.value = saveValue
                p.textContent = `이전 실행 때의 마지막 값: ${saveValue}`
            }

            input.addEventListener('keyup', (e) => {
                const value = e.currentTarget.value
                localStorage.setItem('input', value) // 값을 저장할 때
                // localStorage.input = value 도 가능
            })

            button.addEventListener('click', (e) => {
                localStorage.clear() // 모든 값 제거
                input.value = ''
            })
        })
    </script>
</head>
<body>
    <p></p>
    <button>지우기</button>
    <input type="text">
</body>
</html>

최초
타이핑 후 새로고침
마지막 값 출력

 

지우기 버튼 누르고 새로고침하면 없어짐

============================================================================================

출처 : 혼자 공부하는 자바스크립트

============================================================================================

개발일지 정신없이 작성하다보니 1,2 시간 후딱간거 같다

 

오늘내일 해서 ch 8, 9 도 후딱 마무리해야하는데...

 

게을러 터졌군...

 

다음 주 부터 본격적인 9 to 9 이 걱정된다.