초창기에 개발에 대해 전혀 모를때 인터넷에 있는 많은 정보들을 볼 때 가장 답답한 부분중 하나가 설명하는 사람이 당연히 내가 알꺼라고 생각하고 그냥 넘어가는 부분을 정작 나는 몰라서 그사람의 설명이나 소스까지 도달하기도 어려웠다는 것이지요. 머 그렇다고 항상 모든 것을 다 설명한다는 것도 어렵겠지만 블로그에서는 최대한 자세하게 쓰려고 하고 있기는 하지만 좀 초심을 잃어버린 생각이 들었습니다. 그리고 새로 알게된걸 항상 포스팅으로 하게되지는 않고 그러다 보면 포스팅타이밍을 놓쳐버린 것들도 많죠.
쿡이님의 질문을 받으면서 생각난 김에 JS로 엘리먼트를 다룰때 가장 많이 사용할 추가, 삭제에서 prototype.js가 지원하는 부분에 대해서 다시 한번 정리합니다.
prototype.js에는 Element 클래스가 있습니다. HTML의 DIV, INPUT, LI같은 엘리먼트에 관련된 클래스입니다. Element의 API문서를 보면Element클래스가 지원하는 많은 메서드를 볼 수 있습니다. 엘리먼트와 관련된 속성에 대한 것이라든지, 추가, 삭제, 생성등등의 기능을 지원하고 있습니다.
일반적인 방법
<div id="testDivision" name="testDivision">
<a href="#">Link 1</a>
</div>
간단한 HTML을 가지고 보겠습니다. 엘리먼트를 핸들링할때 JS에서 제공하는 2가지방법이 있습니다. innerHTML을 이용하는 방법과 DOM을 이용하는 방법입니다.
일반적으로는 innerHTML을 이용하는 것이 간단하면서도 편하기 때문에 많이 사용합니다.
var htmlStr = "<a href='#'>Link 2</a>";
var obj = document.getElementById("testDivision");
obj.innerHTML = obj.innerHTML + htmlStr;
사실 설명할 내용도 없긴 하지만 innerHTML은 이름 그대로 해당 엘리먼트의 안에 있는 HTML을 의미하고 있습니다. 내부 HTML을 새로지정하면 새로 지정하는 내용으로 replace가 됩니다. 기본의 innerHTML값과 새로추가할 HTML스트링을 문자열로 이어붙혀서 다시 innerHTML으로 할당해서 HTML의 구조를 동적으로 바꾸는 것입니다. js를 실행하면 HTML이 아래와 같은 모습이 됩니다.
<div id="testDivision" name="testDivision">
<a href="#">Link 1</a>
<a href="#">Link 2</a>
</div>
두번째 방법은 DOM입니다. DOM은 Document Object Model의 약자로 표준이 정해져 있고 대부분의 브라우저가 지원하고 있습니다. 엘리먼트를 추가/삭제같은 DOM Level 2에 정의가 되어 있습니다.(DOM Level 1에서 추가확장되어 현재는 대부분 Level 2를 지원하고 있는 것으로 알고 있습니다.) 이름대로 DOM을 다루기 위해서 만들어진 것이기 때문에 다양한 메서드를 제공하고 있고 좀 더 세련된 느낌의 사용법을 가지고 있습니다.
var elem = document.createElement("a")
elem.setAttribute("href", "#");
elem.appendChild(document.createTextNode("Link 2"));
document.getElementById("testDivision").appendChild(elem);
같은 기능을 DOM으로 구현한 것입니다. 엘리먼트 만들고 속성추가하고 TextNode만들어서 A엘리먼트 안에 넣은 다음에 추가한 것입니다. 메서드로 다양하게 다룰 수 있기는 하지만 저 간단한 소스도 소스로는 꽤 복잡하게 작성되고 있고 한눈에 어떻게 동작할 것인지를 파악하기가 쉽지 않고 복잡한 HTML의 경우에는 훨씬 복잡하게 됩니다. innerHTML에 비해서 특정엘리먼트만 지우는 remove관련 메서드도 지원하고 있기는 하지만 브라우져의 따라 DOM Level 1/2의 지원차이가 있습니다.
DOM은 Dom Test Pages에서 지원여부를 테스트해 볼 수 있고 PPK의 W3C DOM Compatibility에서 브라우져별 차이를 파악할 수 있습니다.
prototype.js 이용하기
당연히 prototype.js를 로드해야하고 그 후에 다음과 같이 사용하면 됩니다.
$("testDivision").insert("<a href='#'>Link 2</a>");
$("testDivision").update("<a href='#'>Link 2</a>");
$("testDivision").remove();
너무 간단한 코드라서 그냥 한 코드블럭에 다 썼습니다. 첫줄 insert만으로 위에서 설명했던 기능과 동일한 기능을 합니다. update는 replace의 기능을 합니다. 2번째 줄을 실행하면 Div안에 link2만 존재하게 되겠고 remove를 실행하면 testDivision DIV자체가 삭제되어버립니다. 간단한 기능만 소개했지만 그외에도 Element관련 다양한 기능을 제공하고 있습니다. prototype.js내부적으로 크로스 브라우징을 지원하기 때문에 브라우저호환에 대해서 큰 걱정없이 사용할 수 있습니다.
추가적으로 좀 더 세밀하게 컨트롤 할 수 있는 기능을 제공하고 있습니다.
$("testDivision").insert({top:"<a href='#'>Link 2</a>"});
// 결과
// <div id="testDivision" name="testDivision">
// <a href="#">Link 2</a><a href="#">Link 1</a>
// </div>
$("testDivision").insert({bottom:"<a href='#'>Link 2</a>"});
// 결과
// <div id="testDivision" name="testDivision">
// <a href="#">Link 1</a><a href="#">Link 2</a>
// </div>
$("testDivision").insert({before:"<a href='#'>Link 2</a>"});
// 결과
// <a href="#">Link 2</a>
// <div id="testDivision" name="testDivision">
// <a href="#">Link 1</a>
// </div>
$("testDivision").insert({after:"<a href='#'>Link 2</a>"});
// 결과
// <div id="testDivision" name="testDivision">
// <a href="#">Link 1</a>
// </div>
// <a href="#">Link 2</a>
위 코드처럼 JSON형태로 사용해서 insert되는 위치를 지정해 줄 수 있습니다. 사용할 수 있는 position값은 top, bottom, before, after입니다. 이걸 이용하면 쉽게 원하는 위치에 엘리먼트의 삽입/삭제가 가능합니다.
좀 복잡한 HTML의 경우에는 script.aculo.us의 Builder을 사용하는 것도 괜찮은 방법 같습니다.
좋은글 잘 보았습니다.
마지막 예제코드 14번 라인의...
$("testDivision").insert({bottom:"<a href='#'>Link 2</a>"});
를
$("testDivision").insert({before:"<a href='#'>Link 2</a>"});
로
해야 할 것 같은데요.
아~ 그러네요... 소스에 오류가 있었군요. 수정해 놓겠습니다. 감사합니다.