0

I've a nested list items. I want to make an multi-dimensional array or json object from the list items. I've tried something like below. But I'm not getting the expected output.

The depth of the list item can be more. So, I'll define a recursive method to do this later.

DEMO Fiddle

HTML:

<div class="dd" id="nestable">
    <ol class="dd-list">
        <li class="dd-item" data-id="1">
            <div class="dd-handle">Sub-indicator 1</div>
            <ol class="dd-list">
                <li class="dd-item" data-id="2">                    
                    <div class="dd-handle">Sub-indicator 2</div>
                    <ol class="dd-list">
                        <li class="dd-item" data-id="3">

                            <div class="dd-handle">Sub-indicator 3</div>
                            <ol class="dd-list">
                                <li class="dd-item" data-id="4">

                                    <div class="dd-handle">Sub-indicator 4</div>
                                </li>
                            </ol>
                        </li>
                    </ol>
                </li>
                <li class="dd-item" data-id="3">

                            <div class="dd-handle">Sub-indicator 3</div>
                            <ol class="dd-list">
                                <li class="dd-item" data-id="4">

                                    <div class="dd-handle">Sub-indicator 4</div>
                                </li>
                            </ol>
                        </li>
            </ol>
        </li>
    </ol>
</div>

JS:

var subIndicTreeObj = {};
var tempObj = [];
var parentId = 0;
var parentId1 = 0;
var parentId2 = 0;

$('#nestable > ol > li').each(function(index, value) { 
    parentId = 0;
    parentId1 = 0;
    parentId2 = 0;

    tempObj.push({'sub_indic_id': $(this).attr('data-id'), 'parent_id': parentId});


    if ($(this).has('ol').length > 0) { 

        parentId = $(this).attr('data-id');

        $(this).find('ol > li').each(function(index1, value1) { 

            tempObj.push({'sub_indic_id': $(this).attr('data-id'), 'parent_id': parentId});


            if ($(this).has('ol').length > 0) {  

                parentId1 = $(this).attr('data-id');

                $(this).find('ol > li').each(function(index2, value2) { 

                    tempObj.push({'sub_indic_id': $(this).attr('data-id'), 'parent_id': parentId1});

                    if ($(this).has('ol').length > 0) { 


                        parentId2 = $(this).attr('data-id');

                        $(this).find('ol > li').each(function(index3, value3) { 

                            tempObj.push({'sub_indic_id': $(this).attr('data-id'), 'parent_id': parentId2});

                        });
                    }

                });
            } 
        });
    } 
});

subIndicTreeObj = tempObj;

console.log(subIndicTreeObj);

Current Output:

 [
  Object{
    sub_indic_id="1",
    parent_id=0
  },
  Object{
    sub_indic_id="2",
    parent_id="1"
  },
  Object{
    sub_indic_id="3",
    parent_id="2"
  },
  Object{
    sub_indic_id="4",
    parent_id="3"
  },
  Object{
    sub_indic_id="4",
    parent_id="2"
  },
  Object{
    sub_indic_id="3",
    parent_id="1"
  },
  Object{
    sub_indic_id="4",
    parent_id="3"
  },
  Object{
    sub_indic_id="4",
    parent_id="1"
  },
  Object{
    sub_indic_id="3",
    parent_id="1"
  },
  Object{
    sub_indic_id="4",
    parent_id="3"
  },
  Object{
    sub_indic_id="4",
    parent_id="1"
  }
]

I want the immediate parent_id of a child. But I'm getting the top level parent_id for some list item. Such as,

Object{
    sub_indic_id="4",
    parent_id="1"
  }

Can anybody help to find out the problem ? Thanks in advance.

2 Answers 2

2

I didn't understand if it's the expected behaviour, anyway, it's recursive, and also find the first child. I just added a > before the ol > li selector.

Note that i also added a data-id='0' to id="nestable" to get the first parent id.

edit

For more detail about > selector as asked in comment, i suggest to have look to some documentation. I mostly learned from w3school. Reporting from that link

The element>element selector is used to select elements with a specific parent.

So, in your code with ol > li you were retriving all the li children of every ol, contained in $(this).

With > ol > li you retrive the direct children of the object on which you're searching, and not also the children of chidren.

var subIndicTreeObj = [];

function findLiChild($obj, parentId) {
  $obj.find('> ol > li').each(function(index1, value1) {
    subIndicTreeObj.push({
      'sub_indic_id': $(this).attr('data-id'),
      'parent_id': parentId
    });

    findOlChild($(this));
  });
}

function findOlChild($obj) {
  if ($obj.has('ol').length > 0) {
    findLiChild($obj, $obj.attr('data-id'));
  }
}

findOlChild($('#nestable'));

console.log(subIndicTreeObj);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="dd" id="nestable" data-id="0">
  <ol class="dd-list">
    <li class="dd-item" data-id="1">
      <div class="dd-handle">Sub-indicator 1</div>
      <ol class="dd-list">
        <li class="dd-item" data-id="2">
          <div class="dd-handle">Sub-indicator 2</div>
          <ol class="dd-list">
            <li class="dd-item" data-id="3">

              <div class="dd-handle">Sub-indicator 3</div>
              <ol class="dd-list">
                <li class="dd-item" data-id="4">

                  <div class="dd-handle">Sub-indicator 4</div>
                </li>
              </ol>
            </li>
          </ol>
        </li>
        <li class="dd-item" data-id="3">

          <div class="dd-handle">Sub-indicator 3</div>
          <ol class="dd-list">
            <li class="dd-item" data-id="4">

              <div class="dd-handle">Sub-indicator 4</div>
            </li>
          </ol>
        </li>
      </ol>
    </li>
  </ol>
</div>

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks a lot. It works. But can you tell me what's the purpose of the > before ol > li ?
Sure. It retrive only the first level children of the object on which you call find. I try to add a better explanation in my answer right now.
0

Try a simple loop:

var data = [];//create the array
$('.dd-item').each(function() {//loop each item
  var parent = $(this).parent().closest('.dd-item');//get the parent
  var parent_id = 0;//set 0 if it has no parent
  if (parent.length) {
    parent_id = parent.attr('data-id');//set parent id if it has
  }
  data.push({
    parent_id: parent_id ,sub_indic_id: $(this).attr('data-id')
  });//append to the array
});
console.log(data);

demo:https://jsfiddle.net/uwqqmz86/

3 Comments

OP is looking to do the reverse
@Rajesh you mean the child is note and the parent id the leaf?\
No. I mean he has the markup and he wishes to generate JSON, Please check other answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.