front

JQuery 예제와 기능에 대해

HJHStudy 2024. 7. 2. 23:54
728x90

이번 포스팅에서는 이전 포스팅에서 알아본 스타일과 클래스에 대한 예제를 확인해 보고 순서대로 속성 값, 이벤트, 좌표, 애니메이션이 어떤 기능을 하는지 알아보고 각 기능에 대해 예제를 알아보는 시간을 가져보도록 하겠다. 

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>자바스크립트 VS jQuery 스타일 다루기-1</title>
    <style>
        div {
            margin: 20px;
            padding: 10px;
            font-size: 26px;
            border: 2px solid red;
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        //자바스크립트로 스타일 접근
        // window.onload = function(){
        //     var content = document.getElementById("test");
        //     //color는 인라인 속성이어서 바로 접근을 해서 값을 얻을 수 있다.
        //     console.log("color = ", content.style.color);
        //     //하지만 아래 3가지의 경우는 외부속성이라서 접근해서 값을 얻을 수가 없다.
        //     console.log("font-size = ", content.style.fontSize);
        //     console.log("border = ", content.style.border);
        //     console.log("margin = ", content.style.margin);
        //     //getComputedStyle()를 이용하여 내,외부 스타일 속성에 접근하여 출력을 할수 있다.
        //     console.log("border = ", window.getComputedStyle(content).border);
        //     console.log("font-size = ", window.getComputedStyle(content).fontSize);
        // }

        //jQuery로 스타일 접근
        $(document).ready(function(){
            var $content = $("#test");
            //jQuery로 스타일에 접근할때는 css()만 사용하면 내외부 상관없이 바로 값을 얻어
            //낼 수가 있다.
            console.log("color = ", $content.css("color"));
            console.log("border = ", $content.css("border"));
            console.log("font-size = ", $content.css("font-size"));
            console.log("margin = ", $content.css("margin"));
        });


    </script>
</head>
<body>
    <div id="test" class="content" style="color: blue;">
        스타일 다루기
    </div>
    
</body>
</html>
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>자바스크립트 VS jQuery 스타일 다루기-2</title>
    <style>
        div {
            margin: 20px;
            padding: 10px;
            font-size: 26px;
            border: 2px solid red;
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        //자바스크립트로 스타일 속성이름
        // window.onload = function(){
        //     var content = document.getElementById("test");
        //     //자바스크립트의 속성이름이 2단어가 연결된다면 낙타표기법으로 표식하고 값을
        //     //설정을 해야 적용된다.
        //     content.style.fontSize = "12px";
        //     //content.style.font-size = "12px"; //에러발생
        // }

        //jQuery로 스타일 속성이름
        $(document).ready(function(){
            var $content = $("#test");
            //jQuery로 스타일 속성이름에 관계없이 그대로 사용을 해도 무방하다.
            $content.css("fontSize", "12px");
            //$content.css("font-size", "12px");
        });
    </script>
</head>
<body>
    <div id="test" class="content" style="color: blue;">
        스타일 다루기
    </div>
    
</body>
</html>

 

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>자바스크립트 VS jQuery 스타일 다루기-3</title>
    <style>
        div {
            margin: 20px;
            padding: 10px;
            font-size: 26px;
            border: 2px solid red;
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        //자바스크립트로 여러 스타일 속성값 변경하기
        // window.onload = function(){
        //     var content = document.getElementById("test");
        //     //자바스크립트로 여러 스타일 속성값을 변경하고자 한다면 스타일의 개수만큼 
        //     //아래와 같은 코드를 추가해야 할 것이다.
        //     content.style.fontSize = "8px";
        //     content.style.border = "5px solid black";
        //     content.style.margin = "50px";
        // }

        //jQuery로 스타일 속성이름
        $(document).ready(function(){
            var $content = $("#test");
            //jQuery로 여러 스타일 속성값을 변경하고자 한다면 css()로 한번에 묶어서
            //속성값을 변경할 수가 있다.
            $content.css({
                fontSize : "8px",
                border : "5px solid black",
                margin : "50px"
            });
            
        });
    </script>
</head>
<body>
    <div id="test" class="content" style="color: blue;">
        스타일 다루기
    </div>
    
</body>
</html>
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>자바스크립트 VS jQuery 스타일 다루기-4</title>
    <style>
        div {
            margin: 20px;
            padding: 10px;
            font-size: 26px;
            border: 2px solid red;
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        //자바스크립트로 단위 생략 
        window.onload = function(){
            var content = document.getElementById("test");
            //자바스크립트로 스타일 속성 값을 변경하고자 할때 단위를 생략을 하면 적용이 안된다.
            //content.style.fontSize = "8px";            
            content.style.fontSize = 8;   //적용 불가
        }

        //jQuery로 스타일 단위 생략 
        // $(document).ready(function(){
        //     var $content = $("#test");
        //     //jQuery로 스타일 속성 값을 변경하고자 할때 단위를 생략을 해도 기본적 단위
        //     //인 px이 적용이 된다.
        //     //$content.css("fontSize","8px");            
        //     $content.css("fontSize",8);   //적용 가능         
        // });
    </script>
</head>
<body>
    <div id="test" class="content" style="color: blue;">
        스타일 다루기
    </div>
    
</body>
</html>
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jQuery를 활용한 스타일 값 설정하기-1</title>
    <style>
        body {
            font-size: 20px;
            font-family: "고딕";            
        }
        .menu {
            padding: 10px;
            list-style: none;
            border: 2px solid black;
        }
        .menu li {
            border: 1px solid aqua;
            margin: 10px;
        }
        li.select {
            background-color: brown;
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        $(document).ready(function(){
            var $item = $(".menu li.select");
            $("#exec").click(function(){
                //폰트사이즈를 값을 알아내어서 숫자로 바꾸고 있는 코드
                var fontSize = parseInt($item.css("fontSize"));
                //console.log(fontSize);
                //폰트 크기를 설정하는데 클릭할 때마다 1씩 증가가 된다.
                $item.css("fontSize", fontSize + 1);
            });           
        });
    </script>
</head>
<body>
    <button id="exec">실행</button>
    <ul class="menu">
        <li>메뉴1</li>
        <li>메뉴2</li>
        <li class="select">메뉴3</li>
        <li>메뉴4</li>
        <li>메뉴5</li>
    </ul>    
</body>
</html>

 

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jQuery를 활용한 스타일 값 설정하기-2</title>
    <style>
        body {
            font-size: 20px;
            font-family: "고딕";            
        }
        .menu {
            padding: 10px;
            list-style: none;
            border: 2px solid black;
        }
        .menu li {
            border: 1px solid aqua;
            margin: 10px;
        }
        li.select {
            background-color: brown;
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        $(document).ready(function(){
            $("#exec").click(function(){
                //기본 폰트 사이즈를 16으로 설정
                var size = 16;

                //each()로 li개수 만큼 루프 돌기
                $(".menu li").each(function(i){
                    $(this).css({
                        fontSize : size
                    });
                    //폰트사이즈가 10씩 증가가 됨
                    size += 10;
                });
            });                
        });
    </script>
</head>
<body>
    <button id="exec">실행</button>
    <ul class="menu">
        <li>메뉴1</li>
        <li>메뉴2</li>
        <li class="select">메뉴3</li>
        <li>메뉴4</li>
        <li>메뉴5</li>
    </ul>    
</body>
</html>
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jQuery를 활용한 스타일 값 다중 설정하기</title>
    <style>
        body {
            font-size: 20px;
            font-family: "고딕";            
        }
        .menu {
            padding: 10px;
            list-style: none;
            border: 2px solid black;
        }
        .menu li {
            border: 1px solid aqua;
            margin: 10px;
        }
        li.select {
            background-color: brown;
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        $(document).ready(function(){
            var $item = $(".menu li.select");
            $("#exec").click(function(){
                //너비와 높이,배경색,글자색 스타일 다중값을 한번에 설정하기
                $item.css({
                    width : 100,
                    height : 100,
                    //아래의 속성들이 만약에 인식이 되지 아니하면 ''(코테이션)으로 감싸야 한다.
                    'background-color' : 'blue',
                    'color' : 'white'
                });                
            });                
        });
    </script>
</head>
<body>
    <button id="exec">실행</button>
    <ul class="menu">
        <li>메뉴1</li>
        <li>메뉴2</li>
        <li class="select">메뉴3</li>
        <li>메뉴4</li>
        <li>메뉴5</li>
    </ul>    
</body>
</html>

 

별도의 설명이 없이 코드만 늘여 놓았다. 각 주석에 따라 설명을 했기 때문에 별도의 설명은 제외하고 코드만 올렸다.

위 코드들은 스타일 적용과 변경을 JQuery를 통한 코드로 알아보았다.

 

다음으로는 class에 관련된 제이쿼리를 확인해 보도록 하자.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jQuery를 활용한 클래스 단일, 다중 삭제하기(removeClass(),toggleClass())</title>
    <style>
        body {
            font-size: 20px;
            font-family: "고딕";            
        }
        .menu {
            padding: 10px;
            list-style: none;
            border: 2px solid black;
        }
        .menu li {
            border: 1px solid aqua;
            margin: 10px;
        }
        li.select {
            background-color: black;
            color : #fff;
            font-size: 30px;
        }
        li.border {
            border: 5px solid yellow;
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        $(document).ready(function(){
            //li객체에 클릭 이벤트를 등록을 하고 있다.
            $(".menu li").click(function(){
                // var $item = $(this);
                // //클릭된 li객체가 select클래스를 가지고 있지 않다면 select클래스를 추가하기
                // if($item.hasClass("select") == false){
                //     $item.addClass("select");
                // }
                // else{  //select클래스를 가지고 있다면, 제거하기
                //     $item.removeClass("select");
                // }

                //toggleClass()는 스위치, 플래그 변수처럼 없으면 추가, 있으면 삭제형태로
                //작동한다.위의 소스가 그대로 적용이 되어있다.
                $(this).toggleClass("select");
            });           
        });
    </script>
</head>
<body>   
    <ul class="menu">
        <li>메뉴1</li>
        <li>메뉴2</li>
        <li class="select">메뉴3</li>
        <li>메뉴4</li>
        <li>메뉴5</li>
    </ul>    
</body>
</html>

 

클릭 메서드를 통해 li요소에 대해 select 클래스를 토글한다. 이는 클래스가 있다면 제거하고 없다면 추가하게 되는 것이다.

 

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>jQuery를 활용한 글자의 랜덤 크기 및 랜덤 색상 출력하기</title>
    <style>
        #panel {
            width: 600px;
            overflow: visible;
            border: 2px solid red;
            font-size: 20px;
        }        
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        var cnt = 0;
        var $panel = null;

        $(document).ready(function(){
            //초기화
            init();
            //타이머 시작
            start();
        });

        function init() {
            $panel = $("#panel");
        }
        function start() {
            //1초마다 addTag함수를 호출하는 것
            setInterval(addTag, 1000);
        }

        function addTag() {
            //span태그를 동적으로 생성하여 얻기
            var $span = $("<span></span>");
            //스타일 값 생성하기
            //색상을 16진수로 랜덤하게 구하고 있는 코드
            var color = "#" + (parseInt(Math.random() * 0xffffff)).toString(16);
            //10px~50px사이의 글자크기를 구하고 있는 코드
            var fontSize = (10 + parseInt(Math.random() * 40)) + "px";
            //위에서 구한 스타일 설정하기
            $span.css({
                color : color,
                fontSize : fontSize,
                display : "inline-block"
            });
            cnt++;
            //span태그 안에 cnt를 추가하고 있는 코드
            $span.html(cnt);
            //패널의 span객체를 추가함으로써 자식노드를 계속 추가를 하는 코드
            $panel.append($span);
        }              
    </script>
</head>
<body>   
    <div id="panel">  
    </div>
</body>
</html>

 

div 단락에 랜덤 크기와 랜덤 색상의 1부터 값을 일정 주기에 따라 화면에 띄우는 예제이다. 이를 통해 각 함수 사용법과 스타일 사용법을 알 수 있다.

 

다음은 속성에 대해 알아보자.

 

속성

속성의 종류

일반 속성 : id, class, 태그, <a> 태그의 링크 정보를 담는 href, <img> 태그의 이미지 정보를 담는 src 등을 말한다.

사용자 정의 속성 : 사용자가 정의하는 속성으로 다음과 같이 사용할 수 있다.

 

속성값 구하기

$대상.attr("속성 이름"); 일반 속성 값 구하기

$대상.data("data-속성 이름"); data로 시작하는 속성 값 구하기

위와 같이 속성 값을 구할 수 있다.

 

속성 값 설정하기

$대상.attr("속성 이름", "값");

$대상.data("data-속성 이름", "값");

 

 

이와 같이 속성 값에 대한 것을 알아보았으니 다음으로 예제를 확인하고 넘어가 보자.

<!DOCTYPE html>
<html lang="ko"">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>속성값 읽기-1(attr())</title>
    <style>
        body{
            font-size: 25px;
        }
        .content {
            text-align: center;
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        $(document).ready(function(){
            //속성값 알아내기
            //img태그의 src속성값을 알아내고 있다.
            console.log("src = "+ $(".content img").attr("src"));
            //a태그의 href속성값을 알아내고 있다.
            console.log("href = " + $(".content a").attr("href"));
        });
    </script>
</head>
<body>
    <div class="content">
        <img src="images/codingBrother.png">
        <br/>
        <a href="http://www.naver.com">네이버</a>
    </div>
    
</body>
</html>

 

콘솔에 각 속성을 나타내는 값을 나타낼 수 있으며 a태그 부분을 클릭하면 해당한 링크로 이동할 수 있다.

 

<!DOCTYPE html>
<html lang="ko"">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>속성값 읽기-2(attr(),data())</title>
    <style>
        body{
            font-size: 25px;
        }
        .content {
            text-align: center;
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        $(document).ready(function(){
            var $content = $(".content");
            //속성값 알아내기
            //data()는 data-로 시작하는 모든 속성값을 Object값으로 리턴해준다.
            console.log("data() = ", $content.data());
            //data-name값을 출력하고 있다.
            console.log("data(name) = ", $content.data("name"));
            //attr()로도 data-name값을 출력할 수가 있다.
            console.log("attr(data-name) = ", $content.attr("data-name"));
            //data()는 data-로 시작하는 값만 출력함을 알 수가 있다.
            console.log("data(temp-data) = ", $content.data("temp-data"));
            //attr()로는 temp-data도 출력되는 것을 알 수가 있다.
            console.log("attr(temp-data) = ", $content.attr("temp-data"));
        });
    </script>
</head>
<body>
    <div class="content" data-name="스파크" data-tel="01011114444" 
         data-img="images/codingBrother.png" temp-data="test">
        <p class="name">jquery</p>
        <p class="tel">01044441111</p>
        <img src="images/codingBrother.png">
    </div>
    
</body>
</html>

 

각 사용자 설정 속성 값을 부여하고 콘솔 로그로 확인할 수 있는 예제이다.

<!DOCTYPE html>
<html lang="ko"">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>속성값 설정-1(attr())</title>
    <style>
        body{
            font-size: 25px;
        }
        .content {
            text-align: center;
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        $(document).ready(function(){
            var $image = $("#image");
            var flag = true;  //flag변수

            $image.click(function(){
                flag = !flag;  //불린값이니깐 반대의 값을 저장한다.
                
                if(flag){
                    //attr()로 속성의 값을 설정하고 있다.
                    $image.attr("src","images/cat.png");
                }
                else {
                    $image.attr("src","images/dog.png");
                }
            });
        });
    </script>
</head>
<body>
    <img src="images/cat.png" id="image">    
</body>
</html>

 

이미지 클릭 시에 이미지의 속성 값을 설정해 주는 예제이다.

 

사용자 설정 속성 값을 HTML 요소에 부여하는 이점에 대해서 알아보고 넘어가자.

 

데이터 저장 및 접근 용이성

data-* 속성은 HTML 요소에 메타데이터를 저장할 수 있는 방법을 제공한다. 이를 통해 자바스크립트 코드에서 쉽게 데이터를 접근하고 조작할 수 있다.

 

HTML과 자바스크립트의 분리

data-* 속성을 사용해 HTML 구조와 자바스크립트 로직을 명확하게 분리할 수 있다. 이는 코드의 유지보수성과 가독성을 향상한다.

 

복잡한 데이터 구조 지원

data-* 속성은 객체나 배열과 같은 복잡한 데이터 구조를 문자열 형식으로 저장하고 자바스크립트에서 쉽게 파싱 할 수 있다. 이는 요소와 관련된 다양한 데이터를 저장하고 접근할 수 있게 한다.

 

SEO와 접근성 유지

검색 엔진과 스크린 리더 등 접근성 도구에 영향을 주지 않는다. 이는 웹 페이지의 SEO와 접근성을 유지하면서 사용자 정의 데이터를 추가할 수 있음을 의미한다.

 

CSS와의 통합

data-* 속성은 CSS에서도 사용할 수 있다. 예시로 특정 data-* 속성을 가진 요소를 스타일링할 수 있다.

div[data-name="테스트"] {
    background-color: yellow;
}

 

JQuery의 편리한 데이터 접근 메서드 제공

$(document).ready(function(){
    var $content = $(".content");
    console.log("data() = ", $content.data()); // 모든 data-* 속성을 객체로 반환
    console.log("data(name) = ", $content.data("name")); // "스파크"
    console.log("attr(data-name) = ", $content.attr("data-name")); // "스파크"
    console.log("data(temp-data) = ", $content.data("temp-data")); // undefined
    console.log("attr(temp-data) = ", $content.attr("temp-data")); // "test"
});

 

속성 접근을 보다 간단하고 직관적으로 만들어 준다.

 

attr(), data() 메서드를 확인하고 다음으로 넘어가 보자.

 

attr() 메서드는 HTML 요소의 속성을 읽거나 설정하는 데 사용된다. 모든 HTML 속성에 접근할 수 있고 사용자 정의 속성도 포함된다.

 

data() 메서드는 data-* 속성에 특화되어 있으며 HTML5에서 도입된 사용자 정의 데이터 속성인 data-* 속성에 접근하고 조작할 때 사용된다.

 

차이점

접근 범위

attr() : 모든 HTML 속성에 접근 가능

data() : 주로 dta-* 속성에 접근

 

데이터 형식

attr() : 문자열 형식으로 값을 읽고 설정

data() :  객체 형식으로 여러 data-* 속성을 한 번에 다룰 수 있으며 숫자나 객체 등 다양한 데이터 형식을 지원

 

성능

attr() : 매번 DOM에 접근해 속성 값을 읽고 설정

data() : 첫 번째 접근 시 DOM에서 값을 읽고 JQuery 객체에 캐시해 성능 최적화

 

데이터 캐싱

attr() : HTML에 즉시 반영

data() : 설정한 데이터는 JQuery 객체에 캐시 되어 HTML에 즉시 반영되지 않음

 

 

이벤트

이벤트란 일종의 알람으로 보면 된다. 웹 페이지에서는 클라이언트 측 사용자가 클릭을 하거나 키보드를 치거나 하는 일련의 행위들을 말한다.

만약 클릭으로 버튼을 클릭한다는 이벤트 흐름을 확인하자.

1. 사용자가 버튼 클릭

2. 이벤트 핸들러 등록 - 제이쿼리를 사용해 버튼에 이벤트 핸들러 등록

3. MouseEvnet 객체 생성 - 브라우저가 마우스이벤트 객체를 생성

4. 이벤트 핸들러 실행 - 제이쿼리가 등록된 이벤트 핸들러 함수를 호출하고 마우스이벤트 객체를 인자로 전달한다.

이 과정을 통해 제이쿼리가 이벤트를 처리하는 일반적인 방식을 설명했다.

 

이벤트 종류

크게 사용하는 분류를 통해 알아보자.

이벤트는 크게 4가지로 정도로 분류가 이루어진다.

 

마우스 이벤트 : 사용자가 마우스 버튼을 눌렀을 때 발생하는 이벤트를 말하며, 이때 사용자가 누른 마우스 버튼,화면상에서 마우스 버튼이 눌린 위치, Ctrl키 또는 Alt, Shift키 등을 누른 상태에서 마우스 버튼을 눌렀는지를 나타내는 정보가 담긴다.

 

키보드 이벤트 : 사용자가 키보드를 눌렀을 때 발생하는 이벤트, 이 때 눌린 키에 대한 정보가 담긴다.

 

태그요소 고유 이벤트 : Element마다 발생하는 고유의 이벤트이며, 예를 들면 <img> 태그요소의 경우 이미지가 모두 로드되면 load() 이벤트를 발생시켜 이미지가 성공적으로 로드됐음을 알리며, <input> 태그요소의 경우 입력한 정보가 바뀌면 change이벤트를 발생시켜 입력 정보가 변경됐음을 알린다.

 

사용자 정의 이벤트 : 개발자가 직접 만들어 사용하는 이벤트, 주로 개발자 고유 라이브러리 또는 클래스를 만들고 이를 사용한 어떤 작업이 끝났음을 사용자에게 알려줄 때 개발자만의 이벤트를 만들어 사용한다.

 

이벤트 단계

자바스크립트의 이벤트를 이해하려면 이벤트 흐름을 알아야 한다. 이벤트는 크게 3단계에 걸쳐 발생한다.

각 캡처 단계, 타겟 단계, 버블 단계로 나눌 수 있다. 각 단계에 대해 알아보자.

 

캡처 단계 - 이벤트가 DOM 트리의 최상위 요소에서 시작하여 이벤트가 발생한 타겟 요소까지 내려가는 단계이다. 이 단계에서 상위요소에서 하위 요소로 이벤트가 전파된다.

가장 먼저 실행되는 이벤트 단계이다. 아울러, 이벤트 흐름은 가장 최상위 노드인 documen에서 시작해서 <html>, <body> 태그를 거쳐 실제 이벤트를 발생시킨 B1 노드 전까지 흐르게 되며 이 단계까지를 캡처 단계라고 한다.

만약, 거쳐오면서 만나는 노드 중 캡쳐 단계에 이벤트 리스너가 등록되어 있다면 이벤트 리스너가 실행된다.

등록 방법은 $대상.get(0).addEventListener(이벤트 이름, 리스너, true);

단, jQuery의 경우 캡처 단계에서 이벤트를 등록하는 기능이 없다. 하여, 다음과 같이 jQuery내부에 들어있는 자바스크립트 DOM에 접근해서 자바스크립트 방식으로 이벤트를 등록해야 한다. 자바스크립트에서 캡쳐 단계에 이벤트를 등록하는 방법은 addEventListener()의 마지막 인자에 true를 설정하면 된다.

 

타겟 단계 - 이벤트가 실제로 발생한 타켓 요소에서 이벤트가 처리되는 단계이다. 이 단계에서는 이벤트 핸들러가 타겟 요소에서 직접 실행된다.

타겟 단계에서는 이벤트 흐름이 이벤트를 발생시킨 노드에 머무르는 단계를 말한다. 이때 이벤트를 발생시킨 노드에 이벤트가 등록되어 있다면 리스너가 실행된다.

등록 방법은 $대상.on(이벤트 이름, 리스너);

on() 메서드와 같은 jQuery의 이벤트 관련 메서드를 사용해 이벤트를 등록하는 경우 타킷과 버블링 단계에 등록이 된다.

자바스크립트로 타깃, 버블링 단계에 이벤트를 등록하는 방법

대상.addEventListener(이벤트 이름, 리스너, false);

캡처 단계에 이벤트 리스너를 등록하는 방법과 다른 점이라면 마지막 매개변수의 값에 false를 대입하는 것이다.

 

버블 단계 = 이벤트가 타겟 요소에서 시작해 다시 DOM 트리의 최상위 요소까지 올라가는 단계이다. 이 단계에서는 하위 요소에서 상위 요소로 이벤트가 전파된다.

버블 단계는 캡처 단계의 역순으로 이벤트가 흐른다는 것이다. 이 흐름은 버블링(bubbling)이라고 한다. 예를 들어 B1노드가 클릭이 된 경우 이벤트는 캡쳐 단계의 역순인 A1노드를 시작으로 body와 html노드를 거쳐 document객체로 흐르게 된다.이 때 만나는 노드에 버블 단계의 이벤트가 등록되어 있다면 리스너가 실행된다.
이벤트 등록 방법

$대상. on(이벤트 이름, 리스너);

앞서 말했듯이 타깃 단계와 버블 단계에 이벤트를 등록하는 방법은 동일하다. 하여, 타깃 단계인지 버블 단계인지를 구분할 때는 Event객체의 eventPhase속성을 사용하면 된다.

모든 이벤트가 버블링이 발생하진 않는다는 것이다. 또한 버블링이 발생하는 이벤트의 경우 버블링을 도중에 멈출 수도 있다는 것이다. 이와 관련해서는 이벤트 객체에 대해 알아야 한다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>이벤트 전파 단계</title>
    <style>
        .outer {
            border: 2px solid red;
            padding: 20px;
        }
        .inner {
            border: 2px solid green;
            padding: 20px;
        }
        .button {
            border: 2px solid blue;
            padding: 10px;
            cursor: pointer;
        }
    </style>
</head>
<body>
    <div class="outer">
        Outer
        <div class="inner">
            Inner
            <div class="button">Button</div>
        </div>
    </div>

    <script>
        document.querySelector('.outer').addEventListener('click', function(event) {
            console.log('Outer 캡처 단계');
        }, true);

        document.querySelector('.inner').addEventListener('click', function(event) {
            console.log('Inner 캡처 단계');
        }, true);

        document.querySelector('.button').addEventListener('click', function(event) {
            console.log('Button 캡처 단계');
        }, true);

        document.querySelector('.outer').addEventListener('click', function(event) {
            console.log('Outer 버블 단계');
        });

        document.querySelector('.inner').addEventListener('click', function(event) {
            console.log('Inner 버블 단계');
        });

        document.querySelector('.button').addEventListener('click', function(event) {
            console.log('Button 버블 단계');
        });
    </script>
</body>
</html>

 

위 예제로 이벤트 각 단계에 대해 알아볼 수 있다.

 

이와 같은 로그를 확인할 수 있고 각 단계별로 어떤 동작을 하는지 확인해 보자.

캡처 단계 : addEventListener 메서드의 세 번째 인자로 true를 전달하면 해당 이벤트 핸들러는 캡처 단계에서 실행된다.

true를 인자로 전달할 경우 이벤트는 상위 요소부터 하위 요소로 전파되면서 핸들러가 실행된다.

Outer - Inner - Button 캡처 단계가 순서대로 출력된다.

 

타겟 단계 : 타겟 요소인 .button에서 이벤트가 발생한다. 특별한 설정 없이 이벤트 핸들러가 실행된다.

버튼 캡처 단계와 버튼 버블 단계 출력 사이에 타켓 단계가 존재하지만 캡처 단계와 버블 단계의 중간이므로 출력이 겹친다.

 

버블 단계 : addEventListener 메서드의 세 번째 인자로 false를 전달하거나 생략하면 해당 이벤트 핸들러는 버블 단계에서 실행된다.

false를 인자로 전달하는 경우 이벤트는 하위 요소부터 상위 요소로 전파되며 핸들러가 실행된다. Button - Inner - Outer 순서로 콘솔에 출력하게 된다.

 

이를 요약하게 된다면

캡처 단계 : 이벤트가 상위 요소에서 타겟 요소로 내려가는 단계

타겟 단계 : 이벤트가 실제로 타겟 요소에서 처리되는 단계

버블 단계 : 이벤트가 타겟 요소에서 상위 요소로 올라가는 단계

제이쿼리는 기본적으로 이벤트를 버블 단계에서 처리하지만 이벤트 전파를 조절하기 위해 stopPropagation이나 stopImmediatePropagation 메서드를 사용할 수 있다.

 

이벤트 객체의 용도와 구조를 확인해 보자.

 

용도

이벤트 객체는 이벤트를 발생시키는 곳에서 이벤트와 관련된 정보를 담아 외부로 보낼 때 사용하는 일종의 저장소이다.

사용자가 웹페이지의 특정 요소를 클릭했다 할 때 브라우저는 클릭한 마우스 버튼 정보와 클릭한 위치정보 등 여러 요소에서 이벤트가 발생했는지에 대한 정보를 이벤트 객체의 자식 객체인 MouseEvent 객체에 담아 사용자에게 알려준다.

 

구조

Event 객체에는 이벤트와 관련된 기본 기능이 구현되어 있다.

 

 

 

MouseEvent는 UIEvent를 상속하고 UIEvent는 Event 객체를 상속한다.

 

일반 이벤트 등록으로 $대상.on("이벤트 이름", 리스너); 로 등록한다.

on() 메서드를 통해 등록하는 방법이 가장 일반적인 방법이다.

 

단축 이벤트 등록

제이쿼리에서는 일반적으로 많이 사용하는 이벤트를 좀 더 쉽게 사용할 수 있게 단축 이벤트 메서드를 가지고 있다.

예시로 click 이벤트를 등록하는 경우 단축이벤트 메서드를 사용하면 간결하게 사용할 수 있다.

$대상.on("click", function(){}); -> $대상.click(function(){});

단축 이벤트 목록

blur, change, load, unload, resize, scroll, select, submit, click, dbclick, mousedown, mouseup, mousemove,mouseover, mouseout, mouseenter, mouseleave, focus, keydown, keyproess, keyup 등

 

등록한 이벤트 제거

on() 메서드 또는 단축형 이벤트 메서드를 이용해 등록한 이벤트를 제거하려면 모두 off() 메서드를 사용한다.

사용법

$대상.off("click", 삭제하고 싶은 이벤트 리스너); 특정 이벤트에 대한 리스너를 제거하고 싶은 경우

$대상.off("click"); 특정 이벤트에 걸려있는 모든 이벤트 리스너를 제거하고 싶은 경우

$대상.off(); 노드에 걸려있는 모든 이벤트를 제거하고 싶은 경우

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>이벤트 등록(일반, 단축) 및 제거</title>
    <style>
        body {
            font-size: 30px;
        }
        #btn, #remove {
            font-size: 25px;
            margin: 20px;
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        $(document).ready(function(){
            //버튼에 일반 이벤트 등록(on())
            // $("#btn").on("click", function(e){
            //     alert("반갑습니다.");
            // });

            //버튼에 단축 이벤트 등록(click())
            //이 단축 이벤트는 내부적으로는 on()형태로 실행이 됨을 알도록 하자.
            // $("#btn").click(function(e){
            //     alert("반갑습니다.");
            // });

            // $("p").on("mouseenter mouseleave", function(e){
            //     console.log("p태그에 들어오거나 나갔습니다.");
            // });   
            //이벤트를 다중으로 걸고자 할때 아래와 같이 사용하면 된다.
            // $("p").on({
            //     click : function(){
            //         console.log("p태그가 클릭되었습니다.");
            //     },
            //     mouseenter : function() {
            //         console.log("p태그에 마우스가 들어왔습니다.");
            //     },
            //     mouseleave : function() {
            //         console.log("p태그에 마우스가 나갔습니다.");
            //     }
            // });  
            //단축이벤트 등록
            $("p").mouseenter(function(e){
                console.log("p태그에 마우스가 들어왔습니다.");
            });
            $("p").click(function(e){
                console.log("p태그에 마우스가 클릭되었습니다.");
            });
            $("p").mouseleave(function(e){
                console.log("p태그에 마우스가 나갔습니다.");
            });
            //이벤트 제거 방법(off())
            $("#remove").click(function(e){
                //$("p").off();  //등록된 이벤트 전부 제거
                $("p").off("click"); //클릭 이벤트만 제거
            });
        });
    </script>
</head>

<body>
    <button id="btn">실행</button>    
    <button id="remove">제거</button>
    <p>안녕하세요</p>
    <div></div>
</body>
</html>

 

이벤트 한 번만 실행

이벤트를 오직 한 번만 실행하고 이후 실행되지 않게 이벤트를 제거하는 경우 one() 메서드를 사용하면 된다.

사용법

$대상.one(이벤트 이름, 이벤트 리스너);

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>이벤트를 단 한번만 실행</title>
    <style>
        body {
            font-size: 30px;
        }
        #btn{
            font-size: 25px;
            margin: 20px;
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        $(document).ready(function(){
            //이벤트를 오직 한번만 실행하고 이후 실행되지 않게 이벤트를 제거하는 경우에
            //one()를 사용하면 된다.
            $("#btn").one("click", function(e){
                alert("안녕하세요.");
            });
          
        });
    </script>
</head>

<body>
    <button id="btn">실행</button>       
</body>
</html>

 

기본 행동 취소

기본 행동이란 a태그의 속성 값으로 연결한 값을 클릭 이벤트 발생 시 링크로 이동하는 것을 기본 행동이라 하고 모든 이벤트가 기본 행동을 취소할 수 있는 것은 아니다. 이벤트 발생 후 실행되는 기본 행동이 있는지 알고 싶다면 이벤트 객체의 cancelable 프로퍼티 값을 확인하면 된다. 이 값이 true면 이벤트 실행 후 기본 행동이 실행된다는 것이다. 이벤트 객체의 preventDefault() 메서드를 이용해 기본 행동이 실행되지 않게끔 할 수 있다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>기본행동 취소</title>
    <style>
        body {
            font-size: 30px;
        } 
        a {
            font-size: 30px;
        }      
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        $(document).ready(function(){
            //기본행동은 어떠한 특정태그가 이벤트가 발생을 하게 되면 해당 태그만이
            //작동하는 기본적인 행동을 의미한다.
            //preventDefault()는 기본행동을 취소해주는 기능을 가지고 있다.
            $("#test").on("click", function(e){
                //alert("반갑습니다.");
                //cancelable값이 true이면 기본행동이 있다.
                console.log("cancelable값 : " + e.cancelable);
                //기본 행동 취소
                e.preventDefault();
            });         
        });
    </script>
</head>

<body>
    <a href="http://www.naver.com" id="test">네이버로 이동</a>
</body>
</html>

 

버블링 멈추기

버블링은 이벤트 흐름의 마지막 단계의 흐름이었다. 모든 이벤트가 버블링이 발생하는 것은 아니고 이벤트가 버블링이 발생하는지 알려면 발생한 이벤트 객체의 bubbles 프로퍼티 값을 확인하면 된다. 이 값이 true라면 이벤트 객체에서 제공하는 stopPropagation() 메서드를 이용해 버블링을 멈출 수 있다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>버블링 멈추기</title>
    <style>
        body {
            font-size: 30px;
        } 
        #btn1, #btn2 {
            font-size: 30px;
        }      
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        $(document).ready(function(){
            //panel클릭 이벤트 리스너를 등록
            $("#panel").click(function(e){
                console.log("panel에 등록된 클릭 이벤트");
                //모든 이벤트가 버블링 발생하는 것이 아니다.
                //bubbles라는 프로퍼티 값이 true이라면 버블링이 발생하는 태그다.
                console.log("panel bubbles : " + e.bubbles);
            });
            //btn1에 클릭 이벤트 리스너를 등록
            $("#btn1").click(function(e){
                console.log("btn1 버블링 처리");
                console.log("btn1 bubbles : " + e.bubbles);
            });

            //btn2에 클릭 이벤트 리스너를 등록
            $("#btn2").click(function(e){
                console.log("btn2 버블링 중지");
                console.log("btn2 bubbles : " + e.bubbles);
                //버블링 중지 메서드 호출
                e.stopPropagation();
            }); 
        });
    </script>
</head>
<body>
    <div id="panel">
        <button id="btn1">버블링처리</button>
        <button id="btn2">버블링중지</button>
    </div>
   
</body>
</html>

 

버블링 활용 - 하나의 이벤트 리스너로 여러 이벤트 처리하기

li 객체는 ul 객체 안에 여러 개로 존재하게 된다 그때 li 객체에 이벤트를 등록하게 되면 li 개수만큼 이벤트 리스너가 등록되는데 이 부분을 버블링을 활용하면 하나의 이벤트 리스너로 다룰 수 있다.

사용법

$대상.on(이벤트명", "선택자", 이벤트 리스너);

on() 메서드를 위의 사용법처럼 3개의 매개변수를 이용해 호출하면 선택자에만 리스너가 등록되어진다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>버블링 활용-1(하나의 이벤트 리스너를 통해서 여러 이벤트를 처리하는 코드)</title>
    <style>
        body {
            font-size: 30px;
        } 
        ul {
            border: 1px solid black;
        }
        ul li {
            border: 1px solid red;
            margin: 20px;
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        $(document).ready(function(){
            //메뉴 항목(li) 클릭 이벤트 등록하기
            //아래 내용은 모든 li객체에 이벤트 리스너가 5개가 등록이 되어있는 것이다.
            //리스너가 많게 되니 효율적인 측면에서 좋은편이 아니다.
            // $(".menu li").on("click", function(e){
            //      //클릭된 태그를 출력하고 있는 코드
            //     console.log(e.target.tagName);
            //     alert($(this).html());
            // });
            
            //ul태그에만 이벤트 리스너 단 1개만 등록을 한 것이다.
            //selector를 이용하여 위의 코드에 비하여 효율적인 코드가 된다.
            //버블링을 이용하여 하나의 이벤트 리스너를 통해서 여러 이벤트를 처리하는 코드
            $(".menu").on("click","li", function(e){
                //클릭된 태그를 출력하고 있는 코드
                console.log(e.target.tagName);
                alert($(this).html());
            });


        });
    </script>
</head>
<body>
    <ul class="menu">
        <li>메뉴1</li>
        <li>메뉴2</li>
        <li>메뉴3</li>
        <li>메뉴4</li>
        <li>메뉴5</li>
    </ul>  
   
</body>
</html>

 

버블링 활용 2 - 라이브 이벤트

버블링을 활용하면 아직 만들어져 있지 않은 노드에서 발생하는 이벤트까지 처리할 수 있다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>버블링 활용-2(라이브 이벤트)-일반적 방법</title>
    <style>
        body {
            font-size: 30px;
        }
        #add {
            font-size: 30px;
        } 
        ul {
            border: 1px solid black;
        }
        ul li {
            border: 1px solid red;
            margin: 20px;
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        $(document).ready(function(){
            // var $menu = $(".menu");
            // var cnt = 5; //카운트 변수 추가
            
            // $("#add").click(function(e){
            //     cnt++; //카운트 증가
            //     //동적으로 메뉴 추가
            //     $menu.append("<li>메뉴" + cnt + "</li>");
            // });
            // //메뉴 항목에 클릭 이벤트 등록
            // //단점은 동적으로 추가하는 신규메뉴는 클릭을 해도 메뉴의 정보가 출력이 안된다.
            // //이유는 바로 이벤트를 등록하는 시점에 신규 메뉴 항목은 등록이 되지 않았어
            // //출력을 되지않는다.
            // $(".menu li").click(function(e){
            //     alert($(this).html());
            // });


            //위의 코드의 단점을 보완한 일반적인 코드    
            var $menu = $(".menu");
            var cnt = 5; //카운트 변수 추가
            
            $("#add").click(function(e){
                cnt++; //카운트 증가
                //동적으로 신규 메뉴 항목 생성
                var $newItem = $("<li>메뉴" + cnt + "</li>"); 

                //신규 메뉴 항목에다가 클릭 이벤트를 등록하는 코드
                //신규 메뉴가 추가될 때마다 이벤트 리스너가 늘어난다.코드의 효율이 
                //나쁘다.
                $newItem.on("click",function(e){
                    alert($(this).html());
                });
                //메뉴 추가
                $menu.append($newItem);
            });
            //메뉴 항목에 클릭 이벤트 등록            
            $(".menu li").click(function(e){
                alert($(this).html());
            });
        });
    </script>
</head>
<body>
    <div>
        <button id="add">추가</button>
    </div>
    <ul class="menu">
        <li>메뉴1</li>
        <li>메뉴2</li>
        <li>메뉴3</li>
        <li>메뉴4</li>
        <li>메뉴5</li>
    </ul>     
</body>
</html>
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>버블링 활용-2(라이브 이벤트)-버블링 활용 방법</title>
    <style>
        body {
            font-size: 30px;
        }
        #add {
            font-size: 30px;
        } 
        ul {
            border: 1px solid black;
        }
        ul li {
            border: 1px solid red;
            margin: 20px;
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        $(document).ready(function(){
            var $menu = $(".menu");
            var cnt = 5; //카운트 변수 추가
            
            $("#add").click(function(e){
                cnt++; //카운트 증가
                //동적으로 신규 메뉴 항목 생성
                var $newItem = $("<li>메뉴" + cnt + "</li>");                
                //메뉴 추가
                $menu.append($newItem);
            });
            //메뉴 항목에 클릭 이벤트 등록            
            //ul태그에만 이벤트 리스너를 등록을 하였다.
            //동적으로 추가되는 메뉴항목의 대한 버블링을 활용하여 이벤트 리스너를 실행하게
            //된다.버블링으로 가능한 코드가 되고 아울러 코드의 효율성이 좋아진다.
            $(".menu").on("click","li",function(e){
                alert($(this).html());
            });
        });
    </script>
</head>
<body>
    <div>
        <button id="add">추가</button>
    </div>
    <ul class="menu">
        <li>메뉴1</li>
        <li>메뉴2</li>
        <li>메뉴3</li>
        <li>메뉴4</li>
        <li>메뉴5</li>
    </ul>     
</body>
</html>

 

이벤트 발생시키기

한 번씩 실제 마우스를 클릭하지 않았지만 클릭한 것처럼 특정 노드에 수동으로 이벤트를 발생시켜야 하는 경우에는 trigger()를 이용하면 된다.

사용법

$대상.trigger("이벤트명");

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>이벤트 강제로 발생시키키(trigger())-1</title>
    <style>
        body {
            font-size: 30px;
        }
        #btn1, #btn2 {
            font-size: 30px;
        } 
        
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        $(document).ready(function(){
            $("#btnA").on("click", function(e){
                //강제로 btnB에 click 이벤트가 발생되도록 한다.
                $("#btnB").trigger("click");
            });

            //btnB에 클릭 이벤트를 등록
            $("#btnB").on("click", function(e){
                alert("버튼B가 클릭되었습니다.");
            });
        });
    </script>
</head>
<body>
    <button id="btnA">버튼A</button>
    <button id="btnB">버튼B</button>    
</body>
</html>

 

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>이벤트 강제로 발생시키키(trigger())-2</title>
    <style>
        .test {
            width: 100px;
            height: 30px;
            margin: 0 auto;
            background-color: black;
            text-align: center;
            color: white;
        }
        #addtest {
            width: 100px;
            margin : 0 auto;
            margin-top: 20px;
            font-size: 20px;
            text-align: center;
            display: block;
        }        
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        $(document).ready(function(){
            var cnt = 0;
            $("#testspan").on("click", function(e){
                ++cnt;
                $("#testspan").text(cnt);
            });
            //버튼 addtest에 클릭이벤트 리스너의 내용이 testspan에 강제로 
            //click이벤트를 발생시키도록 하고 있다.
            $("#addtest").on("click", function(e){
                $("#testspan").trigger("click");
            });           
        });
    </script>
</head>
<body>
    <div class="test">
        숫자 : <span id="testspan"><b>0</b></span>
    </div>
    <button id="addtest">증가</button>    
</body>
</html>

 

사용자 정의 이벤트 만들기

2가지 방법으로 사용자 정의 이벤트를 만들 수 있다.

방법 1

var event = JQuery.Event("이벤트 이름");

event.데이터1 = 값;

event.데이터2 = 값; ...

$대상.trigger(event)

 

방법 2

var event = JQuery.Event("이벤트 이름");

$대상.trigger(event, 데이터1=값, 데이터2=값, ...);

 

위 방법은 이벤트 객체 생성 -> 이벤트 발생 리스너에 보낼 데이터 생성 -> 이벤트 발생 이 순서로 이루어진다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>사용자 정의 이벤트 만들기-1</title>
    <style>
        body {
            font-size: 20px;
            font-family: "맑은 고딕";
        }
        ul, li {
            border: 1px solid gray;
            margin: 15px;
        }
        ul {
            padding: 10px;
        }
        li.select {
            background-color: #ccc;
        }
        #output {
            border: 2px solid black;
            min-height: 100px;
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        $(document).ready(function(){
            var $output = $("#output");
            var $menu = $(".menu");
            var cnt = 5;

            $("#add").click(function(e){
                cnt++;
                //신규 메뉴 항목 생성
                var $newItem = $("<li>메뉴" + cnt + "</li>");
                $menu.append($newItem);  //메뉴에 마지막 자식으로 추가

                //사용자 정의 이벤트 객체 생성
                //이벤트 이름이 addItem이 된다.
                var event = jQuery.Event("addItem");
                //이벤트 데이터를 하나하나 포장하는 개념
                event.item = $newItem;   //사용자 정의 이벤트 item에게 신규 아이템을 저장
                event.itemName = $newItem.text();  //메뉴6, 메뉴7...추가되는 메뉴항목 이름 저장
                event.itemLength = $menu.children().length; //메뉴 항목의 길이 저장
                //addItem사용자 정의 이벤트를 강제로 이벤트 발생시키고 있다.
                $menu.trigger(event);
            });
            //addItem의 이벤트 리스너 등록
            $menu.on("addItem", function(e){
                $output.prepend("<p>추가 아이템 : " + e.itemName + ", 아이템 갯수 : " 
                               + e.itemLength + "</p>")
            });
            
        });
    </script>
</head>
<body>
    <div>
        <button id="add">추가</button>
    </div>
    <ul class="menu">
        <li>메뉴1</li>
        <li>메뉴2</li>
        <li>메뉴3</li>
        <li>메뉴4</li>
        <li>메뉴5</li>
    </ul>
    <p>추가 및 삭제 정보 출력</p>
    <div id="output">        
    </div>
</body>
</html>
<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>사용자 정의 이벤트 만들기-2</title>
    <style>
        body {
            font-size: 20px;
            font-family: "맑은 고딕";
        }
        ul, li {
            border: 1px solid gray;
            margin: 15px;
        }
        ul {
            padding: 10px;
        }
        li.select {
            background-color: #ccc;
        }
        #output {
            border: 2px solid black;
            min-height: 100px;
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        $(document).ready(function(){
            var $output = $("#output");
            var $menu = $(".menu");
            var cnt = 5;

            $("#add").click(function(e){
                cnt++;
                //신규 메뉴 항목 생성
                var $newItem = $("<li>메뉴" + cnt + "</li>");
                $menu.append($newItem);  //메뉴에 마지막 자식으로 추가

                //사용자 정의 이벤트 객체 생성
                //이벤트 이름이 addItem이 된다.
                var event = jQuery.Event("addItem");
                //이벤트 발생시 리스너로 넘길 데이터를 직접 생성
                //넘기는 데이터의 값 : 신규 메뉴 객체, 신규 메뉴의 이름, 메뉴의 길이
                var data = [$newItem, $newItem.text(), $menu.children().length];    
                //addItem사용자 정의 이벤트를 강제로 이벤트 발생시키고 있다.
                //단, 방법1에 비해서 매개변수 2개를 주고 있다는 점을 기억하자.
                $menu.trigger(event, data);
            });
            //addItem의 이벤트 리스너 등록
            $menu.on("addItem", function(e, $item, itemName, itemLength ){
                $output.prepend("<p>추가 아이템 : " + itemName + ", 아이템 갯수 : " 
                               + itemLength + "</p>")
            });
            
        });
    </script>
</head>
<body>
    <div>
        <button id="add">추가</button>
    </div>
    <ul class="menu">
        <li>메뉴1</li>
        <li>메뉴2</li>
        <li>메뉴3</li>
        <li>메뉴4</li>
        <li>메뉴5</li>
    </ul>
    <p>추가 및 삭제 정보 출력</p>
    <div id="output">        
    </div>
</body>
</html>

 

많이 사용되는 이벤트 중 mouseover와 mouseenter의 차이점을 확인해 보자. 위에 예제에서도 사용된 것을 확인할 수 있다.

 

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>mouseover / mouseout의 예제</title>
    <style>
        #parent {
            width: 500px;
            height: 500px;
            position: absolute;
            left: 200px;
            top:100px;
            background-color: red;
        }
        #child {
            width: 200px;
            height: 200px;
            position: absolute;
            left: 100px;
            top : 100px;
            background-color: white;
            
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        //전역 변수 초기화
        var count = 0;
        var $info = null;
        var $child = null;
        $(document).ready(function(){
            $info = $("#info");
            $child = $("#child");
            //parent에 mouseover,mouseout이벤트를 등록을 해두었는데 parent영역에만 올리면
            //정상적인 값이 출력이 되지만, child영역에 mouseover를 하니 parent.out, child.over
            //가 동시에 출력이 된다.
            //mouseover,mouseout이벤트는 부모노드와 자식노드는 별개이면서 자식노드는 독립적
            //인 노드로 판단해서 이벤트가 발생한다.
            $("#parent").mouseover(function(e){
                count++;
                $info.html($info.html() + "<br/>" + count + ", " + e.target.id + ".over");
                
            });

            $("#parent").mouseout(function(e){
                count++;
                $info.html($info.html() + "<br/>" + count + ", " + e.target.id + ".out");
                
            });
            
        });
    </script>
</head>
<body>
    <div id="info">
        이벤트 정보 출력
    </div>
    <div id="parent">
        parent
        <div id="child">
            child
        </div>
    </div>
   
</body>
</html>

전파를 통해 parent와 child를 구성한 코드이며 parent내부에 child가 포함되었지만 독립적인 노드로 판단해 이벤트가 발생하게 된다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>mouseover / mouseout 이벤트의 문제점</title>
    <style>
        #parent {
            width: 300px;
            height: 100px;
            position: absolute;
            left: 200px;
            top:100px;
            background-color: red;
            border: 1px solid red;
            overflow: hidden;
        }
        #child {
            width: 100px;
            height: 200px;
            position: absolute;
            left: 100px;
            top : 0px;
            background-color: white;            
        }
        #child div {
            height: 100px;
            text-align: center;
            line-height: 100px;
            
        }
        #child div.over {
            background-color: yellow;
        }



    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        //전역 변수 초기화
        var count = 0;
        var $info = null;
        var $child = null;
        $(document).ready(function(){
            $info = $("#info");
            $child = $("#child");
            //parent에 mouseover,mouseout이벤트를 등록을 해두었는데 parent영역에만 올리면
            //정상적인 값이 출력이 되지만, parent영역과 child영역에 마우스를 왔다갔다 하면
            //마우스는 더 이상 움직이지 않는데 이벤트 리스너의 내부에 animate()메서드가
            //계속 실행된다.이러한 문제점을 해결하기 위해서는 mouseover / mouseout대신에
            //mouseenter / mouseleave를 사용하면 문제점을 해결할 수가 있다.
            $("#parent").mouseover(function(e){
                count++;
                $info.html($info.html() + "<br/>" + count + ", " + e.target.id + ".over");
                $child.animate({
                    top : -100
                }, 300);
            });

            $("#parent").mouseout(function(e){
                count++;
                $info.html($info.html() + "<br/>" + count + ", " + e.target.id + ".out");
                $child.animate({
                    top : 0
                }, 300);
            });
            
        });
    </script>
</head>
<body>
    <div id="info">
        이벤트 정보 출력
    </div>
    <div id="parent">
        parent
        <div id="child">
            <div>
                out
            </div>       
            <div class="over">
               over
            </div>
        </div>
    </div>
   
</body>
</html>

mouseover와 mouseout 이벤트 문제점을 나타내는 코드이다. 일반적으로 animate 메서드를 이용할 때 멈추는 기능인 stop을 같이 사용하지만 예제를 확인하기 위해 사용하지 않은 것이다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>mouseenter / mouseleave의 예제</title>
    <style>
        #parent {
            width: 500px;
            height: 500px;
            position: absolute;
            left: 200px;
            top:100px;
            background-color: red;
        }
        #child {
            width: 200px;
            height: 200px;
            position: absolute;
            left: 100px;
            top : 100px;
            background-color: white;
            
        }
    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        //전역 변수 초기화
        var count = 0;
        var $info = null;
        var $child = null;
        $(document).ready(function(){
            $info = $("#info");
            $child = $("#child");
            //parent에 mouseenter,mouseleave 이벤트를 등록을 해두었는데 mouseover/mouseout
            //이벤트와는 다르게 child영역이 독립적인 공간이 아니라 parent영역에 일부분으로
            //처리가 되는 것을 볼 수가 있다.
            $("#parent").mouseenter(function(e){
                count++;
                $info.html($info.html() + "<br/>" + count + ", " + e.target.id + ".over");
            });

            $("#parent").mouseleave(function(e){
                count++;
                $info.html($info.html() + "<br/>" + count + ", " + e.target.id + ".out");
            });
            
        });
    </script>
</head>
<body>
    <div id="info">
        이벤트 정보 출력
    </div>
    <div id="parent">
        parent
        <div id="child">
            child
        </div>
    </div>
   
</body>
</html>

이 예제는 mouseenter와 mouseleave 이벤트 예제로 child의 범위까지 parent로 적용되는 것을 확인할 수 있다.

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>mouseenter / mouseleave를 이용한 문제점 해결</title>
    <style>
        #parent {
            width: 300px;
            height: 100px;
            position: absolute;
            left: 200px;
            top:100px;
            background-color: red;
            border: 1px solid red;
            overflow: hidden;
        }
        #child {
            width: 100px;
            height: 200px;
            position: absolute;
            left: 100px;
            top : 0px;
            background-color: white;            
        }
        #child div {
            height: 100px;
            text-align: center;
            line-height: 100px;
            
        }
        #child div.over {
            background-color: yellow;
        }



    </style>
    <script src="libs/jquery-3.5.1.min.js"></script>
    <script>
        //전역 변수 초기화
        var count = 0;
        var $info = null;
        var $child = null;
        $(document).ready(function(){
            $info = $("#info");
            $child = $("#child");
            //ex15에서 생긴 문제점을 해결하기 위해서는 mouseover / mouseout대신에
            //mouseenter / mouseleave를 사용하면 문제점을 해결하였다.
            //이러한 이유로 실무에서는 메뉴 UI컨텐츠를 제작할 때는 mouseenter/mouseleave이벤트
            //를 사용을 한다.
            $("#parent").mouseenter(function(e){
                count++;
                $info.html($info.html() + "<br/>" + count + ", " + e.target.id + ".over");
                $child.animate({
                    top : -100
                }, 300);
            });
            $("#parent").mouseleave(function(e){
                count++;
                $info.html($info.html() + "<br/>" + count + ", " + e.target.id + ".out");
                $child.animate({
                    top : 0
                }, 300);
            });            
        });
    </script>
</head>
<body>
    <div id="info">
        이벤트 정보 출력
    </div>
    <div id="parent">
        parent
        <div id="child">
            <div>
                out
            </div>       
            <div class="over">
               over
            </div>
        </div>
    </div>
   
</body>
</html>

animate의 stop 기능 없이 parent에서 child 영역으로 움직이면 parent의 이벤트 반대의 경우 child의 이벤트만 발생한다. 그리고 불필요한 애니메이션이 실행되지 않는다. 마우스를 통한 UI 콘텐츠 제작 시 mouseenter/mouseleave 이벤트가 선호된다.

 

여기까지 이벤트를 다루는 것까지 예제와 함께 알아보았다. 포스팅이 너무 길어져서 좌표와 애니메이션은 다음 포스팅에서 다루도록 하겠다.

728x90

'front' 카테고리의 다른 글

DOM & CSSOM과 AJAX에 대해서  (0) 2024.07.04
JQuery 예제와 기능에 대해 2  (0) 2024.07.03
JQuery 예제  (0) 2024.07.01
JQuery 알아보기  (1) 2024.07.01
JavaScript 기초 예제  (1) 2024.07.01