Basic Todolist Uncommented

An example of using falcon with a basic, single view, todo list

by stoodder

HTML

<script src="http://code.jquery.com/jquery-1.10.2.min.js"></script>
<script src="http://knockoutjs.com/downloads/knockout-3.0.0.js"></script>
<script src="http://stoodder.github.io/falconjs/scripts/falcon.min.js"></script>
<div id="application"></div>
<template id="todo_list_tmpl">
    <!-- ko if: $view.is_editting_title -->
        <input type="text" data-bind="value: $view.title" />
        <button data-bind="click: $view.saveTitle">Save</button>
    <!-- /ko -->
    <!-- ko ifnot: $view.is_editting_title -->
	    <h3>
            <!-- ko text: $view.title --><!-- /ko -->
	        <a data-bind="click: $view.editTitle">Edit</a>
	    </h3>
    <!-- /ko -->
    <ul class="todo-list" data-bind="foreach: $view.todos">
        <li data-bind="css: {'completed': is_complete}">
            <!-- ko text: text --><!-- /ko -->
            <a data-bind="click: $view.completeTodo">[Complete]</a>
            <a data-bind="click: $view.removeTodo">[X]</a>
        </li>
    </ul>
    <input type="text" data-bind="value: $view.new_todo_text" />
    <button data-bind="click: $view.addTodo">Add</button>
</template>

CSS

a {
    cursor: pointer;
    color: navy;
}

.todo-list {
    padding: 0px;
    margin: 0px;
    list-style: none;
}

.todo-list li.completed {
    color: grey;
    text-decoration: line-through;
}

JavaScript

var Todo = Falcon.Model.extend({
    url: 'todo',

    observables: {
        'text': '',
        'is_complete': ''
    }
});

var Todos = Falcon.Collection.extend({
    model: Todo
});

var TodoListView = Falcon.View.extend({
    url: '#todo_list_tmpl',
    
    defaults: {
        'todos': function() { return new Todos; }
    },
    
    observables: {
        'title': 'Untitled List',
        'is_editting_title': false,
        'new_todo_text': ''
    },
    
    initialize: function(){},

    addTodo: function()
    {
        var todo = new Todo({ text: this.new_todo_text() });
        
        // Append the todo to the end of the colleciton. Note: We didn't need 
        // to define a new Todo model, rather we could have instead passed in 
        // the todo model's data and the collection would have created the todo 
        // for us.
        this.todos.append( todo );
        
        // Reset the todo text.
        this.new_todo_text('');
    },
    
    // Method used to remove a specific todo. Because this will be bound by knockout's 
    // 'click' binding, the specific todo is passed in as the first argument for us.
    removeTodo: function(todo)
    {
        this.todos.remove( todo );
    },
    
    // Method used to mark a todo as complete
    completeTodo: function(todo)
    {
        // The set method is used on this model to set the value of 'is_complete'. 
        // This is useful in the scenario that we might not know if the is_complete 
        // member is an observable or a primitive value.  In this instance calling 
        // todo.is_complete( true ) would yield the same result.
        todo.set('is_complete', true);
    },
    
    // Method used to start editting the list title
    editTitle: function()
    {
        this.is_editting_title( true );
    },
    
    // Method used to 'save' the list's title
    saveTitle: function()
    {
        this.is_editting_title( false );
    }
});

//Initialize our app and the initial...