Skip to content

Instantly share code, notes, and snippets.

@jasonmit
Created January 31, 2014 08:32
Show Gist options
  • Save jasonmit/8728438 to your computer and use it in GitHub Desktop.
Save jasonmit/8728438 to your computer and use it in GitHub Desktop.
Simple Ember Tree View
<script type="text/x-handlebars" data-template-name="application">
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="tree-item">
{{#if view.hasChildren}}
<a {{action 'expand' target=view}}>
{{#if view.parentView.shrinkDepth}}
{{{view.parentView.depthLabel}}}
{{/if}}
{{unbound view.content.label}}
</a>
{{view App.TreeView
fullContent=view.parentView.fullContent
content=view.content.children}}
{{else}}
<span>{{unbound view.content.label}}</span>
{{/if}}
</script>
<script type="text/x-handlebars" data-template-name="index">
{{view App.TreeView
classNames='tree main-tree'
fullContent=controller.content
content=controller.content
isExpanded=true}}
</script>
App = Ember.Application.create({});
App.IndexRoute = Ember.Route.extend({
model: function(){
return [
{ label: 'Advertisers', children: [
{ label: 'Yahoo' },
{ label: 'Netflix' },
{ label: 'Apple' },
{ label: 'ESPN', children: [
{ label: 'ESPN NFL' },
{ label: 'ESPN NHL' },
{ label: 'ESPN MLB' },
{ label: 'ESPN NBA', children: [
{ label: 'Knicks' },
{ label: 'Pistons' },
{ label: 'Heat', children: [ { label: 'Lebron James' } ] }
]}
]},
]},
{ label: 'Yahoo' },
{ label: 'Alpha Natural Resources' }
];
}
});
App.IndexController = Ember.ArrayController.extend({
init: function() {
this._super.apply(this, arguments);
var ctrl = this;
setTimeout(function() {
var anr = ctrl.get('content.lastObject');
Ember.set(anr, 'children', [{ label: 'ANR West'}, { label: 'ANR East' }]);
}, 2000);
}
});
App.TreeItemView = Ember.View.extend({
classNameBindings: ['hasChildren', 'parentView.shrinkDepth'],
templateName: 'tree-item',
hasChildren: function() {
return !Ember.isEmpty(this.get('content.children'));
}.property('content.children'),
actions: {
expand: function() {
var tree = this.get('childViews.firstObject');
if(tree) {
tree.toggleProperty('isExpanded');
}
}
}
});
App.TreeView = Ember.CollectionView.extend({
tagName: 'ul',
classNames: ['tree'],
classNameBindings: ['shrinkDepth'],
isVisibleBinding: 'isExpanded',
itemViewClass: App.TreeItemView,
isExpanded: false,
level: 0,
depthLabel: function() {
return Array(this.get('level') || 0).join('<span class="d">&#9642;</span>');
}.property('level'),
shrinkDepth: function() {
return this.get('level') > 1;
}.property('level'),
determineDepth: function() {
var $view = this;
var content = this.get('content'),
fullContent = this.get('fullContent'),
getPosition = function(arr, target, top) {
return arr.forEach(function(obj, i) {
if(!top) { count = 0; }
if('children' in obj) {
count++;
if(obj.children === target) {
$view.set('level', count);
return;
}
return getPosition(obj.children, target, true);
}
});
};
getPosition(fullContent, content);
}.on('didInsertElement')
});
body {
font-family: HelveticaNeue;
font-size: 12px;
color: #333;
margin: 10px;
}
.shrink-depth .tree { padding-left: 0px; }
.tree { padding-left: 7px; }
.tree .has-children > a {
cursor: pointer;
font-weight: 600;
}
.tree li > a, .tree li > span { display: block; padding: 4px; }
.tree .d { color: #f26c21; }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment