Search code examples
jsonjquerytwitter-bootstrapmustache

twitter bootstrap ajax dropdown


I'm trying to build a dynamic menu using twitter bootstrap. The idea is to load a json file with the menu items inside:

// test.json

{
"children": [
    {
    "text": "Item1",
    "children": [
        {"text": "Item11", "link": "/link11"},
        {"text": "Item12", "link":"/link12"},
        {"text": "Item13", "children": [
            {"text": "Item131", "link":"/link131"},
            {"text": "Item132", "link":"/link132"}
        ]},
        {"text": "Item14", "link":"/link13"}
    ]},
    {
    "text": "Item2",
    "children": [
        {"text": "Item21", "link":"/link21"},
        {"text": "Item22", "link":"/link22"}
    ]},
    {
    "text": "Item3"
    }
]
}

This can be statically rendered in Twitter bootstrap:

// index.html

<!DOCTYPE html>
<html lang="en">
<head>
   <title>Test</title>
   <meta name="viewport" content="width=device-width, initial-scale=1.0">
   <link href="bootstrap/css/bootstrap.min.css" rel="stylesheet" media="screen">
</head>
<body>
<div class="navbar">
    <div class="navbar-inner" id ="navbar-inner-main">
        <div class="container">
            <div class="nav-collapse collapse navbar-responsive-collapse">
                <ul class="nav">
                    <li class="dropdown">
                        <a class="dropdown-toggle" data-toggle="dropdown" href="#">Item1</a>
                        <ul class="dropdown-menu">
                            <li>
                                <a href="/link11">Item11</a>
                            </li>
                            <li>
                                <a href="/link12">Item12</a>
                            </li>
                            <li class="dropdown-submenu">
                                <a class="dropdown-toggle" data-toggle="dropdown" href="#">Item13</a>
                                <ul class="dropdown-menu">
                                    <li>
                                        <a href="/link131">Item131</a>
                                    </li>
                                    <li>
                                        <a href="/link132">Item132</a>
                                    </li>   
                                </ul>
                            </li>
                        </ul>
                    </li>
                    <li class="dropdown">
                        <a class="dropdown-toggle" data-toggle="dropdown" href="#">Item2</a>
                        <ul class="dropdown-menu">
                            <li>
                                <a href="/link21">Item21</a>
                            </li>
                            <li>
                                <a href="/link22">Item22</a>
                            </li>   
                        </ul>
                    </li>
                    <li>
                        <a href="#">Item3</a>
                    </li>
                </ul>
            </div>
        </div>
    </div>
</div>     
<script src="http://code.jquery.com/jquery.js"></script>
<script src="bootstrap/js/bootstrap.min.js"></script>

I'd like to add to index.html a function like this:

<script type="text/javascript">
    $(document).ready(function () {
      $.getJSON('ajax/test.json', function(data) {
      // get json, parse it and append to .nav
      });     
});
</script>

I think the best approach to parse json into unordered list is using templates. I tried with pure and mustache without success. The problem is due to dropdown-submenu class who makes a recursive approach inconsistent.

Do you have any suggestion ?

Thanks in advance


Solution

  • I had similar issue. Here is solution:

    My JSON

    [{
    "name": "Cars",
    "url": "#",
    "parent_id": "-1",
    "id": "1"
     }, {
    "name": "Toyota",
    "url": "#",
    "parent_id": "1",
    "id": "2"
        }, {
    "name": "Corolla",
    "url": "#",
    "parent_id": "2",
    "id": "3"
     }, {
    "name": "2013",
    "url": "#",
    "parent_id": "3",
    "id": "4"
        },
    ...
    

    And here is JS that generate dropdowns with bootstrap classes

    //load JSON file
    $.getJSON('menu.json', function(data) {
    //build menu
    var builddata = function () {
    var source = [];
    var items = [];
    for (i = 0; i < data.length; i++) {
        var item = data[i];
        var label = item["name"];
        var parentid = item["parent_id"];
        var id = item["id"];
        var url = item["url"];
    
        if (items[parentid]) {
            var item = { parentid: parentid, label: label, url: url, item: item };
            if (!items[parentid].items) {
                items[parentid].items = [];
            }
            items[parentid].items[items[parentid].items.length] = item;
            items[id] = item;
        }
        else {
            items[id] = { parentid: parentid, label: label, url: url, item: item };
            source[id] = items[id];
        }
    }
    return source;
    }
    
    var buildUL = function (parent, items) {
    $.each(items, function () {
        if (this.label) {
            var li = $("<li class='js-menu'>" + "<a href='"+ this.url +"'>" + this.label + "      </a></li>");
            li.appendTo(parent);
            if (this.items && this.items.length > 0) {
                var ul = $("<ul class='dropdown-menu js-menu'></ul>");
                ul.appendTo(li);
                buildUL(ul, this.items);
            }
        }
    });
    }
    var source = builddata();
    var ul = $(".json-menu");
    ul.appendTo(".json-menu");
    buildUL(ul, source);
    //add bootstrap classes
    if ($(".json-menu>li:has(ul.js-menu)"))
    {
    $(".json-menu>li.js-menu").addClass('dropdown-submenu');
    }
    if ($(".json-menu>li>ul.js-menu>li:has(> ul.js-menu)"))
    {
    $(".json-menu>li>ul.js-menu li ").addClass('dropdown-submenu');
    }
    $("ul.js-menu").find("li:not(:has(> ul.js-menu))").removeClass("dropdown-submenu");
    });
    

    So all you need is add 'json-menu' class near 'dropdown' bootsrap class

    <ul class="dropdown-menu json-menu">
    </ul>
    

    you can see live example here