<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<!------ Include the above in your HEAD tag ---------->
<!DOCTYPE html><html lang='en' class=''>
<head><script src='//production-assets.codepen.io/assets/editor/live/console_runner-079c09a0e3b9ff743e39ee2d5637b9216b3545af0de366d4b9aad9dc87e26bfd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/events_runner-73716630c22bbc8cff4bd0f07b135f00a0bdc5d14629260c3ec49e5606f98fdd.js'></script><script src='//production-assets.codepen.io/assets/editor/live/css_live_reload_init-2c0dc5167d60a5af3ee189d570b1835129687ea2a61bee3513dee3a50c115a77.js'></script><meta charset='UTF-8'><meta name="robots" content="noindex"><link rel="shortcut icon" type="image/x-icon" href="//production-assets.codepen.io/assets/favicon/favicon-8ea04875e70c4b0bb41da869e81236e54394d63638a1ef12fa558a4a835f1164.ico" /><link rel="mask-icon" type="" href="//production-assets.codepen.io/assets/favicon/logo-pin-f2d2b6d2c61838f7e76325261b7195c27224080bc099486ddd6dccb469b8e8e6.svg" color="#111" /><link rel="canonical" href="https://codepen.io/nilsynils/pen/VKQwBJ?depth=everything&order=popularity&page=61&q=tools&show_forks=false" />
<link href='https://fonts.googleapis.com/css?family=Open+Sans:400,700' rel='stylesheet' type='text/css'>
<style>
body {
font: 16px "Open Sans";
color: darkSlateGrey;
}
</style>
<style class="cp-pen-styles">body {
background: aliceBlue;
}
.wrapper {
width: 80%;
max-width: 800px;
background: #fff;
margin: 3em auto;
padding: 1em 2em;
border: 1px solid lightGrey;
border-radius: 3px;
position: relative;
}
.wrapper h2 {
margin-top: 0;
}
.tools {
padding: 0;
list-style-type: none;
display: inline-flex;
flex-wrap: wrap;
padding: .5em .5em .5em 0;
margin: 0;
}
.tools li {
margin: 0 1em 0 0;
color: grey;
}
.tools li a {
color: grey;
}
.editableContent *::selection {
background: #9dcaff;
}
.editableContent:focus {
outline: none;
}
.modal {
position: absolute;
left: 11em;
top: 4.5em;
display: none;
}
.modal__wrapper {
background: #fff;
padding: 0 .5em;
border: 1px solid lightGrey;
border-radius: 3px;
transition: all 1s;
position: relative;
width: 22em;
}
.modal__wrapper:after, .modal__wrapper:before {
right: 100%;
top: 50%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.modal__wrapper:after {
border-color: rgba(255, 255, 255, 0);
border-right-color: #fff;
border-width: 6px;
margin-top: -6px;
}
.modal__wrapper:before {
border-color: transparent;
border-right-color: lightGrey;
border-width: 7px;
margin-top: -7px;
}
.modal input {
height: 1.5em;
padding: .25em;
width: 20em;
font-size: 16px;
border: 0;
}
.modal input:focus {
outline: none;
}
.visible {
display: block;
}
a.highlighted {
background: blue;
color: white;
}
.editableContent a:hover {
cursor: pointer;
}
.linkWrapper {
position: relative;
}
.hoverPop {
position: absolute;
left: 0;
top: 2.2em;
display: block;
}
.hoverPop__wrapper {
background: #fff;
padding: .5em .5em;
border: 1px solid lightGrey;
border-radius: 3px;
transition: all 1s;
position: relative;
width: auto;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
}
.hoverPop__wrapper:after, .hoverPop__wrapper:before {
bottom: 100%;
left: 50%;
border: solid transparent;
content: " ";
height: 0;
width: 0;
position: absolute;
pointer-events: none;
}
.hoverPop__wrapper:after {
border-color: rgba(255, 255, 255, 0);
border-bottom-color: #fff;
border-width: 6px;
margin-left: -6px;
}
.hoverPop__wrapper:before {
border-color: transparent;
border-bottom-color: lightGrey;
border-width: 7px;
margin-left: -7px;
}
</style></head><body>
<section class="wrapper">
<h2>Simple WYSIWYG Editor</h2>
<ul class="tools">
<li>
<a href='#' data-role='bold'>
<i class="fa fa-bold" aria-hidden="true"></i>
</a>
</li>
<li>
<a href='#' data-role='italic'>
<i class="fa fa-italic" aria-hidden="true"></i>
</a>
</li>
<li>
<a href='#' data-role='insertUnorderedList'>
<i class="fa fa-list" aria-hidden="true"></i>
</a>
</li>
<li>
<a href='#' data-role='insertOrderedList'>
<i class="fa fa-list-ol" aria-hidden="true"></i>
</a>
</li>
<li>
<a href='#' data-role='createLink'>
<i class="fa fa-link" aria-hidden="true"></i>
</a>
</li>
<li>
<a href='#' data-role='unlink'>
<i class="fa fa-unlink" aria-hidden="true"></i>
</a>
</li>
<li>
<a href='#' data-role='insertHorizontalRule'>
<i class="fa fa-minus" aria-hidden="true"></i>
</a>
</li>
<li>
<a href='#' data-role='insertParagraph'>
<i class="fa fa-paragraph" aria-hidden="true"></i>
</a>
</li>
<li>
<a href='#' data-role='justifyLeft'>
<i class="fa fa-align-left" aria-hidden="true"></i>
</a>
</li>
<li>
<a href='#' data-role='justifyCenter'>
<i class="fa fa-align-center" aria-hidden="true"></i>
</a>
</li>
<li>
<a href='#' data-role='justifyRight'>
<i class="fa fa-align-right" aria-hidden="true"></i>
</a>
</li>
<li>
<a href='#' data-role='subscript'>
<i class="fa fa-subscript" aria-hidden="true"></i>
</a>
</li>
<li>
<a href='#' data-role='superscript'>
<i class="fa fa-superscript" aria-hidden="true"></i>
</a>
</li>
<li>
<a href='#' data-role='underline'>
<i class="fa fa-underline" aria-hidden="true"></i>
</a>
</li>
</ul>
<div class="modal">
<div class="modal__wrapper">
<form class="urlForm" name="urlForm">
<input class="url" name="urlField" placeholder="Add URL" />
<i class="fa fa-close closeModal" aria-hidden="true"></i>
</form>
</div>
</div>
<div class="editableContent" contenteditable spellcheck="false">
<p>Click anywhere in the text to start typing or editing the existing text.</p>
<p>This note is editable using a combination of <a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand"><code>execCommand</code></a> and the <a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/contentEditable"><code>contentEditable</code></a> tag. Making the link work without an ugly alert involved a bit of javascript and could certainly be made more robust, but here's a simple version to get things started. I can do things like <b>bold</b> and <i>italic</i> which can be executed with either a keyboard shortcut (<b>cmd/ctrl + b</b> or <i>cmd/ctrl + i</i>) or I can just click on the buttons in the toolbar up above.</p>
<p><!--span class="linkWrapper"><span class="hoverPop"><span class="hoverPop__wrapper"><a href="http://link.address.com">http://link.address.com</a> | <i class="fa fa-edit" aria-hidden="true"></i> | <i class="fa fa-unlink" aria-hidden="true"></i></span></span><a href="#">There are a bunch of other editor options</a></span--> There are a bunch of other options available but I'm sticking with the basics here. Some of the others that could be cool to include are:</p>
<ul>
<li>cut</li>
<li>paste</li>
<li>fontSize</li>
<li>heading</li>
<li>insertImage</li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/API/Document/execCommand#Commands">... and a bunch more</a></li>
</ul>
<p>So give it a go and feel free to use what you want.</p>
</div>
</section>
<script src='//production-assets.codepen.io/assets/common/stopExecutionOnTimeout-b2a7b3fe212eaa732349046d8416e00a9dec26eb7fd347590fbced3ab38af52e.js'></script><script src='https://use.fontawesome.com/ce726fce7b.js'></script>
<script >Array.prototype.map.call(document.querySelectorAll('.tools a:not([data-role="createLink"])'), (action) => {
action.addEventListener("click", (e) => {
e.preventDefault();
document.execCommand(action.dataset.role, false, action.dataset.value);
})
})
// Handle the link modal
const modal = document.querySelector('.modal');
const closeModal = () => {
modal.classList.remove('visible');
}
let closeButton = document.querySelector('.closeModal');
closeButton.addEventListener('click', closeModal);
document.addEventListener('keyup', function(e) {
if (e.keyCode == 27) {
closeModal();
}
});
let otherClicks = (event) => {
if (document.querySelector('.modal').contains(event.target)) {
return false;
} else {
closeModal();
window.removeEventListener('click', otherClicks);
}
};
window.addEventListener('click', otherClicks);
const anchorLink = document.querySelector('a[data-role="createLink"]');
anchorLink.addEventListener('click', () => {
modal.classList.add('visible');
window.savedSel = saveSelection();
document.urlForm.urlField.value="";
document.urlForm.urlField.focus();
})
// Save selected text when URL modal opens. From http://stackoverflow.com/questions/5605401/insert-link-in-contenteditable-element
function saveSelection() {
if (window.getSelection) {
sel = window.getSelection();
if (sel.getRangeAt && sel.rangeCount) {
var ranges = [];
for (var i = 0, len = sel.rangeCount; i < len; ++i) {if (window.CP.shouldStopExecution(1)){break;}
ranges.push(sel.getRangeAt(i));
}
window.CP.exitedLoop(1);
return ranges;
}
} else if (document.selection && document.selection.createRange) {
return document.selection.createRange();
}
return null;
}
function restoreSelection(savedSel) {
if (savedSel) {
if (window.getSelection) {
sel = window.getSelection();
sel.removeAllRanges();
for (var i = 0, len = savedSel.length; i < len; ++i) {if (window.CP.shouldStopExecution(2)){break;}
sel.addRange(savedSel[i]);
}
window.CP.exitedLoop(2);
} else if (document.selection && savedSel.select) {
savedSel.select();
}
}
}
let urlForm = document.querySelector('.urlForm');
urlForm.addEventListener('submit',(e) => {
let urlValue = urlForm.querySelector('.url').value;
restoreSelection(window.savedSel);
document.execCommand("CreateLink", false, urlValue);
closeModal();
e.preventDefault();
})
function getSelectionParentElement() {
var parentEl = null, sel;
if (window.getSelection) {
sel = window.getSelection();
if (sel.rangeCount) {
parentEl = sel.getRangeAt(0).commonAncestorContainer;
if (parentEl.nodeType != 1) {
parentEl = parentEl.parentNode;
}
}
} else if ( (sel = document.selection) && sel.type != "Control") {
parentEl = sel.createRange().parentElement();
}
return parentEl;
}
//# sourceURL=pen.js
</script>
</body></html>