From 5e91d4dc85c39c672386c378f00db5ec50fc742e Mon Sep 17 00:00:00 2001 From: foxdonut Date: Thu, 5 May 2016 17:32:19 -0400 Subject: [PATCH] Working on TodoMVC examples. --- todomvc/common/actions.js | 16 +++++++++ todomvc/common/model.js | 2 +- todomvc/common/receiveUpdate.js | 15 +++++++++ todomvc/common/store.js | 58 +++++++++++++++++++++++++++++++-- todomvc/vanillajs/main.js | 11 ++++--- todomvc/vanillajs/ready.js | 27 +++++++++++++++ todomvc/vanillajs/view.js | 31 ++++++++++++------ 7 files changed, 143 insertions(+), 17 deletions(-) diff --git a/todomvc/common/actions.js b/todomvc/common/actions.js index e69de29b..a4d7d595 100644 --- a/todomvc/common/actions.js +++ b/todomvc/common/actions.js @@ -0,0 +1,16 @@ +/*global window*/ +(function(ref) { + ref.actions = function(sendUpdate) { + return { + saveTodo: function(todo) { + sendUpdate({ saveTodo: { title: todo } }); + }, + deleteTodoId: function(todoId) { + sendUpdate({ deleteTodoId: todoId }); + }, + setCompleted: function(todoId, completed) { + sendUpdate({ setCompleted: { id: todoId, completed: completed } }); + } + }; + }; +})(window); diff --git a/todomvc/common/model.js b/todomvc/common/model.js index 83bbd098..7b1e735f 100644 --- a/todomvc/common/model.js +++ b/todomvc/common/model.js @@ -1,4 +1,4 @@ /*global window*/ (function(ref) { - ref.initialModel = { todoItems: ref.todoStorage.load() }; + ref.initialModel = { todos: ref.todoStorage.loadAll() }; })(window); diff --git a/todomvc/common/receiveUpdate.js b/todomvc/common/receiveUpdate.js index e69de29b..964a2557 100644 --- a/todomvc/common/receiveUpdate.js +++ b/todomvc/common/receiveUpdate.js @@ -0,0 +1,15 @@ +/*global window*/ +(function(ref) { + ref.receiveUpdate = function(model, update) { + if (update.saveTodo) { + model.todos = window.todoStorage.saveTodo(update.saveTodo); + } + else if (update.deleteTodoId) { + model.todos = window.todoStorage.deleteTodoId(update.deleteTodoId); + } + else if (update.setCompleted) { + model.todos = window.todoStorage.setCompleted(update.setCompleted); + } + return model; + }; +})(window); diff --git a/todomvc/common/store.js b/todomvc/common/store.js index 011d4f2f..449661ec 100644 --- a/todomvc/common/store.js +++ b/todomvc/common/store.js @@ -1,13 +1,67 @@ (function(ref) { var STORAGE_KEY = "meiosis-todomvc"; + var nextId = 1; + + var findIndex = function(todos, todoId) { + var index = -1; + + for (var i = 0, t = todos.length; i < t; i++) { + if (todos[i].id === todoId) { + index = i; + break; + } + } + return index; + }; + + var replaceTodoAtIndex = function(todos, todo, index) { + return todos.slice(0, index).concat([todo]).concat(todos.slice(index + 1)); + }; + + var deleteTodoAtIndex = function(todos, index) { + return todos.slice(0, index).concat(todos.slice(index + 1)); + }; ref.todoStorage = { - load: function () { + loadAll: function() { return JSON.parse(localStorage.getItem(STORAGE_KEY) || "[{\"id\":1,\"title\":\"meiosis\",\"completed\":false}]"); }, - save: function (todos) { + saveTodo: function(todo) { + var todos = ref.todoStorage.loadAll(); + + if (parseInt(todo.id, 10) > 0) { + todos = replaceTodoAtIndex(todos, todo, findIndex(todos, todo.id)); + } + else { + todo.id = nextId++; + todos = todos.concat([todo]); + } localStorage.setItem(STORAGE_KEY, JSON.stringify(todos)); + + return todos; + }, + deleteTodoId: function(todoId) { + var todos = ref.todoStorage.loadAll(); + var index = findIndex(todos, todoId); + + if (index >= 0) { + todos = deleteTodoAtIndex(todos, index); + localStorage.setItem(STORAGE_KEY, JSON.stringify(todos)); + } + return todos; + }, + setCompleted: function(updatedTodo) { + var todos = ref.todoStorage.loadAll(); + var index = findIndex(todos, updatedTodo.id); + + if (index >= 0) { + var todo = todos[index]; + todo.completed = updatedTodo.completed; + todos = replaceTodoAtIndex(todos, todo, index); + localStorage.setItem(STORAGE_KEY, JSON.stringify(todos)); + } + return todos; } }; })(window); diff --git a/todomvc/vanillajs/main.js b/todomvc/vanillajs/main.js index 4070128f..631c0e7a 100644 --- a/todomvc/vanillajs/main.js +++ b/todomvc/vanillajs/main.js @@ -1,13 +1,16 @@ /*global meiosis, meiosisVanillaJs, window*/ -(function() { +(function(ref) { var Meiosis = meiosis(meiosisVanillaJs.intoSelector("body")); var createComponent = Meiosis.createComponent; var Main = createComponent({ - initialModel: window.initialModel, - view: window.view + initialModel: ref.initialModel, + view: ref.view, + actions: ref.actions, + ready: ref.ready, + receiveUpdate: ref.receiveUpdate }); Meiosis.run(Main); -})(); +})(window); diff --git a/todomvc/vanillajs/ready.js b/todomvc/vanillajs/ready.js index e69de29b..005b4fb9 100644 --- a/todomvc/vanillajs/ready.js +++ b/todomvc/vanillajs/ready.js @@ -0,0 +1,27 @@ +/*global meiosisVanillaJs, window*/ +(function(ref) { + var ENTER_KEY = 13; + var ESCAPE_KEY = 27; + + ref.ready = function(actions) { + meiosisVanillaJs.delegate(document.body, "input.new-todo", "keypress", function(evt) { + if (evt.keyCode === ENTER_KEY) { + actions.saveTodo(evt.target.value); + } + else if (evt.keyCode === ESCAPE_KEY) { + // TODO + } + }); + + meiosisVanillaJs.delegate(document.body, "input.toggle", "change", function(evt) { + var todoId = parseInt(evt.target.dataset.id, 10); + var completed = evt.target.checked; + actions.setCompleted(todoId, completed); + }); + + meiosisVanillaJs.delegate(document.body, "button.destroy", "click", function(evt) { + var todoId = parseInt(evt.target.dataset.id, 10); + actions.deleteTodoId(todoId); + }); + }; +})(window); diff --git a/todomvc/vanillajs/view.js b/todomvc/vanillajs/view.js index 7d390325..31f519dd 100644 --- a/todomvc/vanillajs/view.js +++ b/todomvc/vanillajs/view.js @@ -7,30 +7,41 @@ }; var main = function(model, _actions) { - var todoItems = (model.todoItems || []).map(todoItem).join(""); + // FIXME + var renderedTodos = (model.todos || []).map(renderTodo).join(""); return "
" + " " + " " + " " + "
"; }; - var todoItem = function(todoItem) { - return "
  • " + + var renderTodo = function(todo) { + var completed = todo.completed ? " class='completed'" : ""; + var checked = todo.completed ? " checked" : ""; + + return "" + "
    " + - "" + - "" + - "" + + "" + + "" + + "" + "
    " + "
  • "; }; - var footer = function(model, _actions) { + var footer = function(model) { + // FIXME + var todos = (model.todos || []); + var notCompleted = function(todo) { return !todo.completed; }; + var itemsLeft = todos.filter(notCompleted).length; + var itemsLeftText = todos.length > 0 ? + (String(itemsLeft) + " item" + (itemsLeft === 1 ? "" : "s") + " left") : ""; + return "