0

I have a function I am using to take a generated nested array and turn it into nested ULs:

const prepareUL = (root, arr) => {
   let ul = document.createElement('ul');
  
   root.appendChild(ul);
   arr.forEach(function(item) {
      let li = document.createElement('li');
      if (Array.isArray(item)) {
         prepareUL(li, item);
         ul.appendChild(li);
         return
      };
      li.appendChild(document.createTextNode(item));
      ul.appendChild(li);
   });
   
}

The generated array looks like:

[
   [
    "text-ID1",
    "Section Title 1",
    "Section paragraph 1",
    "Section Paragraph 2"
    ],
    [
    "text-ID2",
    "Section Title 2",
    "Section paragraph 1",
    "Section Paragraph 2"
    ],
    [
    "text-ID3",
    "Section Title 3",
    "Section paragraph 1",
    "Section Paragraph 2"
    ]
]

I need to get the second element from array and extract it and prepend it to the UL it belongs to as a div. So generated structure would look like:

<ul>
    <div>Section Title 1</div>
    <ul>
        <li>Section paragraph 1</li>
        <li>Section paragraph 2</li>
    </ul>
    <div>Section Title 3</div>
    <ul>
        <li>Section paragraph 1</li>
        <li>Section paragraph 2</li>
    </ul>
    <div>Section Title 3</div>
    <ul>
        <li>Section paragraph 1</li>
        <li>Section paragraph 2</li>
    </ul>
</ul>

My untrained instinct is to use DOM manipulation after the fact, because I know how to do that, but it seems inelegant and like I should be able to do that here. Too new to understand it well enough.

2
  • I suppose it's not good to have div, ul to be children of ul. more info here.. stackoverflow.com/a/11755657/6310485 Commented Sep 23, 2022 at 15:08
  • @harpal Appreciated. I have fixed the output of the code to use legal HTML. Commented Sep 23, 2022 at 17:55

3 Answers 3

1

This should help you

Update:-

        var arr = [
            [
                "text-ID1",
                "Section Title 1",
                "Section paragraph 1",
                "Section Paragraph 2"
            ],
            [
                "text-ID2",
                "Section Title 2",
                "Section paragraph 1",
                "Section Paragraph 2"
            ],
            [
                "text-ID3",
                "Section Title 3",
                "Section paragraph 1",
                "Section Paragraph 2"
            ]
        ];
        const prepareUL = (root, arr) => {
            let main = document.createElement('ul');
            let root2 = document.getElementById(root)

            arr.forEach(function (item) {

                let title_div = document.createElement('div');
                title_div.innerHTML = item[1];

                let item_ul = document.createElement('ul');
                for (var i = 2; i < item.length; i++) {
                    let item_li = document.createElement('li');
                    item_li.innerHTML = item[i];
                    item_ul.append(item_li);
                }
                main.appendChild(title_div);
                main.appendChild(item_ul);

            });
            root2.appendChild(main)
        }

        prepareUL("root", arr);
 <id id="root"></id>

Sign up to request clarification or add additional context in comments.

2 Comments

This is so far the closest, I need the text-ID to be ignored and the Section Title to be pushed to the div.
@chris Code updated
1

To simplify the control about the Array of Arrays (Matrix) I suggest to use for loop, using the for loop, this could be a solution:

const arr = [
    [
    "text-ID1",
    "Section Title 1",
    "Section paragraph 1",
    "Section Paragraph 2"
    ],
    [
    "text-ID2",
    "Section Title 2",
    "Section paragraph 1",
    "Section Paragraph 2"
    ],
    [
    "text-ID3",
    "Section Title 3",
    "Section paragraph 1",
    "Section Paragraph 2"
    ]
]

const prepareUL = (root, arr) => {
   let ul = document.createElement('ul');
  
   root.appendChild(ul);
    
   for (let i=0; i<arr.length; i++) {
     for (let j=0; j<arr[i].length; j++) {
       if (j==0) { continue; }       
       const item = arr[i][j];
       
       if (j==1) {
          let div = document.createElement('div');
          div.appendChild(document.createTextNode(item));
          ul.appendChild(div);
       }else{
          let ul2 = document.createElement('ul');
          let li = document.createElement('li');
         
          if (Array.isArray(item)) {
            prepareUL(li, item);         
            ul.appendChild(li);
            return;
          }       
          li.appendChild(document.createTextNode(item));
          ul2.appendChild(li);
         
          ul.appendChild(ul2);
       }       
     }
   }
   
}

prepareUL(document.getElementById('root'), arr)
<div id="root"></div>

1 Comment

Sorry for the haste, but this doesn't quite generate the right HTML, although it appears to. It actually generates a new UL for every nested LI.
0

If you don't mind to use a tiny library, then the solution can be simplified greatly to this:

<script type="module">
import { insert } from '//cdn.jsdelivr.net/npm/karyon/karyon.js';

const arr = [
   [
    "text-ID1",
    "Section Title 1",
    "Section paragraph 1",
    "Section Paragraph 2"
    ],
    [
    "text-ID2",
    "Section Title 2",
    "Section paragraph 1",
    "Section Paragraph 2"
    ],
    [
    "text-ID3",
    "Section Title 3",
    "Section paragraph 1",
    "Section Paragraph 2"
    ]
];

const out = {is: 'ul', content: arr.map(([id, title, ...sections]) => [
  {content: title},
  {is: 'ul', content: sections.map(li => ({is: 'li', content: li}))}
])}

insert(out, document.body);
</script>

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.