ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [JavaScript] DOM(Document Object Model)
    Legacy/Web 2015. 7. 13. 05:34
    728x90



    HTML 문서의 구조를 가리켜 문서 객체 모델(DOM)이라고 한다. 

    HTML 문서의 각 태그마다 기능(Method)와 속성(Attribute)가 있다. <a> 태그는 페이지를 링크로 이동시키는 기능을 수행한다. 또한 href, title, target 속성이 존재한다. 이 <a>태그 역시 문서 객체의 하나이다. 이처럼 HTML 태그는 각각의 기능과 속성을 가지고 있는 문서 객체이다. DOM을 배우는 주된 목적은 자바스크립트를 이용해 문서 객체를 선택하고 속성 또는 CSS를 적용하기 위해서이다.

    하지만 자바스크립트 DOM은 IE 8 이하 버전과 그 외 크롬, 파이어폭스, 사파리 등의 브라우저들 간에 호환성이 떨어진다는 단점이 있다. 하지만 jQuery는 이런 호환성이 떨어지는 단점들을 모두 해결하였다.


    선택자

    HTML에서 CSS와 자바스크립트 내에서 사용하는 스타일은 모두 선택한 요소의 디자인 속성을 바꿀 때 사용한다는 공통점을 가지고 있다. 하지만 HTML에서 사용하는 스타일은 클라이언트가 지정한 요소에 어떤 동작을 취했을 때 지정한 요소에 스타일을 적용시킬 수 없습니다. 그래서 HTML에서 작성된 스타일은 정적이라고 표현하고, 자바스크립트 내에서 작성한 스타일은 동적이라고 표현한다.

    자바스크립트를 이용하여 특정 문서 객체를 선택하고 여기에 속성 또는 스타일을 적용하기 위해서는 문서 객체의 선택자 사용법을 잘 알고 있어야 한다. 선택자에는 크게 직접 문서에서 요소를 선택해 오는 직접 선택자(id, class, 폼 이름, 소요 이름 선택자)가 있고, 이 선택자를 사용해 선택해 온 문서 객체를 기준으로 가까이에 있는 요소를 선택하는 인접 관계 선택자(parentNode, childNodes, firstChild, children, previousSibling, nextSibling) 선택자가 있다. 


    선택자의 종류

    직접 선택자

     document.getElementById("id 명")

     아이디를 이용해 요소를 선택한다.

     document.getElementsByTagName("태그 명")

     태그의 이름을 이용해 요소를 선택한다.

     document.formName.inputName

     폼 요소의 name 속성을 이용해 요소를 선택한다.

     인접 관계 선택자

     parentNode

     선택한 요소의 부모 요소를 선택한다.

     childNodes

     선택한 요소의 모든 자식 요소를 선택한다. 선택한 모든 요소가 배열 객체로 저장된다.

     children

     선택한 요소의 자식 요소인 태그만 선택한다. 선택한 모든 요소가 배열 객체로 저장된다.

     firstChild

     선택한 요소의 첫 번째 자식 요소만 선택한다.

     previousSibling

     선택한 요소의 이전에 오는 형제 요소만 선택한다.

     nextSibling

     선택한 요소의 다음에 오는 형제 요소만 선택한다.


    선택자의 적용 위치와 방법

    선택자를 사용할 때에는 <head> 태그 영역에 자바스크립트를 선언하게 되면, HTML을 읽어오는 것보다 스크립트의 선택자가 먼저 실행되어 문서 객체를 선택할 수 없게된다.

    HTML 문단 태그보다 먼저 자바스크립트가 문서 상단에 위치해 있어 먼저 실행되면 다음에 오는 문단 태그를 스크립트의 선택자를 사용하여 선택해 올 수 없게된다.

    스크립트에 선택문을 사용할 경우에는 다음과 같이 <body> 태그 영역에 문단 태그 작성을 마친 후 마지막 부분에 작성하거나, 아니면 window.onload=function(){...}를 이용하여 선택문을 작성해야 한다. 여기서 window.onload=function(){...}는 모든 문서 객체를 로딩한 후에 중괄호{} 내에 있는 실행문을 실행하라는 명령어라고 보면 된다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="ko" xml:lang="ko">
        <head>
            <title> new document </title>
            <meta http-equiv="content-type" content="text/html;charset=utf-8" />
        </head>
        <body>
            <h1 id="selector">선택자</h1>
            <script type="text/javascript">
                function Clicked() {
                    document.getElementById("selector").style.color="green";
                }
            </script>
            <button onclick="Clicked()">버튼</button>
        </body>
    </html>
    cs

    올바른 선택자의 위치를 볼 수 있다. selector를 먼저 선언해 준 후 스크립트 코드가 와야 선택할 수 있다.

    (사실 위 코드는 함수 안에 들어가 있으므로 그냥 실행이 되지만 10행과 12행을 지우고 <h1> 태그를 </script> 태그 밑으로 복사하여 실행하면 green 속성은 적용되지 않는다. 다음과 같이 말이다.)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="ko" xml:lang="ko">
        <head>
            <title> new document </title>
            <meta http-equiv="content-type" content="text/html;charset=utf-8" />
        </head>
        <body>
            <script type="text/javascript">
                document.getElementById("selector").style.color="green";
            </script>
            <h1 id="selector">선택자</h1>
        </body>
    </html>
    cs

    어디에 어떻게 써야하는지는 알겠고 조금 실용적인 예제를 살펴보자.

    다음 예제는 직접 선택자를 이용한 예제이다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="ko" xml:lang="ko">
        <head>
            <title> 직접 선택자 예제 </title>
            <meta http-equiv="content-type" content="text/html;charset=utf-8" />
        </head>
        <body>
            <div>
                <h1>선호하는 음식</h1>
                <div id="food_1">
                    <h2 id="title">한식</h2>
                    <ol>
                        <li id="kimchi">
                            <a href="#">김치</a>
                        </li>
                        <li>불고기</li>
                        <li>비빔밥</li>
                    </ol>
                </div>
                <div id="food_2">
                    <h2>양식</h2>
                    <ol id="list">
                        <li>돈가스</li>
                        <li id="pizza">피자</li>
                        <li>파스타</li>
                    </ol>
                </div>
            </div>
            <script type="text/javascript">
            //<![CDATA[
                document.getElementsByTagName("h1")[0].style.color="green";
                document.getElementById("title").style.color="red";
     
                var myList=document.getElementById("food_1").getElementsByTagName("li")[1];
                myList.style.backgroundColor="red";
            //]]>
            </script>
        </body>
    </html>
    cs

    위 예제의 실행결과는 다음과 같다.



    왜 이런 결과가 나왔는지 코드를 분석해보는것이 좋은 공부가 될 것이다.


    인접 관계 선택자

    다음 예제를 실행해보자.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="ko" xml:lang="ko">
        <head>
            <title> 인접 관계 선택자 예제 </title>
            <meta http-equiv="content-type" content="text/html;charset=utf-8" />
        </head>
        <body>
            <div id ="wrap">
                <p>내용1</p>
                <p>내용2</p>
                <p>내용3</p>
                <p>내용4</p>
            </div>
            <script type="text/javascript">
            //<![CDATA[
                document.getElementById("wrap").firstChild.style.color="red";
                var p=document.getElementsByTagName("p")[1];
                p.nextSibling.style.backgrountColor="yellow";
            //]]>
            </script>
        </body>
    </html>
    cs

    아마 예상했던 결과가 나오지 않았을 것이다. 당신이 IE 8버전 이하를 사용하고 있지 않았다면! 내용1이 빨간색으로 바뀌지 않았을 것이다.

    이것은 다음과 같은 코드가 파이어폭스, 크롬, 사파리, IE 9버전 이상과 IE 8버전 이하가 다르기 때문이다. 사실 코드에 더 직관적으로 나타나는 것은 IE 8버전 이하이다. 다른 브라우저 에서는 다음 코드는 같은 코드에 대한 브라우저 간의 차이를 보여준다.


    코드 작성

    IE 8 버전 이하 브라우저 

    그 외의 브라우저 

    <div id="wrap">

        <p>내용1</p>

        <p>내용2</p>

        <p>내용3</p>

        <p>내용4</p>

    </div>

    <div id="wrap">

        <p>내용1</p>

        <p>내용2</p>

        <p>내용3</p>

        <p>내용4</p>

    </div>

    <div id="wrap"><br />

        <p>내용1</p><br />

        <p>내용2</p><br />

        <p>내용3</p><br />

        <p>내용4</p><br />

    </div>

    차이가 보이는가? 파이어폭스, 크롬, 사파리, IE 9버전 이상의 브라우저들은 HTML 코드에 공백이 있거나 줄 바꿈이 들어가면 그것을 한 칸의 공백문자로 인식한다. 때문에 위의 예제에서 firstChild는 공백 문자가 선택되는 것이다.

    이를 해결하기 위해서는 노드 타입을 사용해야한다.


    노드 타입

    HTML 노드에는 HTML 태그를 연결하는 요소(Element) 노드와 텍스트를 연결하는 텍스트(Text)노드, 그리고 속성을 연결해주는 속성(Attribute) 노드가 있다.

    노드들은 다음과 같은 타입 값을 가진다.


    요소(Element) 노드 - 1

    속성(Attrubute) 노드 - 2

    텍스트(Text) 노드 - 3


    선택자로 요소를 가져온 후 .nodeType를 하면 반환되는 값이 노드의 타입 값이다.

    <a href="http://w3.org"id="m">W3C</a> 에서 다음과 같이 코드를 작성하면 다음과 같은 값들을 확인할 수 있다.


    document.getElementById("m").noteType; // 1이 반환된다. <a>라는 요소이기 때문이다.

    document.getElementById("m").firstChild.nodeType; // 3이 반환된다. 'W3C'가 선택되었기 때문이다.

    document.getElementById("m").getAttributeNode("href").nodeType; // 2가 반환된다. href 속성이 선택되었기 때문이다.

    다음과 같이 수정하면 된다.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="ko" xml:lang="ko">
        <head>
            <title> 인접 관계 선택자 예제 </title>
            <meta http-equiv="content-type" content="text/html;charset=utf-8" />
        </head>
        <body>
            <div id ="wrap">
                <p>내용1</p>
                <p>내용2</p>
                <p>내용3</p>
                <p>내용4</p>
            </div>
            <script type="text/javascript">
            //<![CDATA[
                document.getElementById("wrap").children[0].style.color="red";
     
                var p = document.getElementsByTagName("p")[1];
                var nextObj = p.nextSibling;
                while(nextObj.nodeType != 1) {
                    nextObj=nextObj.nextSibling;
                }
                nextObj.style.backgroundColor="yellow";
            //]]>
            </script>
        </body>
    </html>
    cs

    16행~23행이 바뀌었다.

    16행에서는 firstChild에서 children[0]으로 바뀌었는데, 여기서 의아한 사람이 존재할 것이다. <div>태그의 0번째 자식노드는 마찬가지로 <br />이 아닌가? 맞다. 맞는 이야기지만 firstChild와 children 객체배열은 서로 큰 차이점이 있다. firstChild는 텍스트 노드와 요소 노드 모두가 선택될 수 있지만 children 배열은 오직 '요소' 노드만이 선택된다. 때문에 텍스트 노드인 <br />은 children 배열에 저장되지 않는다.


    19행에서는 nextObj 변수를 도입했다. 이렇게 해주는 이유는 우리가 내용3이 있는 <p> 태그에 노란 백그라운드 속성을 지정하려고 하는데 단순히 nextSibling을 하면 이것은 내용2와 내용3에 있는 <br />을 선택하는 결과를 만들기 때문에 그렇다. 그럼 두번 호출하면 될텐데 구지 반복문을 사용한 이유는 좀 더 유연한 코드를 위해서 그렇게 하였다. 혹시 중간에 <br />이 하나만 있을거라고 보장할 수 없을 경우도 있지 않나?


    요소의 속성값 변경, 생성 및 불러오는 방법

     요소 선택.속성명

     요소의 속성값을 반환한다.

     요소 선택.속성값="새 값"

     요소의 속성값을 새 값으로 변경하거나 생성한다.

     요소 선택.getAttribute("속성")

     요소의 속성값을 반환한다.

     요소 선택.setAttribute("속성", "새 값");

     요소의 속성값을 새 값으로 변경하거나 생성한다.


    위에서 선택자에 대해 잘 이해하고 있다면 별로 어려울 것도 없다. 다만 여기서도 주의할 점은 backgroundColor 같은 속성을 CSS와는 다르게 표기해야한다는 것이다. background-color이 아니다. backgroundColor이다.

    추가로 innerHTML이라는 속성도 존재한다. 다음을 보자.

    <h1 id="title"><a href="#">이 링크를 선택해 주세요.</a></h1>

    여기서 <a href="#">이 링크를 선택해 주세요.</a> 를 선택하려면 어떻게 해야할까? <a>태그에는 지금 id나 class가 지정되어 있지 않다.

    하지만 이를 감싸고 있는 <h1>에 id가 지정되어 있으므로 이걸 이용하면 <a>를 선택할 수 있다. 다음과 같은 문법으로 말이다.


    doucument.getElementById("title").innerHTML;

    doucument.getElementById("title").innerHTML="<strong>이 링크를 선택해주세요.</strong>";


    <a href="#">이 링크를 선택해 주세요.</a>가 <strong>이 링크를 선택해주세요.</strong>로 변경된다.


    문서 객체 이벤트 핸들러 적용하기

    이벤트 핸들러 모음 - http://iwantadmin.tistory.com/110

    이벤트 핸들러에는 많은 종류가 있다. 그 중에 onclick 이벤트 핸들러에 대해서만 소개를 해보겠다.

    <a href="#" id="btn1">버튼 1</a>

    위의 HTML코드에 다음과 같은 스크립트를 넣으면

    document.getElementById("btn1").onclick=function(){

    alert("welcome!!!");

    }

    btn1이 클릭되었을 때 HTML코드 상에는 alert가 없지만 자바스크립트 코드로 추가해주고 있다.

    이벤트 핸들러 역시 일종의 속성이라고 생각하면 된다. 단지 함수가 콜백 될 뿐이다.



    폼 요소 선택자

    폼에 있는 요소들(input)을 선택해보자.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
    <html xmlns="http://www.w3.org/1999/xhtml" lang="ko" xml:lang="ko">
        <head>
            <title> new document </title>
            <meta http-equiv="content-type" content="text/html;charset=utf-8" />
        </head>
        <body>
            <form method="post" action="#" name="login">
                <fieldset>
                    <legend>회원 로그인</legend>
                    <p>
                        <label for="id">아이디</label>
                        <input type="text" name="user_id" id="id" />
                        <label for="pw">비밀번호</label>
                        <input type="password" name="user_pw" id="pw" />
                    </p>
                    <input type="submit" value="login" />
                </fieldset>
            </form>
            <script type="text/javascript">
                document.login.onsubmit=function() {
                    var id_v=document.login.user_id.value;
                    var pw_v=document.login.user_pw.value;
     
                    alert(id_v);
                    alert(pw_v);
                }
            </script>
        </body>
    </html>
    cs

    form에는 name이 있다. 이는 document 객체에 그냥 이름으로 적어주면 된다. 우리는 form의 name을 login으로 하였고 자바스크립트 코드에서는 단순히 document.login을 하는 것 만으로도 form을 선택할 수 있다. 이 form에서 name을 가지고 form 내부의 요소들 역시 선택할 수 있는데, form에 적힌 name 값들과 document.login.user_id를 살펴보면 어떻게 접근할 수 있는지 확인할 수 있다. 또한 user_id에 입력되어 있는 값을 가져올 때는 value를 입력하면 된다.

    이 외에도 value, disabled(비활성화), defaultValue(기본으로 설정되었던 값), selected(<selecte>태그에서 <option>중 선택된 상태를 가져온다. 선택 되어 있다면 true 아니면 false를 반환한다.), checked(체크박스와 라디오버튼이 선택되어 있으면 true 아니면 false) 가 있다.

Designed by Tistory.