Ember.js encapsulated controller pattern
Contains no hardcoded "App..." references in the template or view. All dependencies passed into controller thru viewOptions hash.
by lchau
HTML
<script src="https://github.com/downloads/wycats/handlebars.js/handlebars-1.0.rc.1.js"></script>
<script src="https://github.com/downloads/emberjs/ember.js/ember-1.0.pre.min.js"></script>
<div id="example"></div>
<script type="text/x-handlebars" data-template-name="exampleModule">
<header>Example Header</header>
<table>
{{#each content}}
<tr>
<td>{{location}}</td>
<td>{{activity}}</td>
</tr>
{{/each}}
</table>
<footer class="collapsible">footer here</footer>
</script>
CSS
<style>
#example {
font-size: 14px;
}
#example header {
padding: 0.25em;
color: #FFF;
background-color: #008;
font-weight: bold;
}
#example table {
width: 100%;
border: 1px solid #EEE;
border-collapse: collapse;
}
#example tr, #example td {
border: 1px solid #EEE;
}
#example tr.hover {
background-color: #EFF;
}
#example footer {
padding: 0.25em;
background-color: #EEE;
font-size: 0.85em;
text-align: right;
}
</style>
JavaScript
var Example = Ember.Namespace.create({
Views: {} // could have multiple views sharing the same model, but just one for now...
});
Example.Item = Ember.Object.extend({
location: null,
activity: null
});
Example.Controller = Ember.Controller.extend({
init: function() { // called when controller is created
this.model = Ember.ArrayProxy.create({
content: [
Example.Item.create({ location: 'Sonora Pass', activity: 'Camping' }),
Example.Item.create({ location: 'Mt. Tamalpais', activity: 'Hiking' }),
Example.Item.create({ location: 'San Francisco Bay', activity: 'Kayaking' })
]
});
this.view = Example.Views.Module.create(this.viewOptions);
},
ready: function() { // called after controller is created so binding will work
this.view.appendTo(this.view.container);
return this; // make it chainable
}
});
Example.Views.Module = Ember.View.extend({
templateName: 'exampleModule',
didInsertElement : function() { // called when template has been added to the DOM
// bind "content" property to "App.controller.model"
// so that {{#each content}} in the template will refer to "App.controller.model.content"
Ember.bind(this, 'content', this.contentPath);
// this.$() refers to the jQuery wrapped DOM element containing this view
// .on() is required because the 'tr' elements will not exist until Ember.bind() is done
this.$().on('mouseover', 'tr', function() {
$(this).addClass('hover');
}).on('mouseout', 'tr', function() {
$(this).removeClass('hover');
});
}
});
window.App = Ember.Application.create({
ready: function() {
this._super(); // Ember housekeeping
App.controller = Example.Controller.create({
viewOptions: {
container: '#example',
contentPath: 'App.controller.model'
...