다음과 같이 데이터를 구성하고 실행하면

var data = [
                {id:"1", "task": "job1", "startdate": "2016-10-11", "enddate": "2016-12-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"},
                {id:"4", "task": "job4", "startdate": "2016-12-12", "enddate": "2016-12-31"}
            ];

sample6.html

다음과 같이 2 가지 문제가 있는 것을 찾았다.

1. expander 기호의 위치가 행의 맨 앞에 있어서 적절하지 않아 보인다.

2. job1의 expander 기호를 클릭하면 job2만 숨겨진다.

  즉, 손자(job3)은 숨겨지지 않는다.


이 버그도 쉽게 해결할 수 있으니

먼저 해보고 다음 설명을 읽는 것이 좋을 것 이다.


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

sample6_treegrid9.js


먼저 expander 기호의 위치 문제는

노드의 맨 앞에 있는 기호를

뒤로 보내서 task 필드의 값 바로 앞에 두면 된다.

들여쓰기와 expander 기호 표시를 위해

task 필드 앞에 span을 생성하였는데,

기존에는 expander 기호를 맨 앞 span에 넣었다.

이것을 맨뒤 span에 넣으면 된다.


따라서 다음과 같이 코드를 수정한다.

기존    var expander = $(parent[0].cells[0].firstChild).addClass("treegrid9-expander");

변경    var expander = $(parent[0].cells[0]).find("span").last().addClass("treegrid9-expander");

기존에는 첫 번째 TD(task 필드)의

첫번째 자식(span)에 기호를 넣었고,

수정된 코드는 첫 번째 TD(task 필드)의자식 중

span을 찾아서 마지막(last) 자식에 기호를 넣게 작성하였다.

그러면 다음 그림과 같이 task 필드의 값 바로 앞에

expander 기호가 위치하게 된다.


두번째 문제는

job1의 expander 기호를 클릭하면 job2만 숨겨지고

손자(job3)은 숨겨지지 않는 것이다.


이것은 자식 찾기를 한번만 했기 때문에 발생한다.

앞서 코드 구성에서

바로 위 부모만(직계 존손) 자신의

자신의 노드 클래스명에 표시하도록 했고(treegrid9-parent-)

부모는 자신을 부모로 표기한 이 값만을 찾도록 하고 있다. table.find("tr.treegrid9-parent-" + id).each(function(i, e)

즉, 모든 자식을 찾아야 하는데

모든 자식을 찾으려면

나(클릭한 노드)를 중심으로

나를 부모로 하는 자식 노드를 찾아서 숨기거나 보이도록 처리한다.

그리고, 각 자식 노드를

부모로 하는 노드가 있는 지 확인해서 if (table.find("tr.treegrid9-parent-" + id).length>0)

있으면 다시 자식 노드를 찾아서 숨기거나 보이도록 처리한다.

그리고, 다시 각 자식 노드를

부모로 하는 노드가 있는 지 확인해서 if (table.find("tr.treegrid9-parent-" + id).length>0)

이렇게 무한 반복으로

자식 노드를 찾아서 처리해야 한다.

복잡해 보이지만

이것은 재귀 함수를 사용하면 간단하게 처리된다.

기존 코드를 getChildren 함수에 넣고

이 함수를 자식이 있으면 호출하도록 작성하였다.


또, getChildren를 함수내 내장 함수로 작성했다.

개인적으로 JS의 재미있는 기능이라고 생각하며

자세한 내용은 찾아보길 바란다.


지금까지 간단한 TreeGrid를 제작하는 예제를 통해서

자바스크립트, JQuery, JSon 등의 사용법을 익혀보았다.

노드 선택, Ajax 처리 등의 기능을 추가하면

제법 그럴듯한 TreeGrid를 만들 수 있을 것이다.

누군가 제대로 된 오픈 소스 라이브러리를 개발하길 기대하며……


+ Recent posts