Mastering the navigation of the Document Object Model (DOM) is a powerful skill. However, it’s not always clear exactly where elements reside within the DOM. That’s frustrating when you need to make changes to a page that’s already loaded, or when you need to set the cursor position.
Traversing the DOM is like following roadmap directions. And like a roadmap, each element of the web page has an address. You can target these addresses – also called nodes – and make changes to the page.
Usually, changes happen in response to customers pressing a button or some other interaction. But what about finding your way when the changes are inside a textarea? Like collaboration or commenting on text within the textarea?
The textarea is an element inside the page DOM, and the text content inside that textarea also contains elements. And since these elements are nodes, you can navigate through them and place the cursor position at a specific spot.
But it’s not always a direct path through the DOM, through the textarea element, and to a specific cursor position.
For TinyMCE, a rich text editor that's shown its reliability time and again, this process is made possible (with some limits), using specific APIs. This article explains how it’s done, with some examples.
Table of Contents
What’s a cursor position? And what’s a caret?
What you need to set cursor position: JavaScript and more
Getting the cursor position
Setting the cursor position
1. Select content, and then bookmark the position of the content
2. Set the caret position on newly added content
3. Set the caret position at the end of the text area
How to set the caret position
Set up a TinyMCE demo editor
1. Set the cursor position with the Bookmark Manager API
2. Set the cursor position at new elements
3. Set the cursor position at the end of the text editor
Setting the cursor position - one key point
What’s a cursor position? And what’s a caret?
A cursor is a pointer – the graphical icon that represents the mouse. It’s often a small arrow icon that moves around the web page on screen. Sometimes, the “cursor” position is brought up to describe the “caret” position.
A caret is the blinking line that indicates where the next word is going to appear when keydown events (the press of the keyboard) happens. Still unclear? What really matters is the intention – do you want to put the blinking line in a specific place in the text area? Then in that case, you want to set the caret at a specific position.
What you need to set cursor positions: JavaScript and more
With that goal in mind, what skills and knowledge do you need to set the caret in the right spot? You need to know the following:
- Understand JavaScript
- Understand Web APIs
- Have some curiosity about TinyMCE APIs
It’s also important to know the limits of what you're doing. Finding a specific place in the textarea is difficult. It can also be difficult in TinyMCE's text area.
What you can do though, is firstly place the caret at the location you want, and then you can bookmark that location. Then, you can load that location when you need it. That’s the main limit of setting the cursor location – you need to choose the location if you want a specific spot first, save it, and then apply that specific bookmark later on.
Getting the cursor position
While you can set the position using TinyMCE APIs, getting the cursor position coordinates, integers, or a string, represents a more difficult challenge. Using the TinyMCE Bookmark Manager API, you can set the cursor position that you want to get, and then bookmark that cursor position. The API saves the location so you can retrieve it later (more on the API in the following procedures).
Setting the cursor position
1. Select content, and then bookmark the position of the content
Using the TinyMCE Bookmark Manager API, you can configure the editor to hold on to the caret position in the form of a selection of content. A selection, also known as highlighting, happens when the browser recognizes that you have:
- Pushed the mouse button down
- Dragged the cursor across content
- Then let the mouse button move up again.
You can also hold down shift and move the cursor with the arrow keys on the keyboard to select content. It has the same effect. TinyMCE bookmarks the selected location with the Bookmark Manager API, and then loads the selected location later, if or when you request it.
2. Set the caret position on newly added content
If you are adding content into the TinyMCE text area, you can also set the caret position to be at a specific index location within a DOM element, like <p> or <strong> that you’re adding to the editor. The TinyMCE setCursorLocation API can target the content you’re adding, and TinyMCE then essentially picks up your cursor, and puts it down at the integer you want.
For instance, if you write “<strong>bold text</strong>” within the text area, you can use an API to set an integer of “<strong> [5]” to place the caret on the fifth character of the <strong> element, which is the letter “t” in text.
3. Set the caret position at the end of the text area
The expected behavior of the text area caret is to appear at the beginning, that is, the top left hand corner of the text area. The selection.collapse API method allows for this beavior. However, you can set the caret to appear in the lower right of the text area, which is the opposite position to where it ordinarily appears.
How to set the caret position
The first way of doing this involves the TinyMCE Bookmark Manager API. To test this out, the Tutorial below creates a function, and sets the function up to run when a button on the demo web page is clicked.
Set up a TinyMCE demo editor
To put TinyMCE’s APIs for cursor position to the test, the following demo first sets up TinyMCE in a demo document editor:
- Create a new index.html file in your development environment
- Include the following HTML to start up the TinyMCE demo editor:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://cdn.tiny.cloud/1/no-api-key/tinymce/6/tinymce.min.js" referrerpolicy="origin"></script>
<script>
tinymce.init({
selector: "#editor",
});
</script>
</head>
<body>
<h1>TinyMCE Example</h1>
<form method="post">
<textarea id="editor"></textarea>
</form>
</body>
</html>
-
For this cursor position test, the rich text editor resides inside a Document Management System. Setting this up requires using the content_style option to target the body element and change the appearance:
<script>
tinymce.init({
selector: "#editor",
content_style:`
body {
background: #fff;
}
@media (min-width: 840px) {
html {
background: #eceef4;
min-height: 100%;
padding: 0 .5rem
}
body {
background-color: #fff;
box-shadow: 0 0 4px rgba(0, 0, 0, .15);
box-sizing: border-box;
margin: 1rem auto 0;
max-width: 820px;
min-height: calc(100vh - 1rem);
padding:4rem 6rem 6rem 6rem
}
}
`
});
</script>
💡NOTE: You can change the “no-api-key” string to your TinyMCE API key. When you sign up for a FREE TinyMCE API key, you get a 14 day free trial of TinyMCE’s Premium plugins. Using the key also prevents domain identification errors showing up in the text area.
-
Save the changes, and test the index file in the browser. You can also test it by running the index file on your workstation’s local host using a python command or a PHP command:
1. Set the cursor position with the Bookmark Manager API
To test out this API, and see how it works quickly, this tutorial makes use of the Developer Tools console.
- With the developer console open (ctrl + option + j on chrome for instance) highlight the content in the editor that you want to bookmark, and return the cursor position to later.
- Run the following command to bookmark the cursor position:
let bookmark = tinymce.activeEditor.selection.getBookmark();
-
Move the cursor away from the bookmarked content. You can remove the highlighted selection, and include some more content in the editor at this stage.
-
To load the bookmark, run the following command in the developer console:
tinymce.activeEditor.selection.moveToBookmark(bookmark);
With the moveToBookmark method, the editor will return the content set up and selected with the getBookmark command. This is one way to capture the cursor position inside the TinyMCE editor, and then return to it later when it’s needed.
2. Set the cursor position at new elements
For this method, the tutorial sets up an interactive element (a button) and runs the TinyMCE setCursorLocation API command.
-
Set a button element just after the text area in the demo HTML file:
<body>
<h1>TinyMCE Example</h1>
<form method="post">
<textarea id="editor"></textarea>
</form>
<button></button>
-
Give the button the id of buttonSelect
<button id=”buttonSelect”></button>
-
Set up a pair of script tags after the body element of the demo HTML file:
</body>
<script> </script>
</html>
-
Place the following function inside the script tags. This function selects the active editor Body element :
<script>
function selectionCommand() {
let editorBody = tinymce.activeEditor.getBody();
-
Extend the function by using the TinyMCE setContent API to change the editor content
<script>
function selectionCommand() {
let editorBody = tinymce.activeEditor.getBody();
tinymce.activeEditor.setContent('<p>hello <strong>bold</strong> content</p>');
-
To set the cursor position in the new content, add to the function a variable, and assign to it the bold, or strong, element set up in the previous step.
✏️NOTE: This is one method for selecting the TinyMCE text editor, setting content, and then selecting a specific node within the editor.
<script>
function selectionCommand() {
let editorBody = tinymce.activeEditor.getBody();
tinymce.activeEditor.setContent('<p>hello <strong>bold</strong> content</p>');
let nodeStrong = tinymce.activeEditor.dom.select('strong')
-
Add the setCursorLocation API command targeting the variable set up in the previous step (containing the strong tag selection), and set the focus method:
<script>
function selectionCommand() {
let editorBody = tinymce.activeEditor.getBody();
tinymce.activeEditor.setContent('<p>hello <strong>bold</strong> content</p>');
let nodeStrong = tinymce.activeEditor.dom.select('strong');
tinymce.activeEditor.selection.setCursorLocation(nodeStrong[0].firstChild, 2);
tinymce.activeEditor.focus();
}
</script>
-
Add an event listener that’ll be triggered by the button click event, referencing the button added at the beginning of this procedure:
<script>
function selectionCommand() {
let editorBody = tinymce.activeEditor.getBody();
tinymce.activeEditor.setContent('<p>hello <strong>bold</strong> content</p>');
let nodeStrong = tinymce.activeEditor.dom.select('strong');
tinymce.activeEditor.selection.setCursorLocation(nodeStrong[0].firstChild, 2);
tinymce.activeEditor.focus();
}
var buttonSelection = document.getElementById('buttonSelect');
buttonSelection.addEventListener('click', selectionCommand, false);
</script>
-
Save the changes, and then test run the button to set the cursor position:
3. Set the cursor position at the end of the text area
With the selection.collapse API method, you can move the cursor position to the end of the editor.
-
Add a second button the the demo HTML file after the button produced in the previous procedure:
<button id="buttonEnd" class="button_style">
Go to the end
</button>;
-
Add a new function to script tags at the end of the demo HTML file:
function endCommand() {}
-
Use the selection API and the getBody API methods to capture the text area content:
function endCommand() {
tinymce.activeEditor.selection.select(tinyMCE.activeEditor.getBody(), true);
-
Include the collapse API method to move the cursor to the end of the selection range, which is the end of the editor, and then include the focus API:
function endCommand() {
tinymce.activeEditor.selection.select(tinyMCE.activeEditor.getBody(), true);
tinymce.activeEditor.selection.collapse(false);
tinymce.activeEditor.focus();
}
-
Add an event listener to trigger the function when the button is clicked:
var buttonEnd = document.getElementById("buttonEnd");
buttonEnd.addEventListener("click", endCommand, false);
-
Save the changes, and test run the button to move the cursor to the end of the rich text editor:
Setting the cursor position - one key point
Depending on what you need in your web page or app, you can use one of the methods available with the TinyMCE API to set the cursor position in your rich text editor.
Next steps could include setting the Bookmark Manager API to run on events in the interface, such as a mouseup event, following a highlight.
Once you have the DOM node selected in the text area, you can be precise, and set the caret to appear at a specific index number within that DOM node.
The key point to remember is: that setting the cursor position on a specific point in the text area needs a specific DOM node to work correctly.
If you’d like to find out more about TinyMCE, and try some of the Premium plugins, contact us and our customer success team can help you find the rich configuration for your web page or app, and set the cursor position where you need it.