jQuery Sortable - 选择并拖动多个列表项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3774755/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jQuery Sortable - Select and Drag Multiple List Items
提问by danspants
I have a design where I have a list of "available boxes", users take boxes by dragging them from the "available boxes" list to their "My Boxes" list.
我有一个设计,其中有一个“可用框”列表,用户通过将它们从“可用框”列表拖到“我的框”列表中来获取框。
Users more often than not take multiple boxes at a time (max 20), once they have finished with the boxes they drag them back to the "available boxes" list to return them.
用户通常一次拿走多个盒子(最多 20 个),一旦他们用完盒子,他们会将它们拖回“可用盒子”列表以返回它们。
jQuery sortable allows me to drag one box at a time which from a user perspective is undesirable. I've been unable to come up with a simple solution to the issue.
jQuery sortable 允许我一次拖动一个框,从用户的角度来看这是不可取的。我一直无法想出一个简单的解决方案来解决这个问题。
I may have to come up with a different UI method entirely, but first does anyone have any suggestions on how this might be accomplished?
我可能不得不想出完全不同的 UI 方法,但首先有人对如何实现这一点有任何建议吗?
Thanks!
谢谢!
采纳答案by Mottie
I don't have this working using sortable, but I did using draggable & droppable. I don't know if I covered all the functionality you need, but it should be a good start (demo here):
我没有使用 sortable 进行这项工作,但我确实使用了draggable & droppable。我不知道我是否涵盖了您需要的所有功能,但这应该是一个好的开始(此处为演示):
HTML
HTML
<div class="demo">
<p>Available Boxes (click to select multiple boxes)</p>
<ul id="draggable">
<li>Box #1</li>
<li>Box #2</li>
<li>Box #3</li>
<li>Box #4</li>
</ul>
<p>My Boxes</p>
<ul id="droppable">
</ul>
</div>
Script
脚本
$(document).ready(function(){
var selectedClass = 'ui-state-highlight',
clickDelay = 600, // click time (milliseconds)
lastClick, diffClick; // timestamps
$("#draggable li")
// Script to deferentiate a click from a mousedown for drag event
.bind('mousedown mouseup', function(e){
if (e.type=="mousedown") {
lastClick = e.timeStamp; // get mousedown time
} else {
diffClick = e.timeStamp - lastClick;
if ( diffClick < clickDelay ) {
// add selected class to group draggable objects
$(this).toggleClass(selectedClass);
}
}
})
.draggable({
revertDuration: 10, // grouped items animate separately, so leave this number low
containment: '.demo',
start: function(e, ui) {
ui.helper.addClass(selectedClass);
},
stop: function(e, ui) {
// reset group positions
$('.' + selectedClass).css({ top:0, left:0 });
},
drag: function(e, ui) {
// set selected group position to main dragged object
// this works because the position is relative to the starting position
$('.' + selectedClass).css({
top : ui.position.top,
left: ui.position.left
});
}
});
$("#droppable, #draggable")
.sortable()
.droppable({
drop: function(e, ui) {
$('.' + selectedClass)
.appendTo($(this))
.add(ui.draggable) // ui.draggable is appended by the script, so add it after
.removeClass(selectedClass)
.css({ top:0, left:0 });
}
});
});
回答by Aaron Blenkush
Working Solution
工作解决方案
tl;dr: Refer to this Fiddle for a working answer.
tl;dr:请参阅此 Fiddle 以获得有效答案。
I looked everywhere for a solution to the issue of dragging multiple selected items from a sortable into a connected sortable, and these answers were the best I could find.
我到处寻找将多个选定项目从 sortable 拖动到连接的 sortable问题的解决方案,这些答案是我能找到的最好的答案。
However...
然而...
The accepted answer is buggy, and @Shanimal's answeris close, but not quite complete. I took @Shanimal's code and built on it.
接受的答案有问题,@Sanimal 的答案很接近,但还不够完整。我采用了@Sanimal 的代码并以此为基础。
I fixed:
我解决了:
- the disappearing list item bug that @Ryan mentioned,
- cleaned up the syntax errors in the HTML (missing closing tags & nested
<li/>
s).
I added:
我补充说:
- Proper Ctrl + click(or Cmd + clickif on a mac) support for selecting multiple items. Clicking withoutthe Ctrlkey held down will cause that item selected, and other items in the same list to be deselected. This is the same click behavior as the jQuery UI
Selectable()
widget, the difference being thatSelectable()
has a marquee on mousedrag.
- 正确Ctrl + click(或Cmd + click如果在 mac 上)支持选择多个项目。点击没有在Ctrl按住键将使该项目选中,并在同一列表中的其他项目将被取消。这与jQuery UI
Selectable()
小部件的点击行为相同,不同之处在于Selectable()
在 mousedrag 上有一个选取框。
HTML:
HTML:
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
<ul>
<li>Four</li>
<li>Five</li>
<li>Six</li>
</ul>
JavaScript (with jQuery and jQuery UI):
JavaScript(使用 jQuery 和 jQuery UI):
$("ul").on('click', 'li', function (e) {
if (e.ctrlKey || e.metaKey) {
$(this).toggleClass("selected");
} else {
$(this).addClass("selected").siblings().removeClass('selected');
}
}).sortable({
connectWith: "ul",
delay: 150, //Needed to prevent accidental drag when trying to select
revert: 0,
helper: function (e, item) {
var helper = $('<li/>');
if (!item.hasClass('selected')) {
item.addClass('selected').siblings().removeClass('selected');
}
var elements = item.parent().children('.selected').clone();
item.data('multidrag', elements).siblings('.selected').remove();
return helper.append(elements);
},
stop: function (e, info) {
info.item.after(info.item.data('multidrag')).remove();
}
});
NOTE:
笔记:
Since I posted this, I implemented something simmilar - connecting draggable list items to a sortable, with multi-select capability. It is set up almost exactly the same, since jQuery UI widgets are so similar. One UI tip is to make sure you have the delay
parameter set for the draggables or selectables, so you can click to select multiple items without initiating a drag. Then you construct a helper that lookslike all the selected elements put together (make a new element, clone the selected items, and append them), but make sureto leave the original item intact (otherwise it screws up the functionality - I cannot say exactly why, but it involves a lot of frustrating DOM Exceptions).
自从我发布了这个,我实现了一些类似的东西 - 将可拖动的列表项连接到一个可排序的,具有多选功能。它的设置几乎完全相同,因为 jQuery UI 小部件非常相似。一个 UI 提示是确保您delay
为可拖动项或可选择项设置了参数,以便您可以单击以选择多个项目而无需启动拖动。然后你构建一个看起来像所有选定元素放在一起的助手(创建一个新元素,克隆选定的项目,然后附加它们),但确保原始项目完好无损(否则它会破坏功能 - 我不能说正是为什么,但它涉及到很多令人沮丧的 DOM 异常)。
I also added Shift + Clickfunctionality, so that it functions more like native desktop applications. I might have to start a blog so I can expound on this in greater detail :-)
我还添加了Shift + Click功能,使其更像本机桌面应用程序。我可能得写个博客,这样我才能更详细地阐述这一点:-)
回答by Shanimal
JSFiddle: http://jsfiddle.net/hQnWG/
JSFiddle:http: //jsfiddle.net/hQnWG/
<style>
ul {border:1px solid Black;width:200px;height:200px;display:inline-block;vertical-align:top}
li {background-color:Azure;border-bottom:1px dotted Gray}
li.selected {background-color:GoldenRod}
</style>
<h1>Click items to select them</h1>
<ul>
<li>One</li>
<li>Two<li>
<li>Three</li>
</ul><ul>
<li>Four</li>
<li>Five<li>
<li>Six</li>
</ul>
<script>
$("li").click(function(){
$(this).toggleClass("selected");
})
$("ul").sortable({
connectWith: "ul",
start:function(e,info){
// info.item.siblings(".selected").appendTo(info.item);
info.item.siblings(".selected").not(".ui-sortable-placeholder").appendTo(info.item);
},
stop:function(e,info){
info.item.after(info.item.find("li"))
}
})
</script>
回答by neochief
There's a jQuery UI plugin for that: https://github.com/shvetsgroup/jquery.multisortable
有一个 jQuery UI 插件:https: //github.com/shvetsgroup/jquery.multisortable
jsFiddle: http://jsfiddle.net/neochief/KWeMM/
jsFiddle:http: //jsfiddle.net/neochief/KWeMM/
$('ul.sortable').multisortable();
回答by bbe
Aaron Blenkush's solution has a major fault: removing and adding items to the sortable list breaks structure; refresh can help, but if other functions process the listing, a trigger for all of them is needed to refresh and it all becomes overly complex.
Aaron Blenkush 的解决方案有一个重大缺陷:在 sortable list break 结构中删除和添加项目;refresh 可以提供帮助,但如果其他函数处理列表,则需要所有这些函数的触发器来刷新,这一切都会变得过于复杂。
After analysing some solutions at stackoverflow, I've summarized mine in the following:
在分析了 stackoverflow 上的一些解决方案后,我总结了以下几点:
Do not use helper - use start function, cause it already has ui.item, which is the helper by default.
不要使用 helper - 使用 start 函数,因为它已经有 ui.item,这是默认的 helper。
start: function(event, ui){
// only essential functionality below
// get your own dragged items, which do not include ui.item;
// the example shows my custom select which selects the elements
// with ".selected" class
var dragged = ui.item.siblings(arr["nested_item"]).children('.tRow.tSelected').parent(arr["nested_item"]);
// clone the dragged items
var dragged_cloned = dragged.clone();
// add special class for easier pick-up at update part
dragged_cloned.each(function(){$(this).addClass('drag_clone');});
// record dragged items as data to the ui.item
ui.item.data('dragged', dragged);
// hide dragged from the main list
dragged.hide();
// attached cloned items to the ui.item - which is also ui.helper
dragged_cloned.appendTo(ui.item);
},
On the update part:
update: function(event, ui){ // only essential functionality below // attach dragged items after the ui.item and show them ui.item.after(ui.item.data("dragged").show()); // remove cloned items ui.item.children(".drag_clone").remove(); },
在更新部分:
update: function(event, ui){ // only essential functionality below // attach dragged items after the ui.item and show them ui.item.after(ui.item.data("dragged").show()); // remove cloned items ui.item.children(".drag_clone").remove(); },
Stop function may need some copy of the update functionality, but is likely to be separate from update, 'cause if no change - do not submit anything to the server.
停止功能可能需要更新功能的一些副本,但很可能与更新分开,因为如果没有更改 - 不要向服务器提交任何内容。
To add: preserving order of dragged items.
添加:保留拖动项目的顺序。