微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

jquery – 可排序 – 将项目从列表拖放到另一个(复制)

我希望能够选择多个项目,并使用拖放功能将它们从列表复制到另一个项目(双向),只有在它不存在的情况下才会删除

一些帮助将不胜感激.

编辑:关于查理的帖子和小提琴,我怎样才能选择多个项目拖放到另一个列表?就像现在一样,它只允许同时有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());

Charlie’s JSFiddle

解决方法

这是一个允许一次排序多个项目的解决方案.基于 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 举报,一经查实,本站将立刻删除。

相关推荐