Search code examples
javascriptindexofnodelist

Javascript how to append node in its correct index with wrapper


I need to get user entered markup (tables) and if the table does not contain a div with a the class="table", I need to add the div & class. I need to ignore any other children, such as p, span, and only target elements with tables.

<div class="parent">
  <div class="table"><table></table></div>
  <div class="table"><table></table></div>
  <table></table>
  <div><table></table></div>
  <div class="table"><table></table></div>
  <p></p>
  <span></span>
</div>

You can see in the nodelist above, node index 2,3 both need a wrapper div with the class="table", but ignore the p and span.

[].map.call(table, (node) => {
  if (!node.parentNode.classList.contains('table')) {
    const parent = document.getElementsByClassName('parent');
    [].map.call(parent, (nodeChild) => {
      const addWrap = document.createElement('div');
      addWrap.classList.add('table');
      addWrap.appendChild(node);
      nodeChild.append(addWrap);
    });
  }
});

I have tried this, but it appends the node with a wrapper div at the bottom of the index. How do I get the nodes to append in their correct order with the wrapper div? Thanks.


Solution

  • You're better off using a for/loop (using map here is an anti-pattern) to iterate over the child nodes of the parent node and replace the current child node with the new created element.

    Inspect the output in dev tools to see the change.

    const parent = document.querySelector('.parent');
    const { childNodes } = parent;
    
    for (let i = 0; i < childNodes.length; i++) {
      const el = childNodes[i];
    
      // If the node type is an element
      if (el.nodeType === 1) {
    
        // If element is a div add a class
        // if it's missing
        if (el.tagName === 'DIV' && !el.classList.contains('table')) {
          el.classList.add('table');
        }
    
        if (el.tagName === 'TABLE') {
          const div = document.createElement('div');
          div.classList.add('table');
          div.appendChild(el);
    
          // Replace the child node with the new div node
          parent.replaceChild(div, childNodes[i]);    
        }
    
      }
    };
    <div class="parent">
      <div class="table"><table></table></div>
      <div class="table"><table></table></div>
      <table></table>
      <div><table></table></div>
      <div class="table"><table></table></div>
      <p></p>
      <span></span>
    </div>