Tree Combo Recipe
An example of how to build a simple tree widget using can.Control. Includes jQuery, CanJS and all of its plugins. Use it as a starting point when you want to demo something.
by donejs
HTML
<script src="http://canjs.com/release/2.0.1/can.jquery.js"></script>
<script src="http://canjs.com/release/2.0.1/can.ejs.js"></script>
<div id="treeCombo"></div>
<div id="selected"></div>
<script id="treeEJS" type="text/ejs">
<ul class='breadcrumb'>
<li><%= title %></li>
<% breadcrumb.each(function(item){ %>
<li <%=(el)-> el.data('item',item) %>>
<%= item.attr('title') %>
</li>
<%})%>
</ul>
<ul class='options'>
<% selectableItems().each(function(item){ %>
<li class='<%= selected.indexOf(item) >= 0 ? "checked":""%>'
<%=(el)-> el.data('item',item) %> >
<input type="checkbox"
<%= selected.indexOf(item) >= 0 ? "checked":""%>>
<%= item.attr('title') %>
<%if(item.children && item.children.length){ %>
<button class="showChildren">→</button>
<%}%>
</li>
<% }) %>
</ul>
</script>
<script id='selectedEJS' type='text/ejs'>
<b>You've Selected:</b>
<ul>
<% if(this.attr('length')){%>
<% this.each(function(item){ %>
<li><%=item.attr('title')%></li>
<% }) %>
<% } else { %>
<li>Nothing</li>
<% } %>
</ul>
</script>
CSS
@import url(http://fonts.googleapis.com/css?family=Lato:100,400,700);
* {
font-family: 'Lato', sans-serif;
font-size: 16px;
text-shadow: 0 1px 0 #ffffff;
}
.breadcrumb li {
display: inline-block;
padding: 5px 0px;
font-size: 12px;
color: #ccc;
}
.breadcrumb li:before {
content: ">";
}
.breadcrumb li:hover {
cursor: pointer;
}
.breadcrumb li:last-child {
color: #000;
}
.breadcrumb li:first-child:before {
content: ""
}
.breadcrumb li:last-child:hover {
cursor: default;
}
.options li {
padding: 3px 5px;
cursor: pointer;
}
.options li:hover {
background-color: #feffef;
}
.options li.checked {
background-color: #eee;
}
#selected {
margin-top: 20px;
background-color: #eee;
padding: 5px;
}
#selected li{
padding-left: 10px;
}
.showChildren {
background-color: #999;
color: #fff;
-webkit-border-radius: 20px;
-moz-border-radius: 20px;
border-radius: 20px;
padding: 2px 5px;
margin: 5px;
text-shadow: none;
border: none;
font-size: 12px;
cursor: pointer;
}
.showChildren:hover {
background-color: #666;
}
}
JavaScript
// the json data we will be using
var data = [
{ id: 1, title: "Midwest", children: [
{ id: 5, title: "Illinois", children: [
{ id: 23423, title: "Chicago"}, { id: 4563, title: "Springfield"},
{ id: 4564, title: "Naperville"}
]
},
{ id: 6, title: "Wisconsin", children: [
{ id: 232423, title: "Milwaulkee"}, { id: 45463, title: "Green Bay"},
{ id: 45464, title: "Madison"}
]
}]
},
{ id: 2, title: "East Coast", children: [
{ id: 25, title: "New York", children: [
{ id: 3413, title: "New York"}, { id: 4613, title: "Rochester"},
{ id: 4516, title: "Syracuse"}
]
},
{ id: 6, title: "Pennsylvania", children: [
{ id: 2362423, title: "Philadelphia"}, { id: 454663, title: "Harrisburg"},
{ id: 454664, title: "Scranton"}
]
}]
},
{ id: 3, title: "West Coast", children: [
{ id: 75, title: "California", children: [
{ id: 347813, title: "Los Angeles"}, { id: 463213, title: "Sunnyvale"},
{ id: 457516, title: "San Diego"}
]
},
{ id: 66, title: "Oregon", children: [
{ id: 23621, title: "Bend"}, { id: 1111, title: "Salem"},
{ id: 45461, title: "Eugene"}
]
}]
},
{ id: 4, title: "South", children: [
{ id: 65, title: "Texas", children: [
{ id: 343413, title: "Austin"}, { id: 463413, title: "Dalas"},
{ id: 498516, title: "El Paso"}
]
},
{ id: 6, title: "Florida", children: [
{ id: 2360, title: "Orlando"}, { id: 4540, title: "Tampa"},
{ id: 4064, title: "Miami"}
]
}]
}];
// The TreeCombo control
var TreeCombo = can.Control.extend({
init : function(){
// contains items in the breadcrumb
this.options.breadcrumb = new can.Observe.List([]);
// items we should be displaying
var selectableItems = can.compute(function(){
// if there's an item in the breadcrumb
if(this.options.breadcrumb.attr('length')){
//...