DEV Community

Yohei Seki
Yohei Seki

Posted on

How to display other client's cursor (caret) position with CodeMirror

I will explain how to display other person's (other client) cursor (caret) position who are editting in real time with "CodeMirror".

By following the procedure explained in this article, it is also possible to display other client's cusror positions in various colors as shown below.

cattaz_cursor.png

This function is implemented in Fujitsu Laboratories OSS's Markdown-based collaboration tool "Cattaz".

Cattaz

GitHub - Cattaz

Introduction

Since this article focuses on the part where cursor is displayed, the following explanation is omitted.

  • Getting the input event of the CodeMirror editor
  • Communication between CodeMirror editors

Method

It uses the following CodeMirror API.

setBookmark

By using this API, you can insert the generated DOM node (marker / design you want to display) at the specified position in the editor.

In short, you can add DOM node decorating styles to the location of the cursor position sent from another client.

By doing so, you can display the cursor position of other clients.

Here is an example of code that creates a DOM node and sets the DOM node to "setBookmark" in the specified editor position.

(Described in writing the code in ES 2015 (ES6))



// cm: CodeMirror instance
// cursorPos: The position of the cursor sent from another client ({line, ch} about CodeMirror)

// Generate DOM node (marker / design you want to display)
const cursorCoords = cm.cursorCoords(cursorPos);
const cursorElement = document.createElement('span');
cursorElement.style.borderLeftStyle = 'solid';
cursorElement.style.borderLeftWidth = '2px';
cursorElement.style.borderLeftColor = '#ff0000';
cursorElement.style.height = `${(cursorCoords.bottom - cursorCoords.top)}px`;
cursorElement.style.padding = 0;
cursorElement.style.zIndex = 0;

// Set the generated DOM node at the position of the cursor sent from another client
// setBookmark first argument: The position of the cursor sent from another client
// Second argument widget: Generated DOM node
marker = cm.setBookmark(cursorPos, { widget: cursorElement });


Enter fullscreen mode Exit fullscreen mode

You can make cool display by using different DOM node styles.

The above example is a vertical line design like a normal cursor.

The DOM node added with setBookmark will remain at the inserted position in the editor.

Therefore, whenever the cursor position is sent from another client, it is good to delete the inserted DOM node once with the clear () method of setBookmark, then insert the new DOM node again as follows.



// Clear the inserted DOM node
// marker: setBookmark instance
marker.clear();

Enter fullscreen mode Exit fullscreen mode




Step-by-step flow

An example of the step-by-step flow is as follows.

  1. Get cursor position from input event of CodeMirror editor
  2. Send the position of the cursor to other client using Websocket communication etc.
  3. A client that received the position of the cursor sent from other client deletes the DOM node that was previously inserted with setBookmark if it remains
  4. Insert the DOM node as the marker with the setBookmark at the position of the received cursor

In addition, if you manage the cursor position received for each client, you can display cursors of multiple clients at the same time

Summary

In this way, you can display the cursor position of other clients by using "setBookmark" of CodeMirror's API.

Since this function is also implemented in "Cattaz" (as of January 9, 2018), its source code might be helpful.

GitHub - Cattaz

Top comments (1)

Collapse
 
ben profile image
Ben Halpern

Just came across this. Super helpful!