Part Ext : How to create sortable lists using Knockout JS
by corinnekm
HTML
<script src="http://cloud.github.com/downloads/SteveSanderson/knockout/knockout-2.1.0.debug.js"></script>
<table class="fruitGrid">
<thead>
<tr>
<th class="headRow headColumn">
Fruit Name
</th>
<th class="headRow headColumn">
Fruit Colour
</th>
<th class="headRow tools">
</th>
</tr>
</thead>
<tbody data-bind="foreach: fruits, sortable: fruits">
<tr class="row">
<td class="rowItem">
<label class="read" data-bind="text: name" />
</td>
<td class="rowItem">
<label class="read" data-bind="text: colour" />
</td>
</tr>
</tbody>
</table>
CSS
/* Grid */
.fruitGrid {
/* structure */
width: 500px;
padding: 5px;
}
.fruitGrid .headColumn {
/* structure */
padding: 10px;
/* skin */
color: White;
background-color: #888;
}
.fruitGrid .row:nth-child(even) {
/* skin */
background-color:#eee;
}
.fruitGrid .rowItem {
/* structure */
padding: 10px;
}
.fruitGrid .rowItem .read {
/* structure */
display: block;
width: 150px;
}
JavaScript
/*----------------------------------------------------------------------*/
/* Extended KO Bindings */
/*----------------------------------------------------------------------*/
ko.bindingHandlers.sortable = {
init: function (element, valueAccessor) {
// cached vars for sorting events
var startIndex = -1,
koArray = valueAccessor();
var sortableSetup = {
// cache the item index when the dragging starts
start: function (event, ui) {
startIndex = ui.item.index();
// set the height of the placeholder when sorting
ui.placeholder.height(ui.item.height());
},
// capture the item index at end of the dragging
// then move the item
stop: function (event, ui) {
// get the new location item index
var newIndex = ui.item.index();
if (startIndex > -1) {
// get the item to be moved
var item = koArray()[startIndex];
// remove the item
koArray.remove(item);
// insert the item back in to the list
koArray.splice(newIndex, 0, item);
// ko rebinds the array so remove duplicate ui item
ui.item.remove();
}
},
placeholder: 'fruitMoving'
};
// bind
$(element).sortable( sortableSetup );
}
};
/*----------------------------------------------------------------------*/
/* View Model
/*----------------------------------------------------------------------*/
function FruitColourViewModel() {
var self = this;
// data
self.availableColours = [];
self.fruits = ko.observableArray([]);
...