Knockout-js-todo-list-sortable-2

We are going to do the search filter and sorting function.

TodoListApp

Step1 – Sort function

We want to allow users can sort todo items. We are going to use knockout-sortable.js plug-in. It help us to accomplish this function.

index.html:

It is to bind “sortable: {data: todos()}” in ul element in to-do control.

PS : don’t forget to include knockout-sortable plug-in in index.html.

<div class="form-group"  >
    <ul id="todo-list" data-bind="sortable: {data: todos()}">
        <li data-bind="css: { completed: completed, editing: editing }">
            <div class="view">
                <input class="todoCheckbox" data-bind="checked: completed" type="checkbox" >
                <label data-bind="text: title, event: { dblclick: $root.editItem }, css: {textDecoration:completed()==true}" ></label>
                <button class="close pull-right" data-bind="click: $root.remove">&times;</button>
            </div>
            <input class="edit" data-bind="value: title, valueUpdate: 'afterkeydown', enterKey: $root.saveEditing, escapeKey: $root.cancelEditing, selectAndFocus: editing, event: { blur: $root.saveEditing }">
        </li>
    </ul>
</div>

plugin in index.html :

<script type="text/javascript" src="js/libs/knockout-sortable.js"></script>

Step2 – Search and Filter function

Interface

![TodoListApp](/images/knockoutjs_2_1.png)

Search function: user can find to-do item by using key words
Filter function: It filtter to-do item by todo status(active and completed). We will use another plug-in - router.js so as to filter to-do items.

index.html:

plugin in index.html :

<script type="text/javascript" src="js/libs/director.js"></script>

Search & Sorting control:

    <div class="row" data-bind="visible: completedCount() || remainingCount()" style="   margin-top: 8px;">
        <div class="col-xs-5" style="padding-left: 0px;">
            <div class="input-group">
                <span class="input-group-btn">
                <button class="btn btn-default" type="button"><span class="glyphicon glyphicon-search"></span></button>
            </span>
            <input type="search" class="form-control" placeholder="Search"  data-bind="textInput: query" autocomplete="off">
        </div>
    </div>

    <div class="col-xs-3 ">
        <ul class="nav nav-pills" id="filters">
            <li data-bind="css: { active: isActive('all') }">
                <a data-bind="css: { selected: showMode() == 'all' }" href="#/all">All</a>
            </li>
            <li  data-bind="css: { active: isActive('active') }">
                <a data-bind="css: { selected: showMode() == 'active' }" href="#/active">Active</a>
            </li>
            <li  data-bind="css: { active: isActive('completed') }">
                <a data-bind="css: { selected: showMode() == 'completed' }" href="#/completed">Completed</a>
            </li>
        </ul>
    </div>
    <div class="col-xs-2" style="   margin-top: 8px;">
        <span id="todo-count">
            <strong data-bind="text: remainingCount">0</strong>
            <span data-bind="text: getLabel(remainingCount)"></span> left
        </span>
    </div>

</div>

To-do control:

I achieve search and filter function by css attribute. If to-do item does not meet condition, it will be hided.

It is to bind $root.filteredTodos($data) in li element so as to check whether todo meet condition in filteredTodos function.

<div class="form-group"  >
    <ul id="todo-list" data-bind="sortable: {data: todos()}">
        <li data-bind="css: { completed: completed, editing: editing },visible: $root.filteredTodos($data)">
            <div class="view">
                <input class="todoCheckbox" data-bind="checked: completed" type="checkbox" >
                <label data-bind="text: title, event: { dblclick: $root.editItem }, css: {textDecoration:completed()==true}" ></label>
                <button class="close pull-right" data-bind="click: $root.remove">&times;</button>
            </div>
            <input class="edit" data-bind="value: title, valueUpdate: 'afterkeydown', enterKey: $root.saveEditing, escapeKey: $root.cancelEditing, selectAndFocus: editing, event: { blur: $root.saveEditing }">
        </li>
    </ul>
</div>

App.js:

There are two steps in filteredTodos function.

The first step is achieve the filter function.

The Second step is achieve the search function.

this.filteredTodos = function(todo) {
    var result = true;
        switch(this.showMode()){
      case 'active':
        if(todo.completed() != false)
            result = false;
        break;
        case 'completed':
         if(todo.completed() != true)
             result = false
       break;
        }
    if(result){
        var filter = this.query().toLowerCase();
        if(!filter){
            return true;
        }
        else{
          return todo.title().toLowerCase().indexOf(filter) !== -1;
        }
    }else
    {
        return false;
    }
};

In this step, It is to get filter argument by URL(Router).

Router({'/:filter': viewModel.showMode}).init();

When you finish , you can see the TodoApp as below .

PS: I have added some functions in demo. I hope you can study these but I will not explain how to made.

TodoListApp
The complete working demo can be found here .

##Building a Todo app with Knockout.js (1) - A simple todo list

##Building a Todo app with Knockout.js (2) - Filter、Search and Sortable function