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 () {
...