JQuery 可放置 div 在可排序列表中

JQuery droppable div inside a sortable list

我正在尝试创建一个简单的可排序和可拖动列表,其中包含:

到目前为止我设法做到了:JSFiddle

HTML代码:

<h3>DRAGGABLE</h3>
<ul id="draggables">
  <li class="draggable">Item 1</li>
  <li class="draggable">Item 2</li>
  <li class="draggable">Item 3</li>
  <li class="draggable">Item 4</li>
  <li class="draggable">Item 5</li>
</ul>

<h3>SORTABLE</h3>
<ul id="itemsContainer">
  <li class="item">Item 1</li>
  <li class="item">
    <p>Item with drop zone</p>
    <div class="droppable">DROP HERE</div>
  </li>
  <li class="item">Item 3</li>
  <li class="item">Item 4</li>
  <li class="item">Item 5</li>
</ul>

JS代码在这里:

$(".draggable").draggable({
  connectToSortable: '#itemsContainer',
  helper: 'clone',
  revert: 'invalid'
});

$("#itemsContainer").sortable({
  revert: true
});

$(".droppable").droppable({
  drop: function(event, ui) {
    $(this).html("Dropped!");
    $(this).css("background-color", "red");
    $(ui.helper[0]).css("background-color", "green");
  }
});

问题是,当一个项目被放置在 droppable div 中时,它正确地检测到正在发生放置,但该项目仍然被添加到可排序列表中。我认为 "greedy" 选项可以防止这种情况发生。有什么想法吗?

编辑:如果我将样式应用到 ui.helper[0] 对象(又名克隆的可拖动对象),它会一直保持到项目在可排序列表中实际排序为止。

可能有点矫枉过正,但这是我能想到的。

当我们stop拖动一个可拖动的项目时,我们需要查看该项目是否在可放置区域之上,如果是,则将其附加到该区域。

编辑:现在我们可以通过将可排序列表连接到拖放区并接受可排序项,将可排序项从同一列表拖放到拖放区。

jsFiddle

var over = false; // is the item over a droppable area?
var el_over = null; // if over a drop area, what drop area?
var de = null; // the item to detach

$(".draggable-item").draggable({
  connectToSortable: ".list-2",
  stop: function(event, ui) {
    if (over) {
      de = $(this).detach();
      el_over.append(de);
    }
    over = false;
    el_over = null;
  }
});

$(".list-2").sortable({
  connectWith: '.drop-zone, .list-2',
  cursor: "move",
  stop: function(event, ui) {
    if (over) {
      de = ui.item.detach();
      el_over.append(de);
    }
    over = false;
    el_over = null;
  }
});

$(".drop-zone").droppable({
  accept: ".draggable-item, .sortable-item",
  over: function(event, ui) {
    //console.log("over");
    over = true;
    el_over = $(this);
  },
  out: function(event, ui) {
    //console.log("out");
    over = false;
    el_over = null;
  }
});
ul {
  padding: 10px;
  list-style-type: none;
  width: 200px;
}

li {
  text-align: center;
  padding: 5px 10px;
  margin: 5px;
}

.draggable-item {
  background: #9bcdf0;
}

.sortable-item {
  background: #6c2020;
}

.drop-zone {
  min-height: 30px;
  background: #fff;
  padding: 1px 0;
}

.drop-zone .draggable-item {
  width: auto !important;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<ul class="list-1">
  <li class="draggable-item">draggable 1</li>
  <li class="draggable-item">draggable 2</li>
  <li class="draggable-item">draggable 3</li>
  <li class="draggable-item">draggable 4</li>
  <li class="draggable-item">draggable 5</li>
</ul>

<ul class="list-2">
  <li class="sortable-item">sortable 1</li>
  <li class="sortable-item">sortable 2</li>
  <li class="sortable-item">sortable 3
    <div class="drop-zone"></div>
  </li>
  <li class="sortable-item">sortable 4</li>
  <li class="sortable-item">sortable 5</li>
</ul>

更新后的答案: 事实证明,我们不需要那么矫枉过正 XD。如果我们只是将 .drop-zone 初始化为可排序对象并将其连接到自身,并且 list-2 我们会得到相同的结果。

这是更新后的 fiddle

$(".draggable-item").draggable({
    connectToSortable: ".list-2",
});

$(".list-2").sortable({
    connectWith: '.drop-zone, .list-2',
    cursor: "move",
});

$(".drop-zone").droppable({
    accept: ".draggable-item, .sortable-item",
});

$(".drop-zone").sortable({
    connectWith: '.drop-zone, .list-2',
  items: '.draggable-item, .sortable-item',
});