1

I'm working on a chrome extension and need to generate nested DOM-elements based on categories. These categories are saved as strings in an array. The hierarchy level of sub-categories is shown through paths.

Here is an simple example

category array:

let categories = [a, a/b, b, b/c/d];

I want to generate nested div elements like that:

<div id="a">
    <div id="b"></div>
</div>
<div id="b">
    <div id="c">
        <div id="d"></div>            
    </div>
</div>

With my current status I only create the unique top level div's and don't know how to generate the unique sub-categories in the top level div's as well.

categories.forEach(function (i) {

  let splitedCategory = i.split('/');

  let parentID = String(splitedCategory[0]);
  let parentElement = document.getElementById(parentID);

  if(!containerElement.contains(parentElement)) {
    containerElement.innerHTML += '<div id="' + i + '"></div>';
  }
});
iamrobin.
  • 1,554
  • 3
  • 19
  • 31

2 Answers2

2

let categories = ['a', 'a/b', 'b', 'b/c/d'];

function f(str, html = ''){
  str = str.split('/');
  html += `<div id="${str[0]}">`
  if(str.length > 1){
    html += f(str.slice(1).join("/"));
  }
  html += `</div>`;
  return html;
}

categories.map(a=>console.log(f(a, '')))
  • oh that's pure magic, thanks! I just tried to edit the code, that all of the ids are unique but can't really implement it.
    – iamrobin. Jun 04 '18 at 19:43
1

At first you need to format your array as object with levels, then recursivelly create DOM Elements. Here is a full example:

<html>
    <head>
        <meta charset="UTF-8" />
    </head>
    <body>
        <div id="result"></div>
        <script type="text/javascript">
        /**
         * Build HTML tree recursively from object.
         *
         * @param  Object  obj
         * @param  Element context
         * @param  String  prefix
         * @return void
         */

        function buildTree(obj, context, prefix){
            for(var key in obj){
                let div = document.createElement('div'),
                    pID = prefix ? prefix+'_'+key : key;

                div.setAttribute('id', pID);
                div.classList.add(key);
                buildTree(obj[key], div, pID);
                context.appendChild(div);
            }
        }

        /**
         * Format array as tree.
         *
         * @param  Array  arr
         * @param  String separator
         * @return Object
         */

        function arrayToTree(arr, separator){
            let formatted = {};

            if(!separator){
                separator = '/';
            }

            for(let i=0; i<arr.length; i++){
                let category = arr[i],
                    parts    = category.split(separator),
                    current  = formatted;

                for(let e=0; e<parts.length; e++){
                    let lvl = parts[e];

                    if(!current[lvl]){
                        current[lvl] = {};
                    }

                    current = current[lvl];
                }
            }

            return formatted;
        }

        var pathsTree = arrayToTree(['a', 'a/b', 'b', 'b/c/d']),
            resultDiv = document.getElementById('result');

        buildTree(pathsTree, resultDiv);
        </script>
    </body>
</html>
Vitalii
  • 161
  • 1
  • 10
  • thanks for this good answer, helped me a lot! How can I get an unique ID for each element with there path name? For example
    ?
    – iamrobin. Jun 05 '18 at 18:42
  • 1
    @iamrobin. I modified my answer. Now function buildTree has third parameter prefix to help get unique path ID. – Vitalii Jun 05 '18 at 18:57