Created

Embed URL

HTTPS clone URL

SSH clone URL

You can clone with HTTPS or SSH.

Download Gist

Knockout TreeView- A nice binding handler that accepts a dynamic tree of data, and displays a searchable and selectable tree-type list.

View treeview.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
* {
-webkit-touch-callout: none;
-webkit-user-select: none;
-khtml-user-select: none;
-moz-user-select: -moz-none;
-ms-user-select: none;
user-select: none;
font-family: "Segoe UI", "Helvetica", Arial, sans-serif;
}
.navbar{
margin-bottom:10px;
}
.ko-treeview-container {
max-height: 300px;
overflow-y: auto;
overflow-x: hidden;
border: 1px solid #eee;
background-color: white;
border-radius: 3px;
padding-right: 7px;
padding-top: 5px;
}
.ko-treeview-container .navbar {
margin-right: 0px;
}
.ko-treeview-container > .ko-treeview-list {
padding: 0;
margin-left:0px;
}
.ko-treeview-list {
list-style: none;
}
.ko-treeview-listitem {
line-height: 2em;
margin-top: 0px;
}
.ko-treeview-label {
-webkit-transition: all 250ms;
-moz-transition: all 250ms;
-ms-transition: all 250ms;
-o-transition: all 250ms;
cursor: pointer;
display: block;
margin-left: 5px;
width: 100%;
background-color: white;
color: #2980b9;
border-bottom: 1px solid #bdc3c7;
}
.ko-treeview-label:hover {
border-bottom-color: #2980b9;
}
.ko-treeview-cb {
-webkit-transition: all 250ms;
-moz-transition: all 250ms;
-ms-transition: all 250ms;
-o-transition: all 250ms;
float: right;
clear: both;
margin-top: 1em;
margin-left: 5px;
}
.ko-treeview-cb:checked {
margin-top: 1.5em;
}
.ko-treeview-cb:checked + label {
line-height: 50px;
font-weight: bold;
border-bottom-color: #27ae60;
font-size: 1.1em;
color: #27ae60;
}
View treeview.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
<!DOCTYPE html>
<html>
<head>
<link href="http://getbootstrap.com/2.3.2/assets/css/bootstrap.css" rel="stylesheet" type="text/css" />
<link href="http://getbootstrap.com/2.3.2/assets/css/bootstrap-responsive.css" rel="stylesheet" type="text/css" />
<link href="treeview.css" rel="stylesheet" type="text/css" />
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout/2.2.1/knockout-min.js"></script>
<script src="treeview.js"></script>
<meta charset=utf-8 />
<title>Knockout TreeView</title>
</head>
<body>
<div data-bind="treeView:{title:'Some Title',selected:selectedNodes, data:data}">
</div>
<h4>Selected Nodes</h4>
<ul data-bind="foreach: selectedNodes">
<li data-bind="text: $data"></li>
</ul>
</body>
</html>
View treeview.css
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
ko.bindingHandlers.treeView = {
createNodes: function(rootElement, options){
var rootTmpl = '<script id="ko-treeview-root-tmpl"><div class="navbar"><p class="brand" data-bind="text:$data.title">Title</p><div class="container"><form class="navbar-form pull-right col-sm-4"><div class="input-append"><input class="span4" type="text" placeholder="Search" data-bind="value:$data.search, valueUpdate: \'afterkeydown\'"/><span class="add-on"><i class="icon-search"></i></span></div></form></div></div><ul class="ko-treeview-list" data-bind="template:{foreach:$data.data,name:\'ko-treeview-node-tmpl\'}"></ul></script>';
var nodeTmpl = '<script id="ko-treeview-node-tmpl"><li class="ko-treeview-listitem"><div data-bind="template:{name:\'ko-treeview-item-tmpl\',data:$data}"></div><ul class="ko-treeview-list" data-bind="template:{name:\'ko-treeview-node-tmpl\',foreach:$data[$root.childNode]}"></div></li></script>';
var itemTmpl ='<script id="ko-treeview-item-tmpl"><div data-bind="visible:$data[$root.label].indexOf($root.search()) > -1"><input type="checkbox" class="ko-treeview-cb" data-bind="checked: $root.selected, attr:{value:$data[$root.label], id:$data[$root.label]}" /><label class="ko-treeview-label" data-bind="text:$data[$root.label], attr:{for:$data[$root.label]}"></label></div></script>'
//append templates
document.body.insertAdjacentHTML('beforeend', rootTmpl);
document.body.insertAdjacentHTML('beforeend', nodeTmpl);
document.body.insertAdjacentHTML('beforeend', itemTmpl);
//apply first binding
ko.applyBindingsToNode(rootElement, {template:{name:"ko-treeview-root-tmpl"}},options);
},
init: function(element, valueAccessor) {
//style element
element.className = "ko-treeview-container";
//extend options with search
var options = valueAccessor();
options.search = ko.observable("");
//set default data values
if(!options.label) options.label = 'id';
if(!options.childNode) options.childNode = 'children';
//create the tree
ko.bindingHandlers.treeView.createNodes(element,options);
valueAccessor().data.subscribe(function(){
ko.bindingHandlers.treeView.createNodes(element,options);
});
//let this handler control its descendants.
return { controlsDescendantBindings: true };
}
};
 
function vm(){
this.selectedNodes = ko.observableArray([]);
this.data = ko.observableArray([
{
id:"Level 1",
children:[
{id:"Level 1-1",children:[
{id:"Level 1-1-1",children:[
{id:"Level 1-1-1-1"}
]}
]},
{id:"Level 1-2"},
]
},
{
id:"Level 2",
children:[
{id:"Level 2-1",children:[
{id:"Level 2-1-1"}
]},
{id:"Level 2-2"},
]
},
]);
 
}
var myVM = new vm();
ko.applyBindings(myVM);
Owner

@bringking Very nice! Is it possible to give the data a more friendly title attribute along with the id?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.