todomvc: Progress

This commit is contained in:
Tony Garnock-Jones 2016-05-13 20:16:25 -04:00
parent 5c80c2f3bd
commit 7a759de5a1
2 changed files with 50 additions and 15 deletions

View File

@ -40,10 +40,10 @@
</ul> </ul>
</section> </section>
<footer class="footer"> <footer class="footer">
<span class="todo-count"><strong>0</strong> item left</span> <span class="todo-count"><strong></strong> item<span class="s"></span> left</span>
<ul class="filters"> <ul class="filters">
<li> <li>
<a class="selected" href="#/">All</a> <a href="#/">All</a>
</li> </li>
<li> <li>
<a href="#/active">Active</a> <a href="#/active">Active</a>

View File

@ -1,6 +1,11 @@
assertion type todo(id, title, completed); assertion type todo(id, title, completed);
message type deleteTodo(id);
assertion type show(completed); assertion type show(completed);
assertion type activeTodoCount(n);
assertion type completedTodoCount(n);
assertion type totalTodoCount(n);
message type deleteTodo(id);
message type clearCompletedTodos();
/* /*
To Do (ho ho ho) To Do (ho ho ho)
@ -11,10 +16,7 @@ assertion type show(completed);
- pattern the HTML more explicitly on the given template, keep changes to a minimum - pattern the HTML more explicitly on the given template, keep changes to a minimum
- code style https://github.com/tastejs/todomvc/blob/master/contributing.md#code-style - code style https://github.com/tastejs/todomvc/blob/master/contributing.md#code-style
- no todos: make sure #main and #footer are hidden
- mark all as complete/incomplete; make sure it is only ever checked when all the todos are checked - mark all as complete/incomplete; make sure it is only ever checked when all the todos are checked
- count of active todos; pluralize correctly; format correctly
- hide "clear completed" button when no completed todos exist
- persist to localStorage; use correct keys and name. - persist to localStorage; use correct keys and name.
- routing: spec requires that filtering be done "on a model level"; - routing: spec requires that filtering be done "on a model level";
@ -101,6 +103,10 @@ function addTodo(title) {
this.editing = false; this.editing = false;
if (!this.title) :: deleteTodo(this.id); if (!this.title) :: deleteTodo(this.id);
} }
on message clearCompletedTodos() {
if (this.completed) :: deleteTodo(this.id);
}
} until { } until {
case message deleteTodo(this.id); case message deleteTodo(this.id);
} }
@ -120,13 +126,42 @@ ground dataspace G {
} }
actor { actor {
var completedCount = 0;
var activeCount = 0;
react { react {
on asserted Syndicate.UI.locationHash($hash) { on asserted todo(_, _, $completed) { if (completed) completedCount++; else activeCount++; }
// TODO this is a bit icky too on retracted todo(_, _, $completed) { if (completed) completedCount--; else activeCount--; }
var ns = document.querySelectorAll('ul.filters > li > a'); assert activeTodoCount(activeCount);
for (var i = 0; i < ns.length; i++) { ns[i].className = ''; } assert completedTodoCount(completedCount);
var n = document.querySelector('ul.filters > li > a[href="#'+hash+'"]'); assert totalTodoCount(activeCount + completedCount);
n.className = 'selected'; }
}
actor {
var ui = new Syndicate.UI.Anchor();
react {
during activeTodoCount($count) {
assert ui.context('count').html('.todo-count strong', '' + count);
assert ui.context('plural').html('.todo-count span.s', 's') when (count !== 1);
}
during completedTodoCount(0) {
assert Syndicate.UI.uiAttribute('button.clear-completed', 'class', 'hidden');
}
during totalTodoCount(0) {
assert Syndicate.UI.uiAttribute('section.main', 'class', 'hidden');
assert Syndicate.UI.uiAttribute('footer.footer', 'class', 'hidden');
}
on message Syndicate.UI.globalEvent('button.clear-completed', 'click', _) {
:: clearCompletedTodos();
}
}
}
actor {
react {
during Syndicate.UI.locationHash($hash) {
assert Syndicate.UI.uiAttribute('ul.filters > li > a[href="#'+hash+'"]',
'class', 'selected');
} }
during Syndicate.UI.locationHash('/') { during Syndicate.UI.locationHash('/') {
@ -147,6 +182,6 @@ ground dataspace G {
addTodo('Finish PhD'); addTodo('Finish PhD');
} }
G.dataspace.setOnStateChange(function (mux, patch) { // G.dataspace.setOnStateChange(function (mux, patch) {
document.getElementById("ds-state").innerText = Syndicate.prettyTrie(mux.routingTable); // document.getElementById("ds-state").innerText = Syndicate.prettyTrie(mux.routingTable);
}); // });