【问题标题】:Jquery sortable connected lists AJAX callJquery 可排序连接列表 AJAX 调用
【发布时间】:2016-08-11 20:33:48
【问题描述】:

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

我想出了如何使用连接的可排序列表来做到这一点:

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 有一个非常相似的问题,但我无法让这段代码工作。

感谢您的帮助, 罗恩

【问题讨论】:

  • 欢迎来到 Stack Overflow。更新函数将eventui 传递给回调。目前尚不清楚您想对数据做什么......但我怀疑ui 属性会有所帮助。
  • 再看这个,我认为div 和额外的ul 正在扔东西。是否要对任务和子任务进行排序?还是只是将子任务分类为任务?

标签: jquery ajax jquery-ui


【解决方案1】:

这可能是一种复杂的答案,并不完全是您想要的,或者更多。

最初的部分问题是很难访问嵌套列表。因为它们里面没有项目并且基本上呈现给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 方法不适用于嵌套的可排序列表。所以我做了一个函数来构建一个任务对象,其中包含一组子任务作为每个任务的元素。我怀疑使用JSON.serialize() 可能会为您提供可以传递的东西,但您始终可以操纵fullSerial 从对象而不是对象本身返回序列化字符串。

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

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

我希望这会有所帮助。正如我前面所说,它可能超出您的需要,但您的问题会导致复杂的答案。即使没有添加元素。

更新

防止Task被拖入Sub Task的例子: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");
    }
  }
});

【讨论】:

  • 您好 Twisty,非常感谢您的回答! CSS 部分确实超出了我的需要(该列表是完全样式化的应用程序的一部分,我只是将其剥离以使问题更清楚),但是您的“fullSerial”功能正是我想要的。用户应该可以将子任务转化为任务,所以我把$(".parent").sortable中对应的部分删掉了。很高兴:你能想出一种方法来禁止将父子列表拉到另一个孩子身上,因为这很难解析?再次感谢您!罗恩
  • 我会看看能做些什么。在receive 中,可以检查项目是否具有类parent 并执行cancel。这应该会恢复排序。
猜你喜欢
  • 1970-01-01
  • 2015-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多