Tree Combo

Includes jQuery, CanJS and all of its plugins. Use it as a starting point when you want to demo something.

by cherif_b

HTML

<script src="http://canjs.us/release/latest/can.jquery.js"></script>
<script src="http://canjs.us/release/latest/can.construct.proxy.js"></script>
<script src="http://canjs.us/release/latest/can.control.plugin.js"></script>
<script src="http://canjs.us/release/latest/can.observe.attributes.js"></script>
<script src="http://canjs.us/release/latest/can.observe.backup.js"></script>
<script src="http://canjs.us/release/latest/can.observe.delegate.js"></script>
<script src="http://canjs.us/release/latest/can.observe.setter.js"></script>
<script src="http://canjs.us/release/latest/can.observe.validations.js"></script>
<script src="http://canjs.us/release/latest/can.view.modifiers.js"></script>
<script src="http://canjs.us/release/latest/can.fixture.js"></script>
<script src="http://canjs.us/release/latest/can.view.mustache.js"></script>
<script src="http://canjs.us/release/latest/can.construct.super.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'>
  You've selected:
  
  <ul>
    <% if(this.attr('length')){%>
      <% this.each(function(item){ %>
        <li><%=item.attr('title')%></li>
      <% }) %>
    <% } else { %>
      <li>Nothing</li>
    <% } %>
  </ul>
</script>

CSS

.breadcrumb li {
  display: inline-block;
  padding: 5px 0px;
}
.breadcrumb li:before {
  content: ">";
  font-weight: normal; 
}
.breadcrumb li:hover {
  font-weight: bold;  
  cursor: pointer;
}
.breadcrumb li:last-child {
  font-weight: bold;  
}
.breadcrumb li:first-child:before {
   content: ""
}
.breadcrumb li:last-child:hover {
  text-decoration: none;
  cursor: default;
}
.options li {
  padding: 3px 5px;
}
.options li.checked {
  background-color: yellow;
}
#selected {
  margin-top: 20px;
  border-top: solid 1px silver;
}
#selected li{
  padding-left: 10px; 
}

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({
  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...