Jquery可排序连接列表AJAX调用

时间:2016-08-11 20:33:49

标签: jquery ajax jquery-ui

我正在处理包含父项和子项的可排序列表。用户应该能够在它们之间移动项目,还可以移动父项目,包括子项目。

我想出了如何使用连接的可排序列表执行此操作:

https://jsfiddle.net/ron_s/fovah76v/1/

为实现这一目标,我没有使用列表的ID:

$('#id_of_the_list').sortable({ ... })

但是一般的.sortable类:

$('.sortable').sortable({ ... })

我现在的问题是AJAX调用只是抓取父项的ID,而不是子项。

<script type="text/javascript">
$(document).ready(function () {
$('.sortable').sortable({
  connectWith: 'ul.sortable',
  update: function () {
    $.ajax({
      type: 'post', data: $('.sortable').sortable('serialize'), dataType: 'script',
      complete: function (request) {
        $('.sortable');
      }, url: '/tasks/sort_goal_task'
    })
  }
  });
 });
</script>

我认为存在一个非常类似的问题here,但我无法使此代码正常工作。

感谢您的帮助, 罗恩

1 个答案:

答案 0 :(得分:0)

这可能是一种复杂的答案,而不是你正在寻找的,或者更多。

最初问题的一部分是很难到达嵌套列表。由于它们中没有任何项目,因此基本上为ul呈现height为0。我建议你让block至少有一些高度。

我还删除了填充并在li中手动添加,以提供任务和子任务之间的空间关系。我开始将列表与更多类parentchild分开,这样我就可以知道我的样式和工作方式。

这个parentchild关系本身就是2个可排序列表,恰好是嵌套的。因此,我为$(".parent").sortable()$(".child").sortable()创建了选项,以帮助组织它们。这也可以使我们能够接受或拒绝(取消)可排序项目,具体取决于它们的任务类型或起源位置。

这绝不是完美的,我在这里和那里发现了许多奇怪的错误,但核心元素是能够对任务和子任务进行排序并将子任务拖到另一个任务。

工作示例到目前为止:https://jsfiddle.net/Twisty/sv9qdpLb/

<强> HTML

<div id="container">
  <h2>Tasks</h2>
  <ul id="list" class="parent sortable">
    <li id="t1" class="task" data-id="l1">
      Task 1 <span class="add-subTask-button ui-icon ui-icon-plus"></span>
      <ul class="child sortable"></ul>
    </li>
    <li id="t2" class="task" data-id="l2">
      Task 2 <span class="add-subTask-button ui-icon ui-icon-plus"></span>
      <ul class="child sortable">
        <li id="t2_1" class="subTask" data-id="l2-1">
          Sub Task 1 <span class="remove-subTask-button ui-icon ui-icon-minus"></span>
        </li>
        <li id="t2_2" class="subTask" data-id="l2-2">
          Sub Task 2 <span class="remove-subTask-button ui-icon ui-icon-minus"></span>
        </li>
      </ul>
    </li>
    <li id="t3" class="task" data-id="l3">
      Task 3 <span class="add-subTask-button ui-icon ui-icon-plus"></span>
      <ul class="child sortable"></ul>
    </li>
  </ul>
</div>

如果您查看演示,您会发现它们主要是ulli样式列表。是的,你可以使用其他东西,但是将每个列表项处理为它是什么,列表中的对象项,以及调整它的数据和id等属性在很大程度上更容易。

<强> CSS

#container {
  width: 600px;
  margin: 30px auto;
}

ul.parent {
  font-size: 18px;
  width: 200px;
  margin: 0;
  padding: 0;
}

ul.parent li {
  list-style: none;
  margin-bottom: 2px;
  padding-left: 3px;
  border: 1px solid #999;
  border-radius: 6px;
  position: relative;
}

ul.parent li span.ui-icon {
  position: absolute;
  top: .25em;
  right: 2px;
  left: auto;
  cursor: pointer;
}

ul.child {
  display: block;
  font-size: 14px;
  padding-left: 30px;
  min-height: 1em;
}

ul.child li {
  list-style: none;
  border: 1px solid #bbb;
  margin-bottom: 1px;
}

.placeholder {
  background: yellow;
  height: 1em;
}

.handle {
  background: orange;
  width: 20px;
  height: 20px;
  float: left;
  margin: 0 5px 10px 5px;
}

.container {
  overflow: hidden
}

我在这里没有做太多改变只是让一些事情变得更加具体。我还添加了边框,为用户提供了视觉队列或对分组及其关系的认识。

<强>的jQuery

$(document).ready(function() {
  // Make tasks sortable
  function fullSerial() {
    var par = {};
    $.each($("#list").sortable("toArray"), function(key, val) {
      par[val] = $("#" + val + " .child").sortable("toArray");
    });
    return par;
  }

  $(".parent").sortable({
    placeholder: 'placeholder',
    connectWith: ".sortable",
    over: function(e, ui) {
      if (ui.item.hasClass("subTask")) {
        $(".parent").sortable("cancel");
      }
    }
  });

  $(".child").sortable({
    placeholder: 'placeholder',
    accept: ".child",
    connectWith: ".sortable",
  }).disableSelection();

  $(".sortable").on("sortupdate", function() {
    //console.log($(".sortable").sortable("serialize"));
    console.log(fullSerial());
  });

  $(".add-subTask-button").click(function() {
    var task = $(this).parent();
    var taskName = prompt("Enter Sub Task Name.");
    var newId = task.attr("id") + "_" + (task.find("ul.child li").length + 1);
    var subTask = $("<li>", {
      id: newId,
      class: "subTask",
      "data-id": newId
    }).html(taskName + "<span class='remove-subTask-button ui-icon ui-icon-minus'></span>");
    task.find(".child").append(subTask).sortable("refresh");
  });

  $(".remove-subTask-button").click(function() {
    var subTask = $(this).parent();
    var ulElem = subTask.parent();
    subTask.remove();
    ulElem.sortable("refresh");
  });
});

通过测试,我发现serialize方法与嵌套的可排序列表不相符。所以我创建了一个函数来构建一个Task对象,其中包含一系列Sub Tasks作为每个Task的元素。我怀疑使用JSON.serialize()可能会得到你可以传递的东西,但是你总是可以操纵fullSerial从对象而不是对象本身返回一个序列化的字符串。

您可以看到两个排序。由于您的OP不清楚是否要将子任务设置为任务,因此尝试阻止此类活动。我在receive中尝试了相同的代码,它应该恢复排序......但两者都没有。此外,如果你足够狡猾,你可以将整个任务和它的子任务拖动到子任务位置。

为了能够执行更深入的测试,我添加了一种方法来动态添加项目并动态生成/删除子任务。

我希望有所帮助。正如我前面提到的那样,它可能比你需要的更多,但你的问题导致了一个复杂的答案。即使没有添加元素。

<强>更新

阻止将任务拖入子任务的示例:https://jsfiddle.net/Twisty/sv9qdpLb/4/

$(".child").sortable({
  placeholder: 'placeholder',
  connectWith: ".sortable",
  receive: function(e, ui) {
    if (ui.item.hasClass("task")) {
      ui.sender.sortable("cancel");
    }
  }
});