在动态创建的无序列表上使用Sortable

3
这对于经常使用JQuery的人来说可能是一个简单的问题。我只是从S3中读取一个列表到数组中,并使用...
document.getElementById('my-list').appendChild(makeUL(options));

在ID为“my-list”的div内建立一个ul。看起来像这样:
<div id="my-list">
    <ul id="sortable">
        <li class="ui-state-default">LivePD</li>
        <li class="ui-state-default">Football</li>
        <li class="ui-state-default">Walking Dead</li>
        <li class="ui-state-default">Survivor</li>
        <li class="ui-state-default">The Voice</li>
        <li class="ui-state-default">Shark Tank</li>
        <li class="ui-state-default">DWTS</li>
        <li class="ui-state-default">RHOOC</li>
    </ul>
</div>

我有一个可排序的函数,它是:
<script>
    $(function() {
        $("#sortable").sortable();
        $("#sortable").disableSelection();
    });
</script>

这是问题所在。如果我像上面展示的那样将ul硬编码到我的HTML body中,sortable代码就可以正常运行。它会按照预期给ul和li元素添加ui-sortable类。但是如果我使用getElementById动态构建ul,基本的HTML渲染完全相同,但是sortable没有添加这些类。
这是否与DOM执行顺序有关?我无法弄清楚,也找不到其他类似的例子。当然,也完全可以考虑其他想法。

每次动态构建 ul 后,也要调用这些代码 $("#sortable").sortable(); $("#sortable").disableSelection(); - amar9312
那个完美地运行了。在DOM中构建ul后,立即添加了对sortable函数的调用。我认为这与执行顺序有关。我没有做过太多的web/js开发,只是边学边摸索。非常感谢。 - S Graham
2个回答

1
请查看:

jQuery UI API Sortable Refresh Method

它的意思是:

刷新可排序项目。触发所有可排序项目的重新加载,导致新项目被识别。

在动态添加元素时,您将在初始化Sortable之前或之后添加它们。如果在之前完成,则只需组装列表项,然后调用sortable。如果在之后添加项目,则添加项目,然后运行刷新方法。

这是一个有点复杂的例子,但它假设您正在从基于API的列表中添加项目,可能稍后添加更多项目。

$(function() {
  var extData = [{
    label: "LivePD",
    id: 1
  }, {
    label: "Football",
    id: 2
  }, {
    label: "Walking Dead",
    id: 3
  }, {
    label: "Survivor",
    id: 4
  }, {
    label: "The Voice",
    id: 5
  }, {
    label: "Shark Tank",
    id: 6
  }, {
    label: "DWTS",
    id: 7
  }, {
    label: "RHOOC",
    id: 8
  }];

  function updateList(data, target) {
    var sort = target.find(".sortable");
    console.log(data, sort);
    $.each(data, function(k, v) {
      $("<li>", {
        class: "ui-state-default",
        id: target.attr("id") + "-item-" + v.id
      }).html(v.label).appendTo(sort);
    });
    if (sort.hasClass("ui-sortable")) {
      sort.sortable("refresh");
    }
  }

  updateList(extData, $("#my-list"));
  $(".sortable").sortable();
  $(".sortable").disableSelection();
  $(".add").click(function(e) {
    var dlg = $("<div>", {
      title: "Add To " + $(this).parent().find("p").text()
    });
    var that = $(this);
    dlg.append(
      $("<label>").html("Name"),
      $("<input>", {
        type: "text",
        class: "name txt"
      }),
      $("<label>").html("ID"),
      $("<input>", {
        type: "input",
        class: "id txt"
      })
    );
    dlg.dialog({
      modal: true,
      buttons: [{
        text: "Ok",
        click: function() {
          var d = [{
            label: $(this).find(".name").val(),
            id: $(this).find(".id").val()
          }];
          updateList(d, that.parent());
          $(this).dialog("close");
          $(this).remove();
        }
      }, {
        text: "Cancel",
        click: function() {
          $(this).dialog("close");
          $(this).remove();
        }
      }]
    });
  });
});
.sortable {
  list-style-type: none;
  margin: 0;
  padding: 0;
  width: 60%;
}

.sortable li {
  margin: 0 3px 3px 3px;
  padding: 0.4em;
  padding-left: 1.5em;
  font-size: 1.4em;
  height: 18px;
}

.sortable li span {
  position: absolute;
  margin-left: -1.3em;
}

.ui-dialog-content label {
  display: block;
}
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>


<div id="my-list">
  <p>My List</p>
  <ul class="sortable">
  </ul>
  <button id="my-list-add-btn" class="add btn">Add</button>
</div>

如果您有多个列表,这段代码非常有效,因为它允许您对许多不同的列表使用相同的函数。
希望这可以帮助到您。

很好的例子。在我扩展这个实验并渲染新项目时,将需要它来进行更新。感谢您的输入。 - S Graham
@SGraham如果您发现这个答案或其他答案有帮助,请记得点赞。还要记得将其中一个标记为答案。 - Twisty
完成。我猜我在SO上还太新了,直到我的声望提高才能正式点赞。 - S Graham
@SGraham,这会有所改善。将一个响应标记为答案可以帮助解决问题。 - Twisty

-1

你只需要调用它

$("#sortable").sortable(); $("#sortable").disableSelection();

每次动态填充后。

愉快的编码。


1
我已经对这个答案进行了负评,因为OP的代码中已经包含了这些元素。此外,在添加新项目时刷新可排序列表的方法不正确。请参见:http://api.jqueryui.com/sortable/#method-refresh - Twisty
我认为根据问题,答案的精神是好的。鉴于我只是在测试概念,我的原始问题相当基础。在那种情况下,问题在于我只是以错误的DOM执行顺序调用了sortable函数 - 我是一个Web开发新手。感谢大家的帮助和意见。Twisty的全面回答肯定是未来正确的实现方式。 - S Graham

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