javascriptarrayssplitnestedgenerated-code

generate div elements based on string paths


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>';
  }
});

Solution

  • 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>