JSFiddle - React, Tailwind, and code Playground

by bizamajig

HTML

<script src="http://ajax.aspnetcdn.com/ajax/knockout/knockout-2.2.1.js"></script>
<button data-bind="click: addItem">Add item</button>

<p>2 lists of sortable items. 2 lists to show orders updates to the model</p>
<ul class="items" data-bind="foreach: items, jquerysortable: items">
    <li data-bind="text: $data"></li>
</ul>

<ul class="items" data-bind="foreach: moreitems, jquerysortable: moreitems">
    <li data-bind="text: $data"></li>
</ul>

<ul data-bind="foreach: items">
    <li data-bind="text: $data"></li>
</ul>

<ul data-bind="foreach: moreitems">
    <li data-bind="text: $data"></li>
</ul>

CSS

ul{
    float:left;
    width:100px;
    display:block;
    color:gray;
}

ul.items{ color: black; cursor: move;}

JavaScript

ko.bindingHandlers.jquerysortable = {
    init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
        var currentObservableArray = valueAccessor();
        
        // Add the current observableArray to the elements data dictionary
        // we will need this when moving an item from one sortable to another
        $(element).data("ko.source.observablearray", currentObservableArray);
        
        // When we recieve an item from another sortable, we have already added it
        // to the new array, so we just need to remove it from the old array
        $(element).on("sortreceive", function( event, ui ) {
             var sourceObservableArray = ui.sender.data("ko.source.observablearray");
             var item = ko.dataFor(ui.item[0]);
             sourceObservableArray.remove(item);
        });
        
        // This event fires after a sort and before a recieve. 
        // If this is a recieve, the remove item call will not remove anything
        // but we will splice the item into the current observableArray
        $(element).on("sortupdate", function( event, ui ) {
            var item = ko.dataFor(ui.item[0]);
            var newIndex = $(element).children().index(ui.item);
            // newIndex is -1 when we have moved an item out of a sortable into another
            if(newIndex > -1){
                currentObservableArray.remove(item);
                currentObservableArray.splice(newIndex, 0, item);
                ui.item.remove();
            }
        });
    }
};

var SimpleListModel = function(items, moreitems) {
    this.items = ko.observableArray(items);
    this.moreitems = ko.observableArray(moreitems);
    var newItemCount = 1;
    this.addItem = function() {
        this.items.push("NewItem " + newItemCount++);
    }.bind(this);
};
 
ko.applyBindings(new SimpleListModel(["Alpha", "Beta", "Gamma"], ["Delta", "Echo", "Charlie"]));

$(".items").sortable({connectWith:'.items'})