skip to Main Content

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.

2

Answers


  1. Chosen as BEST ANSWER

    Thanks for the answer. It lead me to do this:

    let found = false,
        div;
    
    document.querySelector('div').querySelectorAll('p').forEach(p => {
      if (p.classList.contains('foo')) {
        if (!found) {
          found = true;
          div = document.createElement('div');
          div.classList.add('wrap');
          p.before(div);
        }
        div.append(p);
      } else {
        found = false; 
      }
    });
    

    For me, it's a bit simpler to read.


  2. 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>
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search