JSFiddle - React, Tailwind, and code Playground
by manchagnu
HTML
<script src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script>
<script src="https://raw.github.com/SteveSanderson/knockout.mapping/master/build/output/knockout.mapping-latest.debug.js"></script>
<div class="treeContainer">
<div data-bind="text: name"></div><button class='loadData'>Load data</button>
<!-- ko template: {name: 'items', data: $data} -->
<!-- /ko -->
</div>
<script id='items' type="text/x-template">
<ul data-bind="foreach: items">
<li class="collapsed">
<button class="expander"></button><span data-bind="text: name"></span>
<!-- ko if: hasDetails -->
<ul class="details">
<li data-bind="text: properties.description"></li>
<li data-bind="text: properties.date"></li>
</ul>
<!-- /ko -->
</li>
</ul>
</script>
CSS
ul {
list-style-type: none;
}
li.collapsed > ul {
display: none;
}
ul .details {
border: 1px solid grey;
padding-left: 20px;
}
button.expander {
}
li.collapsed button:after {
content: "+"
}
li button:after {
content: "--"
}
JavaScript
var viewModel = (function(){
var model = {
name: "My Tree",
items: []
};
var mapping = {
items: {
create: function (options) {
options.data.properties = {
description: ko.observable(""),
date: ko.observable("")
};
options.data.hasDetails = false;
/*
options.data.hasDetails = ko.computed(function(){
return options.data.properties.description().length || options.data.properties.date().length;
});
*/
return ko.mapping.fromJS(options.data);
}
}
};
var _viewModel = ko.mapping.fromJS(model, mapping);
return _viewModel;
})();
ko.applyBindings(viewModel, $('.treeContainer')[0]);
var _server = (function(){
var _itemsDetails = {
1: {
description: "This is my first test",
date: new Date()
},
2: {
description: "This is my second descrition",
date: new Date()
}
};
function findItemById( id ) {
var item = _itemsDetails[id];
if (!item){
throw "Item not found";
}
return item;
};
function loadItems () {
var deferred = $.Deferred();
setTimeout(function() {
var model = {
items:[{
id: 1,
name: "item 1"
}, {
id: 2,
name: "item 2"
}]
};
deferred.resolve(model);
}, 2000 );
return deferred.promise();
};
function loadItemDetails(data){
var deferred = $.Deferred();
setTimeout(function() {
var item;
try {
...