How to restore a jquery ui sortable list by using stored structure from db

泪湿孤枕 提交于 2019-12-12 01:27:34

问题


I've tried to store a list-structure in my db (based on this question [1]: How to serialize a nested sortable ul list) and after that I need a way to restore/reset the list if the page is refreshed or load new based on the data from db.

Is there a build-in way to do this or how can I do that?

In my list, I use nested elements to support the way to create flexible nested structure.

This is what I already have

The list

<ul id="mysite" class="mysite editor-ul ui-sortable-handle ui-sortable">
  <li class="draggable editor-li editor-li-head ui-sortable-handle">Headline</li>
  <li class="draggable editor-li ui-sortable-handle" id="p-1">
    Item1
    <ul class="mysite editor-ul ui-sortable"></ul>
  </li>
  <li class="draggable editor-li ui-sortable-handle" id="p-5">
    Item 2
    <ul class="mysite editor-ul ui-sortable">
      <li class="draggable editor-li ui-sortable-handle" id="p-7" style="">
        Item 3
        <ul class="mysite editor-ul ui-sortable"></ul>
      </li>
      <li class="draggable editor-li ui-sortable-handle" id="p-6" style="">
        Item 4
        <ul class="mysite editor-ul ui-sortable"></ul>
      </li>
    </ul>
  </li>
</ul>

The JS Code

$(function() {
  //$(".mysite").sortable({

  $(".mysite").sortable({
    connectWith: ".mysite",
    placeholder: "placeholder",
    update: function(event, ui) {
      var struct = [];
      var i = 0;

      $(".mysite").each(function(ind, el) {
        struct[ind] = {
          index: i,
          class: $(el).attr("class"),
          count: $(el).children().length,
          parent: $(el).parent().is("li") ? $(el).parent().attr("id") : "",
          parentIndex: $(el).parent().is("li") ? $(el).parent().index() : "",
          array: $(el).sortable("toArray"),
          serial: $(el).sortable("serialize")
        };
        i++;
      });
      console.log("Structure", struct);


      $.ajax({
        data: {
          "'.$this->security->get_csrf_token_name().'": "'.$this->security->get_csrf_hash().'",
          "job": "updateSiteStruc",
          "data": struct
        },
        type: "POST",
        url: "'.base_url().'"
      });


      var iArr = [];
      var iSer = [];
      $(".mysite:eq(0) li").each(function(ind, el) {

        if ($(el).attr("id") != undefined) {
          var label = $(el).attr("id");
        } else {
          return true;
        }

        iArr.push(label);
        var pre = label.slice(0, label.indexOf("-")) + "[]=";
        iSer.push(pre + label.slice(label.indexOf("-") + 1));
        if ($(el).children().eq(0).is("ul")) {
          $(el).find("li").each(function() {
            iArr.push($(this).attr("id"));
            iSer.push(pre + $(this).attr("id").slice(label.indexOf("-") + 1));
          });
        }
      });
      console.log("Items Array", iArr);
      console.log("Items Serial", iSer.join("&"));
    }
  }).disableSelection();

});

Based on this I store the structure

  • send by ajax
  • save json_encode($post['data']) in db

So now I have in my db

"[{"array": ["", "p-1", "p-5"], "class": "mysite editor-ul ui-sortable-handle ui-sortable", "count": "3", "index": "0", "parent": "", "serial": "p[]=1&p[]=5", "parentIndex": ""}, {"class": "mysite editor-ul ui-sortable", "count": "0", "index": "1", "parent": "p-1", "serial": "", "parentIndex": "1"}, {"array": ["p-7", "p-6"], "class": "mysite editor-ul ui-sortable", "count": "2", "index": "2", "parent": "p-5", "serial": "p[]=7&p[]=6", "parentIndex": "2"}, {"class": "mysite editor-ul ui-sortable", "count": "0", "index": "3", "parent": "p-7", "serial": "", "parentIndex": "0"}, {"class": "mysite editor-ul ui-sortable", "count": "0", "index": "4", "parent": "p-6", "serial": "", "parentIndex": "1"}]"

Formatted version of string above:

"[{
  "array": ["", "p-1", "p-5"],
  "class": "mysite editor-ul ui-sortable-handle ui-sortable",
  "count": "3",
  "index": "0",
  "parent": "",
  "serial": "p[]=1&p[]=5",
  "parentIndex": ""
}, {
  "class": "mysite editor-ul ui-sortable",
  "count": "0",
  "index": "1",
  "parent": "p-1",
  "serial": "",
  "parentIndex": "1"
}, {
  "array": ["p-7", "p-6"],
  "class": "mysite editor-ul ui-sortable",
  "count": "2",
  "index": "2",
  "parent": "p-5",
  "serial": "p[]=7&p[]=6",
  "parentIndex": "2"
}, {
  "class": "mysite editor-ul ui-sortable",
  "count": "0",
  "index": "3",
  "parent": "p-7",
  "serial": "",
  "parentIndex": "0"
}, {
  "class": "mysite editor-ul ui-sortable",
  "count": "0",
  "index": "4",
  "parent": "p-6",
  "serial": "",
  "parentIndex": "1"
}]"

回答1:


If you want to construct a list of items that can be stored as a string in a DB and then built out as <ul> in HTML, I would suggest using much more complex structure so you can have a deeper relationship within the data.

$(function() {

  var saveData;

  function makeObj(list) {
    var d = [];
    d.push({
      id: list.attr("id"),
      class: list.attr("class"),
      items: []
    });
    list.children("li").each(function(ind, el) {
      var item = {
        attr: {
          index: ind,
          id: $(el).attr('id') || "list-item-" + ind,
          class: $(el).attr('class'),
          style: $(el).attr('style')
        },
        label: el.firstChild.data.trim(),
        children: $("ul", el).length ? true : false,
        childObj: false
      };
      d[0].items.push(item);
    });
    return d;
  }

  function buildList(d, t) {
    console.log(d);
    $.each(d, function(key, item) {
      $("<li>", item.attr).html(item.label).appendTo(t);
    });
  }

  function makeSort(obj, cnwt) {
    obj.sortable({
      connectWith: cnwt,
      placeholder: "placeholder"
    });
  }

  function stringify(d) {
    return JSON.stringify(d);
  }

  function parse(s) {
    return JSON.parse(s);
  }

  $("#saveList").click(function(e) {
    var myData = makeObj($("#mySite"));
    console.log(myData);
    $.each(myData[0].items, function(key, item) {
      if (item.children) {
        myData[0].items[key].childObj = makeObj($("ul:eq(0) > li:eq(" + key + ") > ul"));
      }
    });
    console.log(stringify(myData));
    saveData = stringify(myData);
  });

  $("#loadList").click(function(e) {
    if (saveData.length) {
      console.log(saveData);
      var myData = parse(saveData);
      var newList = $("<ul>", {
        id: myData[0].id,
        class: myData[0].class
      }).insertAfter($(this));
      buildList(myData[0].items, newList);
      makeSort(newList, myData[0].class);
      $.each(myData[0].items, function(key, item) {
        if (item.children) {
          var sList = $("<ul>", {
            id: item.childObj[0].id || "",
            class: item.childObj[0].class
          }).appendTo($("li:eq(" + item.attr.index + ")", newList));
          buildList(item.childObj[0].items, sList);
          makeSort(sList, item.childObj[0].class);
        }
      });
    }
  });
});
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>

<ul id="mySite" class="mysite editor-ul">
  <li class="draggable editor-li editor-li-head">Headline</li>
  <li class="draggable editor-li" id="p-1">Item1
    <ul class="mysite editor-ul"></ul>
  </li>
  <li class="draggable editor-li" id="p-5">Item 2
    <ul class="mysite editor-ul">
      <li class="draggable editor-li" id="p-7" style="">Item 3
        <ul class="mysite editor-ul"></ul>
      </li>
      <li class="draggable editor-li" id="p-6" style="">Item 4
        <ul class="mysite editor-ul"></ul>
      </li>
    </ul>
  </li>
</ul>
<button id="saveList">Save</button>
<button id="loadList">Load</button>

The above example is specific to show the save and load features. To test, click Save and then click Load. The structure is saved to an string and placed in a variable. Then in load, it is read from the string and builds a new copy.

This is less about the sortable and more about the saving and loading. You can use stringify(makeObj()) in update to send the data to your DB. If your list is deeper, you will have to repeat the makeObj() a few times for each layer.

The same goes when you get the data from the DB. Either it will come back as a string where you can use parse() or it will come back as an object. This would be the case if you use PHP to encode_json() and send JSON data directly back to the script.

Sending back String:

buildList(parse(data), $(".target"));

Sending back JSON:

buildList(data, $(".target"));

As you can see, it can get pretty complex. It might be better to find a plugin that can do the heavy work for you. Remember this is just one example and maybe not the best one for what you're doing.

Hope that helps.



来源:https://stackoverflow.com/questions/54193761/how-to-restore-a-jquery-ui-sortable-list-by-using-stored-structure-from-db

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!