, . , knockout.js knockout-sortable.
JSFiddle ( Chrome): http://jsfiddle.net/QWgRF/715/
HTML
, jQuery , .
options, jQuery Sortable .
.
<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>
<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>
JavaScript
. 150, . 0, , .
stop observableArray, html.
helper -, .
var multiSortableOptions = {
delay: 150,
revert: 0,
stop: function(event, ui) {
var db1 = myViewModel.storedProceduresInDB1,
db2 = myViewModel.storedProceduresInDB2,
temp1 = db1(),
temp2 = db2();
ui.item.remove();
db1([]);
db1(temp1);
db2([]);
db2(temp2);
},
helper: function(event, $item) {
var dbId = $item.parent().attr('id').split('_')[1],
itemId = $item.attr('id').split('_')[1],
db = myViewModel['storedProceduresInDB'+dbId];
if(!$item.hasClass('selected')) {
ko.utils.arrayForEach(db(), function(item) {
if(item.Id == itemId) {
item.Selected(true);
} else {
item.Selected(false);
}
});
}
var $selected = $item.parent().find('.selected');
var $helper = $('<li class="helper"/>');
$helper.append($selected.clone());
$selected.not($item).remove();
return $helper;
}
};
. Selected . selectProcedure Selected ctrl + .
checkAndCopy. , , , .
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) {
var items;
if(event.targetParent !== event.sourceParent) {
items = ko.utils.arrayFilter(event.sourceParent(), function(item) {
return item.Selected() && !ko.utils.arrayFirst(event.targetParent(), function(targetItem) {
return targetItem.Id == item.Id;
});
});
items = ko.utils.arrayMap(items, function(item) {
var clone = ko.toJS(item);
clone.Selected = ko.observable(true);
item.Selected(false);
return clone;
});
ko.utils.arrayForEach(event.targetParent(), function(item) {
item.Selected(false);
});
} else {
items = event.sourceParent.remove(function(item) {
return item.Selected();
});
}
items = items.reverse();
for(var i=0; i<items.length; i++) {
event.targetParent.splice(event.targetIndex, 0, items[i]);
}
event.cancelDrop = true;
};
self.selectProcedure = function(array, $data, event) {
if(!event.ctrlKey && !event.metaKey) {
$data.Selected(true);
ko.utils.arrayForEach(array, function(item) {
if(item !== $data) {
item.Selected(false);
}
});
} else {
$data.Selected(!$data.Selected());
}
};
};
, jQuery .
myViewModel = new ViewModel();
ko.applyBindings(myViewModel);