Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Highlight all text between two elements

Given the following example html, I would like to highlight all text between the two image tags (by adding a css background property). I have tried using jquerys .nextUntil() however this only uses the sibling nodes of the first element and so in this case it will not work.

Edit: The image tags below are intended to be invisible placeholders denoting the start and end points for a comment with the corresponding id within my text editor, everything in-between is the focus for the comment.

<div>
    <p>
        Lorem ipsum dolor
        <img class="commentBoundaryStart data-commentid="1" src="img.png"/>
          sit amet,"
    </p>
    <p>
        consectetur adipiscing elit. 
    </p>
    <h2>Header</h2>
    <p>
         Sed maximus laoreet augue
        <img class="commentBoundaryEnd" data-commentid="1" src="img2.png"/>
         , in ultrices sapien lobortis eu.
    </p>
    <p>
        Loremmmmm
    </p>
</div>

2 Answers

After taking inspiration from the answers here I designed my own comprehensive script for handling this problem in an html block of infinite depth and complexity

$(function () {
    var root = $('#textarea-0001');
    var cid = 1;
    
    var startMarker = $("img.commentBoundary[data-commentid='" + cid + "']").first();
    var endMarker = $("img.commentBoundary[data-commentid='" + cid + "']").last();

    // Wrap start points siblings with span
    startMarker.parent().contents().filter(function() {
        return this.nodeType === 3;
    }).wrap("<span></span>");

    // Color its later siblings if they dont have the end point marker
    var has_done = false;
    startMarker.nextAll().andSelf().each(function() {
        if (has_done) {
            return;
        }
        if ($(this).has(endMarker).length > 0 || $(this).is(endMarker)) {
            has_done = true;
            return;
        } else {
            $(this).css("background-color", "rgba(128, 204, 255, 0.5)");
        }
    });

    // Get parents up to root
    var parentsList = startMarker.parentsUntil(root);

    if (parentsList.has(endMarker).length === 0) {
        // go through each of these and access later siblings
        var has_returned = false;
        parentsList.each(function() {
            $(this).nextAll().each(function() {
                if (has_returned) {
                    return;
                }
                if ($(this).has(endMarker).length > 0) {
                    has_returned = true;
                    return;
                } else {
                    $(this).css("background-color", "rgba(51, 173, 255, 0.5)");
                }
            });    
        });
    };


    // find end point marker
    var endPointContainer = root.children().has(endMarker);

    // Wrap end points siblings in spans
    endMarker.parent().contents().filter(function() {
        return this.nodeType === 3;
    }).wrap("<span></span>");

    // Color earlier siblings if they dont have start marker
    var is_done = false;
    $(endMarker.prevAll().andSelf().get().reverse()).each(function() {
        if (is_done) {
            return;
        }
        if ($(this).has(startMarker).length > 0 || $(this).is(startMarker)) {
            is_done = true;
            return;
        } else {
            $(this).css("background-color", "rgba(0, 122, 204, 0.5)");
        }
    });

    // Get parents up until end pointcontainer
    var parentsListEnd = endMarker.parentsUntil(endPointContainer);

    if (parentsListEnd.has(startMarker).length === 0) {
        // Go through each of these and access earlier siblings
        var is_returned = false;
        parentsListEnd.each(function() {
            $(this).prevAll().each(function() {
                if (is_returned) {
                    return;
                }
                if ($(this).has(startMarker).length > 0 || $(this).is(startMarker)) {

                    is_returned = true;
                    return;
                } else {
                    $(this).css("background-color", "rgba(0, 61, 102, 0.5)");
                }
            });

        });
    };
});

        
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
        <div id="textarea-0001">
            <p>
                Lorem ipsum dolor
                <img class="commentBoundary" data-commentid="1" src="img.png"/>
                  sit amet,
            </p>
            <p>
                <span> Hello! </span>
                <span>  consectetur adipiscing elit. </span>
                <h3>Header</h3>
            </p>
            <p>
                 consectetur adipiscing elit. 
            </p>
            <span>
                 consectetur adipiscing elit. 
            </span>
            <p>
                 Sed maximus laoreet augue
                <img class="commentBoundary" data-commentid="1" src="img2.png"/>
                 , in ultrices sapien lobortis eu.
            </p>
            <p>
            </p>
        </div>

possible solution 1 for this case.

It works for only 1 <p> between images. You need to change it a bit if you have more than 1 <p> with nextAll and some if with indexOf img or something like that.

$(function() {

//coment start line
$('img.commentBoundaryStart').parent().contents().filter(function() {
  return this.nodeType == 3;
}).wrap('<span></span>');
$('img.commentBoundaryStart').next().css("background","red");

//middle lines
var has_returned = false;
$('img.commentBoundaryStart').parent().nextAll().each(function() {
    if (has_returned) { return; }
    if ($(this).contents().hasClass("commentBoundaryEnd")) {
        has_returned = true;
        return;
    } else {
        $(this).css("background","red");
    }
}); 

//end line
$('img.commentBoundaryEnd').parent().contents().filter(function() {
  return this.nodeType == 3;
}).wrap('<span></span>');
$('img.commentBoundaryEnd').prev().css("background","red");

});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<p>
    "Lorem ipsum dolor"
    <img class="commentBoundaryStart" data-commentid="1" src="img.png"/>
    "  sit amet,"
</p>
<p>
    " consectetur adipiscing elit. "
</p>
<p>
    " consectetur adipiscing elit. "
</p>
<span>
    " consectetur adipiscing elit. "
</span>
<p>
    " Sed maximus laoreet augue"
    <img class="commentBoundaryEnd" data-commentid="1" src="img2.png"/>
    " , in ultrices sapien lobortis eu."
</p>
<p>
</p>
</div>
like image 32
nada Avatar answered Nov 24 '25 15:11

nada