Commit e280987d authored by Sindre Sorhus's avatar Sindre Sorhus

Batman app: Cleanup

parent e1843aab
# Batman TodoMVC
# Batman • [TodoMVC](http://todomvc.com)
A todo app built using [Batman](http://batmanjs.org), inspired by [TodoMVC](https://github.com/addyosmani/todomvc).
A todo app built using [Batman](http://batmanjs.org)
## Running it
Spin up an HTTP server and visit http://localhost/labs/architecture-examples/batman/index.html
## Run
Spin up an HTTP server and visit http://localhost/labs/architecture-examples/batman/
## Persistence
A quick note: This app uses `Batman.LocalStorage` to persist the Todo records across page reloads. Batman's `localStorage` engine sticks each record under it's own key in `localStorage`, which is a departure from the TodoMVC application specification, which asks that all the records are stored under one key as a big blob. Batman stores records this way so that the whole set doesn't need to be parsed just to find one record or check if that record exists.
## Building it
This app is written in CoffeeScript, so to make changes, please edit `js/app.coffee` and rebuild the JavaScript with the `coffee` compiler.
## Build
This app is written in CoffeeScript, so to make changes, please edit `js/app.coffee` and rebuild the JavaScript with the `coffee` compiler.
\ No newline at end of file
......@@ -7,68 +7,66 @@
<link rel="stylesheet" href="../../../assets/base.css">
</head>
<body>
<div data-yield="main"></div>
<div data-defineview="todos/all">
<section id="todoapp">
<header id="header">
<h1>todos</h1>
<form data-formfor-todo="newTodo" data-event-submit="createTodo">
<input id="new-todo" type="text" placeholder="What needs to be completed?" autofocus data-bind="todo.title">
</form>
</header>
<section id="main" data-showif="Todo.all.length">
<input id="toggle-all" type="checkbox" data-event-change="toggleAll" data-source="Todo.completed.length | equals Todo.all.length">
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list">
<li data-foreach-todo="currentTodos"
data-addclass-completed="todo.completed"
data-addclass-editing="todo.editing" >
<div class="view" data-hideif="todo.editing" data-event-doubleclick="toggleEditing">
<input class="toggle" type="checkbox" data-bind="todo.completed" data-event-change="todoDoneChanged">
<label data-bind="todo.title"></label>
<button class="destroy" data-event-click="destroyTodo"></button>
</div>
<input class="edit" type="text"
data-bind="todo.title"
data-bind-id="'todo-input-' | append todo.id"
data-event-blur="toggleEditing"
data-event-keypress="disableEditingUponSubmit" >
</li>
</ul>
</section>
<footer id="footer" data-showif="Todo.all.length">
<span id="todo-count">
<strong data-bind="Todo.active.length"></strong>
<span data-bind="'item' | pluralize Todo.active.length, false"></span>
left
</span>
<ul id="filters">
<li>
<a data-addclass-selected="currentRoute.action | equals 'all'" data-route="'/'">All</a>
</li>
<li>
<a data-addclass-selected="currentRoute.action | equals 'active'" data-route="'/active'">Active</a>
</li>
<li>
<a data-addclass-selected="currentRoute.action | equals 'completed'" data-route="'/completed'">Completed</a>
</li>
</ul>
<button id="clear-completed" data-event-click="clearCompleted" data-showif="Todo.completed.length">Clear completed (<span data-bind="Todo.completed.length"></span>)</button>
</footer>
</section>
<footer id="info">
<p>Double-click to edit a todo</p>
<p>Template by <a href="http://sindresorhus.com">Sindre Sorhus</a></p>
<p>Created by <a href="http://batmanjs.org">Harry Brundage</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
</div>
<div data-yield="main"></div>
<div data-defineview="todos/all">
<section id="todoapp">
<header id="header">
<h1>todos</h1>
<form data-formfor-todo="newTodo" data-event-submit="createTodo">
<input id="new-todo" type="text" placeholder="What needs to be completed?" autofocus data-bind="todo.title">
</form>
</header>
<section id="main" data-showif="Todo.all.length">
<input id="toggle-all" type="checkbox" data-event-change="toggleAll" data-source="Todo.completed.length | equals Todo.all.length">
<label for="toggle-all">Mark all as complete</label>
<ul id="todo-list">
<li data-foreach-todo="currentTodos"
data-addclass-completed="todo.completed"
data-addclass-editing="todo.editing" >
<div class="view" data-hideif="todo.editing" data-event-doubleclick="toggleEditing">
<input class="toggle" type="checkbox" data-bind="todo.completed" data-event-change="todoDoneChanged">
<label data-bind="todo.title"></label>
<button class="destroy" data-event-click="destroyTodo"></button>
</div>
<input class="edit" type="text"
data-bind="todo.title"
data-bind-id="'todo-input-' | append todo.id"
data-event-blur="toggleEditing"
data-event-keypress="disableEditingUponSubmit">
</li>
</ul>
</section>
<footer id="footer" data-showif="Todo.all.length">
<span id="todo-count">
<strong data-bind="Todo.active.length"></strong>
<span data-bind="'item' | pluralize Todo.active.length, false"></span> left
</span>
<ul id="filters">
<li>
<a data-addclass-selected="currentRoute.action | equals 'all'" data-route="'/'">All</a>
</li>
<li>
<a data-addclass-selected="currentRoute.action | equals 'active'" data-route="'/active'">Active</a>
</li>
<li>
<a data-addclass-selected="currentRoute.action | equals 'completed'" data-route="'/completed'">Completed</a>
</li>
</ul>
<button id="clear-completed" data-event-click="clearCompleted" data-showif="Todo.completed.length">
Clear completed (<span data-bind="Todo.completed.length"></span>)
</button>
</footer>
</section>
<footer id="info">
<p>Double-click to edit a todo</p>
<p>Template by <a href="http://sindresorhus.com">Sindre Sorhus</a></p>
<p>Created by <a href="http://batmanjs.org">Harry Brundage</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
</div>
<script src="../../../assets/base.js"></script>
<script src="js/es5-shim.js"></script>
<script src="js/batman.js"></script>
<script src="js/lib/batman.js"></script>
<script src="js/app.js"></script>
</body>
</html>
</html>
\ No newline at end of file
class Alfred extends Batman.App
@root 'todos#all'
@route "/completed", "todos#completed"
@route "/active", "todos#active"
@root 'todos#all'
@route '/completed', 'todos#completed'
@route '/active', 'todos#active'
class Alfred.TodosController extends Batman.Controller
constructor: ->
super
@set 'newTodo', new Alfred.Todo(completed: false)
all: ->
@set 'currentTodos', Alfred.Todo.get('all')
completed: ->
@set 'currentTodos', Alfred.Todo.get('completed')
@render source: 'todos/all'
active: ->
@set 'currentTodos', Alfred.Todo.get('active')
@render source: 'todos/all'
createTodo: ->
@get('newTodo').save (err, todo) =>
if err
throw err unless err instanceof Batman.ErrorsSet
else
@set 'newTodo', new Alfred.Todo(completed: false, title: "")
todoDoneChanged: (node, event, context) ->
todo = context.get('todo')
todo.save (err) ->
throw err if err && !err instanceof Batman.ErrorsSet
destroyTodo: (node, event, context) ->
todo = context.get('todo')
todo.destroy (err) -> throw err if err
toggleAll: (node, context) ->
Alfred.Todo.get('all').forEach (todo) ->
todo.set('completed', !!node.checked)
todo.save (err) ->
throw err if err && !err instanceof Batman.ErrorsSet
clearCompleted: ->
Alfred.Todo.get('completed').forEach (todo) ->
todo.destroy (err) -> throw err if err
toggleEditing: (node, event, context) ->
todo = context.get('todo')
editing = todo.set('editing', !todo.get('editing'))
if editing
input = document.getElementById("todo-input-#{todo.get('id')}")
input.focus()
input.select()
else
if todo.get('title')?.length > 0
todo.save (err, todo) ->
throw err if err && !err instanceof Batman.ErrorsSet
else
todo.destroy (err, todo) ->
throw err if err
disableEditingUponSubmit: (node, event, context) ->
if Batman.DOM.events.isEnter(event)
@toggleEditing(node, event, context)
constructor: ->
super
@set 'newTodo', new Alfred.Todo(completed: false)
all: ->
@set 'currentTodos', Alfred.Todo.get('all')
completed: ->
@set 'currentTodos', Alfred.Todo.get('completed')
@render source: 'todos/all'
active: ->
@set 'currentTodos', Alfred.Todo.get('active')
@render source: 'todos/all'
createTodo: ->
@get('newTodo').save (err, todo) =>
if err
throw err unless err instanceof Batman.ErrorsSet
else
@set 'newTodo', new Alfred.Todo(completed: false, title: "")
todoDoneChanged: (node, event, context) ->
todo = context.get('todo')
todo.save (err) ->
throw err if err && !err instanceof Batman.ErrorsSet
destroyTodo: (node, event, context) ->
todo = context.get('todo')
todo.destroy (err) -> throw err if err
toggleAll: (node, context) ->
Alfred.Todo.get('all').forEach (todo) ->
todo.set('completed', !!node.checked)
todo.save (err) ->
throw err if err && !err instanceof Batman.ErrorsSet
clearCompleted: ->
Alfred.Todo.get('completed').forEach (todo) ->
todo.destroy (err) -> throw err if err
toggleEditing: (node, event, context) ->
todo = context.get('todo')
editing = todo.set('editing', !todo.get('editing'))
if editing
input = document.getElementById("todo-input-#{todo.get('id')}")
input.select()
else
if todo.get('title')?.length > 0
todo.save (err, todo) ->
throw err if err && !err instanceof Batman.ErrorsSet
else
todo.destroy (err, todo) ->
throw err if err
disableEditingUponSubmit: (node, event, context) ->
if Batman.DOM.events.isEnter(event)
@toggleEditing(node, event, context)
class Alfred.Todo extends Batman.Model
@encode 'title', 'completed'
@persist Batman.LocalStorage
@validate 'title', presence: true
@storageKey: 'todos-batman'
@encode 'title', 'completed'
@persist Batman.LocalStorage
@validate 'title', presence: true
@storageKey: 'todos-batman'
@classAccessor 'active', ->
@get('all').filter (todo) -> !todo.get('completed')
@classAccessor 'active', ->
@get('all').filter (todo) -> !todo.get('completed')
@classAccessor 'completed', ->
@get('all').filter (todo) -> todo.get('completed')
@classAccessor 'completed', ->
@get('all').filter (todo) -> todo.get('completed')
@wrapAccessor 'title', (core) ->
set: (key, value) -> core.set.call(@, key, value?.trim())
@wrapAccessor 'title', (core) ->
set: (key, value) -> core.set.call(@, key, value?.trim())
window.Alfred = Alfred
Alfred.run()
Alfred.run()
\ No newline at end of file
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment