My Draggable, droppable, and sortable list

HTML

<script src="http://rniemeyer.github.com/KnockMeOut/Scripts/knockout-latest.debug.js"></script>
<script src="http://cloud.github.com/downloads/rniemeyer/knockout-sortable/knockout-sortable.js"></script>
<div id="main">
    <h2>Field Types</h2>
    <div class="container types" data-bind="template: { name: 'fieldTypeTmpl', foreach: Types }"></div>
</div>    

<div id="results">
    <h2>Table</h2>
    <input type="text" data-bind="value: table.Name" />
    <div class="container high" data-bind="sortable: { template: 'fieldTmpl', data: table.Fields, options: {update: onUpdate} }"></div>        
</div>

<br style="clear: both;" />

<div id="results">
    <h2>Table debug</h2>
    <ul data-bind="foreach: table.Fields">
        <li data-bind="text: Name"></li>
    </ul>
</div>

<button data-bind="click: function(data, event) {console.log(ko.toJS($root.table, null, 2))}">Save</button>

<pre data-bind="text: ko.toJSON($root.selectedField)"></pre>

    <!-- FIELD -->
    <script id="fieldTmpl" type="text/html">
        <div class="item">
            <div class="handler" data-bind="click: function() {$root.selectField('');}">
                <input data-bind="value: Name, click: function(e) {$root.selectField($data); e.stopPropagation(); }" />
                <a class="delete-field" data-bind="click: function(){$root.deleteField($data)}">x</a>
            </div>
            
            <div style="display:none;" class="body" data-bind="visible: $root.selectedField() === $data">todo: settings</div>
        </div>
        
    </script>

    <!-- FIELD TYPE -->
    <script id="fieldTypeTmpl" type="text/html">
        <div class="item" data-bind="drag: $data, dragOptions: {start: onDragStart, stop: onDragStop}">
            <span href="#" data-bind="text: TypeName"></span>
        </div>
    </script>

CSS

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; }
.container {  width: 225px; min-height: 50px; background-color: #AAA;}
.types{ background-color: orange; }
.trash { background-color: #000;  }
.item { background-color: #DDD; min-width: 100px; }
.handler{ background-color: orange; padding-left: 20px; cursor: move; }
.item input { width: 100px; }
.body { zdisplay:none; }
.delete-field {float: right; width: 20px; height: 20px; background: red; cursor: pointer; text-align: center; }
#main { float: left; }
#results { float: left; width: 250px; }

JavaScript

"use strict";
var dropFieldType = null;
function FieldType(typeName, name) {
    var self = this;
    self.TypeName = ko.observable(typeName || "");
    self.Name = ko.observable(name || this.TypeName());
    self.createField = function () {
        return new Field(
            {
                Name: this.Name(),
                TypeName: this.TypeName()
            }
        );
    }
    self.onDragStart = function(event, ui) {
        dropFieldType  = ko.utils.domData.get(this, "ko_drag_data");
    };
    self.onDragStop = function(event, ui) {
        dropFieldType = null;
    };
}

function Field(json) {
    this.Name = ko.observable(json.Name || "");
    this.TypeName = ko.observable(json.TypeName || "");
}

var vm = function () {
    var self = this;
    self.table = {
        Name: ko.observable(),
        Fields: ko.observableArray([
            /*new Field({Name: "text", Display: "Text", TypeName: "text"}),
            new Field({Name: "image", Display: "Image", TypeName: "image"}),
            new Field({Name: "number", Display: "Number", TypeName: "number"})*/
        ])       
    }

    self.Types = ko.observableArray([
        new FieldType("text"),
    ]);

    self.selectedField = ko.observable();
    self.selectField = function(field) {
        if(self.selectedField() !== field)
            self.selectedField(field);
    };
    
    self.deleteField = function(field) {
        self.table.Fields.remove(field);
    };
        
    self.onUpdate = function (event, ui) {
        if (dropFieldType) {
            var el = ui.item[0],
                field = dropFieldType.createField();
            var targetIndex = ko.utils.arrayIndexOf(ui.item.parent().children(), el);
            $(ui.item).remove();
            self.table.Fields.splice(targetIndex, 0, field);
            //self.selectField(field);
        }

    };
};

ko.bindingHandlers.drag = {
    init: function(element, valueAccessor, allBindingsAccessor) {
        //set meta-data
       ...