Creating a rich-text editor in JavaScript isn't as difficult as you may think it is and it can give you the much needed control over your code and applications as you won't have to rely on 3rd party implementations if you're looking to add any custom functionality.
So today I'll be going over the steps to make a very simple text-editor
with the usual basic functionality, such as text/font styling and
adding embedded links.
While the following post won't be using any incredibly advanced topics
in JavaScript, a fundamental knowledge of the core concepts will help greatly. I always recommend the following book Web Design with HTML, CSS, JavaScript and jQuery for anybody that's relatively new to JavaScript and web development in general.
Creating the editor
Let's start off by creating the actual text editor where users will be typing the given text. For that, we'll be using a standard div tag, and we will be setting the contenteditable attribute to 'true'.
The contenteditable attribute turns any container into an editable text field with default styling set by the browser.
<div class="editor" contenteditable="true">
</div>
About contenteditable
The contenteditable global attribute does indeed turn certain elements, like divs and spans into focusable editable widgets in the browser. These elements can be tabbed through, much like other text input elements, and can have their focus set dynamically as well.
You can also modify the color of the caret that appears within the editable element by specifying the 'caret-color' CSS property.
Which with some very basic styling, a div with contenteditable set to true looks something like the following. This is a regular div element, however you can type text directly into it.
And the CSS styling looks like the following:
.editor
{
border:solid 1px #ccc;
padding: 20px;
min-height:200px;
}
The content inside of the container can be retrieved how you would normally retrieve any content inside of a div element using the innerHTML property of the container or innerText if you're looking to grab just the plain text content.
Creating the toolbar
Next up, let's set up a basic toolbar with the usual text formatting features, such as bolding and italicizing text. I will be using Font Awesome for the icons, as they have all the necessary text editor icons and are very easy to implement.
<div class="sample-toolbar">
<span class="fa fa-bold fa-fw" aria-hidden="true"></span>
<span class="fa fa-italic fa-fw" aria-hidden="true"></span>
<span class="fa fa-list fa-fw" aria-hidden="true"></span>
<span class="fa fa-link fa-fw" aria-hidden="true"></span>
</div>
And again, with some very basic styling, we have something like the following.
And the styling is as follows.
.sample-toolbar
{
border:solid 1px #ddd;
background:#f4f4f4;
padding: 5px;
border-radius:3px;
}
.sample-toolbar > span
{
cursor:pointer;
}
.sample-toolbar > span:hover
{
text-decoration:underline;
}
The benefit of creating your own text-editor, is that you can essentially add any features that you wish and you can then expand on those features.
For now, we'll just handle these 4 basic functions of making text bold,
italic, creating lists and adding a hyperlink to any selected group of
text.
Formatting
JavaScript includes built-in functions to handle the formatting for us, all we have to do is to specify the current text selection and the type of formatting that we are looking to implement. And we can do that with the following helper function.
function format(command, value) {
document.execCommand(command, false, value);
}
The execCommand has the following signature, which we'll break down below.
bool = document.execCommand(aCommandName, aShowDefaultUI, aValueArgument)
The execCommand function returns true if the command and value are valid arguments for the current browser. And false otherwise. The second argument determines whether the default user interface should be shown. However, note that this parameter is not implemented in Firefox.
Bold
Let's start with 'bolding' the selected text. With the built in functions it is as easy as calling the format function with the appropriate values.
<span class="fa fa-bold fa-fw" onclick="format('bold')"></span>
In this case, there is no associated 'value' to go with the 'bold' command, so we can leave the argument out. And the same approach is taken for making text italic.
Italic
<span class="fa fa-italic fa-fw" onclick="format('italic')"></span>
In order to have the formatting take effect, you must be highlighting some text and be inside of a contenteditable container. The browser is in charge of running the command against the right contenteditable container, since you can have many on a single page.
List
And the same thing once again is applicable to creating list items, with the command name of 'insertunorderedlist'.
<span class="fa fa-list fa-fw" onclick="format('insertunorderedlist')"></span>
Next up, let's include the ability to add hyperlinks to some selected text in the editor. This is one of my favorite uses, as I do it often when linking in my articles. There are 2 different ways to accomplish this, and we'll talk about both down below and when to use each.
Hyperlinks
function setUrl() {
let url = document.getElementById('txtUrl').value;
let sText = document.getSelection();
document.execCommand('insertHTML', false, '<a href="' + url + '" target="_blank">' + sText + '</a>');
//format('createlink', url);
}
The first method involves using the 'createlink' command, which takes a 'url' as a value. This is the short and simple way of creating a hyperlink on the selected text. However, if you need to add any extra attributes to the url, such as a class or a target attribute, then you will need to use an alternative method.
Which is where the 'insertHTML' command comes into play. The command replaces whatever content you are highlighting with the given value. In our case, we want to replace the currently selected text, with an anchor tag, our desired attributes, and the selected text itself.
You should end up with something like the following.
Here is some default text. Try entering a URL in the form input above, then select any text here and click on the link icon in the toolbar.
This is a very quick and easy implementation of a text-editor.
But there is much power in having your own custom editor that you can
essentially do whatever you wish to do with. This blog runs off of a
very custom editor that I spent a fair amount of time on, but that makes
my writing much more efficient than I would otherwise be.
The full source is down below for your editing and tweaking pleasures. And if you would like to see any features added, just comment down below.
Full Source
<html>
<head>
<style>
.editor
{
border:solid 1px #ccc;
padding: 20px;
min-height:200px;
}
.sample-toolbar
{
border:solid 1px #ddd;
background:#f4f4f4;
padding: 5px;
border-radius:3px;
}
.sample-toolbar > span
{
cursor:pointer;
}
.sample-toolbar > span:hover
{
text-decoration:underline;
}
</style>
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
</head>
<body>
<div class="sample-toolbar">
<a href="javascript:void(0)" onclick="format('bold')"><span class="fa fa-bold fa-fw"></span></a>
<a href="javascript:void(0)" onclick="format('italic')"><span class="fa fa-italic fa-fw"></span></a>
<a href="javascript:void(0)" onclick="format('insertunorderedlist')"><span class="fa fa-list fa-fw"></span></a>
<a href="javascript:void(0)" onclick="setUrl()"><span class="fa fa-link fa-fw"></span></a>
<span><input id="txtFormatUrl" placeholder="url" class="form-control"></span>
</div>
<div class="editor" id="sampleeditor">
</div>
<script>
window.addEventListener('load', function(){
document.getElementById('sampleeditor').setAttribute('contenteditable', 'true');
document.getElementById('sampleeditor2').setAttribute('contenteditable', 'true');
});
function format(command, value) {
document.execCommand(command, false, value);
}
function setUrl() {
var url = document.getElementById('txtFormatUrl').value;
var sText = document.getSelection();
document.execCommand('insertHTML', false, '<a href="' + url + '" target="_blank">' + sText + '</a>');
document.getElementById('txtFormatUrl').value = '';
}
</script>
</body>
</html>
Fork on Codepen.io