我希望能够选择多个项目,并使用拖放功能将它们从列表复制到另一个项目(双向),只有在它不存在的情况下才会删除…
一些帮助将不胜感激.
编辑:关于查理的帖子和小提琴,我怎样才能选择多个项目拖放到另一个列表?就像现在一样,它只允许同时有1个项目.
HTML:
<div class="list"> <h2>Stored procedures In DB 1</h2> <ul class="list" data-bind="sortable: { data: storedProceduresInDB1,beforeMove: checkAndcopy }"> <li class="item" data-bind="text: Name"></li> </ul> </div><br> <div class="list"> <h2>Stored procedures In DB 2</h2> <ul class="list" data-bind="sortable: { data: storedProceduresInDB2,beforeMove: checkAndcopy }"> <li class="item" data-bind="text: Name"></li> </ul> </div>
码:
var viewmodel = function () { var self = this; self.storedProceduresInDB1 = ko.observableArray([ { Name: 'SP1',Id: 1 },{ Name: 'SP2',Id: 2 },{ Name: 'SP3',Id: 3 } ]); self.storedProceduresInDB2 = ko.observableArray([ { Name: 'SP3',Id: 3 },{ Name: 'SP4',Id: 4 },{ Name: 'SP5',Id: 5 } ]); self.selectedStoredProcedureInDB1 = ko.observable(); self.selectedStoredProcedureInDB2 = ko.observable(); self.selectStoredProcedureInDB1 = function (sp) { self.selectedStoredProcedureInDB1(sp); }; self.selectStoredProcedureInDB2 = function (sp) { self.selectedStoredProcedureInDB2(sp); }; self.checkAndcopy = function(event) { var targetHasItem = ko.utils.arrayFilter(event.targetParent(),function(item) { return item.Id == event.item.Id; }).length; if(!targetHasItem) { event.targetParent.splice(event.targetIndex,event.item); } if(event.targetParent != event.sourceParent) { event.cancelDrop = true; } }; }; ko.applyBindings(new viewmodel());
解决方法
这是一个允许一次排序多个项目的解决方案.基于
this related answer但修改为使用knockout.js和knockout-sortable.
JSfiddle(在Chrome中测试):http://jsfiddle.net/QWgRF/715/
HTML
向可排序项和列表项添加了ID,以便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,$parent.storedProceduresInDB2()),css: { selected: Selected }"> </li> </ul> </div>
JavaScript的
可排序的选项.延迟150以允许点击处理程序用于选择.还原0因为动画看起来很奇怪我们如何搞乱列表和助手.
stop函数重置observableArrays,导致刷新列表html.
辅助函数抓取所有选定的项目并将它们添加到新的帮助程序标记中,以允许拖动多个项目的可视化.
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; } };
查看模型.为每个存储过程添加了Selected observable属性.添加了一个selectProcedure方法,根据点击次数和ctrl点击次数更新新的Selected属性.
还大量修改了checkAndcopy方法.我认为内联评论可以解释它是如何运作的.
var viewmodel = function () { var self = this; self.storedProceduresInDB1 = ko.observableArray([ { Name: 'SP1',Id: 1,Selected: ko.observable(false) },Id: 2,Id: 3,Selected: ko.observable(false) } ]); self.storedProceduresInDB2 = ko.observableArray([ { Name: 'SP3',Id: 4,Id: 5,Selected: ko.observable(false) } ]); self.checkAndcopy = function(event) { var items; if(event.targetParent !== event.sourceParent) { // Get all items that don't yet exist in the target items = ko.utils.arrayFilter(event.sourceParent(),function(item) { return item.Selected() && !ko.utils.arrayFirst(event.targetParent(),function(targetItem) { return targetItem.Id == item.Id; }); }); // Clone the items (otherwise the Selected observable is shared by the item in both lists) items = ko.utils.arrayMap(items,function(item) { var clone = ko.toJS(item); clone.Selected = ko.observable(true); // While we're here,let's deselect the source items so it looks cleaner item.Selected(false); return clone; }); // deselect everything in the target list Now so when we splice only the new items are selected ko.utils.arrayForEach(event.targetParent(),function(item) { item.Selected(false); }); } else { // Moving items within list,grab all selected items from list items = event.sourceParent.remove(function(item) { return item.Selected(); }); } // splice items in at target index items = items.reverse(); for(var i=0; i<items.length; i++) { event.targetParent.splice(event.targetIndex,items[i]); } // always cancel drop Now,since we're manually rearranging everything 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()); } }; };
添加了对View Model的全局引用,以便jQuery代码可以与它进行交互.
myviewmodel = new viewmodel(); ko.applyBindings(myviewmodel);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。