0

I'm trying to save a list into json object by looping through it using a recursive function, so this is what I did so far:
My list:

<ul id="Menu">
    <li>Menu
        <ul>
            <li>Test 1</li>
            <li>Test 2
                <ul>
                    <li>Sub test 2/1</li>
                    <li>Sub test 2/2</li>
                    <li>Sub test 2/3</li>
                </ul>
            </li>
            <li>Test 3</li>
            <li>Test 4</li>     
        </ul>
    </li>
    <li>Menu2</li>
</ul>

My script:

<script>
jQuery(document).ready(function(){
    item = {};
    buildMenu($('#Menu'), item);
    menu.push(item);
    console.log(JSON.stringify(menu));  
});
var menu = [];

function buildMenu(ul, item){
    var children = [];
    ul.find('li').each(function(){
        var current = $(this);
        if(current.find('ul').length > 0){
            var newItem = {};
            buildMenu(current.find('ul'), newItem);
            children.push(newItem);
        }else{
            children.push(current.text());
        }
    });

    var txt = $(this).text();
    console.log('pushing into: '+txt);
    item[txt] = children;   
}
</script>

I want to save each menu and it's children inside it as json objects and send it to php but I'm having wrong output:

[{"MenuTest 1Test 2Sub test 2/1Sub test 2/2Sub test 2/3Test 3Test 4Menu2":[{"Test 1Test 2Sub test 2/1Sub test 2/2Sub test 2/3Test 3Test 4":["Test 1",{"Sub test 2/1Sub test 2/2Sub test 2/3":["Sub test 2/1","Sub test 2/2","Sub test 2/3"]},"Sub test 2/1","Sub test 2/2","Sub test 2/3","Test 3","Test 4"]},"Test 1",{"Sub test 2/1Sub test 2/2Sub test 2/3":["Sub test 2/1","Sub test 2/2","Sub test 2/3"]},"Sub test 2/1","Sub test 2/2","Sub test 2/3","Test 3","Test 4","Menu2"]}]

What's wrong with my function ?

SlimenTN
  • 3,383
  • 7
  • 31
  • 78

2 Answers2

1

is this what you are looking for?

var menu = [];
$(document).ready(function(){
    item = {};
    buildMenu($('#Menu'), item);
    menu.push(item);
    console.log(menu);  
});


function buildMenu(ul, item){
    var children = [];
    ul.children('li').each(function(){
        var current = $(this);
        if(current.children('ul').length > 0){
            var newItem = {};
            buildMenu(current.children('ul'), newItem);
            children.push(newItem);
        }else{
            children.push(current.text());
        }
    })

var txt = ul.parent().html();
txt = txt.replace(/\<ul.*[\s\S]*\<\/ul\>/g,"").trim();
console.log(txt);
item[txt] = children;      
}

you should only select immediate children.

fiddle: https://jsfiddle.net/nsj3gqt5/1/

Shekhar Joshi
  • 958
  • 1
  • 13
  • 26
  • Good answer only one little problem in json object we can't find the name of the parent! [{"":[{"":["Test 1",{"":["Sub test 2/1","Sub test 2/2","Sub test 2/3"]},"Test 3","Test 4"]},"Menu2"]}] – SlimenTN Apr 27 '16 at 09:34
  • I have tried to name the objects, have a look. The outer most object will have blank name. – Shekhar Joshi Apr 27 '16 at 10:03
  • 1
    it's ok I found a solution to put names, and thank you again for you time :) – SlimenTN Apr 27 '16 at 10:30
0

From what I understood, this script will do what you need, create menu with submenus and menu items

$(function() {
    var menu = [];
    buildMenu($('#Menu'), menu);
    console.log(JSON.stringify(menu));  
});

function buildMenu(item, parentList) {
    var isNode = function(item) {
        return item.is('li');
    }
    var isList = function(item) {
        return item.is('ul');
    }
    var hasChildren = function(item) {
        return item.children().length > 0;
    }

    var itemSubList = [];
    if (isNode(item)) {
        if (hasChildren(item)) {
            // This is subMenu
            // console.log("subMenu " + item.justtext().trim());
            var subMenu = {};
            subMenu[item.justtext().trim()] = itemSubList;
            parentList.push(subMenu);
        } else {
            // This is menuItem
            // console.log("menuItem " + item.text()); 
            parentList.push(item.text());
            return;
        }
    } else if (isList(item)) {
        // Processing list
        // console.log("list");
        itemSubList = parentList;
    }   
    item.children().each(function() {
        var child = $(this);
        buildMenu(child, itemSubList);
    });
}

Note that I used justtext jquery plugin to get element's text without child elements, so you should include this script

<!-- include justtext jquery plugin -->
<script src="http://viralpatel.net/blogs/demo/jquery/get-text-without-child-element/jquery.justtext.1.0.js"></script>
Marin Relatic
  • 238
  • 2
  • 9