getSelectedText
by Seth Van Booven
August 03, 2017
HTML
<input type="button" onclick="wrapInSpan('b');" value="Surround">
<div class="pen" contenteditable="true">
<p>One two three four</p>
<p>One two three four</p>
<p>One two three four</p>
</div>
CSS
body { font-family:Georgia,serif; margin:20px; }
div[contenteditable] { border:1px solid #ddd; margin:10px 0; padding:10px; }
div[contenteditable]:focus { outline:none; }
p { margin:10px 0; }
span { font-weight:bold; background:#ff0; }
JavaScript
function wrapInSpan(tag) {
var sel = window.getSelection();
if (sel.isCollapsed) return;
var range = sel.getRangeAt(0);
var parent = range.commonAncestorContainer;
addAnnotationElement(range, parent, tag);
}
function addAnnotationElement(range, elem, tag) {
var text, textParent, origText, prevText, nextText, childCount,
annotationTextRange,
span = document.createElement(tag);
if (elem.nodeType === 3) {
origText = elem.textContent;
annotationTextRange = validateTextRange(range, elem);
if (annotationTextRange == 'textBeforeRangeButIntersect') {
text = origText.substring(0, range.endOffset);
nextText = origText.substring(range.endOffset);
} else if (annotationTextRange == 'textAfterRangeButIntersect') {
prevText = origText.substring(0, range.startOffset);
text = origText.substring(range.startOffset);
} else if (annotationTextRange == 'textExactlyInRange') {
text = origText
} else if (annotationTextRange == 'textWithinRange') {
prevText = origText.substring(0, range.startOffset);
text = origText.substring(range.startOffset, range.endOffset);
nextText = origText.substring(range.endOffset);
} else if (annotationTextRange == 'textNotInRange') {
return;
}
span.textContent = text;
textParent = elem.parentElement;
textParent.replaceChild(span, elem);
if (prevText) {
var prevDOM = document.createTextNode(prevText);
textParent.insertBefore(prevDOM, span);
}
if (nextText) {
var nextDOM = document.createTextNode(nextText);
textParent.insertBefore(nextDOM, span.nextSibling);
}
return;
}
childCount = elem.childNodes.length;
for (var i = 0; i < childCount; i++) {
var elemChildNode = elem.childNodes[i];
if...