<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>
// 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')){ // return the last item's children return this.options.breadcrumb .attr(""+(this.options.breadcrumb.length-1)) .attr('children'); } else{ // return the top list of items return this.options.items; } }, this); // render the template this.element.html( can.view('treeEJS',{ breadcrumb: this.options.breadcrumb, selectableItems: selectableItems, title: this.options.title, selected: this.options.selected })); }, ".showChildren click": function(el, ev){ // add the item to the breadcrumb this.options.breadcrumb.push(el.closest('li').data('item')); // prevents selection ev.stopPropagation(); }, ".breadcrumb li click": function(el){ var item = el.data('item'); // if you clicked on a breadcrumb li with data if(item){ // remove all breadcrumb items after it var index = this.options.breadcrumb.indexOf(item); this.options.breadcrumb.splice(index+1, this.options.breadcrumb.length - index-1) } else { // clear the breadcrumb this.options.breadcrumb.replace([]) } }, ".options li click": function(el){ // toggles an item's existance in the selected array var item = el.data('item'), index = this.options.selected.indexOf(item); if(index === -1 ){ this.options.selected.push(item); } else { this.options.selected.splice(index, 1) } } }); var selected = new can.Observe.List(); new TreeCombo("#treeCombo", { items: new can.Observe.List(data), title: "Locations", selected: selected }); $("#selected").html(can.view('selectedEJS', selected));
@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; } }