knockout-sortable - Asles Implementation with scenes

https://github.com/rniemeyer/knockout-sortable

by Asle Gundersby

HTML

<script src="http://knockoutjs.com/downloads/knockout-2.2.1.js"></script>
<script src="https://rawgithub.com/rniemeyer/knockout-sortable/master/build/knockout-sortable.js"></script>
<div id="extra">
     <h2>Text(s) available for allocation:</h2>

    <div class="new" data-bind="sortable: $root.allocationableTextbatches">
        <div class="student" data-bind="text: title"></div>
    </div>
</div>
<br />
<hr/>

<div id="list">
    <div id="listAccordion" class="accordionDefault" data-bind="visible: (!showEditor() && !listScenesInTable())">
        <div id="accordion" data-bind="jqAccordion: { },template: { name: 'scene-template', foreach: Scenes,  afterAdd: function(elem){$(elem).trigger('valueChanged');} }" class="group accordion ui-widget ui-helper-clearfix"></div>
    </div>
</div>
<!-------------------------------------------------------------- scene-template: begin --------------------------------------------------------->
<script type="text/html" id="scene-template">
    <div data-bind = "attr: {'id': 'scene' + sceneID}, click: $root.selectedScene" class="group ui-widget-content ui-corner-tr"> 
        <div class = "accordion-header ui-widget-header" > <!-- SCENE HEADER BEGINS -->
            <table class="myaccordion-header-table"> 
                <tbody> 
                    <tr><td class="left-upper header-detail"><label for="sequenceNo"> Seq: </label><span data-bind="text:sequenceNo"></span></td>
                        <td class="center" rowspan="2">
                            <h3><b><input name="title" data-bind="value: title, valueUpdate: 'afterkeydown'"/></b></h3>
                        </td>
                    </tr>
                    <tr>
                        <td class="left-bottom header-detail">Id: <span data-bind="text: sceneID"></span ></td>
                    </tr>
                </tbody>
            </table>
        </div> <!-- SCENE HEADER ENDS -->
        
		    <div class="accordion-content"> <!--  SCENE CONTENTS BEGINS -->
   ...

CSS

body {
    font-family: arial;
}
.table {
    float: left;
    text-align: center;
    margin-right: 5px;
}
.table span {
    font-size: .75em;
}
.seats {
    border: 3px solid #666;
    width: 277px;
    height: 215px;
    background-color: #777;
    margin: 1px 0px 3px 0px;
    padding: 1px;
    border-radius: 4px;
    box-shadow: 0px 0px 0px #999;
    overflow-y: auto;
}
.ko_container {
    border: 2px solid #ff8000
}
.student {
    background-color: #444;
    color: #fff;
    border-radius: 3px;
    margin: 2px;
    padding: 1px;
    text-align: center;
    width: 97.5%;
    cursor: move;
    height:20px;
}
.new {
    border: solid 1px #444;
    background-color: #ccc;
    height: 205px;
    width: 500px;
    padding: 2px;
    border-radius: 5px;
    overflow-y:auto;
}
.new div {
    float: left;
}
.note {
    font-style: italic;
    font-size: .75em;
    color: #888;
    margin-bottom: 10px;
}
.count {
    color: #666;
}
.ready {
    color: green;
}
#extra {
    clear: both;
    padding-top: 8px;
}
#master {
    margin-top: 40px;
}
#master td, th {
    font-size: .75em;
    text-align: center;
    padding: 1px;
    border: solid 1px black;
}
#master th {
    color: #666;
}
#message, #error {
    font-size: .75em;
    margin-top: 10px;
    background-color: orange;
    color: #444;
    padding: 2px;
    width: 500px;
    text-align: center;
    border-radius: 5px;
    box-shadow: 2px 2px 2px #999;
    position: absolute;
}
#error {
    background-color: #ff3333;
    color: #ddd;
}

JavaScript

ko.subscribable.fn.subscribeChanged = function (callback) {
    var oldValue;
    this.subscribe(function (_oldValue) {
        oldValue = _oldValue;
    }, this, 'beforeChange');

    this.subscribe(function (newValue) {
        callback(newValue, oldValue);
    });
};

ko.bindingHandlers.jqAccordion = {
    init: function (element, valueAccessor) {
        var options = valueAccessor();
        $(element).accordion(options);
        $(element).bind("valueChanged", function () {
            ko.bindingHandlers.jqAccordion.update(element, valueAccessor);
        });
    },
    update: function (element, valueAccessor) {
        var options = valueAccessor();

        $(element).accordion("destroy").accordion({
            header: ".accordion-header",
            collapsible: true,
            navigation: true,
            heightStyle: "content",
            active: false
        })
            .sortable({
                axis: "x,y",
                handle: ".accordion-header",
                placeholder: "ui-state-highlight",
                start: function (event, ui) {
                    //change bool to true
                    sorting = true;

                    //find what tab is open, false if none
                    active = $(this).accordion("option", "active");

                    //possibly change animation here (to make the animation instant if you like)
                    $(element).accordion("option", "animate", {
                        easing: 'swing',
                        duration: 0
                    });

                    //close tab
                    $(element).accordion({
                        active: false
                    });
                },
                over: function (event, ui) {
                    $(element).accordion({
                        active: false
                    });
                },
                stop: function (event, ui) {
                    //1st: Handle the visible impression during...