Commit 9cc1fe01 authored by Stephen McKamey's avatar Stephen McKamey

Adding poor man's routing support. (#812)

parent 7f9bd8d4
......@@ -3,6 +3,7 @@
xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.todomvc.duel</groupId>
......@@ -17,7 +18,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<resourcesDir>${project.basedir}/src/main/resources</resourcesDir>
<staticapps.version>0.9.9</staticapps.version>
<staticapps.version>0.9.10</staticapps.version>
<merge.version>0.6.0</merge.version>
<duel.version>0.9.6</duel.version>
<slf4j.version>1.7.9</slf4j.version>
......@@ -30,12 +31,19 @@
<merge.cdnMapFile>/cdn.properties</merge.cdnMapFile>
<merge.cdnRoot>/cdn/</merge.cdnRoot>
<merge.cdnFiles>.ico .png .jpg .gif .eot .woff .ttf .svg .svgz</merge.cdnFiles>
<merge.cdnFiles>.ico .png .jpg .gif .cur .eot .woff .ttf .svg .svgz</merge.cdnFiles>
<staticapps.config>${project.basedir}/staticapp.json</staticapps.config>
</properties>
<dependencies>
<!-- SLF4J runtime -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>${slf4j.version}</version>
</dependency>
<!-- DUEL runtime -->
<dependency>
<groupId>org.duelengine</groupId>
......@@ -49,13 +57,6 @@
<artifactId>duel-staticapps</artifactId>
<version>${staticapps.version}</version>
</dependency>
<!-- SLF4J runtime -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jdk14</artifactId>
<version>${slf4j.version}</version>
</dependency>
</dependencies>
<build>
......
......@@ -3,20 +3,20 @@
<%-- This footer should hidden by default and shown when there are todos. --%>
<footer class="footer" if="<%= data.total %>">
<span class="todo-count"><strong><%= data.active %></strong> <%= (data.active === 1) ? 'item' : 'items' %> left</span>
<%-- TODO: implement routing
<ul class="filters">
<li>
<a class="selected" href="#/">All</a>
<a href="#/" class="<%= !data.filter ? 'selected' : null %>">All</a>
</li>
<li>
<a href="#/active">Active</a>
<a href="#/active" class="<%= data.filter === 'active' ? 'selected' : null %>">Active</a>
</li>
<li>
<a href="#/completed">Completed</a>
<a href="#/completed" class="<%= data.filter === 'completed' ? 'selected' : null %>">Completed</a>
</li>
</ul>
--%>
<!-- Hidden if no completed items are left ↓ -->
<%-- Hidden if no completed items are left ↓ --%>
<button class="clear-completed"
if="<%= data.completed %>"
onclick="<%= todos.actions.clearOnClick %>">Clear completed</button>
......
......@@ -11,16 +11,20 @@ var todos = todos || {};
var ESC_KEY = 27;
var ENTER_KEY = 13;
// Poor man's routing.
addEventListener('hashchange', refreshView, false);
function curFilter() {
return document.location.hash.substr(2);
}
function find(selector, scope) {
return (scope || document).querySelector(selector);
}
function refreshView() {
// get the data
var data = {
tasks: todos.model.tasks(),
stats: todos.model.stats()
};
var data = todos.model.viewData(curFilter());
// build the view
var view = todos.views.TodoApp(data).toDOM();
......@@ -141,6 +145,7 @@ var todos = todos || {};
};
/*-- init task list -------------------------------*/
refreshView();
})(todos, window.document);
......@@ -53,25 +53,40 @@ var todos = todos || {};
tasks = [];
}
/*-- export public interface -------------------------------*/
function filterTasks(filter) {
if (filter === 'completed' || filter === 'active') {
var completed = filter === 'completed';
return tasks.filter(function (task) {
return task.completed === completed;
});
}
return tasks;
}
todos.model = {
tasks: function () {
return tasks;
},
function calcStats(filter) {
var stats = {
total: tasks.length,
stats: function () {
var stats = {};
completed: tasks.filter(function (task) {
return task.completed;
}).length,
stats.total = tasks.length;
filter: filter || ''
};
stats.completed = tasks.filter(function (task) {
return task.completed;
}).length;
stats.active = stats.total - stats.completed;
stats.active = stats.total - stats.completed;
return stats;
}
return stats;
/*-- export public interface -------------------------------*/
todos.model = {
viewData: function (filter) {
return {
tasks: filterTasks(filter),
stats: calcStats(filter)
};
},
add: function (title) {
......
......@@ -21,12 +21,15 @@ v=function(a){return"[ "+a+" ]"},x=function(a){if(!l(a)||!l(a.getView)){var b=a;
link:1,menuitem:1,meta:1,param:1,source:1,track:1,wbr:1};q.FAST=!(C&&9>C());q.prototype.append=function(a,b,d){var f=arguments;q.FAST?(f=f.length,1<f&&(2<f&&(b+=d),a+=b),this.value+=a):this.value.push.apply(this.value,f)};q.prototype.toString=function(){return q.FAST?this.value:this.value.join("")};p.prototype.toString=function(){return H(this.value)};p.prototype.write=function(a){(a||m).write(""+this)};var T={allowfullscreen:"allowFullscreen",accesskey:"accessKey",bgcolor:"bgColor",cellpadding:"cellPadding",
cellspacing:"cellSpacing",checked:"defaultChecked","class":"className",colspan:"colSpan",contenteditable:"contentEditable",defaultchecked:"defaultChecked",defaultselected:"defaultSelected",defaultmuted:"defaultMuted","for":"htmlFor",formnovalidate:"formNoValidate",hidefocus:"hideFocus",ismap:"isMap",itemscope:"itemScope",maxlength:"maxLength",muted:"defaultMuted",nohref:"noHref",noresize:"noResize",noshade:"noShade",novalidate:"noValidate",nowrap:"noWrap",pauseonexit:"pauseOnExit",readonly:"readOnly",
rowspan:"rowSpan",selected:"defaultSelected",spellcheck:"spellCheck",tabindex:"tabIndex",truespeed:"trueSpeed",typemustmatch:"typeMustMatch",usemap:"useMap",willvalidate:"willValidate"},u={enctype:"encoding",onscroll:"DOMMouseScroll"},U={autocapitalize:1,autocomplete:1,autocorrect:1,type:1},R=/^[\r\n]+/,S=/[\r\n]+$/;p.prototype.toDOM=function(a,b){4===k(a)&&(a=m.getElementById(a)||("querySelector"in m?m.querySelector(a):null));var d;try{b&&(d=a,a=null),d=N(d||t(this.value[0]),this.value)}catch(f){var c=
v(f);if(c instanceof p)return c.toDOM(a||d);d=m.createTextNode(""+c)}a&&a.parentNode&&a.parentNode.replaceChild(d,a);return d};p.prototype.reload=function(){var a=m;try{var b=this.toDOM();a.replaceChild(b,a.documentElement);if(a.createStyleSheet){for(var d=b.firstChild;d&&"HEAD"!==(d.tagName||"");)d=d.nextSibling;for(var f=d&&d.firstChild;f;){if("LINK"===(f.tagName||""))f.href=f.href;f=f.nextSibling}}}catch(c){a=a.open("text/html"),a.write(""+this),a.close()}};return x}(document,window.ScriptEngineMajorVersion);var todos=todos||{};todos.views=todos.views||{};todos.views.Stats=duel([""," ",["$if",{test:function(a){return a.total}},["footer",{"class":"footer"}," ",["span",{"class":"todo-count"},["strong",function(a){return a.active}]," ",function(a){return 1===a.active?"item":"items"}," left"]," "," ",["!"," Hidden if no completed items are left \u2193 "]," ",["$if",{test:function(a){return a.completed}},["button",{"class":"clear-completed",onclick:function(){return todos.actions.clearOnClick}},"Clear completed"]]]]]);var todos=todos||{};todos.views=todos.views||{};
v(f);if(c instanceof p)return c.toDOM(a||d);d=m.createTextNode(""+c)}a&&a.parentNode&&a.parentNode.replaceChild(d,a);return d};p.prototype.reload=function(){var a=m;try{var b=this.toDOM();a.replaceChild(b,a.documentElement);if(a.createStyleSheet){for(var d=b.firstChild;d&&"HEAD"!==(d.tagName||"");)d=d.nextSibling;for(var f=d&&d.firstChild;f;){if("LINK"===(f.tagName||""))f.href=f.href;f=f.nextSibling}}}catch(c){a=a.open("text/html"),a.write(""+this),a.close()}};return x}(document,window.ScriptEngineMajorVersion);var todos=todos||{};todos.views=todos.views||{};
todos.views.Stats=duel([""," ",["$if",{test:function(a){return a.total}},["footer",{"class":"footer"}," ",["span",{"class":"todo-count"},["strong",function(a){return a.active}]," ",function(a){return 1===a.active?"item":"items"}," left"]," ",["ul",{"class":"filters"}," ",["li"," ",["a",{href:"#/","class":function(a){return!a.filter?"selected":null}},"All"]," "]," ",["li"," ",["a",{href:"#/active","class":function(a){return"active"===a.filter?"selected":null}},"Active"]," "]," ",["li"," ",["a",{href:"#/completed",
"class":function(a){return"completed"===a.filter?"selected":null}},"Completed"]," "]," "]," "," ",["$if",{test:function(a){return a.completed}},["button",{"class":"clear-completed",onclick:function(){return todos.actions.clearOnClick}},"Clear completed"]]]]]);var todos=todos||{};todos.views=todos.views||{};
todos.views.Task=duel([""," ",["li",{"class":function(a){return a.completed?"completed":""}}," ",["div",{"class":"view"}," ",["input",{"class":"toggle",type:"checkbox",checked:function(a){return a.completed},onchange:function(a){return todos.actions.completedOnChange(a.id)}}]," ",["label",{ondblclick:function(){return todos.actions.editOnDblclick}},function(a){return a.title}]," ",["button",{"class":"destroy",onclick:function(a){return todos.actions.removeOnClick(a.id)}}]," "]," ",["input",{"class":"edit",
type:"text",value:function(a){return a.title},onblur:function(a){return todos.actions.editOnBlur(a.id)},onkeydown:function(a){return todos.actions.editOnKeydown(a.id)}}]]]);var todos=todos||{};todos.views=todos.views||{};
todos.views.Tasks=duel([""," ",["$if",{test:function(a){return a.tasks&&a.tasks.length}},["section",{"class":"main"}," ",["input",{"class":"toggle-all",type:"checkbox",checked:function(a){return!a.stats.active},onchange:function(){return todos.actions.toggleOnChange}}]," ",["label",{"for":"toggle-all"},"Mark all as complete"]," ",["ul",{"class":"todo-list"}," ",["$for",{each:function(a){return a.tasks}}," ",["$call",{view:function(){return todos.views.Task}}]]," "]]]]);var todos=todos||{};todos.views=todos.views||{};todos.views.TodoApp=duel(["section",{"class":"todoapp"}," ",["header",{"class":"header"}," ",["h1","todos"]," ",["input",{"class":"new-todo",placeholder:"What needs to be done?",autofocus:!0,onblur:function(){return todos.actions.add_blur},onkeydown:function(){return todos.actions.addOnKeydown}}]," "]," ",["$call",{view:function(){return todos.views.Tasks},data:function(a){return a}}]," ",["$call",{view:function(){return todos.views.Stats},data:function(a){return a.stats}}]]);var todos=todos||{};
(function(j,f,h){function g(a){return b.filter(function(c){return c.id===a})[0]}function d(){var a="undefined"!==typeof JSON?JSON.stringify(b):b;f.setItem(h,a)}var b,e;if(!(e=f)){var i={};e={getItem:function(a){return i[a]},setItem:function(a,c){i[a]=c}}}f=e;b=(e=f.getItem(h))?"undefined"!==typeof JSON?JSON.parse(e):e:[];j.model={tasks:function(){return b},stats:function(){var a={};a.total=b.length;a.completed=b.filter(function(a){return a.completed}).length;a.active=a.total-a.completed;return a},
add:function(a){a={id:((new Date).getTime()+Math.random()).toString(36),title:a,completed:!1};b.push(a);d();return a},find:g,edit:function(a,b){(g(a)||{}).title=b;d()},toggle:function(a,b){(g(a)||{}).completed=b;d()},toggleAll:function(a){b.forEach(function(b){b.completed=a});d()},remove:function(a){for(var c=b.length-1;0<=c;c--)b[c].id===a&&b.splice(c,1);d()},expunge:function(){for(var a=b.length-1;0<=a;a--)b[a].completed&&b.splice(a,1);d()}}})(todos,window.localStorage,"todos-duel");var todos=todos||{};
(function(b,e){function d(){var a={tasks:b.model.tasks(),stats:b.model.stats()},a=b.views.TodoApp(a).toDOM(),c=e.querySelector(".todoapp");c?c.parentNode.replaceChild(a,c):e.body.insertBefore(a,e.body.firstChild);e.querySelector(".new-todo").focus()}b.actions={addOnKeydown:function(a){13===a.keyCode?(a=(this.value||"").trim(),this.value="",a&&(b.model.add(a),d())):27===a.keyCode&&d()},editOnBlur:function(a){return function(){var c=(this.value||"").trim();(this.value=c)?b.model.edit(a,c):b.model.remove(a);
d()}},editOnKeydown:function(a){return function(c){if(13===c.keyCode)this.blur();else if(27===c.keyCode){if(c=b.model.find(a))this.value=c.title;this.blur()}}},removeOnClick:function(a){return function(){b.model.remove(a);d()}},clearOnClick:function(){b.model.expunge();d()},editOnDblclick:function(){for(var a=this;"LI"!==a.tagName;)a=a.parentNode;a.className="editing";(a=(a||e).querySelector("input[type=text]"))&&a.focus()},completedOnChange:function(a){return function(){b.model.toggle(a,this.checked);
d()}},toggleOnChange:function(){b.model.toggleAll(this.checked);d()}};d()})(todos,window.document);
\ No newline at end of file
(function(j,f,h){function g(a){return c.filter(function(b){return b.id===a})[0]}function d(){var a="undefined"!==typeof JSON?JSON.stringify(c):c;f.setItem(h,a)}var c,e;if(!(e=f)){var i={};e={getItem:function(a){return i[a]},setItem:function(a,b){i[a]=b}}}f=e;c=(e=f.getItem(h))?"undefined"!==typeof JSON?JSON.parse(e):e:[];j.model={viewData:function(a){var b;if("completed"===a||"active"===a){var d="completed"===a;b=c.filter(function(a){return a.completed===d})}else b=c;a={total:c.length,completed:c.filter(function(a){return a.completed}).length,
filter:a||""};a.active=a.total-a.completed;return{tasks:b,stats:a}},add:function(a){a={id:((new Date).getTime()+Math.random()).toString(36),title:a,completed:!1};c.push(a);d();return a},find:g,edit:function(a,b){(g(a)||{}).title=b;d()},toggle:function(a,b){(g(a)||{}).completed=b;d()},toggleAll:function(a){c.forEach(function(b){b.completed=a});d()},remove:function(a){for(var b=c.length-1;0<=b;b--)c[b].id===a&&c.splice(b,1);d()},expunge:function(){for(var a=c.length-1;0<=a;a--)c[a].completed&&c.splice(a,
1);d()}}})(todos,window.localStorage,"todos-duel");var todos=todos||{};
(function(b,e){function d(){var a=b.model.viewData(e.location.hash.substr(2)),a=b.views.TodoApp(a).toDOM(),c=e.querySelector(".todoapp");c?c.parentNode.replaceChild(a,c):e.body.insertBefore(a,e.body.firstChild);e.querySelector(".new-todo").focus()}addEventListener("hashchange",d,!1);b.actions={addOnKeydown:function(a){13===a.keyCode?(a=(this.value||"").trim(),this.value="",a&&(b.model.add(a),d())):27===a.keyCode&&d()},editOnBlur:function(a){return function(){var c=(this.value||"").trim();(this.value=
c)?b.model.edit(a,c):b.model.remove(a);d()}},editOnKeydown:function(a){return function(c){if(13===c.keyCode)this.blur();else if(27===c.keyCode){if(c=b.model.find(a))this.value=c.title;this.blur()}}},removeOnClick:function(a){return function(){b.model.remove(a);d()}},clearOnClick:function(){b.model.expunge();d()},editOnDblclick:function(){for(var a=this;"LI"!==a.tagName;)a=a.parentNode;a.className="editing";(a=(a||e).querySelector("input[type=text]"))&&a.focus()},completedOnChange:function(a){return function(){b.model.toggle(a,
this.checked);d()}},toggleOnChange:function(){b.model.toggleAll(this.checked);d()}};d()})(todos,window.document);
\ No newline at end of file
......@@ -12,7 +12,7 @@
<p>Ported to <a href="http://duelengine.org">DUEL</a> by <a href="http://mck.me">Stephen McKamey</a></p>
<p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer>
<script src="./cdn/41614acbac7a243d667ca7ec317c4d0c81ca1d7d.js"></script>
<script src="./cdn/15eb29cf958c6239f5659fd203f96a63f9475655.js"></script>
</body>
</html>
\ 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