Search code examples
javascriptjqueryjquery-pluginsnested-sortable

List numbers of nested lists using the jQuery NestedSortable plugin


The problem / Question

I'm having a problem with getting the list numbers (sortIndex). After getting the sortIndex like in the "Example List", I want to give the sortIndex to the toArray function. So when this function does create an array, there is a sortIndex init. See the "Array Example"

jQuery plugin used: mjsarfatti jQuery nestedSortable

Example list

List in html:

    <ol class="sortable ui-sortable">
    <li id="category_1"><div>Car</div>
       <ol>
           <li id="category_2"><div>Color</div>
                <ol>
                    <li id="category_3"><div>Red</div></li>
                    <li id="category_4"><div>Black</div></li>
                </ol>
           </li>
       </ol>
    </li>
    <li id="category_5"><div>Motor</div></li>
    <li id="category_6"><div>Truck</div></li>
    </ol>

List example, to give you a view of the above lists.

[sortIndex] [Name]
1. Car
    1. Color
       1. Red
       2. Black
2. Motor
3. Truck

Array Example

With the nestedSortable toArray, it would be nice to add the sortIndex to the array(), like this:

["storage":"ArrayObject":private]=>
  array(1) {
    ["newList"]=>
    array(7) {
      [0]=> //This is the OL
      array(5) {
        ["item_id"]=>
        string(0) ""
        ["parent_id"]=>
        string(4) "none"
        ["depth"]=>
        string(1) "0"
        ["left"]=>
        string(1) "1"
        ["right"]=>
        string(2) "38"
      }
      [1]=> // Car
      array(6) {
        ["item_id"]=>
        string(1) "1"
        ["parent_id"]=>
        string(0) ""
        ["sort_index"]=>
        string(1) "1"
        ["depth"]=>
        string(1) "1"
        ["left"]=>
        string(1) "2"
        ["right"]=>
        string(1) "9"
      }
      [2]=> // Color
      array(6) {
        ["item_id"]=>
        string(1) "2"
        ["parent_id"]=>
        string(1) "1"
        ["sort_index"]=>
        string(1) "1"
        ["depth"]=>
        string(1) "2"
        ["left"]=>
        string(1) "3"
        ["right"]=>
        string(1) "8"
      }
      [3]=> // Red
      array(6) {
        ["item_id"]=>
        string(1) "3"
        ["parent_id"]=>
        string(1) "2"
        ["sort_index"]=>
        string(1) "1"
        ["depth"]=>
        string(1) "3"
        ["left"]=>
        string(1) "4"
        ["right"]=>
        string(1) "5"
      }
      [4]=> // Black
      array(6) {
        ["item_id"]=>
        string(1) "4"
        ["parent_id"]=>
        string(1) "2"
        ["sort_index"]=>
        string(1) "2"
        ["depth"]=>
        string(1) "3"
        ["left"]=>
        string(1) "6"
        ["right"]=>
        string(1) "7"
      }
      [5]=> // Motor
      array(6) {
        ["item_id"]=>
        string(2) "5"
        ["parent_id"]=>
        string(0) ""
        ["sort_index"]=>
        string(1) "1"
        ["depth"]=>
        string(1) "1"
        ["left"]=>
        string(2) "10"
        ["right"]=>
        string(2) "11"
      }
      [6]=> // Truck
      array(6) {
        ["item_id"]=>
        string(2) "6"
        ["parent_id"]=>
        string(0) ""
        ["sort_index"]=>
        string(1) "1"
        ["depth"]=>
        string(1) "1"
        ["left"]=>
        string(2) "10"
        ["right"]=>
        string(2) "11"
      }
   }
}

toArray function of nestedSortable Plugin

This is the toArray function of the NestedSortable Plugin. I did insert the

"sort_index": ,

at

ret.push()

The toArray functin:

toArray: function(options) {

            var o = $.extend({}, this.options, options),
                sDepth = o.startDepthCount || 0,
                ret = [],
                left = 2;

            ret.push({
                "item_id": o.rootID,
                "parent_id": 'none',
                "depth": sDepth,
                "left": '1',
                "right": ($(o.items, this.element).length + 1) * 2
            });

            $(this.element).children(o.items).each(function () {
                left = _recursiveArray(this, sDepth + 1, left);
            });

            ret = ret.sort(function(a,b){ return (a.left - b.left); });

            return ret;

            function _recursiveArray(item, depth, left) {

                var right = left + 1,
                    id,
                    pid;

                if ($(item).children(o.listType).children(o.items).length > 0) {
                    depth ++;
                    $(item).children(o.listType).children(o.items).each(function () {
                        right = _recursiveArray($(this), depth, right);
                    });
                    depth --;
                }

                id = ($(item).attr(o.attribute || 'id')).match(o.expression || (/(.+)[-=_](.+)/));

                if (depth === sDepth + 1) {
                    pid = o.rootID;
                } else {
                    var parentItem = ($(item).parent(o.listType)
                                             .parent(o.items)
                                             .attr(o.attribute || 'id'))
                                             .match(o.expression || (/(.+)[-=_](.+)/));
                    pid = parentItem[2];
                }

                if (id) {
                        ret.push({"item_id": id[2], "parent_id": pid, "sort_index": , "depth": depth, "left": left, "right": right});
                }

                left = right + 1;
                return left;
            }

        },

Like I said, it would be nice to give a sort_Index to the toArray function, but I've been looking for days now and I'm pretty clueless on how to solve this.


Solution

  • PROBLEM SOLVED

    By editing the jQuery Plugin.

    Add this line to the _recursiveArray(item, depth, left) function:

    si = ($(item).index(o.item));
    

    Define the var si:

    var right = left + 1,
        id,
        pid,
        si;
    

    And in the ret.push add your variable like this:

    ret.push({"item_id": id[2], "parent_id": pid, "sort_index": si+1, "depth": depth, "left": left, "right": right});
    

    So it will look like this:

    toArray: function(options) {
    
        var o = $.extend({}, this.options, options),
            sDepth = o.startDepthCount || 0,
            ret = [],
            left = 2;
    
        ret.push({
            "item_id": o.rootID,
            "parent_id": 'none',
            "sort_index" : this.element.index(this.element),
            "depth": sDepth,
            "left": '1',
            "right": ($(o.items, this.element).length + 1) * 2
        });
    
        $(this.element).children(o.items).each(function () {
            left = _recursiveArray(this, sDepth + 1, left);
        });
    
        ret = ret.sort(function(a,b){ return (a.left - b.left); });
    
        return ret;
    
        function _recursiveArray(item, depth, left) {
    
            var right = left + 1,
                id,
                pid,
                si;
    
            if ($(item).children(o.listType).children(o.items).length > 0) {
                depth ++;
                $(item).children(o.listType).children(o.items).each(function () {
                    right = _recursiveArray($(this), depth, right);
                });
                depth --;
            }
    
            id = ($(item).attr(o.attribute || 'id')).match(o.expression || (/(.+)[-=_](.+)/));
    
            if (depth === sDepth + 1) {
                pid = o.rootID;
            } else {
                var parentItem = ($(item).parent(o.listType)
                                         .parent(o.items)
                                         .attr(o.attribute || 'id'))
                                         .match(o.expression || (/(.+)[-=_](.+)/));
                pid = parentItem[2];
            }
    
            si = ($(item).index(o.item));
    
            if (id) {
                    ret.push({"item_id": id[2], "parent_id": pid, "sort_index": si+1, "depth": depth, "left": left, "right": right});
            }
    
            left = right + 1;
            return left;
        }
    
    },