JSFiddle - React, Tailwind, and code Playground

by LeGEC

HTML

<p id="doc">Click on a button to see the effect of ".myWrap()" on the corresponding selection. Selected nodes are highlighted in green, wrapper appears as a red frame.</p>
<button id="EG">E,G</button>
<button id="CDF">C,D,F</button>
<button id="BI">B,I</button>
<button id="clear">clear</button>
<div id="A">A
    <div id="B">B</div>
    <div id="C">C
        <div id="D">D</div>
        <div id="E">E</div>
        <div id="F">F</div>
        <div id="G">G</div>
    </div>
    <div id="H">H
        <div id="I">I</div>
        <div id="J">J</div>
    </div>
</div>

CSS

#doc {
    text-align: justify;
    font-size: 12px;
}
div {
    font-weight: normal;
    color: black;
    padding: 3px 3px 3px 6px;
    border:1px solid black;
    margin: 1px;
}
.green {
    font-weight: bold;
    color: green;
    border: 1px solid green
}
.wrapper {
    border: 2px solid red
}

JavaScript

$.fn.myWrap = function (html) {
    if (this.length == 0) {
        return;
    }

    // find closest common ancestor :
    var parents = [];
    this.each(function () {
        var nodes = [this];
        $(this).parents().each(function () {
            nodes.push(this)
        });
        parents.push(nodes);
    });

    var idx = parents[0].length;
    this.each(function (i) {
        var p0 = parents[0],
            pi = parents[i],
            l0 = p0.length,
            li = pi.length;
        if (li < idx) {
            idx = li;
        }

        while (idx > 0) {
            if (p0[l0 - idx] == pi[li - idx]) {
                break;
            }

            idx -= 1;
        }
    });

    if (idx == 0) {
        // no common parent (different iframes for example)
        return;
    }

    var ancestor = parents[0][parents[0].length - idx];

    //special case : one of the nodes is the common ancestor
    var found = false;
    this.each(function () {
        if (this == ancestor) {
            found = true;
            return false;
        }
    });
    if (found) {
        $(ancestor).wrap(html);
        return;
    }

    var minChild = ancestor.children.length,
        maxChild = 0;
    this.each(function (i) {
        var pi = parents[i],
            li = pi.length,
            tgt = pi[li - idx - 1];
        var i = $(tgt).index();
        if (i < minChild) {
            minChild = i
        };
        if (i > maxChild) {
            maxChild = i
        };
    });

    var children = Array.prototype.slice.call(ancestor.children, minChild, maxChild + 1);
    $(children).wrapAll(html);

    return this;
}

//demo
var initialHtml = $('body').html();

$('body').on('click', '#clear', function () {
    $('body').html(initialHtml);
});

$('body').on('click', '#EG', function () {
    $('body').html(initialHtml);
    $("#E,#G").addClass('green').myWrap('<div class="wrapper"></div>');
});

$('body').on('click', '#CDF', function () {
   ...