Skip to content

Instantly share code, notes, and snippets.

@charlesjolley
Created February 18, 2011 07:18
Show Gist options
  • Save charlesjolley/833371 to your computer and use it in GitHub Desktop.
Save charlesjolley/833371 to your computer and use it in GitHub Desktop.
<h1>Todos</h1>
{{#view "createTextField"}}
<input id="new-todo" type="text" placeholder="What needs to be done?">
{{/view}}
{{#view "list"}}
<div id="stats">
<span class='todo-count'>
<span class='number'>{{remainingTodosCount}}</span>
<span class='word'>{{remainingWord}} left.</span>
</span>
{{#view 'clearRemainingView'}}
<a href="#">
Clear {{completedTodosCount}} completed {{remainingWord}}
</a>
{{/view}}
</div>
var Todos = SC.Application.create();
// ..........................................................
// MODEL
//
Todos.Todo = SC.Object.extend({
title: function(key, value) {
if (value !== undefined) this._title = value;
return this._title || 'Unnamed todo...';
}.property().cacheable(),
isDone: false
});
Todos.allTodos = [];
// ..........................................................
// CONTROLLERS
//
Todos.listController = SC.ArrayController.create({
contentBinding: 'Todos.allTodos',
// ..........................................................
// PROPERTIES
//
remainingTodosCount: function() {
this.filterProperty('isDone', false).get('length');
}.property('[].isDone').cacheable(),
completedTodosCount: function() {
return this.get('length') - this.get('remainingTodosCount');
}.property('[].isDone').cacheable(),
remainingWord: function() {
return this.get('remainingTodosCount') === 1 ? "item" : "items";
}.property('remainingTodosCount').cacheable(),
// ..........................................................
// ACTIONS
//
createTodo: function(title) {
this.pushObject(Todos.Todo.create({ title: title, isDone: false }));
},
deleteTodo: function(todo) {
this.removeObject(todo);
},
clearCompletedTodos: function(todo) {
this.filterProperty('isDone', true).forEach(this.deleteTodo, this);
}
});
// ..........................................................
// VIEWS
//
Todos.TodoItemView = SC.TemplateView.extend({
templateName: 'todo_item',
isDoneDidChange: function() {
this.$().toggleClass('done', this.getPath('content.isDone'));
}.observes('this.content.isDone'),
checkbox: SC.CheckboxView.design({
valueBinding: 'this.parentView.content.isDone'
}),
destroyTodoView: SC.TemplateView.design({
mouseUp: function() {
var todo = this.getPath('parentView.content');
this.getPath('page.controller').deleteTodo(todo);
}
})
});
Todos.mainPage = SC.Page.design({
// connect to the main controller...can be easily reconfigured to new
// UIs.
controllerBinding: 'Todos.listController',
app: SC.TemplateView.design({
// ..........................................................
// PROPERTIES (for template)
//
remainingTodosCountBinding: 'this.page.controller.remainingTodosCount',
remainingWordBinding: 'this.page.controller.remainingWord',
// ..........................................................
// SUBVIEWS
//
createTextField: SC.TextFieldView.design({
insertNewline: function() {
this.getPath('page.controller').createTodo(this.get('value'));
this.set('value', '');
},
cancel: function() {
this.set('value', '').blur();
}
}),
list: SC.TemplateCollectionView.design({
contentBinding: 'this.page.controller.arrangedObjects',
exampleView: Todos.TodoItemView
}),
clearRemainingView: SC.TemplateView.design({
mouseUp: function() {
this.getPath('page.controller').clearCompletedTodos();
}
})
})
});
// ..........................................................
// MAIN
//
Todos.main = function() {
Todos.getPath('mainPage.app').append();
};
$.ready(Todos.main);
{{view 'checkbox' }}
<div class="todo-content">{{content.title}}</div>
{{#view 'destroyTodoView'}}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment