Skip to content
Browse files

rework to use model filters instead of css

  • Loading branch information...
1 parent bf6066a commit 2a0744cc8a427076461cbbc69193acca3d04457e @nateps nateps committed Aug 26, 2012
View
2 labs/architecture-examples/derbyjs/package.json
@@ -4,7 +4,7 @@
"version": "0.0.0",
"main": "./server.js",
"dependencies": {
- "derby": "0.3.12",
+ "derby": "0.3.13",
"express": "3.0.0beta4",
"gzippo": ">=0.1.4"
},
View
130 labs/architecture-examples/derbyjs/src/todos/index.coffee
@@ -3,107 +3,79 @@ derby = require 'derby'
derby.use(require '../../ui')
-## ROUTES ##
+view.fn 'noItems',
+ get: (list) -> !list.length
+ set: ->
# Redirect the visitor to a random todo list
get '/', (page) ->
page.redirect '/' + parseInt(Math.random() * 1e9).toString(36)
# Sets up the model, the reactive function for stats and renders the todo list
get '/:groupName', (page, model, {groupName}) ->
- groupTodosQuery = model.query('todos').forGroup(groupName)
- model.subscribe "groups.#{groupName}", groupTodosQuery, (err, group, groupTodos) ->
- model.ref '_group', group
- group.setNull 'id', groupName
-
- todoIds = group.at 'todoIds' or []
-
- # The refList supports array methods, but it stores the todo values
- # on an object by id. The todos are stored on the object 'todos',
- # and their order is stored in an array of ids at '_group.todoIds'
- model.refList '_todoList', 'todos', todoIds
-
- # Create a reactive function that automatically keeps '_stats'
- # updated with the number of remaining and completed todos.
- model.fn '_stats', '_todoList', (list) ->
- remaining = 0
- completed = 0
- if list
- for todo in list
- if todo?.completed
- completed++
- else
- remaining++
- return {
- completed: completed,
- remaining: remaining,
- oneOnly: remaining == 1,
- }
-
- # Do not filter the list by default
- model.del '_filter'
-
- page.render 'todo'
+ model.query('todos').forGroup(groupName).subscribe ->
+ model.set '_groupName', groupName
-# Transitional route for enabling a filter
-get {from: '/:groupName', to: '/:groupName/:filterName'},
- forward: (model, {filterName}, next) ->
- # enable the filter
- model.set '_filter', filterName
- back: (model, params, next) ->
- # disable the filter
- model.del '_filter'
+ model.ref '_list.all', model.filter('todos')
+ .where('group').equals(groupName)
-ready (model) ->
+ model.ref '_list.completed', model.filter('todos')
+ .where('group').equals(groupName)
+ .where('completed').equals(true)
+
+ model.ref '_list.active', model.filter('todos')
+ .where('group').equals(groupName)
+ .where('completed').notEquals(true)
- list = model.at '_todoList'
- group = model.at '_group'
- all_completed = group.at 'all_completed'
+ model.set '_filter', 'all'
+ model.ref '_list.shown', '_list', '_filter'
- group.on 'set', 'all_completed', (all_completed, previous_value, isLocal, e) ->
- # We only want to react to all_completed being set if it's in response
- # to a UI event (as opposed to our checkAllCompleted below checking
- # individual items).
- return unless e
+ page.render()
- # Is there a way to do this with one call rather than iterating?
- for {id} in list.get()
- model.set "todos.#{id}.completed", all_completed
+# Transitional route for enabling a filter
+get from: '/:groupName', to: '/:groupName/:filterName',
+ forward: (model, {filterName}) ->
+ model.set '_filter', filterName
+ back: (model, params) ->
+ model.set '_filter', 'all'
+
+get from: '/:groupName/:filterName', to: '/:groupName/:filterName',
+ forward: (model, {filterName}) ->
+ model.set '_filter', filterName
+ready (model) ->
+ todos = model.at 'todos'
newTodo = model.at '_newTodo'
+
exports.add = ->
# Don't add a blank todo
text = newTodo.get().trim()
newTodo.set ''
return unless text
+ todos.add text: text, group: model.get('_groupName')
- list.push text: text, completed: false, group: group.get('id')
- all_completed.set false
-
- exports.del = (e) ->
+ exports.del = (e, el) ->
# Derby extends model.at to support creation from DOM nodes
- model.at(e.target).remove()
+ todos.del model.at(el).get('id')
exports.clearCompleted = ->
- completed_indexes = (i for {completed}, i in list.get() when completed)
- list.remove(i) for i in completed_indexes.reverse()
- all_completed.set false
-
- exports.checkAllCompleted = ->
- for {completed} in list.get() when not completed
- all_completed.set false
- return
- all_completed.set true
-
- exports.endEdit = (e) ->
- target = e.target
- if target.nodeName == "FORM"
- target.firstChild.blur()
- return
- item = model.at(target)
- item.set '_editing', false
- item.remove() if item.get('text').trim() == ''
+ for {id} in model.get('_list.completed')
+ todos.del id
- exports.startEdit = (e) ->
- item = model.at(e.target)
+ exports.clickToggleAll = ->
+ value = !!model.get('_list.active.length')
+ for {id} in model.get('_list.all')
+ todos.set id + '.completed', value
+
+ exports.submitEdit = (e, el) ->
+ el.firstChild.blur()
+
+ exports.startEdit = (e, el) ->
+ item = model.at(el)
item.set '_editing', true
+
+ exports.endEdit = (e, el) ->
+ item = model.at(el)
+ item.set '_editing', false
+ if item.get('text').trim() == ''
+ todos.del item.get('id')
View
8 labs/architecture-examples/derbyjs/styles/todos/index.styl
@@ -46,14 +46,6 @@ section.empty-list, footer.empty-list {
display: none;
}
-ul#todo-list.active li.completed {
- display: none;
-}
-
-ul#todo-list.completed li.active {
- display: none;
-}
-
section.empty-list #toggle-all {
display: none;
}
View
58 labs/architecture-examples/derbyjs/views/todos/index.html
@@ -1,69 +1,65 @@
-<head:>
+<Head:>
@sindresorhus
sindresorhus added a note Aug 27, 2012

Why only use uppercase first char on some?

@absoludity
Owner
@sindresorhus
sindresorhus added a note Aug 27, 2012

Ok, got it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
<link href=/base.css rel=stylesheet>
- <!-- The following ie inclusion is useless as it'll be stripped
- out before getting to the client, but serves as a reminder
- that it needs to be sorted out for ie compatability :) -->
- <!--[if IE]>
- <script src="/ie.js"></script>
- <![endif]-->
<Title:>
DerbyJS • TodoMVC
<Header:>
<ui:connectionAlert>
-<TodoHeader:>
- <header id="header">
- <h1>todos</h1>
- <form x-bind=submit:add><input id="new-todo" placeholder="What needs to be done?" autofocus value={_newTodo}></form>
- </header>
-
<Body:>
<section id="todoapp">
- <app:TodoHeader>
+ <app:todoHeader>
- <section id="main" class="{#unless _todoList}empty-list{/}">
- <input id="toggle-all" type="checkbox" checked="{_group.all_completed}">
+ <section id="main" class="{#unless _list.shown}empty-list{/}">
+ <input id="toggle-all" type="checkbox" checked="{noItems(_list.active)}" x-bind=click:clickToggleAll>
<label for="toggle-all">Mark all as complete</label>
- <ul id=todo-list class={_filter}>{#each _todoList}<app:todo>{/}</ul>
+ <ul id=todo-list>{#each _list.shown}<app:todo>{/}</ul>
</section>
- <app:TodoFooter>
+ <app:todoFooter>
</section>
- <app:Info>
+ <app:info>
+
+<todoHeader:>
+ <header id="header">
+ <h1>todos</h1>
+ <form x-bind=submit:add><input id="new-todo" placeholder="What needs to be done?" autofocus value={_newTodo}></form>
+ </header>
<todo:>
<li data-id={{id}} class="{#if .completed}completed{else}active{/}{#if ._editing} editing{/}">
<div>
- <input class="toggle" type="checkbox" checked={.completed} x-bind=change:checkAllCompleted>
- <form x-bind=submit:endEdit>
- <input class="text" x-bind="focus:startEdit, blur:endEdit" value="{.text}">
+ <input class="toggle" type="checkbox" checked={.completed}>
+ <form x-bind=submit:submitEdit>
+ <input class="text" x-bind="focus:startEdit, blur:endEdit" value="{.text}">
</form>
<button class="destroy" x-bind=click:del></button>
</div>
</li>
-<TodoFooter:>
- <footer id="footer" class="{#unless _todoList}empty-list{/}">
- <span id="todo-count"><strong>{_stats.remaining}</strong> item{#unless _stats.oneOnly}s{/} left</span>
+<todoFooter:>
+ <footer id="footer" class="{#unless _list.all}empty-list{/}">
+ <span id="todo-count"><strong>{_list.active.length}</strong> item{#unless equal(_list.active.length, 1)}s{/} left</span>
<ul id="filters">
<li class="all">
- <a href="/{{_group.id}}" class="{#unless _filter}selected{/}">All</a>
+ <a href="/{{_groupName}}" class="{#if equal(_filter, 'all')}selected{/}">All</a>
</li>
<li class="active">
- <a href="/{{_group.id}}/active" class="{#if equal(_filter, 'active')}selected{/}">Active</a>
+ <a href="/{{_groupName}}/active" class="{#if equal(_filter, 'active')}selected{/}">Active</a>
</li>
<li class="completed">
- <a href="/{{_group.id}}/completed" class="{#if equal(_filter, 'completed')}selected{/}">Completed</a>
+ <a href="/{{_groupName}}/completed" class="{#if equal(_filter, 'completed')}selected{/}">Completed</a>
</li>
</ul>
- <button x-bind=click:clearCompleted id="clear-completed" class="{#unless _stats.completed}non-completed{/}">Clear completed (<span>{_stats.completed}</span>)</button>
+ <button x-bind=click:clearCompleted id="clear-completed" class="{#unless _list.completed}non-completed{/}">
+ Clear completed (<span>{_list.completed.length}</span>)
+ </button>
</footer>
-<Info:>
+<info:>
<footer id="info">
- <h3>Open this <a href="/{{_group.id}}">ToDo list</a> in another browser, or share it with a friend to collaborate!</h3>
+ <h3>Open this <a href="/{{_groupName}}">ToDo list</a> in another browser, or share it with a friend to collaborate!</h3>
<p>Click on a todo to edit</p>
<p>Template by <a href="http://github.com/sindresorhus">Sindre Sorhus</a></p>
<p>Created by <a href="http://micknelson.wordpress.com">Michael Nelson</a> and <a href="https://github.com/lackac">László Bácsi</a></p>

0 comments on commit 2a0744c

Please sign in to comment.
Something went wrong with that request. Please try again.