KO Sortable Binding v4 - Single array test

by whelkaholism

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout/3.3.0/knockout-min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/knockout.mapping/2.4.1/knockout.mapping.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.2/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.selection/1.0.1/jquery.selection.min.js"></script>
<link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons&amp;_.css">
<div data-bind="text: IsSortable() ? 'SORTABLE ON' : 'SORTING DISABLED'"></div>
<hr/>
<div class="lane" data-bind="sortable: IsSortable() ? {} : false, foreach: Items">
  <div class="vehicle"><i></i><span data-bind="text: ID"></span></div>
</div>
<xmp data-bind="click: purge, html: JSON.stringify(ko.toJS(Items()), null, '\t')"></xmp>

CSS

.lane {
    width: 60px;
    min-height: 60px;
    padding-right: 20px;
    float: left;
    border-right: 1px dotted #000000;
  }
  
  .vehicle {
    margin: 10px;
    width: 40px;
    height: 40px;
    color: #000000;
    cursor: pointer;
    border: 1px solid transparent;
  }
  
  .vehicle:hover {
    color: #00aa00;
    cursor: move;
  }
  
  .vehicle span {
    font-family: Arial;
    font-weight: bold;
    background: #000000;
    color: #ffffff;
    padding: 1px 3px;
    font-size: 10px;
  }
  
  .vehicle i:before {
    font-family: Material Icons;
    content: 'directions_car';
    width: 40px;
    height: 40px;
    font-size: 40px;
    font-style: normal;
  }
  
  .sortable-placeholder {
    border: 1px dotted black;
    margin: 10px;
    width: 40px;
    height: 40px;
    background: rgba(255, 255, 255, 0.5);
  }
  
  xmp {
    float: right;
    font-size: 10px;
    font-weight: bold;
    background: #ffffff;
    padding: 4px;
    margin-right: 50px;
  }

JavaScript

var __i = 0;

function Model(data, mapping)
{
    var _this = this;
    var _vid = 7;
    
    this.IsSortable = ko.observable(true);

    this.Items = ko.observableArray();

    ko.mapping.fromJS({
        Items: [
                        { ID: 1 },
                        { ID: 2 },
                        { ID: 3 },
                        { ID: 4 },
                        { ID: 5 },
                        { ID: 6 }
            ]
        },
    {}, _this);

    this.purge = function()
    {
        _this.Items.valueHasMutated();
    };
}

ko.bindingHandlers.sortable = {
    update:
        function(el, f_valueaccessor, allbindings, viewmodel, bindingcontext) 
        {
            var val = ko.unwrap(f_valueaccessor());
            var obs = allbindings.get('foreach');

            var multicolumn = false;
            var placeholder = 'sortable-placeholder';
            var colsfield = null;
            var itemsfield = null;
            var sorted = null;

            var options = {};

            if (typeof (val) == 'object')
            {
                multicolumn = val.multiColumn;
                val.boundField && (obs = val.boundField);
                placeholder = typeof (val.placeholder) != 'undefined' ? val.placeholder : placeholder;
                options = val.options;
                colsfield = val.columnsField;
                itemsfield = val.itemsField;
                sorted = val.sorted;
                val = true;
            }

            obs && obs(); // Force KO to track this as a dependency
            var obscolumns = obs && colsfield ? obs()[colsfield] : obs;
            var target = multicolumn ? $(el).children().filter('*') : $(el);

            // 
            if (!!val)
            {
                var f_getupdatedcolumnitems = function(colidx, jqcol)
                {
                    var res = [];

                    jqcol.children().filter('*').each(
                        function(itemidx, itemel)
               ...