본문 바로가기

HTML, CSS, ECMA6/자바스크립트(Java Script)

[자바스크립트] Event 처리

자바스크립트


실행 환경 {

‘IDE’ : ‘Eclipse’

‘Java_Version’ : ‘JDK 1.8’

‘Browser’ : ‘Chrome’

}

Event 처리

파일명 : event-ex02.html

<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
<script>
/* inline event */

var onClick = function(){
    console.log("clicked")
}

</script>
</head>
<body>
    <h1 onclick='console.log("clicked")'>Click-1</h1>
    <h1 onclick='onClick()' >Click-2</h1>
</body>
</html>

버튼을 클릭하여 카운터를 늘리는 이벤트처리

DOM Level 0 : Basic Event model (고전적인 이벤트처리)

파일명 : event-ex03.html

<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
<script>
/* DOM Level 0 : Basic Event model (고전적인 이벤트처리)*/

// 처음에 변수들이 로딩될 때 변수에 들어갈 수 있도록 해줘야 DOM이 만들어짐 
window.onload = function(){

    var button1 = document.getElementById('button-1');
    var button2 = document.getElementById('button-2');
    button1.onclick = function(event){
        var counter = document.getElementById('counter-1'); //span 태그 가져옴
        var count = Number(counter.innerText); // 0을 가져오나 명시적으로 number 형변환
        counter.innerText = count+1; //증가된 값을 다시 innerText로 넣어줌 

    }

    button2.onclick = function(event){
        var counter = document.getElementById('counter-2'); //span 태그 가져옴
        var count = Number(counter.innerText); // 0을 가져오나 명시적으로 number 형변환
        counter.innerText = count+1; //증가된 값을 다시 innerText로 넣어줌     
    }

    // DOM Level 0 는 이벤트 핸들러 하나만 연결할 수 있는 단점이 있다. 
    button2.onclick = function(event){
        console.log('another handdler called')

    }
}

</script>
</head>
<body>

    <button id='button-1'>button1</button>
    <button id='button-2'>button2</button>
    <h1> counter1: <span id='counter-1'>0</span></h1>    
    <h1> counter2: <span id='counter-2'>0</span></h1>

</body>
</html>

현재 버튼이 js에서 동일한 기능 2개를 각각 구현하게 되었다. 이를 해겨랗기 위한 data attribute를 써보자

<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
<script>
/* DOM Level 0 : Basic Event model (고전적인 이벤트처리)*/

// 처음에 변수들이 로딩될 때 변수에 들어갈 수 있도록 해줘야 DOM이 만들어짐 
window.onload = function(){

    var button1 = document.getElementById('button-1');
    var button2 = document.getElementById('button-2');    

    button1.onclick = function(event){
        // this : 현재 클릭된 event.targer이다.
        // 이벤트가 일어난 HTMLElement 객체
        var counter = document.getElementById(this.getAttribute('data-counterid')); //span 태그 가져옴
        var count = Number(counter.innerText); // 0을 가져오나 명시적으로 number 형변환
        counter.innerText = count+1; //증가된 값을 다시 innerText로 넣어줌     
    }
}

</script>
</head>
<body>
    <!-- reference되어 id를 동작시킴. -->
    <button id='button-1' data-counterid='counter-1'>button1</button>
    <button id='button-2' data-counterid='counter-2'>button2</button>
    <h1> counter1: <span id='counter-1'>0</span></h1>    
    <h1> counter2: <span id='counter-2'>0</span></h1>

</body>
</html>

DOM Level 2 : Standard Event model (addEventListener)

파일명 : event-ex04.html

<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
<script>
/* DOM Level 2 : Standard Event model (addEventListener) */

window.onload = function(){
    var header = document.getElementById('header');
    //MultiEvent Listener 연결가능
    // onserver pattern
    header.addEventListener('click', function(){
        console.log("click 1")
    })
    header.addEventListener('click', function(){
        console.log("click 2")
    })
    header.addEventListener('click', function(){
        console.log("click 3")
    })
}

</script>
</head>
<body>

    <h1 id='header'> header</h1>

</body>
</html>

위에서 고전적인 모델에서는 하나의 이벤트가 오버라이딩되었지만 DOM Level2에서는 하나의 element에도 여러가지 기능을 추가할 수 있다.

간혹 발생할 수 있는 브라우저간 문제로 인하여 CROSS BROWSING을 위하여 registerEventHandler를 생성한다.

<!DOCTYPE html>
<html>
<head>
<meta charset="EUC-KR">
<title>Insert title here</title>
<script>
// cross browsing을 지원하는 이벤트핸들러 만들기
var registerEventHandler = function(element, eventName, handler){
    // IE8에서 실행 
    // element가 null이 맞는 지 확인하기 && IE8밑 버전이 맞는 지 && 모두 통과되었다면 IE8밑 버전에 실행코드 진행  
    element && element.attachEvent && element.attachEvent('on'+evnetName, handler)

    // Chrome 에서 실행 
    element && element.addEventListener && element.addEventListener(eventName, handler)
}

    registerEventHandler(header, 'click', function(){
        console.log("click 4");
    })
}

</script>
</head>
<body>

    <h1 id='header'> header</h1>

</body>
</html>

Form, client단에서 데이터 검증(validation) 진행하기

파일명 : event-ex05.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<script>

window.onload = function(){
    // client 에서 입력값 검증하는 방법
    var form = document.getElementById('form-login');

    // DOM Level 0 - 이벤트 기본 동작 막기(for validation)
    // _를 사용해 잠시 사용불가처리 
    form._onsubmit = function(event){
        // 이메일 값 받아오기 
        var email = document.getElementById('email').value;
        console.log(email);
        if(email == ''){
            alert('이메일은 필수 입력 항목입니다.');
            document.getElementById('email').focus();
            return false;            
        }
        var password = document.getElementById('password').value;
        console.log(password);
        if(password == ''){
            alert('비밀번호는 필수 입력 항목입니다.');
            document.getElementById('password').focus();
            return false;            
        }

        return true;
    };


    // DOM Level 2 - 이벤트 기본 동작 막기(for validation)
    form.addEventListener('submit', function(event){
        event.preventDefault();
        var email = document.getElementById('email').value;
        console.log(email);
        if(email == ''){
            alert('이메일은 필수 입력 항목입니다.');
            document.getElementById('email').focus();
            return;    
        }
        var password = document.getElementById('password').value;
        console.log(password);
        if(password == ''){
            alert('비밀번호는 필수 입력 항목입니다.');
            document.getElementById('password').focus();
            return;    
        }
        this.submit();
    });

    // DOM Level 2 - 이벤트 기본 동작 막기(for ajax 통신)
    form.addEventListener('submit', function(event){
        event.preventDefault();
        console.log('start log-in with ajax');
    });

    // Achor에 적용하기(이유 : ajax 통신)
    var button = document.getElementById('fetch-data');
    button.addEventListener('click', function(event){

        // 앵커태그에 #을 넣더라도 링크를 누르면  맨 상단으로 이동하지 않도록 조치
        event.preventDefault();
        console.log('fetching start');
    });
}

</script>
</head>
<body>
    <form id='form-login' method='post' action='login'>
        <label>이메일</label><br/>
        <input type='text' name='email' id='email'/><br/>
        <label>패스워드</label><br/>
        <input type='text' name='password' id='password'/><br/>
        <input type='submit' value='로그인'/><br/>
    </form>
    <br/>
    <br/>
    <br/>
    <br/>
    <br/>
    <br/>
    <br/>
    <br/>
    <br/>
    <br/>
    <br/>
    <br/>
    <br/>
    <br/>
    <br/>
    <!-- 앵커태그에 #을 넣더라도 링크를 누르면 페이지의 맨 상단으로 이동한다. 따라서 맨 상단으로 이동하지 않도록 조치를 취해야한다. -->
    <a href='#' id='fetch-data'>다음 10개</a>
</body>
</html>

Event propagation 막는 법

파일명 : event-ex06.html

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<style>
div, h2, span {border:3px solid black;}
</style>
<script>

window.onload = function(){
    // event bubbling
    // ie: outer -> inner -> header -> text 

    document.getElementById('outer-div').addEventListener('click',function(){
        console.log('outer-div')
    })    
    document.getElementById('inner-div').addEventListener('click',function(e){
        // cross browser
        // e == null 인 경우는 IE인 경우이며 다음의 전역객체로 처리(window.event) 
        var event = e || window.event;

        // 이벤트 전달 막기 

        event.cancelBubble = true // IE에서 propagation 막기
        event.stopPropagation && event.stopPropagation // other browsers

        console.log('inner-div')
    })
    document.getElementById('header').addEventListener('click',function(){
        console.log('header')
    })
    document.getElementById('text').addEventListener('click',function(){
        console.log('text')
    })

}

</script>
</head>
<body>
    <!-- 뜻하지 않은 곳에서 이벤트가 일어날 수 있으므로 제어 필요 -->
    <h1>이벤트 propagation(bubbling)</h1>
    <div id='outer-div'>
        <div id='inner-div'>
            <h2 id='header' style="background-color:#f00">
                <span id='text'>Text</span>
            </h2>
        </div>
    </div>
</body>
</html>