<div class="pen" contenteditable="true" spellcheck="false">
<p>One two three four</p>
<p>One two three four</p>
<p>One two three four</p>
</div>
<input type="button" onclick="wrap('strong');" value="Bold">
<input type="button" onclick="wrap('em');" value="Italic">
function wrap(tag) {
var wrapper = document.createElement(tag);
wrapper.classList.add('tag');
var editor = document.querySelector('.pen');
var selection = document.getSelection();
var range = selection.rangeCount && selection.getRangeAt(0);
if (!range) range = document.createRange();
if (!containsNode(editor, range.commonAncestorContainer)) {
range.selectNodeContents(editor);
range.collapse(false);
}
//console.log(range);
var node = getNode(editor, range, false);
// nodes should be wrapped with `span.fancy-text` elements
var wrapped = wrapRangeText(wrapper, range);
if (node.nodeName.toLowerCase() === tag) {
// nodes should be unwrapped
wrapped.unwrap();
}
}
function getNode(root, range, byRoot) {
var node = range.commonAncestorContainer;
if (!node || node === root) return null;
while (node && (node.nodeType !== 1) && (node.parentNode !== root)) node = node.parentNode;
while (node && byRoot && (node.parentNode !== root)) node = node.parentNode;
return containsNode(root, node) ? node : null;
}
function containsNode(parent, child) {
if (parent === child) return true;
child = child.parentNode;
while (child) {
if (child === parent) return true;
child = child.parentNode;
}
return false;
}
// return all text nodes that are contained within `el`
function getTextNodes(el) {
el = el || document.body
var doc = el.ownerDocument || document
, walker = doc.createTreeWalker(el, NodeFilter.SHOW_TEXT, null, false)
, textNodes = []
, node
while (node = walker.nextNode()) {
textNodes.push(node)
}
return textNodes
}
// return true if `rangeA` intersects `rangeB`
function rangesIntersect(rangeA, rangeB) {
return rangeA.compareBoundaryPoints(Range.END_TO_START, rangeB) === -1 &&
rangeA.compareBoundaryPoints(Range.START_TO_END, rangeB) === 1
}
// create and return a range that selects `node`
function createRangeFromNode(node) {
var range =...
Please Whitelist JSFiddle in your content blocker.
Help keep JSFiddle free for always by one of two ways:
Whitelist JSFiddle in your content blocker (two clicks)
Go PRO and get access to additional PRO features →
Join the 4+ million users, and keep the JSFiddle dream alive.
Ad-free
All ads in the editor and listing pages are turned completely off.
Use pre-released features
You get to try and use features (like the Palette Color Generator) months before everyone else.
Fiddle collections
Sort and categorize your Fiddles into multiple collections.
Private collections and fiddles
You can make as many Private Fiddles, and Private Collections as you wish!
Console
Debug your Fiddle with a minimal built-in JavaScript console.