How to create a nested menu using CSV file content

Viewed 516

I need to use a CSV file for creating a webpage menu structure.

Can anyone please help me to create a nested menu in Jacascript using the given CSV structure?

The columns are: Level, Menu name, URL

0;"Service";
1;"Service 1";"http://some-url-1.com"
1;"Service 2";"http://some-url-2.com"
0;"Sales";
1;"Sales 1";"http://some-url-3.com"
1;"Sales 2";"http://some-url-4.com"
1;"Sales 3";
2;"Sales 3 Sub 1";"http://some-ulr-5.com";
0;"Development";"http://some-url-6.com"
0;"Internet";
1;"Internet 1";
2;"Internet 1 Sub 1";"http://some-url-7.com";

The first column shows the menu levels. 0- root level 1- first level 2- second level

Also the order of the menu items should be exactly as given in the CSV file.

3 Answers

you can use this code, this works for more than 3 levels. I commented out ajax call and converted your csv data to string for testing, because SO editor won't get the csv file, you can use ajax and get csv content in your project.

note: i assumed the level/depth of menu item increases by one, but can decrease by more than one.

$(function () {

            var data_str = '0;\"Service\";\n1;\"Service 1\";\"http:\/\/some-url-1.com\"\n1;\"Service 2\";\"http:\/\/some-url-2.com\"\n0;\"Sales\";\n1;\"Sales 1\";\"http:\/\/some-url-3.com\"\n1;\"Sales 2\";\"http:\/\/some-url-4.com\"\n1;\"Sales 3\";\n2;\"Sales 3 Sub 1\";\"http:\/\/some-ulr-5.com\";\n3;\"Sales 3 Sub 1 Sub 1\";\"http:\/\/some-ulr-5.com\";\n4;\"Sales 3 Sub 1 Sub 1 Sub 1\";\"http:\/\/some-ulr-5.com\";\n0;\"Development\";\"http:\/\/some-url-6.com\"\n0;\"Internet\";\n1;\"Internet 1\";\n2;\"Internet 1 Sub 1\";\"http:\/\/some-url-7.com\";';
            CreateMenu();
            function CreateMenu() {
                var lines = data_str.replace(/"/g, '').split(/\r\n|\n/);
                var menu_html = '';
                var levels = [];
                for (var i = 0; i < lines.length; i++) {
                    var menu_item = lines[i].split(';')
                    levels.push(parseInt(menu_item[0]));
                }
                var parent = -1;
                for (var i = 0; i < lines.length; i++) {
                    var menu_item = lines[i].split(';')
                    var link = "";
                    if (levels[i] == 0) {
                        link = menu_item[1];
                    }
                    else {
                        link = '<a href="' + menu_item[2] + '"> ' + menu_item[1] + '</a>';
                    }
                    if (levels[i] < parent) {
                        var prefix = '</ul></li><li>';
                        for (var j = 1; j < parent - levels[i]; j++) {
                            prefix = '</ul></li>' + prefix;
                        }
                        menu_html += prefix + link

                    }
                    if (levels[i] == parent) {
                        menu_html += '</li><li>' + link
                    }
                    if (levels[i] > parent) {
                        menu_html += '<ul><li>' + link
                    }
                    parent = levels[i];

                } 
                $(menu_html).appendTo($('#menu_parent'));
            }
            //$.ajax({
            //    type: "GET",
            //    url: "data.csv",
            //    dataType: "text",
            //    success: function (data) {
            //        data_str = data;
            //        CreateMenu();
            //    }
            //});
        });
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="menu_parent"></div>

You can use JQuery library to build your custom menu. Moreover, you can adjust custom css based on your element's class or attributes. here is a sample menu for your case.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <title></title>
    <script src="https://code.jquery.com/jquery-1.10.2.min.js"></script>
    <script>
        var strcsv = '0; "Service";\r\n1; "Service 1"; "http://some-url-1.com"\r\n1; "Service 2"; "http://some-url-2.com"\r\n0; "Sales";\r\n1; "Sales 1"; "http://some-url-3.com"\r\n1; "Sales 2"; "http://some-url-4.com"\r\n1; "Sales 3";\r\n2; "Sales 3 Sub 1"; "http://some-ulr-5.com";\r\n0; "Development"; "http://some-url-6.com"\r\n0; "Internet";\r\n1; "Internet 1";\r\n2; "Internet 1 Sub 1"; "http://some-url-7.com";';
        function CreateMenu(csvString, dvpanel) {
            var items = csvString.split(/\r\n|\n|\r/);
            for (var i = 0; i < items.length; i++) {
                var spliteditem = items[i].split(/\;/);
                var lvl = spliteditem[0];
                var title = spliteditem[1];
                var url = (spliteditem.length < 3) ? null : spliteditem[2];

                var $holderdv;
                if (lvl == "0") $holderdv = $(dvpanel);
                else {
                    $holderdv = $(dvpanel).find("div[menuitem-level='" + (lvl - 1) + "']").filter(function () { return $(this).attr("menuitem-index") < i; }).last();
                }
                $holderdv
                    .append($("<div menuitem-level='" + lvl + "' menuitem-index='" + i + "'>")
                        .append($("<a href='" + (url == null ? "#" : url) + "'>")
                            .append($("<span>")
                                .html(title))))

            }
        }
        $(function () { CreateMenu(strcsv, $("#MenuPanel")); });
    </script>
    <style>
        div[menuitem-level='0'] {
            margin: 5px;
            background-color: #eaeaea;
        }

        div[menuitem-level='1'] {
            margin: 20px;
            background-color: #d1d1d1;
        }

        div[menuitem-level='2'] {
            margin: 30px;
            background-color: #a5a5a5;
        }
    </style>
</head>
<body>
    <div id="MenuPanel"></div>       
</body>
</html>

You can consider using SlickGrid for this. It is super-easy to use and is awesome performance-wise. Plus, your case, you can create a tree-like structure which you can easily collapse/expand/filter. Check this sample out.

Related