WrapInSpan

by Seth Van Booven

HTML

<div class="pen" contenteditable="true">
<p>One two three four</p>
<p>One two three four</p>
<p>One two three four</p>
</div>
<input type="button" onclick="wrapInSpan('b');" value="Surround">

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

window.rangeIntersectsNode = function(range, node) {
    var nodeRange;
    if (range.intersectsNode) {
        return range.intersectsNode(node);
    } else {
        nodeRange = node.ownerDocument.createRange();
        try {
            nodeRange.selectNode(node);
        } catch (e) {
            nodeRange.selectNodeContents(node);
        }
        return range.compareBoundaryPoints(Range.END_TO_START, nodeRange) == -1 && range.compareBoundaryPoints(Range.START_TO_END, nodeRange) == 1;
    }
}

window.getSelectedElementTags = function() {
    var range, sel, elmlist, treeWalker, containerElement;
    sel = window.getSelection();
    if (sel.rangeCount > 0) {
        range = sel.getRangeAt(0);
    }

    if (range) {
        containerElement = range.commonAncestorContainer;
        if (containerElement.nodeType != 1) {
            containerElement = containerElement.parentNode;
        }

        treeWalker = window.document.createTreeWalker(
        containerElement, NodeFilter.SHOW_TEXT, function(node) {
            return rangeIntersectsNode(range, node) ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT;
        }, false);

        elmlist = [treeWalker.currentNode];
        while (treeWalker.nextNode()) {
            elmlist.push(treeWalker.currentNode);
        }

        return (elmlist);
    }
}

window.wrapInSpan = function(tag) {
		var selObj = window.getSelection();
		if (!selObj) {
    	return;
    }
    var range = selObj.getRangeAt(0);
    var tempElement;
    
    var selectedArr = getSelectedElementTags();
    for (var i = 2; i < (selectedArr.length - 1); i++) {
        tempElement = document.createElement(tag);
        tempElement.innerHTML = selectedArr[i].nodeValue;
        selectedArr[i].parentElement.replaceChild(tempElement, selectedArr[i])
    }
    
    console.log(selectedArr);
    
    var sC = range.startContainer;
    
    if (selectedArr.length == 2) {
    		if (selectedArr[0].nodeName.toLowerCase() == tag)...