웹개발 수업/JavaScript

[Day +62 / Java Script]기초(13. 문서 수정, 14. BOM, 15. 이벤트)

Chole Woo 2021. 9. 17. 20:27
210917 금

 

 

13) 문서 수정

<!DOCTYPE html>
<html lang="ko">

<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>13_문서 수정</title>

    <style>
        .area {
            background: lightgray;
            border: 1px solid black;
            min-height: 200px;
        }

        .circle{
            background: yellow;
            width : 200px;
            border-radius: 50%;
        }
    </style>
</head>

<body>
    <h1>문서 수정</h1>
    <h3>1. 노드 생성</h3>
    <p>
        documnet.createElement(tag) : 태그 이름을 사용해 새로운 요소를 만듦<br>
        document.createTextNode(value) : 텍스트 노드를 만듦(잘 쓰이지 않음)<br>
        element.cloneNode(deep) : 요소를 복제함. deep == true일 경우 모든 자손 요소도 복제됨
    </p>

    <h3>2. 노드 삽입, 삭제</h3>
    <p>
        node.append(노드나 문자열) : node 끝에 노드나 문자열을 삽입<br>
        node.prepend(노드나 문자열) : node 맨 앞에 노드나 문자열을 삽입<br>
        node.before(노드나 문자열) : node 이전에 노드나 문자열을 삽입<br>
        node.after(노드나 문자열) : node 다음에 노드나 문자열을 삽입<br>
        node.replaceWith(노드나 문자열) : node를 노드나 문자열로 대체<br>
        node.remove() : node를 제거
    </p>


    <h3>3. li(텍스트 노드가 있는) 노드 생성</h3>
    <button onclick="test1()">실행확인</button>
    <ul id="list">
        <li>기존 목록1</li>
        <li>기존 목록2</li>
        <li>기존 목록3</li>
    </ul>
    <script>
        function test1() {
            let list = document.querySelector("#list");

            // list의 앞 뒤에 문자열 삽입
            list.before('before');
            list.after('after');
            // 답 : 버튼 누르면 화면에 before, after 텍스트 삽입됨

            //li 노드 생성
            let newList1 = document.createElement('li');
            let newList2 = document.createElement('li');

            // 각 li의 내부 텍스트 설정 
            // 방법1)
            let text = document.createTextNode('새로운 목록 1');
            newList1.append(text);
            // 방법2)
            newList2.textContent = '새로운 목록2';
            // *textContent : node나 element의 텍스트값을 읽어오고 설정할 수 있다

            // ul 태그의 내부에 첫/마지막 항목으로 삽입
            list.append(newList1);
            // 답 : 버튼을 누르면 화면 상에 기존 목록의 가장 뒤에 새로운 목록1이 추가된다.
            
            list.prepend(newList2);
            // 답 : 버튼을 누르면 화면 상에 기존 목록의 가장 앞에 새로운 목록2가 추가된다.

        }
    </script>


    <h3>4. 이미지(텍스트 노드가 없는) 노드 생성</h3>
    <button onclick="test2()">실행 확인</button>
    <div id="area2" class="area"></div>
    <script>
        function test2() {
            // img노드 생성
            let imgTest = document.createElement('img');

            // img 속성 지정
            imgTest.src = 'https://www.iei.or.kr/resources/images/main/main_renewal/top_logo_s.jpg';
            imgTest.width = '200';
            imgTest.height = '100';

            document.getElementById('area2').append(imgTest);
            // 실행 확인 버튼 누르면 노드에 이미지 추가됨
        }
    </script>

    <h3>5. 노드 삭제</h3>
    <button onclick="test3();">맨 앞 이미지 삭제</button>
    <script>
        function test3() {
            // 삭제할 노드 찾기(img 중 첫번째 리턴)
            let img = document.querySelector('img');

            // 존재할 경우(null이 아닌 경우)만 삭제
            if (img)
                img.remove();
        }
    </script>


    <h3>6. 노드 복제</h3>
    <button onclick="test4();">실행 확인</button>
    <ul class="copy">ul 영역
        <li>li 영역</li>
    </ul>
    <script>
        function test4() {
            let origin = document.querySelector('.copy');

            let cloneFalse = origin.cloneNode(false);
            // 의미 : 자식노드는 복사하지 않는다(기본값이 false)
            let cloneTrue = origin.cloneNode(true);
            // 의미 : 자식노드도 복사한다(true)
            origin.before(cloneFalse);
            origin.after(cloneTrue);
        }
    </script>


    <h3>7. 노드 대체</h3>
    <button onclick="test5();">실행 확인</button>
    <script>
        function test5() {
            // 대체할 노드 찾기(img 중 첫번째)
            let img = document.querySelector('img');

            // 존재할 경우 (null이 아닌 경우)만 대체
            if (img) img.replaceWith("<b>이미지 있던 곳</b>");
            // 그냥 텍스트로서 기능하고 있다
            // => 태그가 아닌 문자열로 인식
        }
    </script>


    <h3>8. insertAdjacentHTML</h3>
    <p>
        element.insertAdjacentHTML(where, html)
        : where은 element 기본 상대 위치,
        html은 문자열로 태그 포함한 문자열은 이스케이프 처리 없이 태그로 기능함<br>
        'beforebegin' : element 바로 앞에 html 삽입<br>
        'afterbegin' : element의 첫 번째 자식 요소 바로 앞에 html 삽입<br><br>
        
        'beforeend' : element 마지막 자식 요소 바로 다음에 html 삽입<br>
        'afterend' : element 바로 다음에 html 삽입
    </p>


    <h3>9. 노드 대체 수정</h3>
    <button onclick="test6();">실행 확인</button>
    <script>
        function test6() {
            // 대체 할 노드 찾기(img 태그 중 첫번째 리턴)
            let img = document.querySelector('img');

            // 존재할 경우(null이 아닌 경우)만
            if (img) {
                // 바로 앞에 삽입
                img.insertAdjacentHTML('beforebegin', '<b>이미지가 있던 곳</b>');
                img.remove();
            }
        }
    </script>


    <h3>10. 요소 위치 바꾸기</h3>
    <div class = "first">first</div>
    <div class = "second">second</div>
    <p>
        모든 노드 삽입 메소드는 자동으로 기존에 있던 노드를 삭제하고
        새로운 곳으로 노드를 옮기기 때문에 요소 노드를 다른 곳으로 옮길 때
        기존에 있던 노드를 지울 필요가 없음
    </p>

    <button onclick="test7();">실행 확인</button>
    <script>
        function test7(){
            let first = document.querySelector(".first");
            let second = document.querySelector(".second");
            // second 뒤에 first 삽입
            second.after(first);
        }
    </script>


    <h3>11. 스타일 지정</h3>
    <p>
        프로퍼티 style은 HTML 속성 style에 쓰인 값에 대응되는 객체<br>
        여러 단어를 이어서 만든 프로퍼티는 카멜 표기법을 사용해 이름 지어짐<br>
        ex.background-color => backgroundColor, border-radius => borderRadius<br>
        style 수정 방법에는 class를 변경/추가하여 수정하는 방법도 있음<br>
        className : class 속성에 대응. 대입시 클래스 문자열 전체가 바뀜<br>
        classList : 클래스 하나만 조작할 수 있는 add/remove/toggle 메소드가 있음
    </p>

    <button onclick="test8();">style 수정</button>
    <button onclick="test9();">class 수정</button>
    <div id = "area4" class="area"></div>
    <script>
        // 방법1) 직접 지정 방법
        function test8(){
            let area4 = document.querySelector("#area4");
            area4.style.width = '200px';
            area4.style.backgroundColor = 'yellow';
            area4.style.borderRadius = '50%';
        }

        // 방법2) className 지정 방법, 위에 스타일에 적혀 있음
        function test9(){
            let area4 = document.querySelector("#area4");
            
            // area4.className = 'circle';
            // 전체 클래스명이 circle로 변경되어 height값이 0이 되어 확인 불가
            
            area4.classList.add('circle');
        }
    </script>



</body>

</html>

 

 

14) BOM

<!DOCTYPE html>
<html lang="ko">
<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>14_BOM</title>
    <style>
    .area{
        background : lightgray;
        border : 1px solid black;
        width : 300px;
        height: 100px;
        font-size: 50px;
        color :red;
    }

    .area-big{
        background : lightgray;
        border : 1px solid black;
        min-height : 300px
    }
</style>
</head>
<body>
    <h1>객체</h1>
    <p>window 객체는 자바스크립트의 최상위 객체이며 BOM과 DOM으로 나뉨</p>
    <h3>1. BOM(Browser Object Model)</h3>
    <p>
        location 객체, navigator 객체, history 객체, screen 객체 등
    </p>

    <!-- DOM : Document Object Model / XML이나 HTML 문서에 접근하기 위한 일종의 인터페이스입니다 -->
    
    <h3>2. window 객체</h3>
    <p>브라우저 창에 대한 설정을 하는 객체</p>
    <button onclick="test1();">13_문서수정</button>
    <button onclick="test2();">네이버</button>

    <script>
        function test1(){
            // window.open('주소', '이름 또는 open 방식', '형태');
            window.open('13_문서수정.html', 'popup', 'width=1080, height=800');
            // 같은 디렉토리에 있으므로 파일명만 써도 열 수 있음
            // 창의 이름 지정시 동일한 이름으로 다시 open을 하면 기존의 열린 창에서 열림
            // 다른 이름을 사용하면 또 다른 새창이 열림

            // alert, prompt, confirm 등은 윈도우 객체가 가지고 있음
            // (최상위 객체라서 수정 가능)
        }

        function test2(){
            window.open('https://www.naver.com', '_self');
            // _blank : 새창으로 열림(기본 값), _self : 현재 페이지를 대체
        }
    </script>


    <h3>3. window 객체의 timer 메소드</h3>
    <h4>setTimeout</h4>
    <button onclick="test3();">실행 확인</button>

    <script>
        function test3(){
            let myWindow = window.open();

            // setTime(func, delay)
            // func : 실행 함수, delay : 대기 시간. 밀리세컨 단위.
            // 창객체.close() : 창 닫기
            setTimeout(() => myWindow.close(), 3000);
            // 답 : 새창이 생겼다가 3초 후에 닫힘
        }
        
    </script>


    <h3>4. setInterval 현재 시간</h3>
    <button onclick="test4();">실행 확인</button>
    <div id="area1" class="area"></div>
    <script>
        function test4(){
            let area1 = document.querySelector('#area1');

            setInterval(function(){
                let date = new Date();
                // 의미 : 현재 시간
                area1.textContent = date.getHours() + " : " + date.getMinutes() + " : " + date.getSeconds();
            },1000);
        }

    </script>


    <h4>5. clearInterval 스탑 워치</h4>
    <button onclick="test5();">실행</button>
    <button onclick="test5_2();">정지</button>
    <div id="area2" class="area"></div>
    <script>
        let timer;
        function test5(){
            let area2 = document.querySelector("#area2");
            let count = 0;

            if(timer == undefined){

                timer = setInterval(function(){
                    area2.textContent = parseInt(count/100/60%60) + " : "
                    + parseInt(count/100%60) + " : "
                    + (count%100);
                    count++;
                }, 10)
            }
                // *밀리세컨드 : 1000분의 1초
        }
        function test5_2(){
            
            clearInterval(timer);
            timer = undefined;
        }

    </script>


    <h1>BOM(Brower Object Model)</h1>
    <h3>1. screen 객체</h3>
    <p>
        웹 브라우저 화면이 아닌 운영 체제 화면의 속성을 가지는 객체
    </p>

    <button onclick="test6();">실행 확인</button>
    <script>
        function test6(){
            let width = screen.width;
            let height = screen.height;

            let child = window.open("", "", "width=800, height=500");
            child.resizeTo(width, height);

            let interval = setInterval(function(){
                            if(child==null||child.closed){
                                clearInterval(interval);
                            }

            // * ||(or) : 하나라도 true인 경우 true 반환
            // 즉, "true || false == true"가 됨
            // * &&(and) : 모두 true인 경우만 true를 반환합니다. 
            // 즉, “true && true == true, true && false == false”가 됨

                child.resizeBy(-20, -20);
                // 의미 : 얼마씩 줄어들겠다
                child.moveBy(10, 10);
                // 의미 : 얼마씩 움직이겠다.
            }, 500);
            // 0.5초에 한번씩

            // if가 없으면
            // 창을 닫았을 때 오류 생김 : Uncaught TypeError: child.resizeBy is not a function
            // (당연한 현상)


            console.log("화면 너비 : " + screen.width);
            // 답 화면 너비 : 1536
            console.log("화면 너비 : " + screen.height);
            // 답 화면 너비 : 864
            console.log("실제 화면에서 사용 가능한 너비 : " + screen.availWidth);
            // 답 실제 화면에서 사용 가능한 너비 : 1536
            console.log("실제 화면에서 사용 가능한 높이 : " + screen.availHeight);
            // 답 실제 화면에서 사용 가능한 높이 : 824
            console.log("사용 가능한 색상 수 : " + screen.colorDepth); 
            // 답 사용 가능한 색상 수 : 24
            console.log("한 픽셀 당 비트 수 : " + screen.pixelDepth); 
            // 답 한 픽셀 당 비트 수 : 24
        }
    </script>


    <h3>2. location 객체</h3>
    <p>브라우저 주소 표시줄과 관련된 객체</p>
    <button onclick="test7();">실행 확인</button>
    <div id="area3" class="area-big"></div>
    <script>
        function test7(){
            let area3 = document.querySelector("#area3");
            let html = '';
            for(let key in location){
                html += key + " : " + location[key] + "<br>";
            }
            area3.insertAdjacentHTML('beforeend', html);
            // *html 의미 : html 태그로서의 기능을 갖게 함
        }
    </script>


    <button onclick="location='https://www.naver.com';">네이버</button>
    <button onclick="location.href='https://www.naver.com';">네이버</button>


    <button onclick="location = location">새로고침</button>
    <button onclick="location.href = location.href">새로고침</button>
    <!-- 위쪽으로 올라가는 새로고침들 -->

    <button onclick="location.reload()">현재 위치에서 새로고침</button>

    <button onclick="location.assign('https://google.com')">구글로 이동</button>
    <!-- 뒤로가기 남아있음 -->
    <button onclick="location.replace('https://google.com')">
        구글로 이동(뒤로 가기 불가)</button>
    <!-- 뒤로가기 없어짐 -->


    <h3>3. navigator 객체</h3>
    <p>
        웹 페이지를 실행하고 있는 브라우저에 대한 정보를 가지고 있는 객체
    </p>

    <button onclick="test8();">실행확인</button>
    <div id = "area4" class="area-big"></div>
    <script>
        function test8(){
            let area4 = document.querySelector("#area4");
            let html = '';
            for(let key in navigator){
                html += key + " : " + navigator[key] + "<br>";
            }area4.insertAdjacentHTML('beforeend', html);
        }
    </script>


    <h3>4. history 객체</h3>
    <button onclick="test9();">실행 확인</button>
    <div id="area5" class="area-big"></div>
    <script>
        function test9(){
            document.querySelector("#area5").textContent = "history.length : "
            +  history.length;
            // 답 : history.length : 1

            // 뒤로가기
            history.back();
            // 앞으로 가기
            // history.forward();
            // 전달 숫자만큼 앞/뒤로 가기
            // history.go(1);
            // history.go(-1);
        }
    </script>

</body>
</html>

 

 

15) 이벤트

<!DOCTYPE html>
<html lang="ko">
<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>15_이벤트</title>
    <style>
        .area {
            background: lightgray;
            border : 1px solid black;
            min-height: 100px;
        }

        .div-test{
            border : 1px solid black;
            padding : 20px;
        }

        .div1{background: mistyrose;}
        .div2{background: ivory;}
        .div3{background: honeydew;}
        .div4{background: aliceblue;}
    </style>
</head>
<body>
    <h1>이벤트</h1>
    <ul>
        <li>마우스 이벤트(click, mouseover, mouseout, mousemove)</li>
        <li>폼 요소 이벤트(submit, focus)</li>
        <li>키보드 이벤트(keydown, keyup)</li>
        <li>문서 이벤트</li>
    </ul>
    등의 DOM 이벤트들이 있는데 이러한 이벤트가 발생했을 경우
    실행되는 함수를 이벤트 핸들러를 할당하는 방법은 다양함.
    
    <h3>1. HTML 속성</h3>
    <p>
        HTML 안의 onevent 속성에 이벤트 핸들러 할당하는 방법<br>
        Ex. &lt;h3 oncliclk="실행코드"&gt; 등<br>
        간단한 코드는 그냥 작성하기도 하지만 코드가 같다면 별도의 함수를 만들고 이를 호출함
    </p>


    <button onclick="alert('클릭했네?');">클릭해보세요</button>
    <button onmouseover="mouseover(this);">마우스를 올려보세요</button>
    <script>
        function mouseover(elem){
            alert('마우스를 올리지 마세요!');
            // 핸들러 내부에 쓰인 this의 값은 핸들러가 할당된 요소
            // => 이벤트가 발생한 button
            console.log(elem);
            // 답 : <button onmouseover="mouseover(this);">마우스를 올려보세요</button>
            console.log(elem.innerHTML);
            // 답 : 마우스를 올려보세요
        }
    </script>


    <h3>2. DOM 프로퍼티</h3>
    <p>
        요소 객체가 갖고 있는 onevent 속성에 이벤트 핸들러를 연결하는 방법<br>
        Ex. element.onclick = 이벤트 핸들러(함수);<br>
        해당 프로퍼티는 하나 밖에 없기 때문에 여러 개의 이벤트를 할당할 수 없음<br>
        만약 이벤트 객체를 제거할 때는 속성 값에 null을 넣어주면 됨
    </p>

    <button id='test1'>test1 실행확인</button>
    <button id='test2'>test2 실행확인</button>
    <div id='area1' class="area"></div>


    <script>
        let test1 = document.getElementById('test1');
        let test2 = document.getElementById('test2');

        test1.onclick = function() {
            document.getElementById('area1').innerHTML += 'test1이 실행되었습니다.<br>';



            // 핸들러 내부에 쓰인 this의 값은 핸들러가 할당된 요소
            console.log(this);
            // 답 : <button id="test1">test1 실행확인</button>
            console.log(this.innerHTML);
            // 답 : test1 실행확인
            
            
        };

        test1.onclick = () => alert('이벤트 덮어쓰기!');
        // *이전 내용은 무시됨 -> 하나의 이벤트 밖에 연결하지 못함

        // 선언 되어있는 함수를 핸들러에 할당 할 때는 함수명만 작성
        test2.onclick = removeEvent;


            function removeEvent() {
            document.getElementById('area1').innerHTML 
            += 'test2가 실행되면서 test1 이벤트 제거<br>';
            test1.onclick = null;
        };

    </script>



    <h3>3. addEventListener</h3>
    <p>
        1, 2번 방식의 이벤트 핸들러 할당의 경우 복수의 핸들러 할당 불가<br>
        element.addEventListener(event, handler, [options]);<br>
        element.removeEventListener(event, handler, [options]);<br>
        event : 이벤트 이름, handler 핸들러 함수<br>
        위의 메소드로 핸들러를 추가/삭제하면서 복수의 핸들러를 할당할 수 있음

    </p>

    <!--  *이벤트핸들러 : 영어 뜻풀이 그대로 "어떠한 사건에 대한 동작을 다룬다"라는 의미입니다. -->

    <button id = "btn">실행 확인</button>
    <script>
        let btn = document.querySelector("#btn");

        btn.addEventListener('click', () => alert('첫 번째 이벤트'));

        btn.addEventListener('click', () => btn.style.background = 'red');
        // 버튼 색이 빨강으로 변경됨

        // 핸들러를 삭제하려면 핸들러 할당 시 사용한 함수를 그대로 전달해야 하므로
        // 위와 같은 경우는 삭제 불가. 함수 선언하여 핸들러 할당하기.
        function myFunction(){
            alert('곧 삭제될 친구!');
        }

        btn.addEventListener('mouseover', myFunction);

        // 삭제 테스트
        btn.removeEventListener('mouseover', myFunction);

    </script>


    <h3>4. 이벤트 객체</h3>
    <p>
        이벤트 객체는 이벤트에 대한 상세한 정보(눌린 키보드 키 값, 마우스 클릭된 좌표 등)를
        가지고 있음<br>
        이벤트가 발생하면 브라우저는 이벤트 객체를 핸들러에 인수 형태로 전달함<br>
        핸들러 내부에서 이벤트 타입과 요소 이벤트가 발생한 좌표 등을 확인할 수 있음
    </p>

    <button id="evtObj">이벤트 객체 확인</button>
    <!-- event라는 이름 말고 다른 이름 써줘도 됨 -->

    <button onclick = "console.log(event);">이벤트 객체 확인</button>
    <!--꼭 event라는 이름을 써줘야 함 -->

    <!-- HTML 핸들러 안에서도 event 객체 사용 가능(값 변경 불가능) -->

    <script>
        let evtObj = document.querySelector("#evtObj");
        
        evtObj.onclick = function(event){
            console.log(event.type + " 이벤트");
            // 답 : click 이벤트
            
            console.log(event);
            // 답 : PointerEvent {isTrusted: true, pointerId: 1, width: 1, height: 1, pressure: 0, …}
            console.log(event.target);
            // 답 : <button id="evtObj">이벤트 객체 확인</button>
            console.log(this);
            // 답 : <button id="evtObj">이벤트 객체 확인</button>
            console.log('이벤트가 발생한 곳의 좌표는 ' + event.clientX + " : " + event.clientY);
            // 답
            // 이벤트가 발생한 곳의 좌표는 80 : 696\
            // 마우스 위치를 바꿀때마다 좌표가 변경됨
        }

    </script>


    <h1>버블링과 캡쳐링</h1>
    <p>
        "버블링"이란 한 요소에 이벤트가 발생하면 할당된 핸들러가 동작하고, 
        이어서 부모 요소의 핸들러가 동작하는 것<br>
        가장 최상단의 조상 요소를 만날 때까지 이 과정이 반복되면서 요소 각각에 할당된 핸들러가 동작<br>
        몇 가지 이벤트를 제외하고는 거의 모든 이벤트는 버블링됨
    </p>

    <div class = "div-test div1" onclick = "alert('1번 div');">
        <div class = "div-test div2" onclick = "alert('2번 div');">
            <div class = "div-test div3" onclick = "alert('3번 div');">
                <div class = "div-test div4" onclick = "alert('4번 div');">
                </div>
            </div>
        </div>
    </div>
    <!-- 1번 누르면 1번만 뜸, 4번 누르면 1, 2, 3, 4 다뜸 -->


    <h3>1. 이벤트 버블링 막기</h3>
    <p>
        event.target : 실제 이벤트가 시작된 타겟 요소로 버블링이 진행되어도 변함 없음<br>
        event.currentTarget(==this) : 현재 실행 중인 핸들러가 할당된 요소를 의미
        이벤트 객체의 메소드 event.stopPropgation()을 사용하면 버블링 중단을 명령함<br>
        버블링은 꼭 필요한 경우를 제외하고는 막지 않음
    </p>
        <div class = "div-test div1" onclick = "bubble(event);">
            <div class = "div-test div2" onclick = "bubble(event);">
                <div class = "div-test div3" onclick = "bubble(event);">
                    <div class = "div-test div4" onclick = "bubble(event);">
                    </div>
                </div>
            </div>
        </div>
    
    <script>
        function bubble(event){
            console.log('event.target');
            console.log(event.target);
            console.log('event.currentTarget');
            console.log(event.currentTarget);
            console.log("-------------------------");

            // 즉, event.target은 부모로부터 이벤트가 위임되어 발생하는 
            // 자식의 위치, 내가 클릭한 자식 요소를 반환한다. 
            // 하지만 currentTarget은 이벤트가 부착된 부모의 위치를 반환한다.
           
            event.stopPropagation();
            // => 이것을 실행해야 위의 이벤트를 막을 수 있다.
        }
    </script>


    <h3>2. 이벤트 캡쳐링</h3>
    <p>
        캡쳐링 : 이벤트가 하위 요소로 전파<br>
        버블링 : 이벤트가 상위 요소로 전파<br>
        캡쳐링 단계에서 이벤트를 잡아내려면 addEventListener의 capture 옵션을 true로 설정<br>
        많이 사용하는 속성은 아님
    </p>

    <div class = "div-test div1">
        <div class = "div-test div2">
            <div class = "div-test div3">
                <div class = "div-test div4">
                </div>
            </div>
        </div>
    </div>

    <script>
        let divs = document.querySelectorAll(".div-test");
        for(let i = divs.length - 4; i < divs.length ; i++){
            divs[i].addEventListener('click', e => alert('캡쳐링 : ' + divs[i].className), true);
            divs[i].addEventListener('click', e => alert('버블링 : ' + divs[i].className));
            // false 디폴트이므로 true값을 지워준다
        }
    </script>


    <h3>3. 기본 이벤트의 제거</h3>    
    <p>
        기본 이벤트란<br>
        - a 태그를 통한 페이지 이동<br>
        - submit시 입력 양식 제출 후 페이지 갱신<br>
        등의 브라우저 기본 동작을 말함<br>

        태그에 기본적으로 설정되어 있는 이벤트를 제거하는 방법은<br>
        1. event.preventDefault()<br>
        2. oneevent를 통해 할당된 이벤트 핸들러의 return 값을 false로 반환
    </p>

    <a href="/" onclick="event.preventDefault()">클릭해도 절대 이동할 수 없는 a 태그</a>


    <form onsubmit="return invalidate();">
        <label>비밀번호</label>
        <input type="password" name="password" id="password" required>
        <br>
        <label>비밀번호 확인 : </label>
        <input type ="password" name="pwdCheck" id="pwdCheck" required>
        <input type="submit" value="제출">
    </form>

    <script>
        function invalidate(){
            let password = document.getElementById('password').value;
            let pwdCheck = document.getElementById('pwdCheck').value;
            if(password == pwdCheck){
                alert('비밀번호가 일치합니다');
            } else {
                alert('비밀번호가 일치하지 않습니다');
                return false;
            }
        }
    </script>

</body>
</html>