user3532637 user3532637 - 2 months ago 8
HTML Question

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 follwing 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 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.

Thanks in advance!

Answer

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>