Bind: Todo MVC App

Compare with other implementations of MVC Apps out there.

by Andres Rodriguez

HTML

<script src="https://localhost:63342/bind/lib/bind.js"></script>
<h2>Todos</h2>
<div>
  <span><i>REMAINING</i> of <i>COUNT</i> remaining</span>
  [ <a href="javascript:void(0)" onclick="archive()">archive</a> ]
  <ul>
    <li>
      <input name="done" type="checkbox"/>
      <span class="CLASS">TEXT</span>
    </li>
  </ul>
  <form onsubmit="addTodo(this); return false;">
    <input name="todoText" type="text" size="30" placeholder="add new todo here"/>
    <input type="button" value="add" onclick="addTodo(this.form)"/>
  </form>
</div>

CSS

.done {
    text-decoration: line-through;
    color: grey;
}

JavaScript

// Model for todos
var todos = [
    { text: "learn bind", done: true },
    { text: "build a bind app", done: false }
];

// Adding a todo is equivalent to pushing an element into the array
function addTodo(form) {
    todos.push( { text: form.todoText.value, done:false } );
    form.todoText.value = "";
}

// Function returns the number of remaining todos
function remaining() {
    var count = 0;
    todos.forEach(function(todo) { count += (todo.done ? 0 : 1); });
    return count;
}

// Archive Todos
function archive() {
    for (var i = 0; i < todos.length; i++) {
        if (todos[i].done) todos.splice(i--, 1);
    }
}

// Brains of the mapping using BindJS
function mapper(todos) {
    return {
        "i:nth-of-type(1)": remaining,
        "i:nth-of-type(2)": todos.length,
        "li": todos.map(function(t, i) {
            return {
                "&model": t,
                "@index": i,
                "input@checked": (t.done ? "checked" : bind.NO),
                "span": t.text,
                "span@class": (t.done ? "done" : "")
            };
        })
    };
}

// Bind
var view = document.querySelector("div");
bind(view, todos, mapper);