Select cross boundries
Selection and wrapping around elements cross elements
by Mayank Dixit
HTML
<button id="surround">Make selected text bold</button>
<h1>Title 01 Heading</h1>
<hr />
<h2>Level 02 Heading</h2>
<p>Lorem ipsum <em>emphasised text</em> dolor sit amet, <strong>strong text</strong> consectetur
adipisicing elit, <abbr title="">abbreviated text</abbr> sed do eiusmod tempor incididunt
ut labore et dolore magna aliqua. Ut
<q>quoted text</q> enim ad minim veniam, quis nostrud exercitation <a href="/">link text</a> ullamco
laboris nisi ut aliquip ex ea commodo consequat. Duis aute
<ins>inserted text</ins> irure dolor <u>root <i>first <em>second</em></i></u> in reprehenderit in voluptate velit esse cillum
dolore eu fugiat nulla pariatur. Excepteur sint occaecat <code>code text</code> cupidatat
non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>
<p>
Suspendisse rhoncus, est ac sollicitudin viverra, leo orci sagittis massa, sed condimentum
<acronym
title="">acronym text</acronym>est tortor a lectus. Curabitur porta feugiat ullamcorper.
Integer lacinia mi id odio faucibus eget tincidunt nisl iaculis. Nam adipiscing
hendrerit turpis, et porttitor felis sollicitudin et. Donec dictum massa ac neque
accumsan tempor. Cras aliquam, ipsum sit amet laoreet hendrerit, purus <del>deleted text</del> sapien
convallis dui, et porta leo ipsum ac nunc. Nullam ornare porta dui ac semper.
Cras aliquam laoreet hendrerit. Quisque vulputate dolor eget mi porta vel porta
nisl pretium. Vivamus non leo magna, quis imperdiet risus. Morbi tempor risus
placerat tellus imperdiet fringilla.
</p>
<blockquote>
<p>I am not one who was born in the <i>possession of <u>knowledge</u></i>; I am one who is fond
of antiquity, and earnest in seeking it there.</p>
</blockquote>
<p><cite><a href="/">Confucius, The Confucian Analects</a></cite>, (551 BC - 479 BC)</p>
<h3>Level 03 Heading</h3>
<p>Extended paragraph. <a href="">Lorem ipsum</a> dolor sit amet, consectetur...
CSS
#surround {
position: fixed;
}
h1 {
padding-top: 50px;
}
JavaScript
document.getElementById('surround').onclick = function(){
surroundSelection('b');
};
function surroundSelection(elementType) {
function getAllDescendants (node, callback) {
for (var i = 0; i < node.childNodes.length; i++) {
var child = node.childNodes[i];
getAllDescendants(child, callback);
callback(child);
}
}
function glueSplitElements (firstEl, secondEl){
var done = false,
result = [];
if(firstEl === undefined || secondEl === undefined){
return false;
}
if(firstEl.nodeName === secondEl.nodeName){
result.push([firstEl, secondEl]);
while(!done){
firstEl = firstEl.childNodes[firstEl.childNodes.length - 1];
secondEl = secondEl.childNodes[0];
if(firstEl === undefined || secondEl === undefined){
break;
}
if(firstEl.nodeName !== secondEl.nodeName){
done = true;
} else {
result.push([firstEl, secondEl]);
}
}
}
for(var i = result.length - 1; i >= 0; i--){
var elements = result[i];
while(elements[1].childNodes.length > 0){
elements[0].appendChild(elements[1].childNodes[0]);
}
elements[1].parentNode.removeChild(elements[1]);
}
}
// abort in case the given elemenType doesn't exist.
try {
document.createElement(elementType);
} catch (e){
return false;
}
var selection = getSelection();
if(selection.rangeCount > 0){
var range = selection.getRangeAt(0),
rangeContents = range.extractContents(),
nodesInRange = rangeContents.childNodes,
nodesToWrap = [];
...