2

I have a function that separates words into separate span tags and updates the div I am typing into but every time I update the innerHTML the cursor moves to the start of the box so the next character I type outputs behind the last one instead of after it. Could someone tell me how I can stop the cursor from doing this?

Here is my code

const editorDiv = document.getElementById('editor');

function wrapWords(str, tmpl) {   //separates words into <span>
  return str.replace(/\w+/g, tmpl || "<span>$&</span>");
}

editorDiv.addEventListener('keydown', function(event) {
  editorDiv.innerHTML = wrapWords(editorDiv.innerText)
});
<div id="editor" contenteditable="true">
  <span>hello</span>
</div>

When I type into the div text looks like this: .siht ekil skool txeT

Jax-p
  • 7,225
  • 4
  • 28
  • 58
4ert5yhnb
  • 23
  • 2
  • I would recommend you to use `input` instead of `contenteditable` because it is not friendly solution for caret/cursor handling. You can read how to [Get contentEditable caret position](https://stackoverflow.com/questions/3972014/get-contenteditable-caret-position) and once you have position you can set it back with [How to set caret(cursor) position in contenteditable element (div)?](https://stackoverflow.com/questions/6249095/how-to-set-caretcursor-position-in-contenteditable-element-div). – Jax-p Jun 28 '21 at 13:49
  • I need it to be contenteditable because I need to be able to change the css of each word separately, thanks for the links though, I will check them out – 4ert5yhnb Jun 28 '21 at 13:53
  • Not sure exactly what you want to afford, but you could take a look at the code source of StackOverflow's `tag` system, handled with an input at the end of the list (sorry for the delay, did not press enter...) – Ulysse BN Jun 28 '21 at 16:34
  • I tried doing this earlier but I didn't know how to do that – 4ert5yhnb Jun 30 '21 at 08:04

1 Answers1

2

One way I have solved this in the past is to use 2 seperate elements, positioned on top of each other, with position: absolute, so that they overlap in a pixel-perfect manner.

  • The element on top is a regular input element, and its text color is set to transparent.
  • The element behind it contains the styled text (spans etc.)

This way, you can replace the styled content as the user types, without interfering with the input element's cursor at all.

Sorry that I don't have an 'essential code snippet' at hand, but I hope you get the idea. It did work well in practice for me.

Hoff
  • 38,776
  • 17
  • 74
  • 99