라이브러리화 한다는 것은

HTML 파일에 같이 작성된 자바 스크립트(JS) 코드를

별도의 JS 파일에 함수로 구현하고

이 함수만 호출하면

TreeGrid를 사용할 수 있도록 하겠다는 것이다.

또, 사용자(개발자)가 자신의 상황에 맞추어

간단한 설정만 하면 TreeGrid를 사용할 수 있도록 하는 것이다.

즉, TreeGrid 라이브러리 파일(sample3_treegrid9.js)과

이 라이브러리를 사용하는 HTML 파일(sample3.html)로 분할 해서 구현한다.


라이브러리화한 후,

HTML 파일에 남아있는 코드를 보면

복잡한 코드는 사라지고 option과 data만 남은 것을 볼 수 있다.

option과 data는

TreeGrid 사용자의 상황에 따라 바꿔서 지정하고

사용자는 30 라인에 있는 것처럼

TreeGrid9을 실행만 시키면 된다.


sample3.html


기존의 코드는 다음과 같이 sample3_treegrid9.js파일에 작성하고

HTML(sample3.html)에서는

8 라인에서 작성한 것처럼 <script src="sample3_treegrid9.js"></script>

JS 파일을 가져오기 하면 된다.

sample3_treegrid9.js


이상의 코드와

이전 예제(sample2.html)와 차이는

1 라인의 TreeGrid9 함수뿐이다.

외부 파일로 빼면서 함수로 구성한 것이다.

모든 코드는 동일하다.

다만, HTML에서 호출할 때 함수로 호출하지 않고

New를 사용해서 클래스로 실행했다.

간단하게는 함수화해서 함수를 호출해도 되지만

앞으로 여러 가지 기능을 추가해 나갈 것이기 때문에

클래스 방식으로 사용하였다.

JS에서는 함수와 클래스가 유사하게 사용된다.

자세한 설명은 [JS 클래스]로 검색하면 찾을 수 있다.



본 예제는 모든 데이터를 화면에 출력하고

자식 노드는 부모 노드 보다 뒤로 들여쓰기 하여 구현했다.

이번 단계에서는 부모 노드를 클릭하면

자식 노드를 감추고 보여주는 기능을 구현할 예정인데

쉽게 코드를 설명하기 위해

숨기는 기능부터 먼저 구현해 본다.


기능 구현을 위해 고려해야 할 대상은 다음과 같다.

  • 클릭 대상 선택
  • 자식이 있는 부모와 없는 부모, 자식을 보여주고 있는지 숨기고 있는지 구분하는 방법


둘 다 같은 결과를 필요로 하는데,

하나의 노드(행)를 클릭해서 자식을 숨기게 되면

현재 어떤 노드가 선택되었는지 보여 주는 기능을 구현하기 어렵다.

(행 선택 기능으로 여기서는 구현하지 않는다.)

그리고 두 번째 기능을 구현하기 위해

대부분 노드 앞에 특정 기호를 사용하게 된다.

즉, 특정 기호로 자식이 있는지 없는지 표시하고

특정 기호를 클릭하면 자식을 보이거나 숨기게 구현다.


윈도우 탐색기를 예로 하면

하위 폴더가 있는 경우 + 기호가 나오고

부모 폴더의 + 기호를 클릭하면

하위 폴더가 나타나며 – 기호로 바뀌게 된다.

여기서는 이 기호를 Expander라고 하고

Expander를 클릭하면 자식을 숨기거나

보이도록 구현한다.


다음으로 처리해야 할 것은

Expander를 클릭하면

내 자식 노드들을 찾아서 숨기는 것이다.

나의 자식은 나를 부모로 지정한 노드들을 의미하고

나를 부모로 지정한 노드들은

클래스명에 "treegrid9-parent-"를 이용하여

나(나의 ID)를 지정한 노드들을 의미한다.


이상의 개념을

다음과 같이 코드로 구현하면 되는데

코드를 보기 전에

위 개념을 토대로 직접 작성 해보는 것이 실력향상에 도움이 될 수 있다.


sample4.html

HTML 파일에서 11 라인에 CSS 클래스 하나를 추가 했다.

자식 노드를 숨기고 보여주기 위한 expander와 관련된 것으로

treegrid9-indent와 같은 기능을 하지만

expander 기호에 마우스를 올리면

클릭할 수 있는 기호로 바꾸는 스타일이 추가된 것이다.


sample4_treegrid9.js

먼저 30 라인을 보면 If문 조건이 바뀌었다.

이전에는 첫 번째 필드(i===0)이고

깊이가 0 이상 (depth>0)이면 들여쓰기를 하도록 했는데,

현재는 깊이 조건이 빠져서

모든 노드에서 들여쓰기 span이 생성된다.

자식이 있는 부모에 expander 기호를 붙이게 되면

다음과 같이 자식이 없는 부모와 줄 맞춤이 맞지 않게 된다.

           + Job1
           Job3

따라서 모든 노드에 span을 생성하고

자식이 있는 부모 노드만 span에 expander 기호와

CSS 스타일(treegrid9-expander)를 넣어서 보기 좋게 만들었다.


다음으로 기존 코드에 추가된

13 라인부터 22 라인을 이해하면 된다.

자식이 부모를 지정하는 방식이기 때문에

자식을 생성하다가

부모 ID(row.parent)로 부모를 찾아서 $(".treegrid9-" + row.parent)

부모의 클래스 명에 treegrid9-expanded라는

이름이 있으면 부모 표시가 된 것이니 넘어가고

없으면 부모 표시가 되지 않은 것이니 !parent.hasClass("treegrid9-expanded")

부모 표시와 처리를 진행하게 된다.

클래스명 treegrid9-expanded는 식별자로 사용되는 이름이고

별도의 CSS 지정을 하지 않았다.

이렇게도 많이 사용하기 때문에 기억해두면 좋을 것이다.


부모 처리가 되지 않았으며

먼저, expander로 사용할 span 태그를 찾는다.

여기서는 부모(parent[0] 즉 TR)의

첫 번째 셀(TD) 중에서 첫 번째 자식(span)을

expander 기호를 넣을 태그로 보고 .addClass("treegrid9-expander")

– 기호를 넣어준다. expander.html("-")


expander(기호)를 클릭하면

현재 노드의 자식 노드를 찾아서 숨겨주는 처리를 해야 한다.

클릭한 개체(expander 즉 this)에

가장 가까운(closest) TR을 찾아서 $(this).closest("tr")

현재 노드를 파악하고,

현재 노드의 ID을 추출한 뒤 getNodeId(tr)

해당 ID을 부모로 지정한 "tr.treegrid9-parent-" + id

모든 자식(TR)을 찾아서 find

보이지 않게 (hide) 처리하면 된다.

JQuery의 closest, find, hide를 활용한 코드로

자세한 설명은 찾아 보길 바란다.


마지막으로 현재 노드의 ID 값을 찾는 getNodeId 함수는

getDepth 함수와 같이 정규식을 사용해서

ID 값(숫자)만 남겨서 반환하는 함수이다.


sample4.html 파일을 실행한 후

expander(-)를 클릭해서

다음과 같이 Job2가 숨겨지는지 확인해 보자




앞서의 예제에서는 expander를 클릭하면

자식 노드가 숨겨지게 코드를 작성하였다.

여기서는 expander를 다시 클릭하면

감춰진 자식 노드가 보이는 기능을 구현한다.

즉, expander를 클릭하면 숨겨지고,

다시 클릭하면 나타나고

다시 클릭하면 숨겨지도록 구현한다.


개념부터 정리하면 모든 노드는 펼쳐져 있다.

이때 부모 노드의 expander 기호는 모두 – 이다.

부모 노드의 expander를 클릭하면

기호는 –에서 열수 있다는 의미인 + 기호로 바꾸고

자식 노드들을 보이지 않게(Hide) 처리한다.

다시 expander를 클릭하면

열렸다는 의미로 기호는 – 로 바꾸어 주고

자식 노드들을 보이게(show) 처리하면 된다.


간단한 개념이기 때문에

직접 구현해 본 후 다음 코드를 보는 것이 좋다.


기존 코드에 다음과 같이 몇 라인만 바꾸어 주면 된다.

            if (!parent.hasClass("treegrid9-expanded")){
                parent.addClass("treegrid9-expanded");
                var expander = $(parent[0].cells[0].firstChild).addClass("treegrid9-expander");
                expander.html("-");
                expander.click(function() {
                    var isexpanded = $(this).html() === "-";
                    if (isexpanded) {
                        $(this).html("+");
                    } else {
                        $(this).html("-");
                    }
                    var tr = $(this).closest("tr");
                    var id = getNodeId(tr);
                    table.find("tr.treegrid9-parent-" + id).each(function(i, e){
                        if (isexpanded)
                            $(this).hide();
                        else {
                            $(this).show();
                        }
                    });
                });
            }

sample5_treegrid9.js

expander를 클릭하면

expander의 기호가 무엇인지 판단해서 $(this).html() === "-"

자식 노드를 보일 것인지(show) 숨길 것인지(hide)를 처리한다.


자식노드를 찾는 것도 앞서의 코드와 동일하다.


실행해 보면 트리 라이브러리처럼

자식이 보였다 안보였다 하는 것을 확인 할 수 있다.


이제 데이터를 바꿔서 실행해 보자.

var data = [
                {id:"1", "task": "job1", "startdate": "2016-10-11", "enddate": "2016-11-11"},
                {id:"2", "task": "job2", "startdate": "2016-10-11", "enddate": "2016-10-30", parent: "1"},
                {id:"3", "task": "job3", "startdate": "2016-11-12", "enddate": "2016-12-11", parent: "2"}
            ];

sample5.html

이전 예제에서는 계층 구조(depth)가 1 단계였는데

Job3을 Job2의 자식으로 변경하여 실행해 보자.

다음 그림과 같이 실행된다.

몇 가지 문제가 발생하는 것을 알 수 있다.

먼저, 계층이 많아지니 expander 기호의 위치가

모두 행의 맨 앞에 있어서 적절하지 않아 보인다.

그리고, 마우스로 클릭해보면

바로 아래의 자식은 숨겨지는데

자식의 자식은 숨겨지지 않는다.


어떻게 수정해야 하는지 생각해 보고

다음 예제에서 이 문제를 해결하는 방법을 정리한다.





+ Recent posts