Skip to content

Instantly share code, notes, and snippets.

@alecperkins
Created August 15, 2012 19:57
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save alecperkins/3363111 to your computer and use it in GitHub Desktop.
Save alecperkins/3363111 to your computer and use it in GitHub Desktop.
TodoMVC tutorial in coffeescript
doctype html
html
head
title Todos
body
#todoapp
.title
h1 Todos
.content
#create-todo
input#new-todo
#todos
input.check.mark-all-done(type='checkbox')
ul#todo-list
#todo-stats
script(src='/libs/jquery-1.8.0.js')
script(src='/libs/underscore-1.3.3.js')
script(src='/libs/backbone-0.9.2.js')
script(src='/libs/backbone.marionette-0.9.10.js')
script(src='/libs/coffeescript-1.3.3.js')
script(src='/libs/jade-0.27.2.js')
script(src='/libs/stylus-0.28.2.js')
script
window.log_level = 'debug';
window.log_to_console = true;
script(src='/libs/logging.js')
script(src='/TodoMVC.js')
script(src='/TodoMVC.TodoApp.js')
script(src='/TodoMVC.TodoList.js')
script(src='/TodoMVC.Todos.js')
_.templateSettings =
evaluate : /\{%(.+?)%\}/g
interpolate : /\{\{(.+?)\}\}/g
TodoMVC = new Backbone.Marionette.Application()
TodoMVC.addRegions
list : '#todo-list'
stats : '#todo-stats'
window.TodoMVC = TodoMVC
$(document).ready ->
log 'document:ready'
TodoMVC.start()
TodoMVC.module 'TodoApp', (App, TodoMVC, Backbone, Marionette, $, _) ->
log arguments
class App.TodoForm extends Marionette.ItemView
events:
'keypress #new-todo' : 'createOnEnter'
'click .mark-all-done' : 'toggleAllClicked'
triggers:
'click .todo-clear a' : 'clear:completed'
initialize: ->
@bindTo(@collection, 'update:counts', @countsUpdated, @)
countsUpdated: (counts) ->
$check = @$('.mark-all-done')
$check.prop('checked', counts.allDone)
createOnEnter: (e) ->
if e.keyCode isnt 13
return
$input = $(e.currentTarget)
content = $input.val()
$input.val('')
@trigger 'create:todo',
content: content
toggleAllClicked: (e) ->
$check = $(e.currentTarget)
checked = $check.is(':checked')
@collection.toggleAll(checked)
todoApp =
run: ->
log 'todoApp.run'
@todoList = new TodoMVC.Todos.getAll()
form = @getTodoForm(@todoList)
form.on('create:todo', @todoList.add, @todoList)
form.on('clear:completed', @todoList.clearCompleted, @todoList)
TodoMVC.vent.trigger('app:initialized', @todoList)
getTodoForm: (todos) ->
layout = new App.TodoForm
el: $('#todoapp')
collection: todos
return layout
TodoMVC.addInitializer ->
todoApp.run()
TodoMVC.module 'TodoList', (TodoList, TodoMVC, Backbone, Marionette, $, _) ->
class TodoList.TodoItemView extends Marionette.ItemView
template: _.template """
<div class="todo {{ done ? 'done' : '' }}">
<div class="display">
<input class="check" type="checkbox" {{ done ? 'checked="checked"' : '' }} />
<label class="todo-content">{{ content }}</label>
<span class="todo-destroy"></span>
</div>
<div class="edit">
<input class="todo-input" type="text" value="{{ content }}" />
</div>
</div>
"""
tagName: 'li'
events:
'click input.check': 'checkChanged'
initialize: ->
_.bindAll(@, 'render')
@bindTo(@model, 'change:done', @changeDone, @)
checkChanged: (e) ->
log
checked = $(e.currentTarget).is(':checked')
@model.toggle(checked)
changeDone: (model, done) ->
$check = @$('.check')
$todo = @$('.todo')
if done
$check.prop('checked', true)
$todo.addClass('done')
else
$check.prop('checked', false)
$todo.removeClass('done')
class TodoList.TodoListView extends Marionette.CollectionView
itemView: TodoList.TodoItemView
class TodoList.StatsView extends Marionette.ItemView
template: _.template """
<span class="todo-count">
<span class="number">{{ remaining }}</span>
<span class="word">{{ remaining == 1 ? 'item' : 'items' }}</span> left.
</span>
<span class="todo-clear">
<a href="#">
Clear <span class="number-done">{{ done }}</span>
completed <span class="word-done">{{ done == 1 ? 'item' : 'items' }}</span>
</a>
</span>
"""
initialize: ->
@bindTo(@collection, 'update:counts', @render, @)
serializeData: ->
@collection.counts
todoList =
run: (todos) ->
listView = @getListView(todos)
TodoMVC.list.show(listView)
statsView = @getStatsView(todos)
TodoMVC.stats.show(statsView)
getStatsView: (todos) ->
statsView = new TodoList.StatsView
collection: todos
return statsView
getListView: (todos) ->
listView = new TodoList.TodoListView
collection: todos
return listView
TodoMVC.vent.on 'app:initialized', (todos) ->
todoList.run(todos)
TodoMVC.module 'Todos', (Todos, TodoMVC, Backbone, Marionette, $, _) ->
class Todos.Todo extends Backbone.Model
defaults:
done: false
toggle: (done) ->
@set
done: done
isDone: ->
return @get('done')
class Todos.TodoCollection extends Backbone.Collection
model: Todos.Todo
initialize: ->
log 'Todos.TodoCollection::initialize'
@updateCounts()
@on('add', @updateCounts, @)
@on('remove', @updateCounts, @)
@on('change:done', @updateCounts, @)
clearCompleted: ->
completed = @where({done: true})
_.each completed, (todo) =>
@remove(todo)
toggleAll: (done) ->
@each (todo) ->
todo.toggle(done)
updateCounts: ->
counts =
total: @length
done: @doneCount()
counts.remaining = counts.total - counts.done
counts.allDone = (counts.remaining is 0 and counts.done > 0)
@counts = counts
@trigger('update:counts', counts)
doneCount: ->
doneCount = @reduce (memo, todo) ->
if todo.isDone()
memo += 1
return memo
, 0
return doneCount
Todos.getAll = ->
log 'Todos.getAll'
if not Todos.todoList
Todos.todoList = new Todos.TodoCollection()
return Todos.todoList
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment