function Task(name) { this.name = ko.observable(name); } var viewModel = { tasks: ko.observableArray([ new Task("Get dog food"), new Task("Mow lawn"), new Task("Fix car"), new Task("Fix fence"), new Task("Walk dog"), new Task("Read book") ]), selectedTask: ko.observable(), selectTask: function(task) { this.selectedTask(task); }, addTask: function() { var task = new Task("new"); this.selectedTask(task); this.tasks.push(task); } }; //connect items with observableArrays ko.bindingHandlers.sortableList = { init: function(element, valueAccessor) { var list = valueAccessor(); $(element).sortable({ update: function(event, ui) { //retrieve our actual data item var item = ui.item.tmplItem().data; //figure out its new position var position = ko.utils.arrayIndexOf(ui.item.parent().children(), ui.item[0]); //remove the item and add it back in the right spot if (position >= 0) { list.remove(item); list.splice(position, 0, item); } ui.item.remove(); } }); } }; //control visibility, give element focus, and select the contents (in order) ko.bindingHandlers.visibleAndSelect = { update: function(element, valueAccessor) { ko.bindingHandlers.visible.update(element, valueAccessor); if (valueAccessor()) { setTimeout(function() { $(element).focus().select(); }, 0); //new tasks are not in DOM yet } } } ko.applyBindings(viewModel);
<div id="main"> <h2>Tasks</h2> <div class="container" data-bind="template: { name: 'taskTmpl', foreach: tasks}, sortableList: tasks"></div> <a href="#" data-bind="click: addTask">Add Task</a> <script id="taskTmpl" type="text/html"> <div class="item"> <a href="#" data-bind="text: name, click: function() { viewModel.selectTask($data); }, visible: $data !== viewModel.selectedTask()"></a> <input data-bind="value: name, visibleAndSelect: $data === viewModel.selectedTask(), event: { blur: function() { viewModel.selectTask(''); } }" /> </div> </script> </div> <div id="results"> <h2>Tasks</h2> <ul data-bind="template: { name: 'resultTmpl', foreach: tasks }"></ul> </div> <script id="resultTmpl" type="text/html"> <li data-bind="text: name"></li> </script>
body { font-family: arial; } h2 { font-weight: bold; } div { padding: 5px; margin: 5px; border: black 1px solid; } p, a { font-size: .8em; } ul { padding-bottom: 10px; } li { padding: 2px; } .container { width: 125px; min-height: 50px; background-color: #AAA;} .item { background-color: #DDD; cursor: move; } .item input { width: 100px; } #main { float: left; } #results { margin-left: 175px; width: 150px; }