WEB/JavaScript

[JavaScript] TreeView 사용하기 (fancytree)

S0PH1A 2019. 6. 3. 17:44
반응형

[JavaScript] TreeView 사용하기 (fancytree)


사용하고자 하는 Tree 조건은 다음과 같았다.

* Tree(트리) 사용 조건
  1. 방향키로 노드간 이동 가능해야 한다.
  2. shift, ctrl이용해서 다중 선택이 가능해야 한다.
  3. 폴더간 드래그 앤 드롭으로 이동이 가능해야 한다.
  4. 루트 노드는 이동 불가해야 한다.
  5. 자식노드는 자식노드 하위로 이동 불가해야 한다.

위 조건을 모두 만족하는 트리를 찾기 힘들었다.
처음에는 가장 많이 쓰는 라이브러리를 찾아 구현되어 있지 않는 조건들은 stackoverflow 나 git 등에서 찾아 기능을 추가하려고 했으나, 쉽지 않았다.

완성된 프로젝트에 트리 부분만 떼다 붙이려니 여러가지 오류가 발생했었다.

  1. jstree

    • 가장 많이 사용함.
    • 위 조건 모두 구현 가능함.
    • 하지만, Electron에서 코드를 삽입하니 jstree() 를 찾을 수 없다는 오류만 뜸....
  2. jqtree

    • 사용이 간단함.
    • shift, ctrl 기능이 없음.
    • 다중 선택은 되나, 불편함. ( 다중 선택하여 노드 이동이 안됨 )
    • shift, ctrl 를 이용하여 다중 선택까진 구현했으나,
      부모가 다른 자식을 선택할 경우와 다중 선택한 파일을 이동시키는 부분에서 막힘....
  3. fancytree

    • jqtree보단 많이 사용하는 듯 함.
    • 위 모든 조건 다 만족하는 엄청나게 많은 기능을 제공함.
    • 루프 노드 이동을 막는 코드는 구글에 많이 존재했지만, 자식 노드 하위로 이동을 막는 부분을 찾기 힘들었다.
    • 하지만, 모든 조건에 맞게 구현이 가능했다.

 

# fancytree

  1. 설치

    $ npm install jquery.fancytree --save
  2. 사용

  • Electron에서는 CreateTree 옵션을 이용해서 fancytree를 생성할 수 있다.
  • dragEnter에 조건에 원하는 조건을 추가해 줬다.
<!-- HTML -->
<!-- fancytree -->
<link href="../node_modules/jquery.fancytree/dist/skin-win8/ui.fancytree.min.css" rel="stylesheet">

<div id="tree"></div>

 

// JavaScript
const fancytree = require('jquery.fancytree');

// 필요한 모듈을 취사선택해서 추가한다.
require('jquery.fancytree/dist/modules/jquery.fancytree.ui-deps');
require('jquery.fancytree/dist/modules/jquery.fancytree');
require('jquery.fancytree/dist/modules/jquery.fancytree.dnd5');
require('jquery.fancytree/dist/modules/jquery.fancytree.multi');

// 선언
const _tree = fancytree.createTree('#tree', {
        extensions: ["dnd5", "multi"],
        checkbox: true,
        selectMode: 3,
        source: [],
          activate: function (event, data) {},
        lazyLoad: function (event, data) {
            //   data.result = {url: "ajax-sub2.json"}
        },
        dnd5: {
            preventSameParent: false, // Prevent dropping nodes under the same direct parent
            autoExpandMS: 1000,
            refreshPositions: true,
            multiSource: true, // drag all selected nodes (plus current node)
            dragStart: function (node, data) {
                // 루트 노드 이동 방지
                if (node.isFolder() || node.getLevel() === 1) {
                    return false;
                }
                return true;
            },
            dragEnter: function (node, data) {
                if (data.node.parent.parent === null) { // 부모 노드는 over만 가능
                    return ["over"];
                } else {  // 자식 노드 끼리는 over불가능(위치 변경만 가능)
                    return ["before", "after"]
                }
            },
            dragOver: function (node, data) {
                // data.node.info("dragOver", data);
                return true;
            },
            dragEnd: function (node, data) {
                data.node.info("dragEnd", data);
            },
            dragDrop: function (node, data) {
                var sourceNodes = data.otherNodeList;

                $.each(sourceNodes, function (i, o) {
                    o.info("move to " + node + ": " + data.hitMode);
                    o.moveTo(node, data.hitMode);
                });

                node.debug("drop", data);
                node.setExpanded();
            }
        }
});
반응형