Notice
Recent Posts
Recent Comments
Link
«   2024/09   »
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
Tags
more
Archives
Today
Total
관리 메뉴

개발자입니다

[비트캠프] 28일차(6주차3일) - Javascript(이벤트: 등록, 정보 다루기, 전파, 기본 동작 중지) 본문

네이버클라우드 AIaaS 개발자 양성과정 1기/Javascript

[비트캠프] 28일차(6주차3일) - Javascript(이벤트: 등록, 정보 다루기, 전파, 기본 동작 중지)

끈기JK 2022. 12. 14. 11:39

 

이벤트 - 리스너 등록하기

    이벤트(event)
    => 사용자나 시스템에 의해 태그의 상태가 바뀌는 것을 가리킨다.
    => 각 태그 별로 발생하는 이벤트가 정해져 있다.
    => 물론 개발자가 임의의 이벤트를 발생시킬 수 있다.
    
    리스너(listener) = 이벤트 핸들러(event handler)
    => 이벤트가 발생할 때 호출되는 메서드이다.
    => HTML 태그나 자바스크립트 코드에서 이벤트에 대해 함수를 등록해야 한다.
    
    click 이벤트
    => 사용자가 태그를 클릭할 때 발생한다.
    
    click 이벤트에 대해 리스너를 등록하는 방법
    1) HTML 태그의 onclick 속성에 자바스크립트 코드를 넣는다.
       => 사용자가 태그를 클릭하면 이 속성에 등록된 자바스크립트 코드가 실행된다.
       => 이 방식은 태그 안에 자바스크립트 코드가 섞여 있기 때문에 유지보수할 때 힘들다.
       => HTML 태그는 태그대로, 자바스크립트 코드는 코드대로 분리되어 있어야 유지보수가 쉽다.
       => 태그 안에 자바스크립트 코드를 넣어야 하기 때문에 긴 코드를 넣기가 불편한다.
    
    2) 태그 객체의 onclick 프로퍼티에 함수를 등록한다.
       => 사용자가 태그를 클릭하면 onclick이라는 이름으로 등록된 함수를 호출한다.
       => HTML 태그와 자바스크립트 코드가 분리되어 있어서 유지보수하기 쉽다.
       => 이 방식은 이벤트에 대해 한 개의 리스너만 등록할 수 있다.
    
    3) 태그 객체의 addEventListener()를 이용하여 호출될 함수를 등록한다.
       => 사용자가 태그를 클릭하면 해당 이벤트에 등록된 함수가 호출된다.
       => 이 또한 HTML 태그와 자바스크립트 코드가 분리되어 있어서 유지보수에 좋다.
       => 특히 여러 개의 리스너를 등록할 수 있다.

// ex06\exam01-1.html

<h1>이벤트 - 리스너 등록하기</h1>
<button id="btn1-1" onclick="var str='Hello'; window.alert(str);">버튼1-1</button><br>
<input id="input1" type="text">
<button id="btn1-2" onclick="btn1Click()">버튼1-2</button><br>
<button id="btn2">버튼2</button><br>
<button id="btn3">버튼3</button><br>

<script>

// 방법1:
function btn1Click() {
  var msg = document.getElementById('input1');
  if (msg.value == 'ok') {
    console.log('하하하');
  } else {
    console.log('-.-');
  }
}


// 방법2:
//var btn2 = document.getElementById("btn2");
var btn2 = document.querySelector("#btn2"); // 둘 중 아무거나 사용하면 된다.
//var btn2 = $("#btn2");

/*
    function f1() {
      var str = "Hello2a!";
      window.alert(str);
      console.log(this); // this는 이 함수가 소속된 객체를 통해 호출될 때 그 객체를 가리킨다.
    }
    btn2.onclick = f1; // 함수의 주소를 객체 프로퍼티로 저장하는 순간 그 객체에 소속된다.
*/

/*
    btn2.onclick = function () {
      var str = "Hello2b!";
      window.alert(str);
      console.log(this); // 일반 함수에서 this는 그 함수가 소속된 객체이다.
    };
*/


btn2.onclick = () => {
  var str = "Hello2c!";
  window.alert(str);
  console.log(this); // arrow function에서 this는 window 객체이다.
};


// 방법3:
// => addEventListener(이벤트명, 리스너);
// => 주의!
//    클릭 이벤트의 이름은 "onclick"이 아니라, "click"이다.
//
var btn3 = document.querySelector("#btn3");

btn3.addEventListener("click", btn3Click);
function btn3Click() {
  var str = "Hi1!!";
  window.alert(str);
  console.log(this); // this는 btn3 객체이다.
}

btn3.addEventListener("click", function () {
  var str = "Hi2!!";
  window.alert(str);
  console.log(this); // this는 btn3 객체이다.
});

btn3.addEventListener("click", () => {
  var str = "Hi3!!";
  window.alert(str);
  console.log(this); // this는 window 객체이다.
});

 

 

이벤트 - 리스너 실행 순서

한 태그에 세가지 방법으로 등록된 리스너가 있을 때 호출되는 순서는?
=> 만약 태그 객체에 대해 onclick 프로퍼티로 리스너를 등록했다면, 태그의 onclick 속성에 등록된 자바스크립트 코드는 실행되지 않는다.
=> 태그 객체에 대해 onclick 프로퍼티로 등록한 리스너가 먼저 실행된다. 그런 후에 addEventListener()로 등록한 리스너를 호출한다.
=> 주의!
이 호출 순서에 의존하여 코드를 작성하지 말라! 또한 세가지 방법 중에 한 가지 방법으로 리스너를 등록하라! 그렇게 일관성이 있어야 유지보수가 쉬워진다.

<h1>이벤트 - 리스너 실행 순서</h1>
<button id="btn1" onclick="var str='Hello1'; window.alert(str);">버튼1</button><br>

<script>
    var btn1 = document.querySelector("#btn1");

    // 태그의 onclick 속성에 자바스크립트가 있든
    // 태그 객체의 onclick 프로퍼티에 리스너를 등록하였든 상관없이
    // 리스너를 추가한다.
    btn1.addEventListener("click", () => {
        var str = "Hello3";
        window.alert(str);
    });


    // 태그의 onclick 속성 값을 설정했다면 그 값을 대체한다.
    //
    btn1.onclick = () => {
        var str = "Hello2";
        window.alert(str);
    };

 

 

이벤트 - 각 태그 객체에 따로따로 이벤트 리스너를 등록해야 한다.
<button class="btn1">btn1-버튼1</button>
<button class="btn1">btn1-버튼2</button>
<button class="btn1">btn1-버튼3</button><br>
<button class="btn2">btn2-버튼1</button>
<button class="btn2">btn2-버튼2</button>
<button class="btn2">btn2-버튼3</button><br>

<script>
    "use strict"

    var el = document.querySelectorAll(".btn1");

    // querySelectorAll()의 리턴 값은 NodeList 이다.
    // 태그 객체가 아니다.
    // 따라서 addEventListener() 함수가 없다.
    /*
            el.addEventListener("click", () => {
                console.log(this);
            });
    */

    // 또한 onclick 프로퍼티도 없다.
    // 따라서 다음 코드는 의미 없다.
    /*
            el.onclick = () => {
                console.log(this);
            };
    */

    // 다음과 같이 각 태그 객체에 리스너를 추가하던가!
    /*
            for (var e of el) {
                e.onclick = function () {
                    console.log(this);
                }
            }
    */

    // 다음처럼 한 개의 함수를 정의한 후에
    // 각 태그에 리스너로 등록하던가!
    function f1() {
        console.log(this);
    }
    for (var e of el) {
        e.onclick = f1
    }

    // JQuery
    //$(".btn1").on('click', function() {
    //  console.log(this);
    //});

    //$(".btn1").click(function() {
    //  console.log(this);
    //});

 

 

이벤트 - 이벤트 정보 다루기 I

이벤트가 발생하면 웹브라우저는 이벤트 정보를 객체에 담아서 리스너를 호출할 때 파라미터로 전달한다.
이벤트 객체는 이벤트 종류에 따라 미리 정의된 생성자에 의해서 초기화된다. 즉 이벤트 종류에 따라 특정 생성자가 이벤트 객체를 준비한다.
예)
=> 마우스 클릭, 더블클릭, 누를 때, 뗄 때 - PointerEvent() 생성자가 초기화시킨다.
=> 키보드에서 키를 누를 때, 뗄 때, 눌렀다 땔 때 - KeyboardEvent() 생성자가 초기화시킨다.
=> 콘텐트를 편집할 때 - InputEvent() 생성자가 초기화시킨다.
=> UI 객체가 포커스를 얻었을 때, 잃었을 때 - FocusEvent() 생성자가 초기화시킨다.

태그의 onclick 속성에 자바스크립트 코드를 둘 때 이벤트 정보를 사용하는 방법?
=> "event" 라는 이름으로 정의된 객체가 있다. 그 객체를 사용하면 된다.
=> 이 event 객체는 PointerEvent()가 초기화시킨 객체이다.
=> 즉 PointerEvent() 생성자가 추가한 속성을 사용할 수 있다.

PointerEvent 주요 속성
=> altKey : Alt 키 누름 여부
=> ctrlKey : Ctrl 키 누름 여부
=> button : 누른 버튼 번호
=> offsetX/Y : 버튼 영역을 기준으로 X/Y 좌표
=> clientX/Y : 웹브라우저 내용창을 기준으로 X/Y 좌표
=> screenX/Y : 바탕화면 영역을 기준으로 X/Y 좌표

<button id="btn1" onclick="console.log(event)">버튼1</button><br>

 

 

이벤트 - 이벤트 정보 다루기 II

HTML 태그의 onclick 속성에 많은 자바스크립트 코드를 넣을 수 없을 때, 함수를 만들고 호출하라!
=> 물론 event 객체를 함수를 호출할 때 넘겨줘야 한다.
    당연히 함수에서는 event 객체를 받는 파라미터가 있어야 한다.

 

<button id="btn1" onclick="btn1Click(event)">버튼1</button><br>

<script>
function btn1Click(e) {
  console.log(e);
  console.log(e.constructor.name);
  console.log(e instanceof MouseEvent);
	console.log(
			e.altKey, e.ctrlKey, e.button,
			e.offsetX, e.offsetY,
			e.clientX, e.clientY,
			e.screenX, e.screenY)
}

 

 

이벤트 - 이벤트 정보 다루기 III
<div>
테스트!
<button id="btn1">버튼1</button><br>
</div>
<script>
"use strict"

// 태그 객체의 onclick 프로퍼티에 리스너 등록하고 이벤트 정보 추출
document.getElementById("btn1").onclick = function(e) {
	console.log(
			e.altKey, e.ctrlKey, e.button,
			e.offsetX, e.offsetY,
			e.clientX, e.clientY,
			e.screenX, e.screenY)
};

/*
$("#btn1").click(function(e) {
	  console.log(
      e.altKey, e.ctrlKey, e.button,
      e.offsetX, e.offsetY,
      e.clientX, e.clientY,
      e.screenX, e.screenY)
});
*/

// id가 부여된 태그는 window 객체를 통해 바로 접근할 수 있다.
/*
window.btn1.onclick = function() {
	console.log("test..ok!");
};
*/

 

 

이벤트 - 이벤트 정보 다루기 IV
<button id="btn1">버튼1</button><br>

<script>
"use strict"

// addEventListener() 사용
document.getElementById("btn1").addEventListener("click", function(e) {
	console.log(
		e.altKey, e.ctrlKey, e.button,
		e.offsetX, e.offsetY,
		e.clientX, e.clientY,
		e.screenX, e.screenY)
});

 

 

이벤트 - 이벤트가 발생된 태그 알아내기

리스너가 일반 함수나 익명 함수일 경우, this가 가리키는 객체가 이벤트가 발생된 객체이다.

<button id="btn1" data-no="100">버튼1</button><br>

<script>

document.getElementById("btn1").addEventListener("click", function (e) {
    console.log(this);

    // 이벤트가 발생한 객체의 속성 값 알아내기
    // => 개발자가 임의로 추가한 속성인 경우 반드시 getAttribute()를 사용해야 한다.
    console.log(this.getAttribute("data-no"));

    // 개발자가 태그에 임의로 추가한 속성은 다음과 같이 일반적인 방법으로 꺼낼 수 없다. 
    console.log(this["data-no"]); // undefined

    // 태그에 원래 있던 속성이라면 일반적인 문법으로 접근할 수 있다.
    console.log(this.id);
});

 

 

이벤트 - 이벤트가 발생된 태그 알아내기 II

arrow function인 경우 this는 window 객체를 가리킨다.

<button id="btn1" data-no="100">버튼1</button><br>

<script>

document.getElementById("btn1").addEventListener("click", (e) => {
  console.log(this); // window 객체이다.

  // 그럼 arrow function(자바에서는 Lambda라 부른다)에서는
  // 이벤트가 발생된 객체를 알 수 없는가?
  // => 있다!
  //    이벤트 객체에 이벤트가 발생된 태그의 주소가 들어 있다.
  console.log(e.target);

  // 이벤트가 발생한 객체의 속성 값 알아내기
  console.log(e.target.getAttribute("data-no"));
});

 

 

이벤트 - 이벤트가 발생된 태그 알아내기 III

여러 개의 태그에 같은 리스너를 등록했을 경우 리스너가 호출될 때 어떤 태그인지 알아내는 방법!

<button id="btn1" class="b1" data-no="100">버튼1</button><br>
<button id="btn2" class="b1" data-no="200">버튼2</button><br>
<button id="btn3" class="b2" data-no="300">버튼3</button><br>
<button id="btn4" class="b2" data-no="400">버튼4</button><br>
<p id="message"></p>

<script>
    "use strict"

    var el = document.querySelectorAll(".b1");
    var p = document.querySelector("#message");

    p.style.width = "200px";
    p.style.height = "100px";

    // 스타일 이름에 공백이나 특수 문자가 포함된 경우 
    // 자바스크립트에서 프로퍼티 이름을 사용할 수 없다.
    //p.style.background-color = "gray"; // 프로퍼티 이름 중간에 - 문자가 있으면 안된다.

    // 그래서 다음과 같이 대괄로 문법으로 스타일을 설정해야 한다. 
    p.style["background-color"] = "yellow";

    // 웹브라우저 API는 
    // 개발자들이 스타일 이름을 프로퍼티 이름 규칙에 따라 사용할 수 있도록
    // 스타일 이름을 변경한 프로퍼티를 제공한다.
    // 예) background-color ===> backgroundColor 
    // 예) border-top-width ===> borderTopWidth
    // 따라서 다음과 같이 배경색을 지정할 수 있다.
    // p.style.backgroundColor = "yellow";

    p.style.color = "green";
    p.style.border = "5px dashed red";

    var btnClick = function (event) {
        p.innerHTML = this.getAttribute("data-no");
    };

    for (var e of el) {
        e.addEventListener("click", btnClick);
    }

 

 

이벤트 - 이벤트 단계

이벤트가 발생하면 다음 3단계로 전달 된다.
1) capture phase
    => 부모 태그에서 자식 태그로 내려가는 단계
2) target phase
    => 이벤트가 발생된 목적지에 도달한 단계
3) bubble phase
    => 다시 목적지에서 부모 태그로 올라가는 단계

다음과 같은 방법으로 이벤트 리스너를 등록하면,
이벤트가 발생했을 때
capture phase 단계는 건너뛰고
target과 bubble 단계에서 호출된다.
=> <태그 onclick="자바스크립트 코드"></태그>
=> <태그객체.onclick = function() {}
=> <태그객체.addEventListener("click", function() {});

#btn1이나 #btn2를 클릭하면,
=> 버튼에 등록된 click 리스너가 호출된다.
=> 부모들에 등록된 click 리스너도 위로 올라가면서 순차적으로 호출된다.

<body onclick="console.log('body')">
    <div id="d1" onclick="console.log('#d1')">d1
        <div id="d2" onclick="console.log('#d2')">d2
            <button id=" btn1" onclick="console.log('#btn1')">버튼1</button>
            <button id="btn2" onclick="console.log('#btn2')">버튼2</button>
        </div>
    </div>

 

이벤트 단계

event 발생 → ① capture phase로 전달 → ② target phase로 전달 → ③ bubble phase로 전달

 

button#btn2 를 click하면 event가 html로 전달된다.

① capture phase에 html → body → div#d1 → div#d2 로 전달된다.

② target phase에 div#d2 → button#btn2 로 전달된다.

③ bubble phase에 button#btn2 → div#d2 → div#d1 → body → html → ~ 로 전달된다.

 

 

이벤트 단계와 리스너 호출

이벤트 등록은 3개 방법이 있다.

태그객체.onclick = function() {-}

태그객체.addEventListener(

               "click",

               function() { - });

태그객체.addEventListener(

               "click"

               function() { - },

               false);

→ event 발생 → 캡쳐 단계 무시 → 타겟 단계에서 리스너 호출 → 버블 단계에서 리스너 호출

 

이벤트 발생시 html ~ div#d2 건너뛰고 바로 ① target phase 가서 button#btn2 리스너 호출한다.

 

 

script에 document.getElementById(" - ").onclick 으로 클릭이벤트 등록하는 방법

    <h1>이벤트 - 이벤트 단계</h1>
    <div id="d1">d1
        <div id="d2">d2
            <button id="btn1">버튼1</button>
            <button id="btn2">버튼2</button>
        </div>
    </div>
    <script>
        "use strict"

        document.getElementById("btn1").onclick = function (e) {
            console.log("버튼1...");
        };

        document.getElementById("btn2").onclick = function (e) {
            console.log("버튼2...");
        };

        document.getElementById("d2").onclick = function (e) {
            console.log("d2...");
        };

        document.getElementById("d1").onclick = function (e) {
            console.log("d1...");
        };

        document.body.onclick = function (e) {
            console.log("body...");
        };

 

        addEventListener(
           이벤트명,
           리스너,
           캡쳐단계에서 실행 할지 여부  <== 캡쳐 단계에서 실행 여부
        );

        document.getElementById("btn1").addEventListener("click", function (e) {
            console.log("버튼1...");
        });

        document.getElementById("btn2").addEventListener("click", function (e) {
            console.log("버튼2...");
        });

        document.getElementById("d2").addEventListener("click", function (e) {
            console.log("d2...");
        });

        document.getElementById("d1").addEventListener("click", function (e) {
            console.log("d1...");
        });

        document.body.addEventListener("click", function (e) {
            console.log("body...");
        });

 

addEventListener 의 3번째 argument에 false는 기본이며 캡쳐 단계 실행 여부를 설정한다.

        document.getElementById("btn1").addEventListener("click", function (e) {
            console.log("버튼1...");
        }, false);

        document.getElementById("btn2").addEventListener("click", function (e) {
            console.log("버튼2...");
        }, false);

        document.getElementById("d2").addEventListener("click", function (e) {
            console.log("d2...");
        }, false);

        document.getElementById("d1").addEventListener("click", function (e) {
            console.log("d1...");
        }, false);

        document.body.addEventListener("click", function (e) {
            console.log("body...");
        }, false);

 

 

이벤트 - bubble 대신 capture와 target 단계에서 호출되는 리스너 등록하기

세번째 파라미터를 true로 설정하면, capture 단계와 target 단계에서만 호출된다.

    <div id="d1">d1
        <div id="d2">d2
            <button id="btn1">버튼1</button>
            <button id="btn2">버튼2</button>
        </div>
    </div>
    <script>
        "use strict"

        document.getElementById("btn1").addEventListener("click", function (e) {
            console.log("버튼1...");
        }, true);

        // target, bubble  단계에서 호출되도록 설정한다.
        document.getElementById("btn2").addEventListener("click", function (e) {
            console.log("버튼2...");
        });

        // capture, target 단계에서 호출되도록 설정한다.
        document.getElementById("d2").addEventListener("click", function (e) {
            console.log("d2...");
        }, true);

        // capture, target 단계에서 호출되도록 설정한다.
        document.getElementById("d1").addEventListener("click", function (e) {
            console.log("d1...");
        }, true);

        // capture, target  단계에서 호출되도록 설정한다.
        document.body.addEventListener("click", function (e) {
            console.log("body...");
        }, true);

 

정리!
=> addEventListener(이벤트, 리스너, false) : target, bubble 단계일 때 리스너가 호출된다.
   - 세 번째 파라미터가 없으면 기본이 false이다.
=> addEventListener(이벤트, 리스너, true) : capture, target 단계일 때 리스너가 호출된다.

 

 

이벤트 - 이벤트 전파 막기

이벤트가 발생하면 capture-target-bubble 단계로 진행한다.
target 단계에서 bubble 단계로 진행하는 것을 막지 않으면 부모 태그에 등록된 리스너까지 호출되는 문제가 발생한다.

    <div id="d1">d1
        <div id="d2">d2
            <button id="btn1">버튼1</button>
            <button id="btn2">버튼2</button>
        </div>
    </div>
    <script>
        "use strict"

        // 방법1: Event.stopPropagation()을 호출하라!
        // => 이벤트 bubbling을 막는다.
        // => 단 target에 등록된 함수는 모두 호출된다.
        //
        document.getElementById("btn1").addEventListener("click", function (e) {
            console.log("버튼1...1");
            e.stopPropagation(); // 버블링을 하지 않도록 설정한다.
        });
        document.getElementById("btn1").addEventListener("click", function (e) {
            console.log("버튼1...2");
        });
        document.getElementById("btn1").addEventListener("click", function (e) {
            console.log("버튼1...3");
        });

        //방법2: Event.stopImmediatePropagation()을 호출하라!
        //=> 이벤트 bubbling을 막는다.
        //=> target에 등록된 함수라도 즉시 현 함수에서 실행을 마감한다.
        //
        document.getElementById("btn2").addEventListener("click", function (e) {
            console.log("버튼2...1");
            e.stopImmediatePropagation(); // 이 리스너까지만 실행한다.
        });
        document.getElementById("btn2").addEventListener("click", function (e) {
            console.log("버튼2...2");
        });
        document.getElementById("btn2").addEventListener("click", function (e) {
            console.log("버튼2...3");
        });

        document.getElementById("d2").addEventListener("click", function (e) {
            console.log("d2...");
        });

        document.getElementById("d1").addEventListener("click", function (e) {
            console.log("d1...");
        });

        document.body.addEventListener("click", function (e) {
            console.log("body...");
        });

 

 

이벤트 - 이벤트 전파 기능을 이용하지 않는 경우

자식 태그에 대해 이벤트 리스너를 등록할 때 그 자식 태그를 클릭했을 때만 호출된다.
예) 제목을 출력하는 a 태그에 click 리스너를 등록하면 정확하게 제목을 클릭해야만 동작한다.

  <table border="1">
    <thead>
      <tr>
        <th>번호</th>
        <th>제목</th>
        <th>작성자</th>
        <th>등록일</th>
        <th>조회수</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>1</td>
        <td><a href="https://www.daum.net" data-no="1">제목</a></td>
        <td>홍길동</td>
        <td>2019-4-29</td>
        <td>100</td>
      </tr>
      <tr>
        <td>2</td>
        <td><a href="https://www.daum.net" data-no="2">제목</a></td>
        <td>임꺽정</td>
        <td>2019-4-29</td>
        <td>800</td>
      </tr>
      <tr>
        <td>3</td>
        <td><a href="https://www.daum.net" data-no="3">제목입니다.</a></td>
        <td>유관순</td>
        <td>2019-4-29</td>
        <td>900</td>
      </tr>
    </tbody>
  </table>
  <script>
    "use strict"

    var el = document.querySelectorAll("tbody a");

    for (var e of el) {
      e.addEventListener("click", function (e) {
        console.log(e.target);
        console.log(e.target.getAttribute("data-no") + " 번 게시물의 제목을 눌렀음!");
      });
    }

 

 

이벤트 - 이벤트 전파 기능을 이용하기

부모 태그에 리스너를 등록하면 훨씬 더 광범위하게 클릭 이벤트를 처리할 수 있다.
즉 자식 태그의 이벤트를 부모 태그에서 처리할 수 있다. 어떻게? 부모로 이벤트가 전파되는 기능을 이용하는 것이다.

  <table border="1">
    <thead>
      <tr>
        <th>번호</th>
        <th>제목</th>
        <th>작성자</th>
        <th>등록일</th>
        <th>조회수</th>
      </tr>
    </thead>
    <tbody>
      <tr data-no="1">
        <td>1</td>
        <td><a href="https://www.daum.net" onclick="return false;">제목</a></td>
        <td>홍길동</td>
        <td>2019-4-29</td>
        <td>100</td>
      </tr>
      <tr data-no="2">
        <td>2</td>
        <td><a href="https://www.daum.net" onclick="return false;">제목</a></td>
        <td>임꺽정</td>
        <td>2019-4-29</td>
        <td>800</td>
      </tr>
      <tr data-no="3">
        <td>3</td>
        <td><a href="https://www.daum.net" onclick="return false;">제목입니다.</a></td>
        <td>유관순</td>
        <td>2019-4-29</td>
        <td>900</td>
      </tr>
    </tbody>
  </table>
  <script>
    "use strict"

    var el = document.querySelectorAll("tbody tr");

    for (var e of el) {
      e.addEventListener("click", function (e) {
        // e.target 은 이벤트가 발생한 객체를 가리킨다.
        // console.log(e.target);
        // console.log(e.target.getAttribute("data-no") + " 번 게시물의 제목을 눌렀음!");

        // 리스너가 등록된 태그를 가리키고 싶다면,
        // e.currentTarget 프로퍼티의 값을 사용하라!
        console.log(e.currentTarget);
        console.log(e.currentTarget.getAttribute("data-no") + " 번 게시물의 제목을 눌렀음!");
        console.log("-------------------------------");

        // 자바스크립트에서 다른 페이지로 이동시킨다.
        window.location.href = "https://www.daum.net/board?no=" + e.currentTarget.getAttribute("data-no");
      });
    }

 

 

이벤트 - 프로그래밍으로 이벤트 발생시키기

사용자의 행위가 아닌 프로그래밍으로 특정 이벤트를 발생시킬 수 있다.

<div id="d1">d1
    <div id="d2">d2
        <button id="btn1">버튼1</button>
        <button id="btn2">버튼2</button>
    </div>
</div>
<script>
"use strict"

document.getElementById("btn1").addEventListener("click", function(e) {
	// #btn1을 눌렀을 때 #btn2에 click 이벤트 발생시키기
	// 1) MouseEvent 만들기
	var myEvent = new MouseEvent("click");

	// 2) 위에서 생성한 이벤트 객체를 #btn2에 보낸다.
	document.getElementById("btn2").dispatchEvent(myEvent);
});

document.getElementById("btn2").addEventListener("click", function(e) {
    console.log("버튼2...");
});

 

객체와 인스턴스

var e = new MouseEvent() 명령어로 객체가 만들어 지는데 MouseEvent의 "인스턴스(instance)" 라 한다. 함수(생성자)를 통해서 초기화된 객체이다.

var f = function() { - } 는 객체이나 객체라 하지는 않는다.

 

다음은 객체이다.

"Hello" : 스트링 리터럴

100

true

new Object() : Object의 "인스턴스"

function() { - }

 

 

이벤트 - 커스텀 이벤트 발생시키기

javascript에 정의된 이벤트가 아닌 개발자가 임의의 이벤트를 만들어 발생시킬 수 있다.
=> Event() 생성자를 사용해서 이벤트 객체를 만들어야 한다.

  <div id="d1">d1
    <div id="d2">d2
      <button id="btn1">버튼1</button>
      <button id="btn2">버튼2</button>
    </div>
  </div>
  <script>
    "use strict"

    document.getElementById("btn1").addEventListener("click", function (e) {
      // #btn1을 눌렀을 때 #btn2에 "ohora" 이벤트를 발생시키기
      // 1) Event 만들기
      var myEvent = new Event("ohora");

      // 2) 위에서 생성한 이벤트 객체를 #btn2에 보낸다.
      document.getElementById("btn2").dispatchEvent(myEvent);
    });

    // "ohora" 이벤트를 처리하고 싶다면,
    // 다음과 같이 이벤트 이름을 "ohora"로 지정하라!
    document.getElementById("btn2").addEventListener("ohora", function (e) {
      console.log("버튼2...");
    });

 

 

이벤트 - 커스텀 이벤트 발생시키기 II

커스텀 이벤트에 데이터를 첨부해서 보내기
=> CustomEvent() 생성자를 사용해서 이벤트 객체를 만들어야 한다.

  <div id="d1">d1
    <div id="d2">d2
      <button id="btn1">버튼1</button>
      <button id="btn2">버튼2</button>
    </div>
  </div>
  <script>
    "use strict"

    document.getElementById("btn1").addEventListener("click", function (e) {
      // #btn1을 눌렀을 때 #btn2에 "ohora" 이벤트를 발생시키기
      // 1) CustomEvent 만들기
      // => 이벤트 객체에 데이터를 첨부할 때는 "detail"이라는 이름으로 데이터를 첨부하라!

      var myEvent = new CustomEvent("ohora", {
        detail: "hello!!"
      });

      // 2) 위에서 생성한 이벤트 객체를 #btn2에 보낸다.
      document.getElementById("btn2").dispatchEvent(myEvent);
    });

    // "ohora" 이벤트를 처리하고 싶다면,
    // 다음과 같이 이벤트 이름을 "ohora"로 지정하라!
    document.getElementById("btn2").addEventListener("ohora", function (e) {
      console.log("버튼2...", e.detail);
    });

 

 

이벤트 - 커스텀 이벤트 발생시키기 III

커스텀 이벤트에 여러 개의 데이터를 첨부해서 보내기.
=> CustomEvent() 생성자를 사용해서 이벤트 객체를 만들어야 한다.

<div id="d1">d1
    <div id="d2">d2
        <button id="btn1">버튼1</button>
        <button id="btn2">버튼2</button>
    </div>
</div>
<script>
"use strict"

document.getElementById("btn1").addEventListener("click", function(e) {
	// #btn1을 눌렀을 때 #btn2에 "ohora" 이벤트를 발생시키기
	// 1) CustomEvent 만들기
	// => 이벤트 객체에 데이터를 첨부할 때는 "detail"이라는 이름으로 데이터를 첨부하라!
	var myEvent = new CustomEvent("ohora",
			{detail: {
                name:"홍길동", 
                age:20, 
                tel:"1111-2222"
            }
        });

	// 2) 위에서 생성한 이벤트 객체를 #btn2에 보낸다.
	document.getElementById("btn2").dispatchEvent(myEvent);
});

// "ohora" 이벤트를 처리하고 싶다면,
// 다음과 같이 이벤트 이름을 "ohora"로 지정하라!
document.getElementById("btn2").addEventListener("ohora", function(e) {
    console.log("버튼2...");
    console.log("name=", e.detail.name);
    console.log("age=", e.detail.age);
    console.log("tel=", e.detail.tel);
});

 

 

이벤트 - a 태그의 기본 동작을 중단시키기
  1. onclick 내용에 return false 입력하기
  2. 함수를 리턴하고 함수 내에 return false 입력하기
  3. preventDefault() 로 기본동작 중단하기. addEventListener 사용시 이 방법만으로 중단된다. - 가급적 이 방법 사용
  <p>a 태그의 링크를 클릭하면 href 에 등록한 URL을 요청하는 것이
    a 태그의 기본 동작이다.</p>
  <a href="http://www.daum.net" onclick="alert('OK!')">a 태그의 기본 동작 계속</a><br>

  <!-- 기본 동작을 막고 싶다면 onclick 속성에 작성하는 스크립트의 리턴 값을 false로 지정하라! -->
  <a href="http://www.daum.net" onclick="alert('OK!'); return false">a 태그의 기본 동작 취소 1</a><br>

  <!-- a 태그의 onclick에 작성할 스크립트가 많다면 별도의 함수에 작성하고 호출한다.
     이때 함수의 리턴 값에 따라 a 태그의 기본 동작을 제어하는 기법이
     다음 예이다. -->
  <a href="http://www.daum.net" onclick="return f1()">a 태그의 기본 동작 취소 2</a><br>

  <!-- 태그.onclick = 함수() {} -->
  <a id="link3" href="http://www.daum.net">a 태그의 기본 동작 취소 3</a><br>

  <!-- 태그.onclick = 함수() {} : preventDefault() -->
  <a id="link4" href="http://www.daum.net">a 태그의 기본 동작 취소 4</a><br>

  <!-- 태그.addEventListener("click", 함수() {}) -->
  <a id="link5" href="http://www.daum.net">a 태그의 기본 동작 취소 5</a><br>

  <!-- 태그.addEventListener("click", 함수() {}) : preventDefault() -->
  <a id="link6" href="http://www.daum.net">a 태그의 기본 동작 취소 6</a><br>

  <script>
    "use strict"

    function f1() {
      alert("OK!");
      return false
    }

    document.querySelector("#link3").onclick = function () {
      alert("OK!");
      return false; // false를 리턴하면 a 태그의 기본 동작을 취소한다.
    };

    document.querySelector("#link4").onclick = function (e) {
      e.preventDefault(); // a 태그의 기본 동작을 비활성화시킨다. 리스너 호출이 끝난 후 서버에 요청하지 않는다.
      alert("OK!");
    };

    document.querySelector("#link5").addEventListener("click", function () {
      alert("OK!");
      return false; // addEventListener()로 함수를 등록하면
      // return 값으로 a 태그의 기본 동작을 취소할 수 없다.
    });

    document.querySelector("#link6").addEventListener("click", function (e) {
      // addEventListener()로 함수를 등록한다면
      // Event.preventDefault()를 사용하여 a 태그의 기본 동작을 취소해야 한다.
      e.preventDefault();
      alert("OK!");
    });

 

 

이벤트 - form의 submit 버튼 만들기

button에 type 지정하지 않으면 기본은 submit 이다.

  <form action="https://www.daum.net">
    <input type="text" name="title">
    <button>전송1</button>
  </form>

  <form action="https://www.daum.net">
    <input type="text" name="title">
    <button type="submit">전송2</button>
  </form>

  <form action="https://www.daum.net">
    <input type="text" name="title">
    <input type="submit" value="전송3">
  </form>

 

 

이벤트 - form의 submit 동작을 중단시키기
  1. form 태그에 onsubmit="return false" 옵션을 추가한다.
  2. js에서 해당 객체 submit시 실행되는 함수에 return false 입력하기
  3. js에서 해당 객체 submit시 실행되는 함수에 preventDefault() 입력하기. addEventListener 사용시 이 방법만이 중지시킬수 있다. - 가급적 이 방법 사용
  <p>form의 submit 버튼을 클릭하면 서버에 요청을 한다.</p>


  <form action="https://www.daum.net" onsubmit="return false">
    <input type="text" name="title">
    <button>전송 막기1</button>
  </form>

  <form action="https://www.daum.net" id="form2">
    <input type="text" name="title">
    <button>전송 막기2</button>
  </form>

  <form action="https://www.daum.net" id="form3">
    <input type="text" name="title">
    <button>전송 막기3</button>
  </form>

  <form action="https://www.daum.net" id="form4">
    <input type="text" name="title">
    <button>전송 막기4</button>
  </form>

  <form action="https://www.daum.net" id="form5">
    <input type="text" name="title">
    <button>전송 막기5</button>
  </form>

  <form action="https://www.daum.net" id="form6">
    <input type="text" name="title">
    <!-- 일반 버튼은 서버에 전송을 수행하지 않는다. -->
    <button type="button">전송 막기6</button>
    <input type="button" value="전송 막기6">
  </form>

  <script>
    "use strict"

    // "submit" 이벤트가 발생했을 때 호출될 리스너를 등록한다.
    // "submit" 이벤트는 언제 발생하는가?
    // - submit 버튼을 클릭할 때 발생한다!
    //
    document.querySelector("#form2").onsubmit = () => {
      return false;
    };

    document.querySelector("#form3").onsubmit = (e) => {
      e.preventDefault();
    };

    document.querySelector("#form4").addEventListener("submit", (e) => {
      e.preventDefault();
    });

    document.querySelector("#form5").addEventListener("submit", (e) => {
      return false; // addEventListener()로 이벤트 핸들러를 등록할 때는
      // return false 가 의미없다. 동작되지 않는다.
      // 반드시 e.preventDefault()를 호출하라!
    });

 

 

이벤트 - form 데이터 검증

1. return false로 서버에 제출 막기

  <form id="form1" action="http://www.daum.net">
    이름(*): <input type="text" id="name1" name="username"><br>
    <button>전송</button>
  </form>

  <script>
    "use strict"

    document.querySelector("#form1").onsubmit = () => {
      // submit 타입의 버튼을 클릭하면 onsubmit 으로 등록한 함수가 호출된다.
      // 여기에서 입력 폼 값을 검증하는 일을 한다.
      //
      var name = document.querySelector("#name1");
      if (name.value == "") {
        alert("필수 입력 항목이 비어 있습니다.");
        return false; // false를 리턴하면 입력 폼의 값을 서버에 제출하지 않는다.
        // 즉 HTTP 요청을 수행하지 않는다.
      }

      // true를 리턴하거나 아무것도 리턴하지 않으면 원래대로
      // 입력 폼의 값을 서버에 제출한다. 즉 HTTP 요청을 수행한다.
    };

 

2. 일반 버튼에 onclick 사용. return ; 로 서버에 제출 막기

  <form id="form2" action="http://www.daum.net">
    이름(*): <input type="text" id="name2"><br>
    <button id="btn2" type="button" name="username">전송</button>
  </form>

  <script>
    "use strict"

    document.querySelector("#btn2").onclick = () => {
      var name = document.querySelector("#name2");
      if (name.value == "") {
        alert("필수 입력 항목이 비어 있습니다.");
        return; // submit 버튼이 아니라 일반 버튼이기 때문에 false를 리턴할 필요가 없다.
      }

      // 일반 버튼을 클릭했을 때 입력 폼의 값을 서버에 제출하려면
      // form 태그 객체에 대해 submit() 함수를 호출하라!
      //
      document.querySelector("#form2").submit();
    }

 

3. preventDefault() 로 서버에 제출 막기 - 가급적 이 방법 사용

  <form id="form3" action="http://www.daum.net">
    이름(*): <input type="text" id="name3"><br>
    <button id="btn3">전송</button>
  </form>

  <script>
    "use strict"

    document.querySelector("#form3").addEventListener("submit", (e) => {
      console.log("okok!");
      var name = document.querySelector("#name3");
      if (name.value.length < 2) {
        alert("2자 이상을 입력하세요.");
        //return false; // addEventListener()로 등록한 경우 return false는 안 먹힌다.
        e.preventDefault();
        return;
      }
    });

 

 

 


 

조언

 

*알고리즘 책 사서 얆은 거 스터디 한 다음에 백준 사이트 가서 문제 풀면서 '2년 후 네카라쿠배 가겠다' 생각하라. 문제 풀면서 소회를 깃에 남겨라.

 

 


 

과제

 

/