IT

[jQuery]트리구조 플러그인 - fancytree

집탱구리 2017. 4. 20. 15:17
반응형

Fancytree 
트리구조



일하다보니 메뉴구성을 트리구조로 보여줘야 할 필요가 있었는데

차장님이 사용해보라고 알려주심.

괜춘한듯.

여기저기 필요한데가 많을것 같아서 포스팅 한다.


아이콘은 js파일에서 수정 할 수 있다.

그리고 사용방법이 그리 어렵지는 않은데

뭔가 트리구조에 대한 이해가 필요할것 같다.


예제 사이트 주소 → http://wwwendt.de/tech/fancytree/demo/

github 주소 → https://github.com/mar10/fancytree/

document 주소 → https://github.com/mar10/fancytree/wiki

api reference 주소 → http://wwwendt.de/tech/fancytree/doc/jsdoc/



내가 사용해본것만 설명 하도록 하겠다.

그래봤자 몇개 안된다. 하핫.


1. default

가장 기본적인 사용방법이다.


트리구조를 만들어 놓고 id를 부여한다.

 <div id="tree">

    <ul id="treeData" style="display: none;">

      <li id="id1" title="Look, a tool tip!">item1 with key and tooltip

      <li id="id2">item2

      <li id="id3" class="folder">Folder <em>with some</em> children

        <ul>

          <li id="id3.1">Sub-item 3.1

            <ul>

              <li id="id3.1.1">Sub-item 3.1.1

              <li id="id3.1.2">Sub-item 3.1.2

              <li id="id3.1.3">Sub-item 3.1.3

            </ul>

          <li id="id3.2">Sub-item 3.2

            <ul>

              <li id="id3.2.1">Sub-item 3.2.1

              <li id="id3.2.2">Sub-item 3.2.2

            </ul>

        </ul>

      <li id="id4" class="expanded">Document with some children (expanded on init)

        <ul>

          <li id="id4.1"  class="active focused">Sub-item 4.1 (active and focus on init)

            <ul>

              <li id="id4.1.1">Sub-item 4.1.1

              <li id="id4.1.2">Sub-item 4.1.2

            </ul>

          <li id="id4.2">Sub-item 4.2

            <ul>

              <li id="id4.2.1">Sub-item 4.2.1

              <li id="id4.2.2">Sub-item 4.2.2

            </ul>

        </ul>

    </ul>

  </div>

  <script type="text/javascript">

    $(function(){

      // using default options

      $("#tree").fancytree();

    });

  </script>



2.Complex
테이블태그를 사용해서 리스트를 만들고
그안에 입력폼을 사용 하여 submit을 할 수도 있다.


 <script src="../src/jquery.fancytree.js"></script>

  <script src="../src/jquery.fancytree.dnd.js"></script>            // drag and drop.

  <script src="../src/jquery.fancytree.edit.js"></script>            // 트리의 name을 수정 할 수 있다.

  <script src="../src/jquery.fancytree.gridnav.js"></script>      // table과 함께 테이블 그리드를 만든다.

  <script src="../src/jquery.fancytree.table.js"></script>         // 테이블 구조를 만든다.

<script type="text/javascript">

var CLIPBOARD = null;

/* //테이블 안에 들어갈 데이터들을 json으로 넣을 수 있다.

// title : 트리의 이름

// folder : boole형식으로 부모노드인지 정한다.

// expanded : boole형식으로 펼친채로 보여줄지 여부를 정한다.

// children: 자식 노드들의 배열이다.

// children의 데이터들은 마찬가지로 title을 사용 할 수 있다.

// 그리고 나머지 데이터 명을 선언해서 값을 넣어주면 테이블에서 불러다 쓸 수 있다.


  SOURCE = [

    {title: "node 1", folder: true, expanded: true, children: [

      {title: "node 1.1", foo: "a"},

      {title: "node 1.2", foo: "b"}

     ]},

    {title: "node 2", folder: true, expanded: false, children: [

      {title: "node 2.1", foo: "c"},

      {title: "node 2.2", foo: "d"}

     ]}

  ];

*/


$(function(){


  $("#tree").fancytree({

    checkbox: true,            // 체크박스 사용여부.

    titlesTabbable: true,     // Add all node titles to TAB chain

    quicksearch: true,        // Jump to nodes when pressing first character

    // 위에서 선언한 json코드를 여기에 넣는다.

   //  source: SOURCE,

     source: { url: "ajax-tree-products.json"}, // api패키지에 첨부된 json파일의 url이다.


    extensions: ["edit", "dnd", "table", "gridnav"], // 필요한 확장 요소들


    dnd: {  //드래그앤드롭

      preventVoidMoves: true,

      preventRecursiveMoves: true,

      autoExpandMS: 400,

      dragStart: function(node, data) {

        return true; // 드래그 가능 : true

      },

      dragEnter: function(node, data) {

        // return ["before", "after"]; // 다른 노드의 앞,뒤에만 가능

        return true; // 자식노드로도 옮겨 넣을 수 있다.

      },

      dragDrop: function(node, data) {

        data.otherNode.moveTo(node, data.hitMode);

      }

    },

    edit: { // title 수정

      triggerStart: ["f2", "dblclick", "shift+click", "mac+enter"], // 수정전환 키 조합

      close: function(event, data) {

        if( data.save && data.isNew ){

          // Quick-enter: add new nodes until we hit [enter] on an empty title

          $("#tree").trigger("nodeCommand", {cmd: "addSibling"});

        }

      }

    },

    table: {

      indentation: 20,

      nodeColumnIdx: 2,

      checkboxColumnIdx: 0

    },

    gridnav: {

      autofocusInput: false,

      handleCursorKeys: true

    },


    lazyLoad: function(event, data) {

      data.result = {url: "../demo/ajax-sub2.json"};

    },

    createNode: function(event, data) {

      var node = data.node,

        $tdList = $(node.tr).find(">td");


      // Span the remaining columns if it's a folder.

      // We can do this in createNode instead of renderColumns, because

      // the `isFolder` status is unlikely to change later

      if( node.isFolder() ) {

        $tdList.eq(2)

          .prop("colspan", 6)

          .nextAll().remove();

      }

    },

    renderColumns: function(event, data) {

      var node = data.node,

        $tdList = $(node.tr).find(">td");


       // 테이블 컬럼의 인덱스에 각각의 값이나 input등을 커스텀하게 넣을 수 있다.

      // (Index #0 is rendered by fancytree by adding the checkbox) : 0번째 인덱스는 체크박스 사용일 때 노출된다.


      // Set column #1 info from node data:

      $tdList.eq(1).text(node.getIndexHier());

      // (Index #2 is rendered by fancytree)

      // Set column #3 info from node data:

      $tdList.eq(3).find("input").val(node.key);

      $tdList.eq(4).find("input").val(node.data.foo);


      // Static markup (more efficiently defined as html row template):

      // $tdList.eq(3).html("<input type='input' value='" + "" + "'>");

      // ...

    }

  }).on("nodeCommand", function(event, data){

    // Custom event handler that is triggered by keydown-handler and

    // context menu:

    var refNode, moveMode,

      tree = $(this).fancytree("getTree"),

      node = tree.getActiveNode();


    switch( data.cmd ) {

    case "moveUp":

      refNode = node.getPrevSibling();

      if( refNode ) {

        node.moveTo(refNode, "before");

        node.setActive();

      }

      break;

    case "moveDown":

      refNode = node.getNextSibling();

      if( refNode ) {

        node.moveTo(refNode, "after");

        node.setActive();

      }

      break;

    case "indent":

      refNode = node.getPrevSibling();

      if( refNode ) {

        node.moveTo(refNode, "child");

        refNode.setExpanded();

        node.setActive();

      }

      break;

    case "outdent":

      if( !node.isTopLevel() ) {

        node.moveTo(node.getParent(), "after");

        node.setActive();

      }

      break;

    case "rename":

      node.editStart();

      break;

    case "remove":

      refNode = node.getNextSibling() || node.getPrevSibling() || node.getParent();

      node.remove();

      if( refNode ) {

        refNode.setActive();

      }

      break;

    case "addChild":

      node.editCreateNode("child", "");

      break;

    case "addSibling":

      node.editCreateNode("after", "");

      break;

    case "cut":

      CLIPBOARD = {mode: data.cmd, data: node};

      break;

    case "copy":

      CLIPBOARD = {

        mode: data.cmd,

        data: node.toDict(function(n){

          delete n.key;

        })

      };

      break;

    case "clear":

      CLIPBOARD = null;

      break;

    case "paste":

      if( CLIPBOARD.mode === "cut" ) {

        // refNode = node.getPrevSibling();

        CLIPBOARD.data.moveTo(node, "child");

        CLIPBOARD.data.setActive();

      } else if( CLIPBOARD.mode === "copy" ) {

        node.addChildren(CLIPBOARD.data).setActive();

      }

      break;

    default:

      alert("Unhandled command: " + data.cmd);

      return;

    }


  // }).on("click dblclick", function(e){

  //   console.log( e, $.ui.fancytree.eventToString(e) );


  }).on("keydown", function(e){

    var cmd = null;


    // console.log(e.type, $.ui.fancytree.eventToString(e));

    switch( $.ui.fancytree.eventToString(e) ) {

    case "ctrl+shift+n":

    case "meta+shift+n": // mac: cmd+shift+n

      cmd = "addChild";

      break;

    case "ctrl+c":

    case "meta+c": // mac

      cmd = "copy";

      break;

    case "ctrl+v":

    case "meta+v": // mac

      cmd = "paste";

      break;

    case "ctrl+x":

    case "meta+x": // mac

      cmd = "cut";

      break;

    case "ctrl+n":

    case "meta+n": // mac

      cmd = "addSibling";

      break;

    case "del":

    case "meta+backspace": // mac

      cmd = "remove";

      break;

    // case "f2":  // already triggered by ext-edit pluging

    //   cmd = "rename";

    //   break;

    case "ctrl+up":

      cmd = "moveUp";

      break;

    case "ctrl+down":

      cmd = "moveDown";

      break;

    case "ctrl+right":

    case "ctrl+shift+right": // mac

      cmd = "indent";

      break;

    case "ctrl+left":

    case "ctrl+shift+left": // mac

      cmd = "outdent";

    }

    if( cmd ){

      $(this).trigger("nodeCommand", {cmd: cmd});

      // e.preventDefault();

      // e.stopPropagation();

      return false;

    }

  });


  /*

   * Tooltips

   */

  // $("#tree").tooltip({

  //   content: function () {

  //     return $(this).attr("title");

  //   }

  // });


  /*

   * Context menu (https://github.com/mar10/jquery-ui-contextmenu)

   */

  $("#tree").contextmenu({

    delegate: "span.fancytree-node",

    menu: [

      {title: "Edit <kbd>[F2]</kbd>", cmd: "rename", uiIcon: "ui-icon-pencil" },

      {title: "Delete <kbd>[Del]</kbd>", cmd: "remove", uiIcon: "ui-icon-trash" },

      {title: "----"},

      {title: "New sibling <kbd>[Ctrl+N]</kbd>", cmd: "addSibling", uiIcon: "ui-icon-plus" },

      {title: "New child <kbd>[Ctrl+Shift+N]</kbd>", cmd: "addChild", uiIcon: "ui-icon-arrowreturn-1-e" },

      {title: "----"},

      {title: "Cut <kbd>Ctrl+X</kbd>", cmd: "cut", uiIcon: "ui-icon-scissors"},

      {title: "Copy <kbd>Ctrl-C</kbd>", cmd: "copy", uiIcon: "ui-icon-copy"},

      {title: "Paste as child<kbd>Ctrl+V</kbd>", cmd: "paste", uiIcon: "ui-icon-clipboard", disabled: true }

      ],

    beforeOpen: function(event, ui) {

      var node = $.ui.fancytree.getNode(ui.target);

      $("#tree").contextmenu("enableEntry", "paste", !!CLIPBOARD);

      node.setActive();

    },

    select: function(event, ui) {

      var that = this;

      // delay the event, so the menu can close and the click event does

      // not interfere with the edit control

      setTimeout(function(){

        $(that).trigger("nodeCommand", {cmd: ui.cmd});

      }, 100);

    }

  });

});

</script>

<table id="tree">

    <colgroup>

    <col width="30px">

    <col width="50px">

    <col width="350px">

    <col width="50px">

    <col width="50px">

    <col width="30px">

    <col width="30px">

    <col width="50px">

    </colgroup>

    <thead>

      <tr> <th></th> <th>#</th> <th></th> <th>Ed1</th> <th>Ed2</th> <th>Rb1</th> <th>Rb2</th> <th>Cb</th></tr>

    </thead>

    <tbody>

      <!-- Define a row template for all invariant markup: -->

      <tr>

        <td class="alignCenter"></td>

        <td></td>

        <td></td>

        <td><input name="input1" type="input"></td>

        <td><input name="input2" type="input"></td>

        <td class="alignCenter"><input name="cb1" type="checkbox"></td>

        <td class="alignCenter"><input name="cb2" type="checkbox"></td>

        <td>

          <select name="sel1" id="">

            <option value="a">A</option>

            <option value="b">B</option>

          </select>

        </td>

      </tr>

    </tbody>

  </table>


 

반응형

'IT' 카테고리의 다른 글

[MySQL] 문자열 자르기, 합치기, 치환하기  (0) 2018.02.09
[jQuery]select박스  (2) 2017.04.26
[PHP]PhpMyAdmin 설치  (0) 2017.04.12
[리눅스]가상서버 만들기 2탄  (0) 2017.04.09
[Ubuntu]가상서버 만들기 1탄  (0) 2017.04.04