Unable to move cursor in contenteditable section

I am currently working on developing a rich text editor in React, but I have encountered an issue that has me stuck. The problem I am facing is that as I type each character, the insertion point does not update accordingly, causing the cursor to remain stuck on the left side while new characters are being inserted at the leftmost position. Furthermore, when I manually move the cursor to the end of a word and try typing again, it unexpectedly shifts back to the left.

You can view a screenshot of my text editor here.

import React from "react";
import { useState } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
  faBold,
  faCode,
  faFileCode,
  faFilm,
  faImage,
  faItalic,
  faLink,
  faList,
  faListOl,
  faQuoteRight,
  faStrikethrough,
  faUnderline,
} from "@fortawesome/free-solid-svg-icons";
import "./textEditor.css";

// Rest of the JavaScript code...

CSS

.editor-wrapper {
  width: 100%;
  height: 500px;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.editor {
  width: 70%;
  // Additional styling properties...
}

Answer №1

To address this issue, I introduced a new function that directs the cursor's focus towards the user by utilizing the useEffect hook with a listener attached to the content hook. Here is how the function works:

function focus() {
  const contentEle = document.getElementById('content');
  const range = document.createRange();
  const selection = window.getSelection();
  range.setStart(contentEle, contentEle.childNodes.length);
  range.collapse(true);
  selection.removeAllRanges();
  selection.addRange(range);
}

useEffect(() => {
  focus();
}, [content]);

This code now includes the newly created function.

// Importing necessary dependencies
import React from "react";
import { useState, useEffect } from "react";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import {
  faBold,
  faCode,
  faFileCode,
  faFilm,
  faImage,
  faItalic,
  faLink,
  faList,
  faListOl,
  faQuoteRight,
  faStrikethrough,
  faUnderline,
} from "@fortawesome/free-solid-svg-icons";
import "./textEditor.css";

const TextEditor = () => {
  // State hooks declaration
  const [content, setContent] = useState("");
  const [isBold, setIsBold] = useState(false);
  const [isItalic, setIsItalic] = useState(false);
  const [isUnderline, setIsUnderline] = useState(false);
  const [isStrikeThrough, setStrikeThrough] = useState(false);
  const [isBlockquote, setIsBlockquote] = useState(false);
  const [isHeading1, setIsHeading1] = useState(false);
  const [isHeading2, setIsHeading2] = useState(false);
  const [isOrderedList, setIsOrderedList] = useState(false);
  const [isUnorderedList, setIsUnorderedList] = useState(false);
  const [isInlineCode, setIsInlineCode] = useState(false);
  const [isCodeBlock, setIsCodeBlock] = useState(false);

  // Function to handle text formatting
  const handleFormat = (style, value = null) => {
    // Toggling state for corresponding style
    switch (style) {
      case "bold":
        setIsBold(!isBold);
        break;
      case "italic":
        setIsItalic(!isItalic);
        break;
      case "underline":
        setIsUnderline(!isUnderline);
        break;
      // Other cases omitted for brevity
    }

    // Applying the selected style
    document.execCommand(style, false, value);
  };

  // Defining the focus function
  function focus() {
    const contentEle = document.getElementById('content');
    const range = document.createRange();
    const selection = window.getSelection();
    range.setStart(contentEle, contentEle.childNodes.length);
    range.collapse(true);
    selection.removeAllRanges();
    selection.addRange(range);
  }

  // Triggering focus on content change
  useEffect(() => {
    focus();
  }, [content]);

  return (
    <!-- Component structure and button implementations here -->
  );
};

export default TextEditor;

For more details and to access the updated project with this solution, you can visit the following link: https://github.com/pablosalazzar/stackoverflow-answer-2

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to incorporate images from an external module into my React project?

Is there a way to include images from an external module (npm install external-module) in my project's public assets? The images are located in the directory path myProject/node_modules/external-module/dist/img. ...

I desire the div to display based on the conditions set in the PHP file

Hi, I am looking to display the div with ID "msga" when a certain condition is met and show the div with ID "msgb" when another condition is met. Here is my PHP code: if(isset($_POST['aa'])) { echo "a"; } if (isset($_POST['bb']))) { ...

Seeking assistance with design patterns for creating a reusable dialog

I have a table of users and I want to be able to edit the data for each user by popping up a dialog. Currently, the basic structure is as follows: { header: 'Edit User', cell: (cell) => { return ( <> <SimpleFormD ...

In ReactJS, material-ui utilizes the class `Mui-disabled` to designate read-only components

Creating a new component using TextField and needing to apply the same style for text fields with either the readOnly or disabled property. Attempted to utilize the className property, but it was not successful. // some logic here .. <TextField { ...

Having some issues with validating numbers in typescript

When implementing react hook form in my React app, I encountered an issue while validating specific fields and had to add some conditions to the schema. yup .object({ test1: yup.number().when('test2', (test2: number, schema: yup.NumberSchem ...

Searching for TypeScript type definitions for the @Angular libraries within Angular 2

After updating my application to Angular2 v2.0.0-rc.1, I am encountering TypeScript compile errors and warnings when webpack bundles my application. These messages appear for any @angular packages referenced in my TypeScript source files: ERROR in ./src/a ...

Troubleshooting Autocomplete User Interface Problems

I am currently working on a website user interface and I have encountered an issue specifically in IE7. When searching for a company, the display is not showing up correctly, as demonstrated in the image below. This problem only occurs in IE7, it works fi ...

Encountered a JSON error while implementing in an ASP project

Currently, I am working with JavaScript and C# in aspnet. My goal is to pass 3 values from the Asp Page to the code behind, using the Json method. Below is how I achieve this: //initialize x, y and nome var requestParameter = { 'xx': x, 'yy ...

A guide on extracting data from onChange event to successfully upload an image in React

Hey everyone, I have two functions that I need help with: changeProfileImage=(event)=>{ this.setState({file:event.target.files[0]}); } and the upload function: upload(file) { let formData = new FormData(); co ...

React: Dynamically update text input based on selected option

After selecting an option, I want to display a new text input. However, the old value entered remains on the screen even when I change the selection. How can I improve this functionality? Any suggestions would be appreciated. class loadComponent extends ...

Using JavaScript to enhance event handling for a `select` element in a progressive manner

I have an advanced <select> element in my HTML. It is structured like this: <ul> <li></li> <li></li> ... </ul> In the current setup, a click event handler is attached to each individual li element. If the ...

Ways to disable .animate() specifically for a particular element

I have implemented a countdown using which smoothly animates the numbers down and fades to opacity 0. Update. I have also created a demo on jsFiddle here: http://jsfiddle.net/Mw4j2/ // The .static class is added when the animation // complet ...

Exploring Laravel's method for retrieving data from multiple tables in the controller

In an effort to make my jQuery call more dynamic, I have a controller with the following method: public function api(Request $request , $project_id){ return Program::where('project_id',$project_id)->get(); } This results in: [{"id":178," ...

ngx-slick-carousel: a carousel that loops infinitely and adjusts responsively

I have implemented ngx-slick-carousel to showcase YouTube videos in my project. However, I am facing two main issues. Firstly, the carousel is not infinite, and when the last video is reached, there appears to be white spaces before it loops back to the fi ...

Importing ReactDOM alone does not result in the rendering of anything

Having just started delving into the world of React, I've been grappling with getting a React app up and running. Despite my efforts, all I can manage to see is a blank page. Can anyone offer some assistance? HTML Markup (index.html) <html> & ...

Get a CSV file through EmberJs

I have been experimenting with various function calls, but I am unable to figure out how to initiate a CSV download in EmberJs. Below is the most recent code I have tried: let endpoint = '/api/foo/'; let options = { url: endpoint, type: ...

Embed fashion and graph elements into a CSV document (generated from <script>)

Encountering an issue with my code. I am looking to export an HTML table to a CSV file (specifically Libre Office Calc, regardless of csv, xls or xlsx format, as long as it runs on a Linux Server). Found a script online that works well after some modificat ...

Despite seeming false, my Javascript if statement still evaluates to true

On my webpage, I have a button and a form. The intended functionality is for the button to display the form when clicked, and hide it when clicked again. The issue I'm facing is that no matter if the statement is true or false, the first if statement ...

Real estate for a targeted audience

1. Overview I have a list of selectors that should always apply certain properties. Some selectors require additional properties to be added. I'm struggling to find a way to achieve this without repeating code. 2. Minimal CSS Example (MCVE) 2.1 ...

Troubleshooting Issue with Absolute Positioning and Hover Effect on Material UI Button

I have a div containing a hidden button and an inner div filled with graphs and text. Occasionally, I need to blur the inner div and make the button float on top in the center of the blurred section, similar to the layout seen on subscription prompts found ...