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...