Search code examples
javascriptjquerysplitwrapall

How to wrap multiple spans into a div


I have a JS code that wraps all lines into a span. I know I'm suppose to use wrapall but don't have any idea on where to start. Now I'm trying to find a way to wrap each of those spans into a div but limit a total to 4 spans. So for example if I have 5 spans, how would I wrap 4 spans into a div and the last one into a div like so:

<div class="wrap">
 <span class="line_wrap"></span>
 <span class="line_wrap"></span>
 <span class="line_wrap"></span>
 <span class="line_wrap"></span>
</div>
<div class="wrap">
 <span class="line_wrap"></span>
</div>

Working example:

$(".emails .multi-items").each(function (i) {
  var $cont = $('.content')

  var text_arr = $cont.text().split(' ');
  
  for (i = 0; i < text_arr.length; i++) {
      text_arr[i] = '<span>' + text_arr[i] + ' </span>';
  }
  
  $cont.html(text_arr.join(''));
  
  $wordSpans = $cont.find('span');
  
  var lineArray = [],
      lineIndex = 0,
      lineStart = true,
      lineEnd = false
  
      $wordSpans.each(function(idx) {
          var pos = $(this).position();
          var top = pos.top;
  
          if (lineStart) {
              lineArray[lineIndex] = [idx];
              lineStart = false;
  
          } else {
              var $next = $(this).next();
  
              if ($next.length) {
                  if ($next.position().top > top) {
                      lineArray[lineIndex].push(idx);
                      lineIndex++;
                      lineStart = true
                  }
              } else {
                  lineArray[lineIndex].push(idx);
              }
          }
  
      });
  
  
  //console.log( lineArray)
  for (i = 0; i < lineArray.length; i++) {
      var start = lineArray[i][0],
          end = lineArray[i][1] + 1;
  
      /* no end value pushed to array if only one word last line*/
      if (!end) {
          $wordSpans.eq(start).wrap('<span class="line_wrap">')
      } else {
          $wordSpans.slice(start, end).wrapAll('<span class="line_wrap">');
      }
  
  };
});
.line_wrap{ border-top: 1px solid green}
.message-contain {padding:35px 0}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="emails">
<ul class="multi-items">
  <div class="message-contain">
      <div class="content">
          Lorem Khaled Ipsum is a major key to success. They will try to close the door on you, just open it. Watch your back, but more importantly when you get out the shower, dry your back, it’s a cold world out there. The other day the grass was brown, now it’s green because I ain’t give up. Never surrender. Every chance I get, I water the plants, Lion! In life you have to take the trash out, if you have trash in your life, take it out, throw it away, get rid of it, major key. You do know, you do know that they don’t want you to have lunch. I’m keeping it real with you, so what you going do is have lunch. Every chance I get, I water the plants, Lion! In life you have to take the trash out, if you have trash in your life, take it out, throw it away, get rid of it, major key. You do know, you do know that they don’t want you to have lunch.
      </div>
  </div>
<div class="message-contain">
      <div class="content">
          Lorem Khaled Ipsum is a major key to success. They will try to close the door on you, just open it. Watch your back, but more importantly when you get out the shower, dry your back, it’s a cold world out there. The other day the grass was brown, now it’s green because I ain’t give up. Never surrender. Every chance I get, I water the plants, Lion! In life you have to take the trash out, if you have trash in your life, take it out, throw it away, get rid of it, major key. You do know, you do know that they don’t want you to have lunch. I’m keeping it real with you, so what you going do is have lunch. Every chance I get, I water the plants, Lion! In life you have to take the trash out, if you have trash in your life, take it out, throw it away, get rid of it, major key. You do know, you do know that they don’t want you to have lunch.
      </div>
  </div>
</ul>
</div>


Solution

  • Here you go with a solution

    $(".emails .multi-items").each(function (i) {
      var $cont = $('.content')
    
      var text_arr = $cont.text().split(' ');
      
      for (i = 0; i < text_arr.length; i++) {
          text_arr[i] = '<span>' + text_arr[i] + ' </span>';
      }
      
      $cont.html(text_arr.join(''));
      
      $wordSpans = $cont.find('span');
      
      var lineArray = [],
          lineIndex = 0,
          lineStart = true,
          lineEnd = false
      
          $wordSpans.each(function(idx) {
              var pos = $(this).position();
              var top = pos.top;
      
              if (lineStart) {
                  lineArray[lineIndex] = [idx];
                  lineStart = false;
      
              } else {
                  var $next = $(this).next();
      
                  if ($next.length) {
                      if ($next.position().top > top) {
                          lineArray[lineIndex].push(idx);
                          lineIndex++;
                          lineStart = true
                      }
                  } else {
                      lineArray[lineIndex].push(idx);
                  }
              }
      
          });
      
     
      for (i = 0; i < lineArray.length; i++) {
          var start = lineArray[i][0],
              end = lineArray[i][1] + 1;
      
          /* no end value pushed to array if only one word last line*/
          if (!end) {
              $wordSpans.eq(start).wrap('<span class="line_wrap">')
          } else {
              $wordSpans.slice(start, end).wrapAll('<span class="line_wrap">');
          }
      
      };
      
      var line_wrap = $(".line_wrap");
      
      for(var i=-1; i<line_wrap.length; i=i+4) {
          $('.line_wrap:eq('+i+'),.line_wrap:eq('+(i-1)+'),.line_wrap:eq('+(i-2)+'), .line_wrap:eq('+(i-3)+')').wrapAll('<div class="wrap">');
        
      }
    });
    .line_wrap{ border-top: 1px solid green}
    .message-contain {padding:35px 0}
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <div class="emails">
    <ul class="multi-items">
      <div class="message-contain">
          <div class="content">
              Lorem Khaled Ipsum is a major key to success. They will try to close the door on you, just open it. Watch your back, but more importantly when you get out the shower, dry your back, it’s a cold world out there. The other day the grass was brown, now it’s green because I ain’t give up. Never surrender. Every chance I get, I water the plants, Lion! In life you have to take the trash out, if you have trash in your life, take it out, throw it away, get rid of it, major key. You do know, you do know that they don’t want you to have lunch. I’m keeping it real with you, so what you going do is have lunch. Every chance I get, I water the plants, Lion! In life you have to take the trash out, if you have trash in your life, take it out, throw it away, get rid of it, major key. You do know, you do know that they don’t want you to have lunch.
          </div>
      </div>
    </ul>
    </div>

    Additional below code added to your code

    var line_wrap = $(".line_wrap");
    
    for(var i=-1; i<line_wrap.length; i=i+4) {
      $('.line_wrap:eq('+i+'),.line_wrap:eq('+(i-1)+'),.line_wrap:eq('+(i-2)+'), .line_wrap:eq('+(i-3)+')').wrapAll('<div class="wrap">');
    
    }
    

    Get all the elements with class line_wrap and then loop through each element.

    Hope this will help you