Commit f83a3caa authored by Stephen Sawchuk's avatar Stephen Sawchuk

DUEL bug fixed, code style.

parent b852875e
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
<%-- could have embedded in 'tasks' for-loop, but this allows us to add single tasks --%> <%-- could have embedded in 'tasks' for-loop, but this allows us to add single tasks --%>
<li class="<%= data.completed ? 'complete' : '' %>"> <li class="<%= data.completed ? 'completed' : '' %>">
<div class="view"> <div class="view">
<input class="toggle" type="checkbox" checked="<%= data.completed %>" <input class="toggle" type="checkbox" checked="<%= data.completed %>"
......
/*global window */
/*jshint camelcase:false */
var todos = todos || {}; var todos = todos || {};
(function( todos, document ) { (function (todos, document) {
'use strict';
/*-- private members -------------------------------*/ /*-- private members -------------------------------*/
var ENTER_KEY = 13, var ENTER_KEY = 13;
STATS_ID = 'footer', var STATS_ID = 'footer';
TODOAPP_ID = 'todoapp', var TODOAPP_ID = 'todoapp';
TASKS_ID = 'main', var TASKS_ID = 'main';
LIST_ID = 'todo-list', var LIST_ID = 'todo-list';
EDITING_CSS = 'editing'; var EDITING_CSS = 'editing';
function getById( id ) { function getById(id) {
return document.getElementById( id ); return document.getElementById(id);
} }
function refreshStats( stats ) { function refreshStats(stats) {
// get the data // get the data
var data = stats || todos.model.stats(); var data = stats || todos.model.stats();
// build the view // build the view
var view = todos.views.Stats( data ).toDOM(); var view = todos.views.Stats(data).toDOM();
// replace old stats // replace old stats
var old = getById( STATS_ID ); var old = getById(STATS_ID);
if ( old ) { if (old) {
old.parentNode.replaceChild( view, old ); old.parentNode.replaceChild(view, old);
} else { } else {
getById( TODOAPP_ID ).appendChild( view ); getById(TODOAPP_ID).appendChild(view);
} }
} }
...@@ -39,47 +43,47 @@ var todos = todos || {}; ...@@ -39,47 +43,47 @@ var todos = todos || {};
}; };
// build the view // build the view
var view = todos.views.Tasks( data ).toDOM(); var view = todos.views.Tasks(data).toDOM();
// replace old task list // replace old task list
var old = getById( TASKS_ID ); var old = getById(TASKS_ID);
if ( old ) { if (old) {
old.parentNode.replaceChild( view, old ); old.parentNode.replaceChild(view, old);
} else { } else {
getById( TODOAPP_ID ).appendChild( view ); getById(TODOAPP_ID).appendChild(view);
} }
refreshStats( data.stats ); refreshStats(data.stats);
} }
function add( input ) { function add(input) {
var title = (input.value || '').trim(); var title = (input.value || '').trim();
input.value = ''; input.value = '';
if ( !title ) { if (!title) {
return; return;
} }
var task = todos.model.add( title ); var task = todos.model.add(title);
var list = getById( LIST_ID ); var list = getById(LIST_ID);
if ( list ) { if (list) {
// add new at the top // add new at the top
list.appendChild( todos.views.Task( task ).toDOM() ); list.appendChild(todos.views.Task(task).toDOM());
refreshStats(); refreshStats();
} else { } else {
refreshAll(); refreshAll();
} }
} }
function edit( input, id ) { function edit(input, id) {
var title = (input.value || '').trim(); var title = (input.value || '').trim();
input.value = title; input.value = title;
if ( title ) { if (title) {
todos.model.edit( id, title ); todos.model.edit(id, title);
} else { } else {
todos.model.remove( id ); todos.model.remove(id);
} }
refreshAll(); refreshAll();
} }
...@@ -88,74 +92,84 @@ var todos = todos || {}; ...@@ -88,74 +92,84 @@ var todos = todos || {};
// event handlers // event handlers
todos.actions = { todos.actions = {
add_blur: function( e ) { addBlur: function () {
add( this ); add(this);
}, },
add_keypress: function( e ) { add_keypress: function (e) {
if ( e.keyCode === ENTER_KEY ) { if (e.keyCode === ENTER_KEY) {
add( this ); add(this);
} }
}, },
edit_blur: function( id ) { edit_blur: function (id) {
// create a closure around the ID // create a closure around the ID
return function( e ) { return function () {
edit( this, id ); edit(this, id);
}; };
}, },
edit_keypress: function( id ) { edit_keypress: function () {
// create a closure around the ID // create a closure around the ID
return function(e) { return function (e) {
if ( e.keyCode === ENTER_KEY ) { if (e.keyCode === ENTER_KEY) {
// just blur so doesn't get triggered twice // just blur so doesn't get triggered twice
this.blur(); this.blur();
} }
}; };
}, },
remove_click: function( id ) { remove_click: function (id) {
// create a closure around the ID // create a closure around the ID
return function( e ) { return function () {
todos.model.remove( id ); todos.model.remove(id);
refreshAll(); refreshAll();
}; };
}, },
clear_click: function() { clear_click: function () {
todos.model.expunge(); todos.model.expunge();
refreshAll(); refreshAll();
}, },
content_dblclick: function( id ) { content_dblclick: function () {
// create a closure around the ID // create a closure around the ID
return function( e ) { var toggleEditingMode = function (li) {
var li = this; if (li.tagName !== 'LI') {
return toggleEditingMode(li.parentNode);
}
li.className = EDITING_CSS; li.className = EDITING_CSS;
li.getElementsByTagName( 'input' )[1].focus();
var input = li.getElementsByTagName('input')[1];
input.focus();
input.value = input.value;
};
return function () {
toggleEditingMode(this);
}; };
}, },
completed_change: function( id ) { completed_change: function (id) {
// create a closure around the ID // create a closure around the ID
return function( e ) { return function () {
var checkbox = this; var checkbox = this;
todos.model.toggle( id, checkbox.checked ); todos.model.toggle(id, checkbox.checked);
refreshAll(); refreshAll();
}; };
}, },
toggle_change: function( e ) { toggle_change: function () {
var checkbox = this; var checkbox = this;
todos.model.toggleAll( checkbox.checked ); todos.model.toggleAll(checkbox.checked);
refreshAll(); refreshAll();
} }
}; };
/*-- init task list -------------------------------*/ /*-- init task list -------------------------------*/
(function( body ) { (function (body) {
// build out task list // build out task list
var view = todos.views.TodoApp({ var view = todos.views.TodoApp({
tasks: todos.model.tasks(), tasks: todos.model.tasks(),
...@@ -163,7 +177,7 @@ var todos = todos || {}; ...@@ -163,7 +177,7 @@ var todos = todos || {};
}).toDOM(); }).toDOM();
// insert at top // insert at top
body.insertBefore( view, body.firstChild ); body.insertBefore(view, body.firstChild);
})( document.body ); })(document.body);
})( todos, document ); })(todos, window.document);
/*global window */
var todos = todos || {}; var todos = todos || {};
(function( todos, localStorage, KEY ) { (function (todos, localStorage, KEY) {
'use strict';
/*-- private members -------------------------------*/ /*-- private members -------------------------------*/
...@@ -8,22 +11,22 @@ var todos = todos || {}; ...@@ -8,22 +11,22 @@ var todos = todos || {};
// model uses localStorage as the underlying data store // model uses localStorage as the underlying data store
// this creates a poor man's localStorage polyfill // this creates a poor man's localStorage polyfill
localStorage = localStorage || (function() { localStorage = localStorage || (function () {
var storage = {}; var storage = {};
return { return {
getItem: function( key ) { getItem: function (key) {
return storage[ key ]; return storage[key];
}, },
setItem: function( key, value ) { setItem: function (key, value) {
storage[ key ] = value; storage[key] = value;
} }
}; };
})(); })();
function create( title, completed ) { function create(title, completed) {
return { return {
// fast, compact, non-repeating, unique ID: e.g., 'c2wwu0vz.pz4zpvi' // fast, compact, non-repeating, unique ID: e.g., 'c2wwu0vz.pz4zpvi'
id: (new Date().getTime() + Math.random()).toString( 36 ), id: (new Date().getTime() + Math.random()).toString(36),
title: title, title: title,
completed: !!completed completed: !!completed
}; };
...@@ -31,16 +34,15 @@ var todos = todos || {}; ...@@ -31,16 +34,15 @@ var todos = todos || {};
function save() { function save() {
// if doesn't support JSON then will be directly stored in polyfill // if doesn't support JSON then will be directly stored in polyfill
var value = typeof JSON !== 'undefined' ? JSON.stringify( tasks ) : tasks; var value = typeof JSON !== 'undefined' ? JSON.stringify(tasks) : tasks;
localStorage.setItem( KEY, value ); localStorage.setItem(KEY, value);
} }
// initialize storage // initialize storage
var value = localStorage.getItem( KEY ); var value = localStorage.getItem(KEY);
if ( value ) { if (value) {
// if doesn't support JSON then will be directly stored in polyfill // if doesn't support JSON then will be directly stored in polyfill
tasks = typeof JSON !== 'undefined' ? JSON.parse( value ) : value; tasks = typeof JSON !== 'undefined' ? JSON.parse(value) : value;
} else { } else {
tasks = []; tasks = [];
} }
...@@ -48,90 +50,77 @@ var todos = todos || {}; ...@@ -48,90 +50,77 @@ var todos = todos || {};
/*-- export public interface -------------------------------*/ /*-- export public interface -------------------------------*/
todos.model = { todos.model = {
tasks: function () {
tasks: function() {
return tasks; return tasks;
}, },
stats: function() { stats: function () {
var stats = { var stats = {};
total: tasks.length,
active: tasks.length,
completed: 0
};
var i = tasks.length; stats.total = tasks.length;
while ( i-- ) {
if ( tasks[i].completed ) { stats.completed = tasks.filter(function (task) {
stats.completed++; return task.completed;
} }).length;
}
stats.active -= stats.completed; stats.active = stats.total - stats.completed;
return stats; return stats;
}, },
add: function( title ) { add: function (title) {
var task = create( title, false ); var task = create(title, false);
tasks.push( task ); tasks.push(task);
save(); save();
return task; return task;
}, },
edit: function( id, title ) { edit: function (id, title) {
var i = tasks.length; tasks.filter(function (task) {
while ( i-- ) { return task.id === id;
if ( tasks[i].id === id ) { })[0].title = title;
tasks[i].title = title;
save(); save();
return;
}
}
}, },
// toggle completion of task // toggle completion of task
toggle: function( id, completed ) { toggle: function (id, completed) {
var i = tasks.length; tasks.filter(function (task) {
while ( i-- ) { return task.id === id;
if ( tasks[i].id === id ) { })[0].completed = completed;
tasks[i].completed = completed;
save(); save();
return;
}
}
}, },
// toggle completion of all tasks // toggle completion of all tasks
toggleAll: function( completed ) { toggleAll: function (completed) {
var i = tasks.length; tasks.forEach(function (task) {
while ( i-- ) { task.completed = completed;
tasks[i].completed = completed; });
}
save(); save();
}, },
remove: function( id ) { remove: function (id) {
var i = tasks.length; tasks.forEach(function (task, index) {
while ( i-- ) { if (task.id === id) {
if ( tasks[i].id === id ) { tasks.splice(index, 1);
tasks.splice( i, 1 );
save();
return;
}
} }
});
save();
}, },
expunge: function() { expunge: function () {
var i = tasks.length; tasks.forEach(function (task, index) {
while ( i-- ) { if (task.completed) {
if ( tasks[i].completed ) { tasks.splice(index, 1);
tasks.splice( i, 1 );
}
} }
});
save(); save();
} }
}; };
})(todos, window.localStorage, 'todos-duel');
})( todos, window.localStorage, 'todos-duel' );
...@@ -12,7 +12,7 @@ ...@@ -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>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> <p>Part of <a href="http://todomvc.com">TodoMVC</a></p>
</footer> </footer>
<script src="./cdn/cb86ce6c04dc2c3e1a7111b0000b1252c883d20c.js"></script> <script src="./cdn/4340176df828f72a94b201a48c223860b95908dc.js"></script>
</body> </body>
</html> </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