Build a basic text editor with a JavaScript class

Learn how to use an ES6 JavaScript class with getters and setters to build a basic text editor that sets, replaces, appends, backspaces, and clears text.
May 01, 2023JavaScript
5 min read

Let's build a basic text editor using a JavaScript class. This class will implement the most common features of a basic text editor, namely the setting, replacing, appending, backspacing, and clearing of text. This JavaScript class will track both the text and the position of a fake mouse cursor.

Rather than creating methods like getText and setText, we'll use JavaScript ES6's getter and setter methods via the get and set keywords. We'll use the same approach for the cursor position methods.

TextEditor class

The TextEditor class will have several methods:

  • Getter and setter methods for text.
  • Getter and setter methods for cursorPosition.
  • An appendText method to add new text at the current cursor position.
  • A clearText to delete all the text.
  • A capitalizeText method to transform the text to uppercase.
  • A replaceText method to find and replace all occurrences of a specified text with new text.
  • A backspace method to remove the character before the current cursor position, if there is one.
  • A moveCursorLeft method to move the cursor one position to the left, unless it's already at the beginning of the text.
  • A moveCursorRight method to move the cursor one position to the right, unless it's already at the end of the text.

We'll need to rename the class's text variable to _text to avoid a name collision with the getter and setter methods that are also named text. We'll also use the underscore for the cursorPosition variable.

text-editor.js
class TextEditor {
  constructor() {
    this._text = '';
    this._cursorPosition = 0;
  }

  set text(newText) {
    this._text = newText;
    this._cursorPosition = this._text.length;
  }

  get text() {
    return this._text;
  }

  appendText(newText) {
    if (this._cursorPosition > 0) {
      // from character 0 to the cursor position
      const beforeCursor = this._text.slice(0, this._cursorPosition);
      // if there are characters after the cursor
      const afterCursor = this._text.slice(this._cursorPosition);
      this._text = beforeCursor + newText + afterCursor;
      this._cursorPosition = beforeCursor.length + newText.length;
    } else {
      this._text += newText;
      this._cursorPosition = this._text.length;
    }
  }

  clearText() {
    this._text = '';
    this._cursorPosition = 0;
  }

  capitalizeText() {
    this._text = this._text.toUpperCase();
  }

  replaceText(oldText, newText) {
    this._text = this._text.replace(oldText, newText);
    this._cursorPosition = this._text.length;
  }

  backspace() {
    if (this._cursorPosition > 0) {
      // from character 0 to the first character to exclude
      const beforeCursor = this._text.slice(0, this._cursorPosition - 1);
      // if there are characters after the cursor
      const afterCursor = this._text.slice(this._cursorPosition);
      this._text = beforeCursor + afterCursor;
      this._cursorPosition--;
    }
  }

  moveCursorLeft() {
    if (this._cursorPosition > 0) {
      this._cursorPosition--;
    }
  }

  moveCursorRight() {
    if (this._cursorPosition < this._text.length) {
      this._cursorPosition++;
    }
  }

  get cursorPosition() {
    return this._cursorPosition;
  }

  set cursorPosition(position) {
    this._cursorPosition = position;
  }
}

We can now create an instance of the TextEditor class and use its methods to perform operations on actual text. We'll do this within the same JavaScript file.

Using the TextEditor class

Let's start by setting some initial text.

const editor = new TextEditor();
editor.text = 'Hello, world!';
console.log(editor.text); // Hello, world!
console.log(editor.cursorPosition); // 13

Now that we have some text, let's navigate through the text by moving the cursor to the left.

editor.moveCursorLeft();
console.log(editor.cursorPosition); // 12

Let's move the cursor to the right in order to return it to its previous position.

editor.moveCursorRight();
console.log(editor.cursorPosition); // 13

Let's manually set the cursor position.

editor.cursorPosition = 12;
console.log(editor.cursorPosition); // 12

Let's delete a character from the text by using the backspace method.

editor.backspace();
console.log(editor.text); // Hello, worl!
console.log(editor.cursorPosition); // 11

Let's re-add the character that we just deleted by using the appendText method.

editor.appendText('d');
console.log(editor.text); // Hello, world!

Let's capitalize all the text.

editor.capitalizeText();
console.log(editor.text); // HELLO, WORLD!

Let's replace 'WORLD' with 'Universe' by using the replaceText method.

editor.replaceText('WORLD', 'Universe');
console.log(editor.text); // HELLO, Universe!

Let's use the clearText method to delete all the text

editor.clearText();
console.log(editor.text); // empty string

Let's use the appendText method from the current cursor position of 0 to define new text.

editor.appendText('Goodbye!');
console.log(editor.text); // Goodbye!

Conclusion

This exercise of building a text editor helped us learn how to use JavaScript ES6 classes.

All the functionality that we defined for the text editor is encapsulated within a class, making it organized and reusable. We can create multiple instances of the TextEditor class and manipulate text independently. Each instance will maintain its own text content and cursor position, allowing for separate editing sessions.

JavaScript classes give us a structured approach to organizing our code. They allow us to create modular components that are easy to test, maintain, and reuse.

The current state of the TextEditor class is just a starting point. It can be extended to include more advanced features, such as text formatting, undo/redo functionality, text selection, and more. We could also connect this class to a user interface for a more interactive experience.

New
Be React Ready

Learn modern React with TypeScript.

Learn modern React development with TypeScript from my books React Ready and React Router Ready.