44. 네트워크 통신  - jQuery Ajax


jQuery이용해서 Ajax를 사용하게 되면 많은 이점이 있는데 그 중의 하나가 크로스브라우징의 문제를 jQuery가 알아서 해결해준다는 것이다. 뿐만 아니라 여러가지 편리한 기능들을 제공한다. 이번 시간에는 jQuery를 이용해서 Ajax 통신을 하는 법을 알아보자.

jQuery는 Ajax와 관련해서 많은 API를 제공한다. 

그 중에서 가장 중요한 API는 $.ajax이다.

1) $.ajax


$.ajax의 문법은 아래와 같다.
1
jQuery.ajax( [settings ] )


setting는 Ajax 통신을 위한 옵션을 담고 있는 객체가 들어간다. 주요한 옵션을 열거해보면 아래와 같다.
  • data
    서버로 데이터를 전송할 때 이 옵션을 사용한다. 
  • dataType
    서버측에서 전송한 데이터를 어떤 형식의 데이터로 해석할 것인가를 지정한다. 값으로 올 수 있는 것은 xml, json, script, html이다. 형식을 지정하지 않으면 jQuery가 알아서 판단한다.
  • success
    성공했을 때 호출할 콜백을 지정한다.
    Function( PlainObject data, String textStatus, jqXHR jqXHR )
  • type
    데이터를 전송하는 방법을 지정한다. get, post를 사용할 수 있다.

위의 내용을 바탕으로 Ajax 통신을 해보자. 다음 예제는 Ajax 수업의 예제를 JQuery화한 것이다.

time.php
<?php
$d1 = new DateTime;
$d1->setTimezone(new DateTimezone("asia/seoul"));
echo $d1->format('H:i:s');
?>

demo1.html
<p>time : <span id="time"></span></p>
<input type="button" id="execute" value="execute" />
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
    $('#execute').click(function(){
        $.ajax({
            url:'./time.php',
            success:function(data){
                $('#time').append(data);
            }
        })
    })
</script>
XMLHttpRequest에 비해서 코드가 훨씬 간결해졌다. 

2) POST 방식

time2.php
<?php
$d1 = new DateTime;
$d1->setTimezone(new DateTimezone($_POST['timezone']));
echo $d1->format($_POST['format']);
?>

demo2.html
<p>time : <span id="time"></span></p>
<form>
    <select name="timezone">
        <option value="Asia/Seoul">asia/seoul</option>
        <option value="America/New_York">America/New_York</option>
    </select>
    <select name="format">
        <option value="Y-m-d H:i:s">Y-m-d H:i:s</option>
        <option value="Y-m-d">Y-m-d</option>
    </select>
</form>
<input type="button" id="execute" value="execute" />
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
    $('#execute').click(function(){
        $.ajax({
            url:'./time2.php',
            type:'post',
            data:$('form').serialize(),//서버로 데이터 전송
            success:function(data){
                $('#time').text(data);
            }
        })
    })
</script>

아래 코드는 form 태그의 정보를 값의이름=값의내용& 형식으로 바꿔준다.

1
data:$('form').serialize(),

3) JSON 처리
$.ajax 이용해서 JSON 처리하는 방법을 알아보자.

time3.php
<?php
$timezones = ["Asia/Seoul", "America/New_York"];
echo json_encode($timezones);
?>

demo3.html
<p id="timezones"></p>
<input type="button" id="execute" value="execute" />
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
    $('#execute').click(function(){
        $.ajax({
            url:'./time3.php',
            dataType:'json',
            success:function(data){
                var str = '';
                for(var name in data){
                    str += '<li>'+data[name]+'</li>';
                }
                $('#timezones').html('<ul>'+str+'</ul>');
            }
        })
    })
</script>



블로그 이미지

가카리

소프트웨어와 하드웨어 프로그래밍, 취업 및 직장생활 전문 블로그


43. 네트워크 통신  - JSON

1) JSON이란?

JSON(JavaScript Object Notation)의 약자로 JavaScript에서 객체를 만들 때 사용하는 표현식을 의미한다. 이 표현식은 사람도 이해하기 쉽고 기계도 이해하기 쉬우면서 데이터의 용량이 작다. 이런 이유로 최근에는 JSON이 XML을 대체해서 설정의 저장이나 데이터를 전송등에 많이 사용된다. JSON에 대한 자세한 내용은 아래 JSON의 공식홈페이지를 참조한다. 


2) JSON API

ECMAscript 5에는 JSON을 공식적으로 지원하는 API가 포함되었다. 

JSON.parse()

인자로 전달된 문사열을 자바스크립트의 데이터로 변환한다.

JSON.stringify()

인자로 전달된 자바스크립트의 데이터를 문자열로 변환한다.

3) Ajax와 JSON

JSON의 진가는 서버와 통신을 할 때 드러난다. Ajax 수업의 내용을 조금 개조해서 타임라인의 항목을 리스트로 표현하는 에플리케이션을 만들어보자.

우선 서버 쪽에서는 타임라인의 리스트를 콤마로 구분해서 전달한다.

time.php
<?php
$timezones = ["Asia/Seoul", "America/New_York"];
echo implode(',', $timezones);//배열의 원소를 콤마로 구분해서 합치라는 의미
?>

결과
Asia/Seoul,America/New_York
클라이언트 측에서는 이를 받아서 처리한다.

demo2.html
<p id="timezones"></p>
<input type="button" id="execute" value="execute" />
<script>
document.querySelector('input').addEventListener('click', function(event){
    var xhr = new XMLHttpRequest();
    xhr.open('GET', './time.php');
    xhr.onreadystatechange = function(){
        if(xhr.readyState === 4 && xhr.status === 200){
            var _tzs = xhr.responseText;
            var tzs = _tzs.split(',');//콤마로 구분해서 배열로 쪼개라는 의미
            var _str = '';
            for(var i = 0; i< tzs.length; i++){
                _str += '<li>'+tzs[i]+'</li>';
            }
            _str = '<ul>'+_str+'</ul>';//맨앞에 ul 묶음
            document.querySelector('#timezones').innerHTML = _str;//p태그에 값을 넣음
        }
    }
    xhr.send();
});
</script>

주목해야 부분은 아래와 같다.

1
2
3
var _tzs = xhr.responseText;
var tzs = _tzs.split(',');
var _str = '';

메소드 split는 인자의 값을 기준으로 문자를 잘라서 배열로 만든다. 서버에서 전송한 Asia/Seoul,America/New_York를 split(',')하면 배열 ['Aasia/Seoul','America/New_York']가 만들어진다.

PHP의 배열을 클라이언트로 전송하기 위해서 콤마로 구분된 문자열을 만들었다. 자바스크립트에서는 이를 받아서 콤마를 구분자로 다시 배열로 만들었다. 

만약 PHP의 배열을 그대로 자바스크립트에서 사용할 수 있다면? 반대로 자바스크립트의 배열을 그대로 PHP에서 사용할 수 있다면 얼마나 편리할까? 이 때 사용하는 것이 JSON이다. 

위의 예제를 JSON화시켜보자.


time2.php
<?php
$timezones = ["Asia/Seoul", "America/New_York"];
header('Content-Type: application/json');
echo json_encode($timezones);//PHP 데이터를 JSON 형식으로 바꿔줌
?>

json_encode는 PHP의 데이터를 JSON 형식으로 전환해주는 PHP의 내장함수다.


결과
1
["Asia\/Seoul","America\/New_York"]

이를 처리하는 JavaScript 코드를 보자.

<pid="timezones"></p>
<input type="button" id="execute" value="execute" />
<script>
document.querySelector('input').addEventListener('click', function(event){
    var xhr = new XMLHttpRequest();
    xhr.open('GET', './time2.php');
    xhr.onreadystatechange = function(){
        if(xhr.readyState === 4 && xhr.status === 200){
            var _tzs = xhr.responseText;
            var tzs = JSON.parse(_tzs);
            var _str = '';
            for(var i = 0; i< tzs.length; i++){
                _str += '<li>'+tzs[i]+'</li>';
            }
            _str = '<ul>'+_str+'</ul>';
            document.querySelector('#timezones').innerHTML = _str;
        }
    }
    xhr.send();
});
</script>


아래코드를통해서서버에서전송한 JSON 데이터를 JavaScript배열로만들수있었다.
1
var tzs = JSON.parse(_tzs);

4) 서버로 데이터 전송

서버로 JSON 데이터를 전송하는 것도 가능하다. 아래 예제를 참고하자.

demo4.html
<p>time : <span id="time"></span></p>
<select id="timezone">
    <option value="Asia/Seoul">asia/seoul</option>
    <option value="America/New_York">America/New_York</option>
</select>
<select id="format">
    <option value="Y-m-d H:i:s">Y-m-d H:i:s</option>
    <option value="Y-m-d">Y-m-d</option>
</select>
<input type="button" id="execute" value="execute" />
<script>
document.querySelector('input').addEventListener('click', function(event){
    var xhr = new XMLHttpRequest();
    xhr.open('POST', './time3.php');
    xhr.onreadystatechange = function(){
        document.querySelector('#time').innerHTML = xhr.responseText;
    }
    var data = new Object();
    data.timezone = document.getElementById('timezone').value;
    data.format = document.getElementById('format').value;
    xhr.setRequestHeader("Content-Type", "application/json");
    xhr.send(JSON.stringify(data));
});

time3.php
<?php
$data = json_decode(file_get_contents('php://input'), true);
$d1 = new DateTime;
$d1->setTimezone(new DateTimezone($data['timezone']));
echo $d1->format($data['format']);
?>



블로그 이미지

가카리

소프트웨어와 하드웨어 프로그래밍, 취업 및 직장생활 전문 블로그


42. 네트워크 통신  - Ajax

1) Ajax

웹브라우저는 대단히 정적인 시스템이었다. 내용이 바뀌면 페이지 새로고침을 해서 내용을 새롭게 변경해야 했다. 이것은 웹이 전자 문서를 염두에 두고 고안된 시스템이기 때문에 당연하게 생각 되었다. 

그러다 Ajax 개념이 도입되면서 모든 것이 바뀌었다. Ajax는 웹브라우저와 웹서버가 내부적으로 데이터 통신을 하게 된다. 그리고 변경된 결과를 웹페이지에 프로그래밍적으로 반영함으로써 웹페이지의 로딩 없이 서비스를 사용할 수 있게 한다. 

Ajax는 Asynchronous JavaScript and XML의 약자다. 한국어로는 비동기적 자바스크립트와 XML 정도로 직역할 수 있는데 자바스크립트를 이용해서 비동기적으로 서버와 브라우저가 데이터를 주고 받는 방식을 의미한다. 이 때 사용하는 API가 XMLHttpRequest이다. 그렇다고 꼭 XML을 사용해서 통신해야 하는 것은 아니다. 사실 XML 보다는 JSON을 더 많이 사용한다.

IE5,6 에서는 XMLHttpRequest 객체 대신 ActiveXObject("Msxml2.XMLHTTP.6.0")을 사용해야 한다. 여기서는 다루지 않는다.

1) XMLHttpRequest

이 때 사용하는 API가 XMLHttpRequest이다. 다음 예제를 보자.

본 예제를 실행하기 위해서는 서버 환경이 구축 되어 있어야 한다. 서버 구축에 대한 설명은 우리 수업의 범위를 넘어서기 때문에 여기서는 언급하지 않는다. 하지만 학습하는데는 큰 문제가 없다. 중요한 주제이기 때문에 꼭 학습하기 바란다.
time.php

아래 코드는 현재 시간을 출력한다.

<?php
$d1 = new DateTime;
$d1->setTimezone(new DateTimezone("asia/seoul"));
echo $d1->format('H:i:s');
?>


demo1.html

아래 코드는 time.php에 접속해서 현재 시간은 페이지에 표시한다.

<p>time : <span id="time"></span></p>
<input type="button" id="execute" value="execute" />
<script>
document.querySelector('input').addEventListener('click', function(event){
    var xhr = new XMLHttpRequest();
    xhr.open('GET', './time.php');
    xhr.onreadystatechange = function(){
        if(xhr.readyState === 4 && xhr.status === 200){
            document.querySelector('#time').innerHTML = xhr.responseText;
        }
    }
    xhr.send();
});
</script>

코드를 분석해보자.

1
var xhr = new XMLHttpRequest();

XMLHttpRequest 객체를 생성한다.

1
xhr.open('GET', './time.php');

접속하려는 대상을 지정한다. 첫번째 인자는 form 태그의 method에 대응하는 것으로 GET/POST 방식을 주로 사용한다. 두번째 인자는 접속하고자 하는 서버쪽 리소스의 주소로 form 태그의 action에 해당한다.

1
2
3
4
5
xhr.onreadystatechange = function(){
if(xhr.readyState === 4 && xhr.status === 200){
document.querySelector('#time').innerHTML = xhr.responseText;
}
}

onreadystatechange 이벤트는 서버와의 통신이 끝났을 때 호출되는 이벤트이다. readyState는 통신의 현재 상태를 알려준다. 4는 통신이 완료되었음을 의미한다. status는 HTTP 통신의 결과를 의미하는데 200은 통신이 성공했음을 의미한다. responseText 프로퍼티는 서버에서 전송한 데이터를 담고 있다. 이것을 id가 time 엘리먼트의 하위로 삽입한다. 이를 통해서 현재 서버에서 가져온 현재시간을 페이지 리로딩 없이 가져올 수 있다.


2) POST 방식

post 방식으로 데이터를 전송하는 방법을 알아보자.

GET과 POST 방식에 대한 자세한 내용은 생활코딩 HTML 수업을 참고하자.

demo2.html

아래 예제는 시간대와 시간의 출력 형식을 지정하는 예제다. 

<p>time : <span id="time"></span></p>
<select id="timezone">
    <option value="Asia/Seoul">asia/seoul</option>
    <option value="America/New_York">America/New_York</option>
</select>
<select id="format">
    <option value="Y-m-d H:i:s">Y-m-d H:i:s</option>
    <option value="Y-m-d">Y-m-d</option>
</select>
<input type="button" id="execute" value="execute" />
<script>
document.querySelector('input').addEventListener('click', function(event){
    var xhr = new XMLHttpRequest();
    xhr.open('POST', './time2.php');
    xhr.onreadystatechange = function(){
        document.querySelector('#time').innerHTML = xhr.responseText;
    }
    xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
    var data = '';
    data += 'timezone='+document.getElementById('timezone').value;
    data += '&format='+document.getElementById('format').value;
    xhr.send(data);
});
</script>


중요한 부분을 살펴보자. 데이터 전송방법을 GET에서 POST로 변경했다. 
1
xhr.open('POST', './time2.php');


서버로 전송할 데이터 타입의 형식(MIME)을 지정한다. 
1
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");


서버로 전송할 데이터를 형식에 맞게 만든다. 이름=값&이름=값... 의 형식을 지켜야 한다. 
1
2
3
var data = '';
data += 'timezone='+document.getElementById('timezone').value;
data += '&format='+document.getElementById('format').value;


send 메소드의 인자로 전송할 데이터를 전달한다.
1
xhr.send(data);



time2.php

아래는 Ajax를 이용해서 전송한 데이터를 받아서 현재 시간을 출력해주는 서버쪽 구현이다. 

<?php
$d1 = new DateTime;
$d1->setTimezone(new DateTimezone($_POST['timezone']));
echo $d1->format($_POST['format']);
?>


블로그 이미지

가카리

소프트웨어와 하드웨어 프로그래밍, 취업 및 직장생활 전문 블로그


41. jQuery on API 사용법

1) 기본 사용법

on은 jQuery에서 가장 중요한 이벤트 API이다. on API를 통해서 jQuery에서 이벤트를 다루는 방법을 알아보자.

on의 기본적인 문법은 아래와 같다.

1
.on( events [, selector ] [, data ], handler(eventObject) )
  • event : 등록하고자 하는 이벤트 타입을 지정한다. (예: "click")
  • selector : 이벤트가 설치된 엘리먼트의 하위 엘리먼트를 이벤트 대상으로 필터링함
  • data : 이벤트가 실행될 때 핸들러로 전달될 데이터를 설정함
  • handler : 이벤트 핸들러 함수

1) selector

selector 파라미터는 이벤트 대상을 필터링한다. 아래 예제를 보자.
on메소드의 2번째 인자이다.

<ul>
    <li><a href="#">HTML</a></li>
    <li><a href="#">CSS</a></li>
    <li><a href="#">JavaScript</a></li>
</ul>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
    $('ul').on('click','a, li', function(event){
        console.log(this.tagName);
    })
</script>


위의 예제는 ul 엘리먼트의 하위 엘리먼트 중에  a, li 엘리먼트들에 대해서만 이벤트가 발생한다. 주의 할 것은 ul 엘리먼트는 이벤트가 발생하지 않는다는 점이다. 이것은 jQuery에서 이벤트 버블링을 구현하는 방법이기도 하다.

2) late binding

jQuery는 존재하지 않는 엘리먼트에도 이벤트를 등록할 수 있는 놀라운 기능을 제공한다. 아래 코드를 보자. 

<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
    $('ul').on('click','a, li', function(event){
        console.log(this.tagName);
    })
</script>
<ul>
    <li><a href="#">HTML</a></li>
    <li><a href="#">CSS</a></li>
    <li><a href="#">JavaScript</a></li>
</ul>

위의 코드는 실행되지 않는다. ul 엘리먼트가 존재하지 않을 때 이벤트 설치를 시도하고 있기 때문이다. 존재하지 않는 엘리먼트에 이벤트를 달 수 없다는 것은 이미 배운 바가 있다. 그런데 jQuery는 존재하지 않는 엘리먼트에게도 이벤트를 설치할 수 있다. (body에 달면 된다.)

<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
    $('body').on('click','a, li', function(event){
        console.log(this.tagName);
    })
</script>
<ul>
    <li><a href="#">HTML</a></li>
    <li><a href="#">CSS</a></li>
    <li><a href="#">JavaScript</a></li>
</ul>

3) 다중 바인딩

하나의 엘리먼트에 여러개의 이벤트 타입을 동시에 등록하는 방법을 알아보자. (실행)

<input type="text" id="target"/>
<p id="status"></p>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
    $('#target').on('focus blur', function(e){
        $('#status').html(e.type);
    })
</script>

한번에 여러개의 이벤트 타입을 선택했다. 만약 이벤트에 따라서 다른 핸들러를 실행하고 싶다면 아래와 같이 코드를 변경한다.

<input type="text" id="target"/>
<p id="status"></p>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
    $('#target').on({
        'focus' : function(e){
 
        },
        'blur' : function(e){
            
        }
    })
</script>

4) 이벤트 제거

이벤트를 제거할 때는 off를 사용한다. 

<input type="text" id="target"></textarea>
<input id="remove"  type="button" value="remove" />
<p id="status"></p>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
  var handler = function(e){
    $('#status').text(e.type+Math.random());
  };
  $('#target').on('focus blur', handler)
  $('#remove').on('click' , function(e){
    $('#target').off('focus blur', handler);//handler 이벤트가 삭제된다. 다른 이벤트는 삭제되지 않는다.
    console.log(32);
  })
</script>

블로그 이미지

가카리

소프트웨어와 하드웨어 프로그래밍, 취업 및 직장생활 전문 블로그


40. jQuery 이벤트 vs 자바스크립트 이벤트

jQuery는 이벤트와 관련해서 편리한 기능을 제공한다.  아래 예제는 직접 이벤트 프로그래밍을 하는 것과 jQuery를 이용하는 것의 차이점을 보여준다. (실행)

<input type="button" id="pure" value="pure"/>
<input type="button" id="jquery" value="jQuery" />
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
    // 순수하게 구현했을
    var target = document.getElementById('pure');
    if(target.addEventListener){
        target.addEventListener('click', function(event){
            alert('pure');
        });
    } else {
        target.attachEvent('onclick', function(event){
            alert('pure');
        });
    }
 
    // jQuery 사용했을
    $('#jquery').on('click', function(event){
        alert('jQuery');
    })
</script>

코드 분량에 큰차이가 있다. jQuery는 크로스 브라우징을 알아서 처리해주고, 이벤트를 보다 적은 코드로 구현할 수 있도록 해준다. 이런 이유 때문에 jQuery와 같은 라이브러리를 사용하는 것이다. 



블로그 이미지

가카리

소프트웨어와 하드웨어 프로그래밍, 취업 및 직장생활 전문 블로그

39. 마우스

1) 이벤트 타입

웹브라우저는 마우스와 관련해서 다양한 이벤트 타입을 지원한다.

  • click
    클릭했을 때 발생하는 이벤트. 
  • dblclick
    더블클릭을 했을 때 발생하는 이벤트
  • mousedown
    마우스를 누를 때 발생
  • mouseup
    마우스버튼을 땔 때 발생
  • mousemove
    마우스를 움직일 때
  • mouseover
    마우스가 엘리먼트에 진입할 때 발생
  • mouseout
    마우스가 엘리먼트에서 빠져나갈 때 발생
  • contextmenu
    컨텍스트 메뉴가 실행될 때 발생

2) 키보드 조합

마우스 이벤트가 호출될 때 특수키(alt, ctrl, shift)가 눌려진 상태를 감지해야 한다면 이벤트 객체의 프로퍼티를 사용한다. 이 때 사용하는 프로퍼티는 아래와 같다.

  • event.shiftKey
  • event.altKey
  • event.ctrlKey

3) 마우스 포인터 위치

마우스 이벤트와 관련한 작업에서는 마우스 포인터의 위치를 알아내는 것이 중요할 때가 있는데 이런 경우 이벤트 객체의 clientX와 clientY를 사용한다.
아래 예제는 지금까지 살펴본 이벤트와 관련된 기능을 종합적으로 보여준다. (실행)

<html>
    <head>
        <style>
            body{
                background-color: black;
                color:white;
            }
            #target{
                width:200px;
                height:200px;
                background-color: green;
                margin:10px;
            }
            table{
                border-collapse: collapse;
                margin:10px;
                float: left;
                width:200px;
            }
            td, th{
                padding:10px;
                border:1px solid gray;
            }
        </style>
    </head>
    <body>
        <div id="target">
 
        </div>
        <table>
            <tr>
                <th>event type</th>
                <th>info</th>
            </tr>
            <tr>
                <td>click</td>
                <td id="elmclick"></td>
            </tr>
            <tr>
                <td>dblclick</td>
                <td id="elmdblclick"></td>
            </tr>
            <tr>
                <td>mousedown</td>
                <td id="elmmousedown"></td>
            </tr>        
            <tr>
                <td>mouseup</td>
                <td id="elmmouseup"></td>
            </tr>        
            <tr>
                <td>mousemove</td>
                <td id="elmmousemove"></td>
            </tr>        
            <tr>
                <td>mouseover</td>
                <td id="elmmouseover"></td>
            </tr>        
            <tr>
                <td>mouseout</td>
                <td id="elmmouseout"></td>
            </tr>
            <tr>
                <td>contextmenu</td>
                <td id="elmcontextmenu"></td>
            </tr>        
        </table>
        <table>
            <tr>
                <th>key</th>
                <th>info</th>
            </tr>
            <tr>
                <td>event.altKey</td>
                <td id="elmaltkey"></td>
            </tr>
            <tr>
                <td>event.ctrlKey</td>
                <td id="elmctrlkey"></td>
            </tr>
            <tr>
                <td>event.shiftKey</td>
                <td id="elmshiftKey"></td>
            </tr>
        </table>
        <table>
            <tr>
                <th>position</th>
                <th>info</th>
            </tr>
            <tr>
                <td>event.clientX</td>
                <td id="elemclientx"></td>
            </tr>
            <tr>
                <td>event.clientY</td>
                <td id="elemclienty"></td>
            </tr>
        </table>
        <script>
        var t = document.getElementById('target');
        function handler(event){
            var info = document.getElementById('elm'+event.type);
            var time = new Date();
            var timestr = time.getMilliseconds();
            info.innerHTML = (timestr);
            if(event.altKey){
                document.getElementById('elmaltkey').innerHTML = timestr;
            }
            if(event.ctrlKey){
                document.getElementById('elmctrlkey').innerHTML = timestr;
            }
            if(event.shiftKey){
                document.getElementById('elmshiftKey').innerHTML = timestr;
            }
            document.getElementById('elemclientx').innerHTML = event.clientX;
            document.getElementById('elemclienty').innerHTML = event.clientY;
        }
        t.addEventListener('click', handler);
        t.addEventListener('dblclick', handler);
        t.addEventListener('mousedown', handler);
        t.addEventListener('mouseup', handler);
        t.addEventListener('mousemove', handler);
        t.addEventListener('mouseover', handler);
        t.addEventListener('mouseout', handler);
        t.addEventListener('contextmenu', handler);
        </script>
    </body>
</html>

실행 화면



블로그 이미지

가카리

소프트웨어와 하드웨어 프로그래밍, 취업 및 직장생활 전문 블로그


38. 문서 로딩

웹페이지를 프로그래밍적으로 제어하기 위해서는 웹페이지의 모든 요소에 대한 처리가 끝나야 한다. 이것을 알려주는 이벤트가 load, DOMContentLoaded이다.

아래 코드의 실행결과는 null이다. <p id="target">Hello</p>가 로딩되기 전에 자바스크립트가 실행되었기 때문이다.

<html>
    <head>
        <script>
        var t = document.getElementById('target');
        console.log(t);
        </script>
    </head>
    <body>
        <p id="target">Hello</p>
    </body>
</html>

이를 해결하기 위한 방법은 아래와 같이 스크립트를 문서 끝에 위치시키는 것이다.

<p id="target">Hello</p>
<script>
    var t = document.getElementById('target');
    console.log(t);
</script>

또 다른 방법은 load 이벤트를 이용하는 것이다.

<head>
    <script>
        window.addEventListener('load', function(){
            var t = document.getElementById('target');
            console.log(t);
        })
    </script>
</head>
<body>
    <p id="target">Hello</p>
</body>

그런데 load 이벤트는 문서내의 모든 리소스(이미지, 스크립트)의 다운로드가 끝난 후에 실행된다. 이것을 에플리케이션의 구동이 너무 지연되는 부작용을 초래할 수 있다.

DOMContentLoaded는 문서에서 스크립트 작업을 할 수 있을 때 실행되기 때문에 이미지 다운로드를 기다릴 필요가 없다.

<html>
    <head>
        <script>
            window.addEventListener('load', function(){
                console.log('load');
            })
            window.addEventListener('DOMContentLoaded', function(){
                console.log('DOMContentLoaded');
            })
        </script>
    </head>
    <body>
        <p id="target">Hello</p>
    </body>
</html>

DOMContentLoaded 이벤트는 IE9을 포함한 모든 브라우저에서 지원하고 있다.


블로그 이미지

가카리

소프트웨어와 하드웨어 프로그래밍, 취업 및 직장생활 전문 블로그


36. 이벤트 타입


아래는 onclick 이벤트 타입의 예제다. 이벤트 타입이라는 것은 이벤트의 종류라고 할 수 있다.
1
<input type="button" onclick="alert(1);" />


웹브라우저는 많은 종류의 이벤트 타입을 제공한다. 하위 토픽에서는 주요한 이벤트 타입을 중심으로 어떤 이벤트 타입이 있는지 알아보겠다.
37. 폼

폼과 관련된 이벤트 타입을 알아보자.

1) submit

submit은 폼의 정보를 서버로 전송하는 명령인 submit시에 일어난다.

form 태그에 적용된다.

아래 예제는 전송 전에 텍스트 필드에 값이 입력 되었는지를 확인한다. 만약 값이 입력되지 않았다면 전송을 중단한다.

<form id="target" action="result.html">
    <label for="name">name</label> <input id="name" type="name" />
    <input type="submit" />
</form>
<script>
var t = document.getElementById('target');
t.addEventListener('submit', function(event){
    if(document.getElementById('name').value.length === 0){
        alert('Name 필드의 값이 누락 되었습니다');
        event.preventDefault();//이벤트 실행 방지
    }
});
</script>


2) change
change는 폼 컨트롤의 값이 변경 되었을 때 발생하는 이벤트다.

input(text,radio,checkbox), textarea, select 태그에 적용된다.

<p id="result"></p>
<input id="target" type="name" />
<script>
var t = document.getElementById('target');
t.addEventListener('change', function(event){
    document.getElementById('result').innerHTML=event.target.value;
});
</script>

3) blur, focus

focus는 엘리먼트에 포커스가 생겼을 때, blur은 포커스가 사라졌을 때 발생하는 이벤트다. 

다음 태그를 제외한 모든 태그에서 발생한다. <base>, <bdo>, <br>, <head>, <html>, <iframe>, <meta>, <param>, <script>, <style>, <title>


<input id="target" type="name"/>
<script>
var t = document.getElementById('target');
t.addEventListener('blur', function(event){
    alert('blur'); 
});
t.addEventListener('focus', function(event){
    alert('focus');
});
</script>



블로그 이미지

가카리

소프트웨어와 하드웨어 프로그래밍, 취업 및 직장생활 전문 블로그



31. 이벤트 등록방법(inline)

인라인(inline) 방식으로 이벤트를 등록하는 방법을 알아보자. 인라인 방식은 이벤트를 이벤트 대상의 태그 속성으로 지정하는 것이다. 다음은 버튼을 클릭했을 때 Hello world를 경고창으로 출력한다.

<input type="button"onclick="alert('Hello world');"value="button"/>

이벤트가 발생한 대상을 필요로하는 경우 this를 통해서 참조할 수 있다.

<!--자기자신을참조하는불편한방법-->
<input type="button" id="target" onclick="alert('Hello world, '+document.getElementById('target').value);" value="button" />

<!--this통해서간편하게참조할있다-->
<input type="button"onclick="alert('Hello world, '+this.value);"value="button"/>

인라인 방식은 태그에 이벤트가 포함되기 때문에 이벤트의 소재를 파악하는 것이 편리하다. 하지만 정보인 HTML과 제어인 JavaScript가 혼재된 형태이기 때문에 바람직한 방법이라고 할수는 없다. 

32. 이벤트 등록방법(프로퍼티 리스너)

프로퍼티 리스너 방식은 이벤트 대상에 해당하는 객체의 프로퍼티로 이벤트를 등록하는 방식이다. 인라인 방식에 비해서 HTML과 JavaScript를 분리할 수 있다는 점에서 선호되는 방식이지만 뒤에서 배울 addEventListener 방식을 추천한다. 

<input type="button" id="target" value="button"/>
<script>
    var t = document.getElementById('target');
    t.onclick = function(){
        alert('Hello world');
    }
</script>

1) 이벤트 객체
이벤트가 실행된 맥락의 정보가 필요할 때는 이벤트 객체를 사용한다. 이벤트 객체는 이벤트가 실행될 때 이벤트 핸들러의 인자로 전달된다. 

<body>
    <input type="button" id="target" value="button" />
<script>
    var t = document.getElementById('target');
    t.onclick = function(event){
        alert('Hello world, '+event.target.value)
    }
</script>

ie8 이하 버전에서는 이벤트 객체를 핸들러의 인자가 아니라 전역객체의 event 프로퍼티로 제공한다. 또한 target 프로퍼티도 지원하지 않는다. 아래는 이 문제를 해소하기 위한 코드다.

<input type="button" id="target" value="button"/>
<script>
    var t = document.getElementById('target');
    t.onclick = function(event){
        var event = event || window.event;//익스8이전은 window.event였음
        var target = event.target || event.srcElement;//익스8이전은 srcElement였음
        alert('Hello world, '+target.value)
    }
</script>

33. 이벤트 등록방법(addEventListener)

addEventListener은 이벤트를 등록하는 가장 권장되는 방식이다. 이 방식을 이용하면 여러개의 이벤트 핸들러를 등록할 수 있다.

<input type="button" id="target" value="button"/>
<script>
    var t = document.getElementById('target');
    t.addEventListener('click', function(event){
        alert('Hello world, '+event.target.value);
    });
</script>

이 방식은 ie8이하에서는 호환되지 않는다. ie에서는 attachEvent 메소드를 사용해야 한다. 

var t =document.getElementById('target');
if(t.addEventListener){
    t.addEventListener('click', function(event){
        alert('Hello world, '+event.target.value);
    });
} else if(t.attachEvent){
    t.attachEvent('onclick', function(event){
        alert('Hello world, '+event.target.value);
    })
}

이 방식의 중요한 장점은 하나의 이벤트 대상에 복수의 동일 이벤트 타입 리스너를 등록할 수 있다는 점이다. 
(프로퍼티 방법은 1개의 이벤트만 등록할 수 있다.)

<input type="button" id="target" value="button"/>
<script>
    var t = document.getElementById('target');
    t.addEventListener('click', function(event){
        alert(1);
    });
    t.addEventListener('click', function(event){
        alert(2);
    });
</script>

이벤트 객체를 이용하면 복수의 엘리먼트에 하나의 리스너를 등록해서 재사용할 수 있다. 

34. 이벤트 전파(버블링, 캡처링)

HTML 태그는 중첩되어 있다. 따라서 특정한 태그에서 발생하는 이벤트는 중첩되어 있는 태그들 모두가 대상이 될 수 있다. 이런 경우 중첩된 태그들에 이벤트가 등록 되어 있다면 어떻게 처리 될까? (실행)

<html>
    <head>
        <style>
            html{border:5px solid red;padding:30px;}
            body{border:5px solid green;padding:30px;}
            fieldset{border:5px solid blue;padding:30px;}
            input{border:5px solid black;padding:30px;}
        </style>
    </head>
    <body>
        <fieldset>
            <legend>event propagation</legend>
            <input type="button" id="target" value="target">         
        </fieldset>
        <script>
        function handler(event){
            var phases = ['capturing', 'target', 'bubbling']
            console.log(event.target.nodeName, this.nodeName, phases[event.eventPhase-1]);
        }
        document.getElementById('target').addEventListener('click', handler, true);
        document.querySelector('fieldset').addEventListener('click', handler, true);
        document.querySelector('body').addEventListener('click', handler, true);
        document.querySelector('html').addEventListener('click', handler, true);
        </script>
    </body>
</html>


이벤트가 부모에서부터 발생해서 자식으로 전파되고 있다. 이러한 방식을 capturing이라고 한다. ie 낮은 버전에서는 작동하지 않기 때문에 많이 사용하지는 않는다.(바깥에서 안쪽으로 이벤트가 전파됨 즉 캡처링이라고 함)
코드를 아래와 같이 변경해보자. (실행)

document.getElementById('target').addEventListener('click', handler,false);
document.querySelector('fieldset').addEventListener('click', handler, false);
document.querySelector('body').addEventListener('click', handler, false);
document.querySelector('html').addEventListener('click', handler, false);

차이점은 addEventListener의 3번째 인자가 false로 변경 되었다.(3번째 인자는 useCapturing임)

이번에는 순서가 반대로 되었다. 자식부터 부모로 이벤트가 전파되는 것을 버블링(bubbling)이라고 한다.

이벤트 전파를 중간에 가로막을 수도 있다.

아래처럼 코드를 변경해보자. (실행)

function handler(event){
    var phases = ['capturing', 'target', 'bubbling']
    console.log(event.target.nodeName, this.nodeName, phases[event.eventPhase-1]);
}
function stophandler(event){
    var phases = ['capturing', 'target', 'bubbling']
    console.log(event.target.nodeName, this.nodeName, phases[event.eventPhase-1]);
    event.stopPropagation();
}
document.getElementById('target').addEventListener('click', handler, false);
document.querySelector('fieldset').addEventListener('click', handler, false);
document.querySelector('body').addEventListener('click', stophandler, false);
document.querySelector('html').addEventListener('click', handler, false);


event.stopPropagation(); 에 의해서 HTML의 이벤트는 호출되지 않은 것을 알 수 있다.



블로그 이미지

가카리

소프트웨어와 하드웨어 프로그래밍, 취업 및 직장생활 전문 블로그


30. 이벤트
1) 이벤트란?

이벤트(event)는 어떤 사건을 의미한다. 브라우저에서의 사건이란 사용자가 클릭을 했을 '때', 스크롤을 했을 '때', 필드의 내용을 바꾸었을 '때'와 같은 것을 의미한다. 

<!DOCTYPE html>
<html>
<body>
    <input type="button" onclick="alert(window.location)" value="alert(window.href)" />
    <input type="button" onclick="window.open('bom.html')" value="window.open('bom.html')" />
</body>
</html>

onclick 속성의 자바스크립트 코드(alert(window.location))는 사용자가 이 버튼을 클릭 했을 '때' 실행된다. 즉 js 개발자는 어떤 일이 발생했을 때 실행 되어야 하는 코드를 등록하고, 브라우저는 그 일이 발생했을 때 등록된 코드를 실행하게 된다. 이러한 방식을 이벤트 프로그래밍이라고 한다.

2) event target

target은 이벤트가 일어날 객체를 의미한다. 아래 코드에서 타겟은 버튼 태그에 대한 객체가 된다.

<input type="button" onclick="alert(window.location)" value="alert(window.href)"/>

3) event type

이벤트의 종류를 의미한다. 위의 예제에서는 click이 이벤트 타입이다. 그 외에도 scroll은 사용자가 스크롤을 움직였다는 이벤트이고, mousemove는 마우스가 움직였을 때 발생하는 이벤트이다.

이벤트의 종류는 이미 약속되어 있다. 아래 링크는 브라우저에서 지원하는 이벤트의 종류를 보여준다.


4) event handler

이벤트가 발생했을 때 동작하는 코드를 의미한다. 위의 예제에서는 alert(window.location)이 여기에 해당한다.



블로그 이미지

가카리

소프트웨어와 하드웨어 프로그래밍, 취업 및 직장생활 전문 블로그

29. 문서의 기하학적 특성

1) 요소의 크기와 위치
우선 엘리먼트의 크기를 알아내는 방법을 살펴보자.

<style>
    body{
        padding:0;
        margin:0;
    }
    #target{
        width:100px;
        height:100px;
        border:50px solid #1065e6;
        padding:50px;
        margin:50px;
    }
</style>
<div id="target">
    Coding
</div>
<script>
var t = document.getElementById('target');
console.log(t.getBoundingClientRect());
</script>


화면에 표시된 모습은 아래와 같다.

즉 엘리먼트의 테두리와 body 태그 사이의 거리가 50px이다. 그리고 테두리를 포함한 엘리먼트의 크기는 300px이다. 이 값을 알아내고 싶을 때 사용하는 API가 getBoundingClientRect이다. 이를 콘솔에서 실행한 결과는 아래와 같다.

즉 엘리먼트의 크기와 위치를 알고 싶을 때는 getBoundingClientRect를 사용하면 된다는 것을 알 수 있다. 

getBoundingClientRect의 height width 값을 IE는 제공하지 않는다.

만약 엘리먼트가 중첩되어 있다면 어떻게 될까?


위와 같이 엘리먼트를 중첩했을 때 coding 엘리먼트와 문서와의 거리는 200px이다. getBoundingClientRect를 호출해보자. (실행)

<style>
    body{
        padding:0;
        margin:0;
    }
    div{
        border:50px solid #1065e6;
        padding:50px;
        margin:50px;
    }
    #target{
        width:100px;
        height:100px;
    }
</style>
<div>
    <div id="target">
        Coding
    </div>
</div>
<script>
var t = document.getElementById('target');
console.log(t.getBoundingClientRect());
console.log(t.offsetParent);
</script>


실행 결과는 아래와 같다.


즉 엘리먼트의 위치를 의미하는 top, right의 값을 통해서 기준이 그 부모가 아니라 body라는 것을 알 수 있다. 그리고 이를 명시적으로 확인할 수 있는 방법은 offsetParent 속성을 호출하는 것이다. 만약 부모 중 CSS position의 값이 static인 td, th, table 엘리먼트가 있다면 이 엘리먼트가 offsetParent가 된다. 
오래된 브라우저에서는 getBoundingClientRect를 지원하지 않을 수 있기 때문에 이런 경우 offsetLeft와 offsetTop 프로퍼티를 사용한다.
테두리를 제외한 엘리먼트의 크기를 알고 싶다면  ClientWidth, ClientHeight를 사용한다. (실행)

<script>
var t = document.getElementById('target');
console.log('clientWidth:', t.clientWidth, 'clientHeight:', t.clientHeight);
</script>

2) Viewport

요소의 위치를 생각할 때는 사실 조금 더 복잡해진다. 문서가 브라우저의 크기보다 큰 경우는 스크롤이 만들어지는데 스크롤에 따라서 위치의 값이 달라지기 때문이다. 이를 이해하기 위해서는 우선 viewport에 대한 이해가 선행되어야 한다.


3) Viewport 좌표

위의 그림처럼 뷰포트는 문서의 내용 중 사용자에게 보여주는 영역을 의미한다. 이에 따라서 문서의 좌표가 있고 뷰포트의 자표가 있다. 우리가 위에서 살펴본 getBoundingClientRect는 viewport의 좌표를 사용한다. 

아래 예제를 실행해보면 1초에 한번씩 getBoundingClientRect의 top 속성과 window.pageYOffset의 값이 출력된다. (실행)

<style>
    body{
        padding:0;
        margin:0;
    }
    div{
        border:50px solid #1065e6;
        padding:50px;
        margin:50px;
    }
    #target{
        width:100px;
        height:2000px;
    }
</style>
    <div>
        <div id="target">
            Coding
        </div>
    </div>
 
<script>
var t = document.getElementById('target');
setInterval(function(){
    console.log('getBoundingClientRect : ', t.getBoundingClientRect().top, 'pageYOffset:', window.pageYOffset);
}, 1000)
</script>

이를 통해서 알 수 있는 것은 getBoundingClientRect의 값이 스크롤에 따라서 달라지는 뷰포트의 좌표를 사용하고 있다는 것이다. 또한 스크롤의 정도를 알고 싶을 때는 pageYOffset을 사용하면 된다는 것도 알 수 있다.  (pageXOffset도 할 수 있음)

오래된 브라우저에서는 pageYOffset 대신 scrollTop 속성을 사용해야 한다.

4) 문서의 좌표
그럼 문서의 좌표를 알고 싶으면 어떻게 해야 하나? 뷰포트의 좌표에 스크롤된 정도를 더해서 알 수 있다. 아래와 같이 코드를 조금 수정했다. (실행)

setInterval(function(){
    console.log('getBoundingClientRect : ', t.getBoundingClientRect().top, 'pageYOffset:', window.pageYOffset, 'document y:', t.getBoundingClientRect().top+window.pageYOffset);
}, 1000)

5) 스크롤
그럼 문서의 스크롤 값을 변경하는 것은 어떻게 하는 것일까? scrollLeft와 scrollTop 프로퍼티를 이용하면 된다. (실행)

<style>
    body{
        padding:0;
        margin:0;
    }
    div{
        border:50px solid #1065e6;
        padding:50px;
        margin:50px;
    }
    #target{
        width:100px;
        height:2000px;
    }
</style>
<input type="button" id="scrollBtn" value="scroll(0, 1000)" />
<script>
    document.getElementById('scrollBtn').addEventListener('click', function(){
        window.scrollTo(0, 1000);
    })
</script>
<div>
    <div id="target">
        Coding
    </div>
</div>

6) 스크린의 크기
스크린의 크기는 모니터의 크기와 브라우저 뷰포트의 크기가 있다. 이를 알아내는 방법은 아래와 같다. (실행)

<script>
console.log('window.innerWidth:', window.innerWidth, 'window.innerHeight:', window.innerHeight);
console.log('screen.width:', screen.width, 'screen.height:', screen.height);
</script>
window.inner*은 뷰포트의 크기를 나타내고, screen.*은 스크린의 크기(사용하는 모니터의 크기)를 나타낸다.



블로그 이미지

가카리

소프트웨어와 하드웨어 프로그래밍, 취업 및 직장생활 전문 블로그


27. Text 객체 값 API

텍스트 노드는 DOM에서 실질적인 데이터가 저장되는 객체이다. 따라서 텍스트 노드에는 값과 관련된 여러 기능들이 있는데 이번 시간에는 값을 가져오는 두개의 API를 알아본다. (둘 다 같은 의미임)
  • nodeValue
  • data

<ul>
    <li id="target">html</li>
    <li>css</li>
    <li>JavaScript</li>
</ul>
<script>
    var t = document.getElementById('target').firstChild;
    console.log(t.nodeValue);
    console.log(t.data);
</script>



28. Text 객체 조작 API

텍스트 노드가 상속 받은 CharacterData 객체는 문자를 제어할 수 있는 다양한 API를 제공한다. 아래는 조작과 관련된 API들의 목록이다.
  • appendData()
  • deleteData()
  • insertData()
  • replaceData()
  • substringData()

<!DOCTYPE html>
<html>
<head>
    <style>
    #target{
        font-size:77px;
        font-family: georgia;
        border-bottom:1px solid black;
        padding-bottom:10px;
    }
    p{
        margin:5px;
    }
    </style>
</head>
<body>
<p id="target">Cording everybody!</p>
<p> data : <input type="text" id="datasource" value="JavaScript" /></p>
<p>   start :<input type="text" id="start" value="5" /></p>
<p> end : <input type="text" id="end" value="5" /></p>
<p><input type="button" value="appendData(data)" onclick="callAppendData()" />
<input type="button" value="deleteData(start,end)" onclick="callDeleteData()" />
<input type="button" value="insertData(start,data)" onclick="callInsertData()" />
<input type="button" value="replaceData(start,end,data)" onclick="callReplaceData()" />
<input type="button" value="substringData(start,end)" onclick="callSubstringData()" /></p>
<script>
    var target = document.getElementById('target').firstChild;
    var data = document.getElementById('datasource');
    var start = document.getElementById('start');
    var end = document.getElementById('end');
    function callAppendData(){
        target.appendData(data.value);
    }
    function callDeleteData(){
        target.deleteData(start.value, end.value);
    }
    function callInsertData(){
        target.insertData(start.value, data.value);
    }
    function callReplaceData(){
        target.replaceData(start.value, end.value, data.value);
    }
    function callSubstringData(){
        alert(target.substringData(start.value, end.value));
    }
</script>
</body>
</html>




블로그 이미지

가카리

소프트웨어와 하드웨어 프로그래밍, 취업 및 직장생활 전문 블로그

26. Text 객체

1) 소개

텍스트 객체는 텍스트 노드에 대한 DOM 객체로 CharcterData를 상속 받는다. 
아래는 텍스트 노드를 찾는 예제다. 주목할 것은 DOM에서는 공백이나 줄바꿈도 텍스트 노드라는 점이다.

<p id="target1"><span>Hello world</span></p>
<p id="target2">
    <span>Hello world</span>
</p>
<script>
var t1 = document.getElementById('target1').firstChild;
var t2 = document.getElementById('target2').firstChild;
 
console.log(t1.firstChild.nodeValue);
try{
    console.log(t2.firstChild.nodeValue);  
} catch(e){
    console.log(e);
}
console.log(t2.nextSibling.firstChild.nodeValue);
 
</script>

실행결과
Hello world
TypeError {stack: (...), message: "Cannot read property 'nodeValue' of null"}
Hello world


2) 주요기능



텍스트 노드의 값을 가져오는 API
  • data
  • nodeValue


조작
  • appendData()
  • deleteData()
  • insertData()
  • replaceData()
  • subStringData()


생성

아래 그림을 보면 TEXT객체는 생활코딩 텍스트 자체를 의미한다.



블로그 이미지

가카리

소프트웨어와 하드웨어 프로그래밍, 취업 및 직장생활 전문 블로그

25. Document 객체

1) 소개

Document 객체는 DOM의 스팩이고 이것이 웹브라우저에서는 HTMLDocument 객체로 사용된다. HTMLDocument 객체는 문서 전체를 대표하는 객체라고 할 수 있다. 아래 코드는 이를 보여준다.

<script>
//document 객체는 window 객체의 소속이다.
console.log(window.document);
//document 객체의 자식으로는 Doctype html 있다.
console.log(window.document.childNodes[0]);
console.log(window.document.childNodes[1]);
</script>


2) 주요 API

노드 생성 API


document  객체의 주요 임무는 새로운 노드를 생성해주는 역할이다. 이에 대한 내용은 노드 변경 API에서 학습했기 때문에 여기서는 언급하지 않는다.

  • createElement()
  • createTextNode()

문서 정보 API

  • title (document.title)
  • URL (document.URL)ㅊ
  • referrer (document.referrer)
  • lastModified (document.lastModified)
블로그 이미지

가카리

소프트웨어와 하드웨어 프로그래밍, 취업 및 직장생활 전문 블로그


24. 문자열로 노드 제어

노드 변경 API에서는 여러 메소드를 이용해서 노드를 제어하는 방법에 대해서 알아봤다. 그런데 이 방식은 복잡하고 장황하다. 좀 더 편리하게 노드를 조작하는 방법을 알아보자.

1) innerHTML
innerHTML는 문자열로 자식 노드를 만들 수 있는 기능을 제공한다. 또한 자식 노드의 값을 읽어올 수도 있다. 

<ul id="target">
    <li>HTML</li>
    <li>CSS</li>
</ul>
<input type="button" onclick="get();" value="get" />
<input type="button" onclick="set();" value="set" />
<script>
    function get(){
        var target = document.getElementById('target');
        alert(target.innerHTML);//HTML소스코드를 바로 보여줌
    }
    function set(){
        var target = document.getElementById('target');
        target.innerHTML = "<li>JavaScript Core</li><li>BOM</li><li>DOM</li>";
    }
</script>

2) outerHTML
outerHTML은 선택한 엘리먼트를 포함해서 처리된다.

<ul id="target">
    <li>HTML</li>
    <li>CSS</li>
</ul>
<input type="button" onclick="get();" value="get" />
<input type="button" onclick="set();" value="set" />
<script>
    function get(){
        var target = document.getElementById('target');
        alert(target.outerHTML);
    }
    function set(){
        var target = document.getElementById('target');
        target.outerHTML = "<ol><li>JavaScript Core</li><li>BOM</li><li>DOM</li></ol>";
    }
</script>

3) innerText, OuterText
innerHtml, outerHTML과 다르게 이 API들은 값을 읽을 때는 HTML 코드를 제외한 문자열을 리턴하고, 값을 변경할 때는 HTML의 코드를 그대로 추가한다.

<ul id="target">
    <li>HTML</li>
    <li>CSS</li>
</ul>
<input type="button" onclick="get();" value="get" />
<input type="button" onclick="set();" value="set" />
<script>
    function get(){
        var target = document.getElementById('target');
        alert(target.innerText);
    }
    function set(){
        var target = document.getElementById('target');
        target.innerText = "<li>JavaScript Core</li><li>BOM</li><li>DOM</li>";
    }
</script>

4) insertAdjacentHTML()

좀 더 정교하게 문자열을 이용해서 노드를 변경하고 싶을 때 사용한다.

<ul id="target">
    <li>CSS</li>
</ul>
<input type="button" onclick="beforebegin();" value="beforebegin" />
<input type="button" onclick="afterbegin();" value="afterbegin" />
<input type="button" onclick="beforeend();" value="beforeend" />
<input type="button" onclick="afterend();" value="afterend" />
<script>
    function beforebegin(){
        var target = document.getElementById('target');
        target.insertAdjacentHTML('beforebegin','<h1>Client Side</h1>');
    }
    function afterbegin(){
        var target = document.getElementById('target');
        target.insertAdjacentHTML('afterbegin','<li>HTML</li>');
    }
    function beforeend(){
        var target = document.getElementById('target');
        target.insertAdjacentHTML('beforeend','<li>JavaScript</li>');
    }
    function afterend(){
        var target = document.getElementById('target');
        target.insertAdjacentHTML('afterend','<h1>Server Side</h1>');
    }
</script>


블로그 이미지

가카리

소프트웨어와 하드웨어 프로그래밍, 취업 및 직장생활 전문 블로그

23. jQuery Node 변경 API

jQuery를 이용해서 노드를 제어하는 방법을 알아보자. jQuery에서 노드를 제어하는 기능은 주로 Manipulation 카테고리에 속해 있다. 

1) 추가

추가와 관련된 주요한 메소드는 4가지다. 각각의 관계를 그림으로 나타내면 아래와 같다.

아래 코드는 위의 API를 이용해서 문서의 구조를 변경한 예이다. (실행)

<div class="target">
    content1
</div>
 
//타겟
<div class="target">
       //타겟 바로 이전
    content2
       //타겟 바로 이후
</div>
//타겟
 
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
    $('.target').before('<div>before</div>');//타겟의 이전에 들어감
    $('.target').after('<div>after</div>');//타겟의 다음에 들어감
    $('.target').prepend('<div>prepend</div>');//타겟내의 바로 전에 들어감
    $('.target').append('<div>append</div>');//타겟내의 바로 이후에 들어감
</script>


2) 제거

제거와 관련된 API는 remove와 empty가 있다. remove는 선택된 엘리먼트를 제거하는 것이고 empty는 선택된 엘리먼트의 텍스트 노드를 제거하는 것이다. (실행)

<div class="target" id="target1">
    target 1
</div>
 
<div class="target" id="target2">
    target 2
</div>
 
<input type="button" value="remove target 1" id="btn1" />
<input type="button" value="empty target 2" id="btn2" />
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
    $('#btn1').click(function(){
        $('#target1').remove();
    })
    $('#btn2').click(function(){
        $('#target2').empty();
    })
</script>


3) 바꾸기

replaceAll과 replaceWith는 모두 노드의 내용을 교체하는 API이다. replaceWith가 제어 대상을 먼저 지정하는 것에 반해서 replaceAll은 제어 대상을 인자로 전달한다. (실행)
<div class="target" id="target1">
    target 1
</div>
 
<div class="target" id="target2">
    target 2
</div>
 
<input type="button" value="replaceAll target 1" id="btn1" />
<input type="button" value="replaceWith target 2" id="btn2" />
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
    $('#btn1').click(function(){
        $('<div>replaceAll</div>').replaceAll('#target1');//target1 앞에걸로 바꿈
    })
    $('#btn2').click(function(){
        $('#target2').replaceWith('<div>replaceWith</div>');//target2 앞에걸로바꿈
    })
</script>


4) 복사

<div class="target" id="target1">
    target 1
</div>
 
<div class="target" id="target2">
    target 2
</div>
 
<div id="source">source</div>
 
<input type="button" value="clone replaceAll target 1" id="btn1" />
<input type="button" value="clone replaceWith target 2" id="btn2" />
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
    $('#btn1').click(function(){
        $('#source').clone().replaceAll('#target1');
    })
    $('#btn2').click(function(){
        $('#target2').replaceWith($('#source').clone());
    })
</script>

5) 이동
dom manipulation API 인자로 특정 노드를 선택하면 이동의 효과가 난다. (실행)

<div class="target" id="target1">
    target 1
</div>
 
<div id="source">source</div>
 
<input type="button" value="append source to target 1" id="btn1" />
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script>
    $('#btn1').click(function(){
        $('#target1').append($('#source'));
    })
</script>


블로그 이미지

가카리

소프트웨어와 하드웨어 프로그래밍, 취업 및 직장생활 전문 블로그

22. Node 변경 API

1) 노드 추가

노드의 추가와 관련된 API들은 아래와 같다.
노드를 추가하기 위해서는 추가할 엘리먼트를 생성해야 하는데 이것은 document 객체의 기능이다. 아래 API는 노드를 생성하는 API이다.

<ul id="target">
    <li>HTML</li>
    <li>CSS</li>
</ul>
<input type="button" onclick="callAppendChild();" value="appendChild()" />
<input type="button" onclick="callInsertBefore();" value="insertBefore()" />
<script>
    function callAppendChild(){
        var target = document.getElementById('target');
        var li = document.createElement('li');
        var text = document.createTextNode('JavaScript');
        li.appendChild(text);
        target.appendChild(li);
    }
 
    function callInsertBefore(){
        var target = document.getElementById('target');
        var li = document.createElement('li');
        var text = document.createTextNode('jQuery');
        li.appendChild(text);
        target.insertBefore(li, target.firstChild);//firstChild(#TextNode) 앞에 li 추가함
    }
</script>



2) 노드 제거

노드 제거를 위해서는 아래 API를 사용한다. 이 때 메소드는 삭제 대상의 부모 노드 객체의 것을 실행해야 한다는 점에 유의하자.

<ul>
    <li>HTML</li>
    <li>CSS</li>
    <li id="target">JavaScript</li>
</ul>
<input type="button" onclick="callRemoveChild();" value="removeChild()" />
<script>
    function callRemoveChild(){
        var target = document.getElementById('target');
        target.parentNode.removeChild(target);
    }
</script>


3) 노드 바꾸기

노드 바꾸기에는 아래 API가 사용된다.

<ul>
    <li>HTML</li>
    <li>CSS</li>
    <li id="target">JavaScript</li>
</ul>
<input type="button" onclick="callReplaceChild();" value="replaceChild()" />
<script>
    function callReplaceChild(){
        var a = document.createElement('a');
        a.setAttribute('href', 'http://opentutorials.org/module/904/6701');
        a.appendChild(document.createTextNode('Web browser JavaScript'));
 
        var target = document.getElementById('target');
        target.replaceChild(a,target.firstChild);
    }
</script>


블로그 이미지

가카리

소프트웨어와 하드웨어 프로그래밍, 취업 및 직장생활 전문 블로그


21. Node 종류 API

노드 작업을 하게 되면 현재 선택된 노드가 어떤 타입인지를 판단해야 하는 경우가 있다. 이런 경우에 사용할 수 있는 API가 nodeType, nodeName이다. 
  • Node.nodeType
    node의 타입을 의미한다. 
  • Node.nodeName
    node의 이름 (태그명을 의미한다.)

1) Node Type

노드의 종류에 따라서 정해진 상수가 존재한다. 아래는 모든 노드의 종류와 종류에 따른 값을 출력하는 예제다.
for(var name in Node){
   console.log(name, Node[name]);
}

결과
ELEMENT_NODE 1
ATTRIBUTE_NODE 2
TEXT_NODE 3
CDATA_SECTION_NODE 4
ENTITY_REFERENCE_NODE 5
ENTITY_NODE 6
PROCESSING_INSTRUCTION_NODE 7
COMMENT_NODE 8
DOCUMENT_NODE 9
DOCUMENT_TYPE_NODE 10
DOCUMENT_FRAGMENT_NODE 11
NOTATION_NODE 12
DOCUMENT_POSITION_DISCONNECTED 1
DOCUMENT_POSITION_PRECEDING 2
DOCUMENT_POSITION_FOLLOWING 4
DOCUMENT_POSITION_CONTAINS 8
DOCUMENT_POSITION_CONTAINED_BY 16
DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC 32

아래 예제는 노드 종류 API를 이용해서 노드를 처리하는 예제다. 함수가 자기 자신을 호출하는 것을 재귀함수라고 하는데 본 예제는 재귀 함수의 예를 보여준다.

<!DOCTYPE html>
<html>
<body id="start">
<ul>
    <li><a href="./532">html</a></li>
    <li><a href="./533">css</a></li>
    <li><a href="./534">JavaScript</a>
        <ul>
            <li><a href="./535">JavaScript Core</a></li>
            <li><a href="./536">DOM</a></li>
            <li><a href="./537">BOM</a></li>
        </ul>
    </li>
</ul>
<script>
function traverse(target, callback){
    if(target.nodeType === 1){
        //if(target.nodeName === 'A')
        callback(target);
        var c = target.childNodes;
        for(var i=0; i<c.length; i++){
            traverse(c[i], callback);      
        }  
    }
}
traverse(document.