Text 2

Text 3

Text 4

Text 5

Text 6

Text 2

Text 3

Text 4

Text 5

Text 6

Text 2

Text 3

Text 4

Text 5

Text 6

Grouping HTML elements by their class name

51 Views Asked by At

Say I have HTML that looks a bit like this

<div>
  <p>Text 1</p>
  <p class="foo">Text 2</p>
  <p>Text 3</p>
  <p>Text 4</p>
  <p>Text 5</p>
  <p>Text 6</p>
  <p class="foo">Text 7</p>
  <p class="foo">Text 8</p>
  <p>Text 9</p>
  <p class="foo">Text 10</p>
  <p>Text 11</p>
  <p class="foo">Text 12</p>
  <p class="foo">Text 13</p>
  <p class="foo">Text 14</p>
  <p class="foo">Text 15</p>
  <p>Text 16</p>
</div>

Any p element with the class "foo" gets wrapped in a div but any contiguous p elements with the class "foo" get wrapped into the same div as the first p (in the series). So the above HTML would end up looking like

<div>
  <p>Text 1</p>
  <div class="wrap">
    <p class="foo">Text 2</p>
  </div>
  <p>Text 3</p>
  <p>Text 4</p>
  <p>Text 5</p>
  <p>Text 6</p>
  <div class="wrap">
    <p class="foo">Text 7</p>
    <p class="foo">Text 8</p>
  </div>
  <p>Text 9</p>
  <div class="wrap">
    <p class="foo">Text 10</p>
  </div>
  <p>Text 11</p>
  <div class="wrap">
    <p class="foo">Text 12</p>
    <p class="foo">Text 13</p>
    <p class="foo">Text 14</p>
    <p class="foo">Text 15</p>
  </div>
  <p>Text 16</p>
</div>

I know how to get elements with the class "foo" but I'm lost trying to work out if there are contiguous p.foo elements that I need to wrap in the same div.

Should I just iterate through the nodes in the container div, append a wrapper div when I find a p.foo and just keep appending contiguous p.foo elements? I've had a few goes but it seems to fail for different ways I sort the original p elements.

1

There are 1 best solutions below

0
Mamun On

The provided code dynamically wraps consecutive paragraphs with the class foo inside separate <div> elements with the class wrap:

<style>
  /* Styles for better visualization */
  body {
    font-family: Arial, sans-serif;
    margin: 0;
    padding: 0;
  }
  
  .wrap {
    background-color: #f0f0f0;
    padding: 10px;
    margin-bottom: 10px;
  }
  
  .foo {
    background-color: #ffff99;
    padding: 5px;
    margin: 5px 0;
  }
</style>
<body>

  <div>
    <p>Text 1</p>
    <p class="foo">Text 2</p>
    <p>Text 3</p>
    <p>Text 4</p>
    <p>Text 5</p>
    <p>Text 6</p>
    <p class="foo">Text 7</p>
    <p class="foo">Text 8</p>
    <p>Text 9</p>
    <p class="foo">Text 10</p>
    <p>Text 11</p>
    <p class="foo">Text 12</p>
    <p class="foo">Text 13</p>
    <p class="foo">Text 14</p>
    <p class="foo">Text 15</p>
    <p>Text 16</p>
  </div>

<script>

function wrapFooElements() {
    //select all paragraphs with class "foo"
    var paragraphs = document.querySelectorAll('p.foo');
    //variable to keep track of the current wrap
    var currentWrap = null;

    //loop through each paragraph with class "foo"
    for (var i = 0; i < paragraphs.length; i++) {
        var paragraph = paragraphs[i];
        
        //check if a new wrap is needed or if the current wrap can be reused
        if (!currentWrap || paragraph.previousElementSibling !== currentWrap) {
            //create a new wrap element
            currentWrap = document.createElement('div');
            currentWrap.classList.add('wrap');
            //insert the wrap before the current paragraph
            paragraph.parentNode.insertBefore(currentWrap, paragraph);
        }
        
        //move the paragraph inside the current wrap
        currentWrap.appendChild(paragraph);
    }
}

// Call the function to wrap paragraphs with class "foo"
wrapFooElements();
</script>