简体   繁体   中英

JQuery collect group of elements, unwrap each and then wrap all in new element

I am trying to convert markup for a listing of businesses in which every line is a <p> and only the business name is also wrapped in <strong> . Instead I want each business' entire listing to be wrapped in one <p> and use <br/> to separate the lines. Here is the original markup:

<div class="wrapper">
   <p><strong>Name of Business 1</strong></p>
   <p>Membership Level 1</p>
   <p>Name of Owner 1</p>
   <p>555 Someplace Ave 1</p>
   <p>Nowhere, OH 55555 1</p>
   <p>555-555-5555 1</p>
   <p><a href="mailto:test@test.com">test@test.com</a> 1</p>
   <p>Business Description 1</p>
   <p><strong>Name of Business 2</strong></p>
   <p>Membership Level 2</p>
   <p>Name of Owner 2</p>
   <p>555 Someplace Ave 2</p>
   <p>Nowhere, OH 55555 2</p>
   <p>555-555-5555 2</p>
   <p><a href="mailto:test@test.com">test@test.com</a> 2</p>
   <p>Business Description 2</p>
</div>

Here is what I need to change it to:

<div class="wrapper">
    <p>
        <strong>Name of Business 1</strong><br>
        Membership Level 1<br>
        Name of Owner 1<br>
        555 Someplace Ave 1<br>
        Nowhere, OH 43021 1<br>
        555-555-5555 1<br>
        <a href="mailto:test@test.com">test@test.com</a> 1<br>
        Business Description 1<br>
    </p>
    <p>
        <strong>Name of Business 2</strong><br>
        Membership Level 2<br>
        Name of Owner 2<br>
        555 Someplace Ave 2<br>
        Nowhere, OH 43021 2<br>
        555-555-5555 2<br>
        <a href="mailto:test@test.com">test@test.com</a> 2<br>
        Business Description 2<br>
    </p>
</div>

I managed to get it done with some of the most ugly convoluted code ever. Basically I took a step by step approach, as I just couldn't get any chained solution to work.

Here is that unfortunate solution:

  jQuery('p > strong').parent('p').addClass('strong').has('br').addClass('clean'); jQuery('p:not(.clean)').addClass('unwrap'); jQuery('.unwrap.strong').nextUntil('.strong').each( function(){ var theHTML = jQuery(this).html(); jQuery(this).replaceWith('<span class="tomove">' + theHTML + '<br/></span>'); }); jQuery('span.tomove').each(function(){ jQuery(this).appendTo( jQuery(this).prev('p.strong') ); }); jQuery('.unwrap strong').each(function(){ var theHTML = jQuery(this).html(); jQuery(this).replaceWith('<strong>' + theHTML + '</strong><br/>'); }); jQuery('span.tomove').replaceWith(function(){ return jQuery(this).contents(); }); jQuery('p.strong.unwrap').addClass('clean').removeClass('unwrap'); 
 p {background:yellow} strong {background:red;color:white;} 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <div class="wrapper"> <p><strong>Name of Business 1</strong></p> <p>Membership Level 1</p> <p>Name of Owner 1</p> <p>555 Someplace Ave 1</p> <p>Nowhere, OH 55555 1</p> <p>555-555-5555 1</p> <p><a href="mailto:test@test.com">test@test.com</a> 1</p> <p>Business Description 1</p> <p><strong>Name of Business 2</strong></p> <p>Membership Level 2</p> <p>Name of Owner 2</p> <p>555 Someplace Ave 2</p> <p>Nowhere, OH 55555 2</p> <p>555-555-5555 2</p> <p><a href="mailto:test@test.com">test@test.com</a> 2</p> <p>Business Description 2</p> </div> 

I imagine there is a way to process this in one chained command, but I kept getting tripped up trying to build the reference using .nextUntil() and/or .add() while trying to unwrap each <p> and add the <br/> within that chain before wrapping each group.

Can anyone provide a better solution for this?

The following uses the Strong element as a divider. The JSbin supplied adds them to a new div to show the before / after.

http://jsbin.com/soyelozemi/4/edit

jQuery(document).ready(function(){
  var insert = $('<div class="wrapper2"></div>');
  var tempHolder = $('<p></p>');
  jQuery('.wrapper p').each(function(index){
    jQuery(tempHolder).append($(this).html() + '<br/>');
    if(jQuery(this).next().find('strong').length || index == jQuery('.wrapper p').length-1){
      jQuery(insert).append(tempHolder);
      tempHolder = jQuery('<p></p>');
    }
  });
  jQuery('.after').append(jQuery(insert));
});

Here's what I came up with; it should work regardless of the number of businesses and data parameters can vary in lengths. It does require that the first 'p' element is contains a 'strong' element and no other data field other than business names have a strong element:

$(document).ready(function(){   
 var businesses = [], bizIndex = -1;
 $('.wrapper > p').each(function(i){
     var html = $(this).html();
     if ($(this).find('strong').length) {
       bizIndex++;
       businesses.push([html]);
     }
     else {
         businesses[bizIndex].push(html);
     }

 });
 $('.wrapper').empty();

 $.each(businesses, function(i) {
     var business = businesses[i];
   $('.wrapper').append($('<p>').html(business.join('<br>')+'<br>'));
 });
});

https://jsfiddle.net/2rz7jp4z/3/

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM