Draggable, droppable, and sortable list
http://www.knockmeout.net/2011/05/dragging-dropping-and-sorting-with.html
by Sameer Shemna
HTML
<script src="http://knockoutjs.com/downloads/knockout-2.2.1.debug.js"></script>
<script src="http://cdnjs.cloudflare.com/ajax/libs/knockout-sortable/0.8.1/knockout-sortable.min.js"></script>
<h2>Multi-select sortable with Knockout.js</h2>
<p><code>Click</code> to select individual items</p>
<p><code>Ctrl + Click</code> to select multiple items</p>
<div class="list">
<h2>Stored procedures In DB 1</h2>
<ul class="list" id="sortableForDB_1" data-bind="sortable: { data: storedProceduresInDB1, beforeMove: checkAndCopy, options: multiSortableOptions }">
<li class="item" data-bind="attr: { id: 'sp_'+Id }, text: Name, click: $root.selectProcedure.bind($data, $parent.storedProceduresInDB1()), css: { selected: Selected }"></li>
</ul>
</div><br>
<div class="list">
<h2>Stored procedures In DB 2</h2>
<ul class="list" id="sortableForDB_2" data-bind="sortable: { data: storedProceduresInDB2, beforeMove: checkAndCopy, options: multiSortableOptions }">
<li class="item" data-bind="attr: { id: 'sp_'+Id }, text: Name, click: $root.selectProcedure.bind($data, $parent.storedProceduresInDB2()), css: { selected: Selected }"></li>
</ul>
</div>
CSS
h2 {
font-weight: bold;
}
div, li {
padding: 5px;
margin: 5px 0;
border: black 1px solid;
}
.helper {
padding:0;
margin:0;
border:0;
}
ul {
padding-bottom: 10px;
}
.item {
background-color: #DDD;
cursor: default;
}
.item.selected {
background-color:#FED;
cursor: move;
}
body {
font-family: arial;
font-size: 14px;
}
.list {
padding: 1em;
background-color: #EEEEDD;
border: 1px solid #CCC;
max-width: 600px;
}
.list input {
font-family: Arial;
}
.list b {
font-weight: bold;
}
.list p {
margin-top: 0.9em;
margin-bottom: 0.9em;
}
.list-select {
width: 100%;
height: 8em;
}
.list h2 {
margin-top: 0.4em;
}
p, a {
font-size: .8em;
}
.trash { background-color: #000; }
JavaScript
var multiSortableOptions = {
delay: 150,
revert: 0,
stop: function(event, ui) {
// Force lists to refresh all items
var db1 = myViewModel.storedProceduresInDB1,
db2 = myViewModel.storedProceduresInDB2,
temp1 = db1(),
temp2 = db2();
ui.item.remove();
db1([]);
db1(temp1);
db2([]);
db2(temp2);
},
helper: function(event, $item) {
// probably a better way to pass these around than in id attributes, but it works
var dbId = $item.parent().attr('id').split('_')[1],
itemId = $item.attr('id').split('_')[1],
db = myViewModel['storedProceduresInDB'+dbId];
// If you grab an unhighlighted item to drag, then deselect (unhighlight) everything else
if(!$item.hasClass('selected')) {
ko.utils.arrayForEach(db(), function(item) {
if(item.Id == itemId) {
item.Selected(true);
} else {
item.Selected(false);
}
});
}
// Create a helper object with all currently selected items
var $selected = $item.parent().find('.selected');
var $helper = $('<li class="helper"/>');
$helper.append($selected.clone());
$selected.not($item).remove();
return $helper;
}
};
var ViewModel = function () {
var self = this;
self.storedProceduresInDB1 = ko.observableArray([
{ Name: 'SP1', Id: 1, Selected: ko.observable(false) },
{ Name: 'SP2', Id: 2, Selected: ko.observable(false) },
{ Name: 'SP3', Id: 3, Selected: ko.observable(false) }
]);
self.storedProceduresInDB2 = ko.observableArray([
{ Name: 'SP3', Id: 3, Selected: ko.observable(false) },
{ Name: 'SP4', Id: 4, Selected: ko.observable(false) },
{ Name: 'SP5', Id: 5, Selected: ko.observable(false) }
]);
self.checkAndCopy = function(event)...