javascriptjqueryhtmlnextsibling

How to wrap previous and next sibling text of <br> with div using jquery?


Following HTML structure is given and cannot be changed:

<div id="cone" class="team">
  <div class="default"></div>
  ...
  <div class="default">
    <img src="img.jpg" width="271" height="271" alt="" border="0"> First Text line<br> Second text line (optional)
    <img src="img.jpg" width="271" height="271" alt="" border="0"> First Text line<br> Second text line (optional) ...
  </div>
</div>

I want to get to the following result using jQuery:

<div id="cone" class="team">
  <div class="default"></div>
  ...
  <div class="default">
    <img src="img.jpg" width="271" height="271" alt="" border="0">
    <div class="desc">
      First Text line<br> Second text line (optional)
    </div>
    <img src="img.jpg" width="271" height="271" alt="" border="0">
    <div class="desc">
      First Text line<br> Second text line (optional)
    </div>
    ...
  </div>
</div>

I have tried:

$(".team img").each(function () {
    $(this.nextSibling).wrap('<div class="desc"></div>');
});

But this only wraps the first line:

<img src="fileadmin/dateien/bilder/team/platzhalter_team.jpg" width="271" height="271" alt="" border="0">
<div class="desc">First Text line</div>
<br>
Second text line (optional)

Important: There can be one line, two lines, even three lines of text after the <img> Tag.


Solution

  • You need to iterate br element in .default and add your new tag in loop. You can get previous/next text sibling of element using Node.previousSibling and Node.nextSibling property.

    $(".default > br").each(function(){
        // Store previous/next sibling of br in variable then remove it.
        var prev = $(this.previousSibling).remove()[0].textContent;
        var next = $(this.nextSibling).remove()[0].textContent;
        // Insert new tag before br.
        $(this).before("<div class='desc'>" + prev + "<br>" + next + "</div>");  
    }).remove(); // Remove br after loop
    

    $(".default > br").each(function(){
        var prev = $(this.previousSibling).remove()[0].textContent;
        var next = $(this.nextSibling).remove()[0].textContent;
        $(this).before("<div class='desc'>" + prev + "<br>" + next + "</div>");
    }).remove();
    .desc { color: red }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="cone" class="team">    
        <div class="default"></div> 
        <div class="default">       
            <img src="img.jpg" width="271" height="271" alt="" border="0">
            First Text line<br>
            Second text line (optional)
            <img src="img.jpg" width="271" height="271" alt="" border="0">
            First Text line<br>
            Second text line (optional)
            ...
        </div>
    </div>


    Edit:

    If your html has multiple <br>, you need to replace br with custom text and after wrap, replace target text to <br>. In example i used [br].

    $(".default").html(function(i, html){
        return html.replace(/<br>/g, "[br]");
    });
    $(".default > img").each(function(){
        $(this.nextSibling).wrap('<div class="desc"></div>');
    });
    $(".default").html(function(i, html){
        return html.replace(/\[br\]/g, "<br>");
    });
    

    $(".default").html(function(i, html){
        return html.replace(/<br>/g, "[br]");
    });
    $(".default > img").each(function(){
        $(this.nextSibling).wrap('<div class="desc"></div>');
    });
    $(".default").html(function(i, html){
        return html.replace(/\[br\]/g, "<br>");
    });
    .desc { color: red }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <div id="cone" class="team">    
        <div class="default"></div> 
        <div class="default">       
            <img src="img.jpg" width="271" height="271" alt="" border="0">
            First Text line<br>
            Second text line (optional)<br>
            Third text line
            <img src="img.jpg" width="271" height="271" alt="" border="0">
            First Text line<br>
            Second text line (optional)<br>
            Third text line
            ...
        </div>
    </div>