jQuery可拖拽和放置在两个容器之间以及排序

29
我正在尝试开发一个具有以下功能的小页面:
  1. 页面将具有两个div:一个是#origin,包含许多缩略图图像,第二个是#drop,其中可以放置图像(最多只能放3张)。
  2. 需要可以从#drop拖放图像回到原始位置。
  3. #drop需要可排序,因为所选3个图像的顺序很重要。
  4. 将图像放在#drop上时,这些图像应该排列,就像它们从一开始就是这样显示的。

我以前从未使用过jQuery,甚至在之前的工作页面原型中,我已经通过本地HTML5拖放事件在两个容器之间实现了拖放,但是当我将sortable() jQuery功能添加到#drop时,这些图像不能再被拖回到#origin,这破坏了我的功能。

所以,我重新开始,并想要使用jQuery实现拖放功能和排序功能。我已经阅读了所有可拖动、可放置和可排序功能的API,但我在实现此功能时遇到了麻烦。不确定是每个功能使用的设置是否正确。

在小提琴上,您可以看到图像变得可拖动,我可以看到我指定的设置生效(不透明度、光标),但是这些图像无法放置在#drop上。
据我所知,使图像可拖动,图像具有“draggable”类,并使用“.draggable”接受使#drop可放置的组合应该允许最基本的功能,但即使如此,也似乎无法实现。另外,我读到如果可拖动和可放置都具有相同的“scope”设置,它也应该起作用,但事实并非如此。
以下是页面代码的简单版本,以及jsFiddle链接:http://jsfiddle.net/39khs/ 代码:
CSS:
#origin {
  background-color: green;
}
#drop {
  background-color: red;
  min-height: 120px;
}

js:

$("img").draggable({ helper: "clone", opacity: 0.5, cursor: "crosshair", scope: "drop" });
$("#drop").droppable({ accept: ".draggable", scope: "drop"});
$("#drop").sortable();

html:

<div id="wrapper">
    <div id="origin" class="fbox">
        <img src="http://placehold.it/140x100" id="one" title="one" class="draggable" />
        <img src="http://placehold.it/140x100" id="two" title="two" class="draggable" />
        <img src="http://placehold.it/140x100" id="three" title="three" class="draggable" />
    </div>
  <p>test</p>
    <div id="drop" class="fbox">

    </div>
</div>

任何帮助都非常感谢。
2个回答

67

以下是最终结果的 JSFiddle 链接:

http://jsfiddle.net/39khs/82/

关键在于处理 "drop" 事件并手动将被拖动的图像从 #origin 中删除并添加到 #drop 中。这实际上是我在第一次实现时所做的,但不知道如何使用 jQuery 精确执行:

 $(dropped).detach().css({top: 0,left: 0}).appendTo(droppedOn);

我不确定为什么jQuery实际上没有将拖动的元素从旧容器中移除并添加到新容器中,但这是必须做的,以便新放置的项目能正确显示,而不仅仅是在被放置的位置显示,而忽略css的布局和样式。

关键的代码行由@Barry Pitman在以下SO问题中提供:

jQuery draggable + droppable: how to snap dropped element to dropped-on element

更新:今天我有些空闲时间,想检查是否可以只使用sortable实现,结果居然能够实现。

http://jsfiddle.net/wj4ak/5/

只需要两行代码就可以使得从一个容器到另一个容器进行拖放,并对项目进行排序。它们根本不需要放在ul/ol列表中。唯一让人烦恼的事情是我原本并不想让源div上的项目可排序,但目前来说我可以接受。


23
如果您想使用.droppable().draggable().sortable(),那么您只需要使用.sortable()
使用您的 jsfiddle,我进行了以下更改:
HTML:
<div id="wrapper">
    <div id="origin" class="fbox">
    <ul id="sort1" class="list">
      <li><img src="http://placehold.it/140x100" id="one" title="one" class="draggable" /></li>
      <li><img src="http://placehold.it/140x100" id="two" title="two" class="draggable" /></li>
      <li><img src="http://placehold.it/140x100" id="three" title="three" class="draggable" /></li>
    </ul>
    </div>
  <p>test</p>
    <div id="drop" class="fbox">
      <ul id="sort2" class="list"></ul>
    </div>
</div>

JAVASCRIPT:

$( "#sort1, #sort2" ).sortable({
      helper:"clone", 
      opacity:0.5,
      cursor:"crosshair",
      connectWith: ".list",
      receive: function( event, ui ){ //this will prevent move than 3 items in droppable list
         if($(ui.sender).attr('id')==='sort1' && $('#sort2').children('li').length>3){
           $(ui.sender).sortable('cancel');
         }
      }
});

$( "#sort1,#sort2" ).disableSelection();

CSS:

#origin
{
  background-color: green;
}
#drop
{
  background-color: red;
  min-height: 120px;
}
.list
{ 
  min-height: 120px;
} 
.list li
{
 display: inline-block;
 list-style-type: none;
 padding-right: 20px;
}

DEMO: http://jsfiddle.net/39khs/80/

希望这有所帮助,如有任何问题,请告诉我!


链接:


谢谢Dom。知道sortable包含拖放和排序很好,但我不喜欢需要添加ol/ul列表的标记。我已经在没有它们的情况下使其工作了...但是在某个时候,我会尝试看看是否可以仅使用sortable而不需要ul/ol来完成它。 - GR7
如果在要放置的div中有占位符,我该如何使用它? - Jeroen Bellemans
这对我来说很好用,而且不需要使用ul / ol。我喜欢这种方法的简洁性。 - Nathan Clement

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接