Creating a menu as nested unordered lists from JSON data

Posted on

Problem

I have a JSON input using which I have written below function to recursively create an unordered list.

Is there more precise way to achieve it?

$(document).ready(function () {
        var htmlTxt = "";
        var cat = [];
        var htmlStrTxt = "";
        var url = "#";

        function recurseMenu(parent, level) {
            htmlStrTxt = '<ul>';
            for (var x in menuItems) {
                if (menuItems[x].parentId == parent) {
                    htmlStrTxt += '<li><img/><a href="' + url + '">' + menuItems[x].title + '</a>';

                    if (menuItems[x].childCount > 0) {
                        htmlStrTxt += recurseMenu(menuItems[x].id, level + 1);
                    }
                    htmlStrTxt += '</li>';
                }
            }
            return htmlStrTxt + '</ul>';
        }

        var htmlTxt = recurseMenu(null, 0);
        $("#listContainer").html(htmlTxt);
     });
<!-- Test case -->
<div id="listContainer"></div>
<script>
var menuItems = {
        "menu-0": {
            "id": "menu-0",
            "title": "Home",
            "parentId": null,
            "childCount": 0
        },
        "menu-1": {
            "id": "menu-1",
            "title": "About",
            "parentId": null,
            "childCount": 2
        },
        "menu-3": {
            "id": "menu-3",
            "title": "About Sub1",
            "parentId": "menu-1",
            "childCount": 2
        },
        "menu-5": {
            "id": "menu-5",
            "title": "About Sub2",
            "parentId": "menu-1",
            "childCount": 0
        },
        "menu-4": {
            "id": "menu-4",
            "title": "About Sub1 sub1",
            "parentId": "menu-3",
            "childCount": 0
        },
        "menu-6": {
            "id": "menu-6",
            "title": "Contact",
            "parentId": null,
            "childCount": 2
        },
        "menu-7": {
            "id": "menu-7",
            "title": "Contact sub1",
            "parentId": "menu-6",
            "childCount": 0
        },
        "menu-8": {
            "id": "menu-8",
            "title": "Contact sub2",
            "parentId": "menu-6",
            "childCount": 1
        },
        "menu-9": {
            "id": "menu-9",
            "title": "Contact sub2 sub1",
            "parentId": "menu-8",
            "childCount": 0
        },
        "menu-10": {
            "id": "menu-10",
            "title": "About Sub1 sub2",
            "parentId": "menu-3",
            "childCount": 2
        },
        "menu-11": {
            "id": "menu-11",
            "title": "About Sub1 sub2 sub1",
            "parentId": "menu-10",
            "childCount": 0
        } ,
        "menu-12": {
            "id": "menu-11",
            "title": "About Sub1 sub2 sub2",
            "parentId": "menu-10",
            "childCount": 0
        }
      };
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Solution

At the very least, you should clean up your variables:

  • htmlTxt is declared as var twice in the same scope. I don’t think you even need it at all.
  • cat is never used.
  • htmlStrTxt would be better as a local function within recurseMenu(). A shorter variable name would do just as well.
  • The level parameter is useless.
$(document).ready(function () {
        var url = "#";

        function recurseMenu(parent) {
            var s = '<ul>';
            for (var x in menuItems) {
                if (menuItems[x].parentId == parent) {
                    s += '<li><img/><a href="' + url + '">' + menuItems[x].title + '</a>';

                    if (menuItems[x].childCount > 0) {
                        s += recurseMenu(menuItems[x].id);
                    }
                    s += '</li>';
                }
            }
            return s + '</ul>';
        }

        $("#listContainer").html(recurseMenu());
     });
<!-- Test case -->
<div id="listContainer"></div>
<script>
var menuItems = {
        "menu-0": {
            "id": "menu-0",
            "title": "Home",
            "parentId": null,
            "childCount": 0
        },
        "menu-1": {
            "id": "menu-1",
            "title": "About",
            "parentId": null,
            "childCount": 2
        },
        "menu-3": {
            "id": "menu-3",
            "title": "About Sub1",
            "parentId": "menu-1",
            "childCount": 2
        },
        "menu-5": {
            "id": "menu-5",
            "title": "About Sub2",
            "parentId": "menu-1",
            "childCount": 0
        },
        "menu-4": {
            "id": "menu-4",
            "title": "About Sub1 sub1",
            "parentId": "menu-3",
            "childCount": 0
        },
        "menu-6": {
            "id": "menu-6",
            "title": "Contact",
            "parentId": null,
            "childCount": 2
        },
        "menu-7": {
            "id": "menu-7",
            "title": "Contact sub1",
            "parentId": "menu-6",
            "childCount": 0
        },
        "menu-8": {
            "id": "menu-8",
            "title": "Contact sub2",
            "parentId": "menu-6",
            "childCount": 1
        },
        "menu-9": {
            "id": "menu-9",
            "title": "Contact sub2 sub1",
            "parentId": "menu-8",
            "childCount": 0
        },
        "menu-10": {
            "id": "menu-10",
            "title": "About Sub1 sub2",
            "parentId": "menu-3",
            "childCount": 2
        },
        "menu-11": {
            "id": "menu-11",
            "title": "About Sub1 sub2 sub1",
            "parentId": "menu-10",
            "childCount": 0
        } ,
        "menu-12": {
            "id": "menu-11",
            "title": "About Sub1 sub2 sub2",
            "parentId": "menu-10",
            "childCount": 0
        }
      };
</script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Leave a Reply

Your email address will not be published. Required fields are marked *