본문

jQuery기반의 깔끔한 트리메뉴, jsTree #1

[그림 1] jsTree의 예시. 노드 선택(단일/다중/체크박스), 추가/수정/삭제, 비동기적 로딩이 가능하다.

자바스크립트가 나오기 초창기부터 트리메뉴는 발전하기 시작하였다. 90년대 중반즘에 윈도95에서 동작하는 자바스크립트 트리메뉴를 보고 신기해서 서점에 달려가 html/js 책을 망설임 없이 사버렸었다. 그당시에는 책들이 조잡하고 야시시 했기 때문에 가장 무난한 표지와 두께의 책을 고르려 했으나, 결국 책을 뒤적이다 <li>태그의 예시를 프린트해놓은 책을 보고 그게 js 트리메뉴인줄 알고 샀던것... 물론 그것도 신기해 했었지만 js가 제대로 설명되지도 않은 허접한 책이라 실망했었다. 이후에도 자바 애플릿이니 뭐니 해서 온갖 트리메뉴를 보아 왔고, 그로부터 시간이 많이지났다. 이제는 어쩌다 보니(jQuery) 그당시와는 전혀 다른 언어로 바뀌는 느낌이다. 

나는 jQuery를 좋아한다. 비슷한 prototype도 있지만 jQuery는 facebook, prototype은 myspace같은 느낌이랄까?? 그리고 전에도 올렸다시피, 이전작업에 jQuery가 도움을 주어 더욱 호감이 간다. 그래서 나는 jQuery빠돌이가 되기로 했다. 모든 작업은 jQuery를 통해서 할것이라고!! 그래서 빠심으로 이번에는 jQuery를 지원하는 tree를 찾아보기로 했다. 역시나 이미 많은 tree들이 있었지만 내가 원하는것은 xml/json을 지원하는 간단한 트리. 물론 유명한 많은 프로젝트들이 있었지만, 그중에서 비록 문서화가 제대로 안되어 있고 예제도 거의 없어 접근하기가 쉽지만은 않지만 무궁한 가능성을 보아 jsTree를 선택하였다.

우선 jsTree에 대한 계층을 살펴보면 다음과 같다. jQuery라는 framework내에 jsTree라는 component가 있고 그 안에 core, ui, themes, html_data, hotkeys, json_data, cookies, sort, DND, checkbox, xml_data, search, contextmenu 등의 plugin들이 있다. 사용자는 jsTree를 사용하는데 있어 원하는 plugin을 선택하고 그 플러그인에 대한 각각의 설정을 할 수 있다. 그럼 jsTree의 Core Plugin에 있던 예제를 분석하여 jsTree에 다가가보자. 2번을 먼저 보는편이 더욱 편할 수 있다.


1. jsTree 기본사항
<script type="text/javascript" src="_lib/jquery.js"></script>
<script type="text/javascript" src="jquery.jstree.min.js"></script>

=> 우선 jQuery와 jsTree 라이브러리를 불러와야 한다. jsTree의 상위에 jQuery가 있어 종속성을 갖기 떄문이다.


<script>
jQuery("some-selector-to-container-node-here").jstree([ config_object ]);
 
jQuery("some-selector-to-container-node-here")
 .jstree({
  core : { /* core에 대한 옵션이 이곳에 들어간다.*/ },
  themes : { /* themes에 대한 옵션이 이곳에 들어간다.*/ },
  plugins : [ "themes", "html_data", "some-other-plugin" ]
 });

=> jsTree가 들어갈 컨테이너(개체)를 jQuery화 시킨 후, 그것은 또한 jsTree화 시킨다는 의미의 명령을 위의 두가지 형태로 나타낼 수 있다. 물론 정확한 설명은 아니지만 이렇게 생각하는게 처음접하여 이해하기는 쉽다. jstree에는 첫번째 항목과 같이 config_object처럼 환경을 설정해주는 변수를 넣을 수 있으며, 기본설정에서 많은 변화가 없을 경우는 소스의 간략화를 위하여 두번째와같이 인라인으로 처리해 줄 수 있다. 플러그인은 config_object내에서 하부객체를 통해 설정되는데, 위의 소스를 보면 개략적으로 이해할 수 있을것이다. plugins라는 하부객체는 사용자가 어떤 플러그인을 사용할까에 대해서 정의하는 객체이고, 정의된 각 plugin에 대해서 설정하려면 사용된 plugin의 이름으로 하부객체를 만들어 정의해주면 된다. 단, core라는 플러그인은 plugins에 암시적으로 포함되어 있다.


jQuery("some-selector-to-container-node-here").jstree("operation_name" [, argument_1, argument_2, ...]);
jQuery.jstree._reference(needle).operation_name([ argument_1, argument_2, ...]);

=>주어진 인스턴스에 대해 작업을수행하는데있어 위의 두가지 방법이 사용될 수 있는데, 물론 첫번째 방법이 가장 직관적이고 좋다. 참고로 needle은 dom노드/컨테이너 선택자/컨테이너 내의 노드를 의미한다.


jQuery("some-container")
 .bind("loaded.jstree", function (event, data) {
  alert("TREE IS LOADED");
 })
 .jstree({ /* configuration here */ });
 
=>트리의 모든 변화는 이벤트를 통해 전파되며, 모든 이벤트들은 jstree 네임스페이스를 통해 전파되며, 발생된 함수의 이름을 따게 된다. 몇몇 이벤트들은 인스턴스가 완성되기 전에 바인딩을 하는것이 좋을 수 있다. data에는 아래와 같이 값이 넘어가게 된다.
 {
 "inst" : /* 실제 트리 인스턴스 */,
 "args" : /* 함수에 넘겨진 인자값들  */,
 "rslt" : /* 이벤트에 사용된 어떠한 데이터  */,
 "rlbk" : /* 롤백객체(선택적으로 사용됨)) */
}



 2. 예제를 통한 jsTree 알아보기
<input type="button" class="button" value="toggle_node" id="toggle_node" style="clear:both;" />
<
div id="demo1" class="demo">
 <ul>
  <li id="phtml_1">
   <a href="#">Root node 1</a>
   <ul>
    <li id="phtml_2">
     <a href="#">Child node 1</a>
    </li>
    <li id="phtml_3">
     <a href="#">Child node 2</a>
    </li>
   </ul>
  </li>
  <li id="phtml_4">
   <a href="#">Root node 2</a>
  </li>
 </ul>
</
div>

<
script type="text/javascript" class="source">
$(function () {
 $("#toggle_node").click(function () {
  $("#demo1").jstree("toggle_node","#phtml_1");
 });
 $("#demo1")
  .bind("open_node.jstree close_node.jstree", function (e) {
   $("#log1").html("Last operation: " + e.type);
  })
  .jstree({ "plugins" : [ "themes", "html_data" ] });
});
</
script>

이 본문의 기반이 되는 위 예제를 포함한 페이지는, jsTree 공식 홈페이지의 Core부분 명세서 페이지인 여기에서 확인할 수 있다.

toggle_node의 id를 가진 객체(버튼)에서 클릭이벤트가 발생하면, demo1의 id를 가진(div 컨테이너)의 jstree toggle_node라는 작업이수행되며, 그 작업에 대한 인자로 #phtml_1가 주어진다 (즉, phtml_1의 id를 가진 li객체) 다시말하면, 버튼이 클릭되면 phtml_1항목(즉 Root Node1)가 열렸다 닫힐것이라는 것을 의미한다.
 
그리고 다음 부분은 demo1이라는 id를 가진 객체(div 컨테이너)에서 일어난 이벤트를 바인딩한다는것을 의미한다. bind의 원형은 .bind( eventType, [ eventData ], handler(eventObject) )라는 사실과 eventType는 스페이스로 이어진 이벤트들의 문자열으로 나열할 수 있고 만약 이벤트에 점(.)이 있을 경우 [이벤트.네임스페이스]의 형태로 구성된다는 사실을 기억하자.
그러면 그 줄은 open_node와 close_node의 두개의 이벤트가 jstree 네임스페이스 상에서 발할 때 뒤의 인라인 함수를 발생한다는 의미를 알게 된다. 그리고 jstree를 생성하는데 있어 themes(ui 통일성), html_data(div컨테이너 내의 html을 불러오기 위해) 두개의 plugin을 추가하였다.  

다음 게시물에서는 xml과 연동(지난번에 작성된 nginx의 Autoindex페이지를 파싱하여 xml로 출력하기) 하여 윈도우 탐색기와 동일하게 작동하는 소스를 알아보고, xml등의 외부 데이터 사용시 문제가 되는 부분에 대한 버그를 수정하는 방법도 다룰것이다.

댓글

Holic Spirit :: Tistory Edition

design by tokiidesu. powerd by kakao.