Created
January 31, 2014 08:32
-
-
Save jasonmit/8728438 to your computer and use it in GitHub Desktop.
Simple Ember Tree View
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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">▪</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