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>
<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 |