Ember Tree View
by fangyang
HTML
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<script src="https://raw.github.com/wycats/handlebars.js/1.0.0-rc.3/dist/handlebars.js"></script>
<script type="text/javascript">
window.ENV = window.ENV || {};
ENV.EXPERIMENTAL_CONTROL_HELPER = true;
</script>
<script src="//cdnjs.cloudflare.com/ajax/libs/ember.js/1.0.0-rc.1/ember.js"></script>
<script data-template-name="application" type="text/x-handlebars">
<h1>Ember.js Tree Example</h1>
{{control "treeBranch" App.treeRoot}}
<p><a href="http://billysbilling.com/blog/How-to-implement-a-tree-in-Ember-js">Read the blog post</a></p>
</script>
<script data-template-name="tree" type="text/x-handlebars">
{{control "treeBranch" content}}
</script>
<script data-template-name="tree-branch" type="text/x-handlebars">
{{each children itemController="treeNode" itemViewClass="App.TreeNodeView"}}
</script>
<script data-template-name="tree-node" type="text/x-handlebars">
<span {{bindAttr class=":toggle-icon children.length::leaf"}} {{action toggle}}>
{{#if isExpanded}}
▼
{{else}}
▶
{{/if}}
</span>
<a {{action click}} class="text">{{text}}</a>
{{#if isExpanded}}
{{control "treeBranch" content}}
{{/if}}
</script>
CSS
body {
color: #444;
font-family: Helvetica, Arial, sans-serif;
font-size: 14px;
padding: 30px;
margin: 0px;
}
h1 {
font-size: 24px;
line-height: 1.2em;
margin: 0px 0px 10px 0px;
}
/* Branch */
.tree-branch {
padding: 0px;
margin: 0px;
}
.tree-node .tree-branch {
padding-left: 10px; /* Nested tree branches should be indented */
}
/* Node */
.tree-node {
list-style: none;
line-height: 20px;
}
/* Arrow */
.tree-node .toggle-icon {
cursor: pointer;
display: inline-block;
width: 10px;
margin-right: 0px;
font-size: 10px;
}
.tree-node .toggle-icon:hover {
opacity: 0.8;
}
.tree-node .toggle-icon.leaf {
visibility: hidden;
}
/* Node text */
.tree-node .text {
cursor: pointer;
text-decoration: underline;
}
.tree-node .text:hover {
text-decoration: none;
}
JavaScript
App = Ember.Application.create();
App.TreeBranchController = Ember.ObjectController.extend({
});
App.register('controller:treeBranch', App.TreeBranchController, {singleton: false});
App.TreeBranchView = Ember.View.extend({
tagName: 'ul',
templateName: 'tree-branch',
classNames: ['tree-branch']
});
App.TreeNodeController = Ember.ObjectController.extend({
isExpanded: false,
toggle: function() {
this.set('isExpanded', !this.get('isExpanded'));
},
click: function() {
console.log('Clicked: '+this.get('text'));
}
});
App.register('controller:treeNode', App.TreeNodeController, {singleton: false});
App.TreeNodeView = Ember.View.extend({
tagName: 'li',
templateName: 'tree-node',
classNames: ['tree-node']
});
App.set('treeRoot', {
text: 'Root',
children: [
{
text: 'People',
children: [
{
text: 'Basketball players',
children: [
{
text: 'Lebron James',
children: []
},
{
text: 'Kobe Bryant',
children: []
}
]
},
{
text: 'Astronauts',
children: [
{
text: 'Neil Armstrong',
children: []
},
{
text: 'Yuri Gagarin',
children: []
}
]
}
]
},
{
text: 'Fruits',
children: [
{
text: 'Banana',
children: []
},
{
text: 'Pineapple',
...