Home > Mobile >  Text cursor problem when inserting characters into a contenteditable element
Text cursor problem when inserting characters into a contenteditable element

Time:06-01

There is a pre element that is contenteditable. I wanted to add tab character via TAB button. So, I added js method called putTab. This method works fine. But there is a problem about text cursor. While typing normally, the view is constantly shifting to the right. But when pressing the tab key, the view does not continue to slide to the right after the end of the line. Then, for example, when I press the 'A' key, I suddenly get the expected view by sliding to the right.

I could not find any clear information about following the text cursor after adding character in JS method:

function putTab() {
  var pre = document.getElementById("typearea");
  var doc = pre.ownerDocument.defaultView;
  var sel = doc.getSelection();
  var range = sel.getRangeAt(0);      

  var tabNode = document.createTextNode("    ");
  range.insertNode(tabNode);

  range.setStartAfter(tabNode);
  range.setEndAfter(tabNode);
  sel.removeAllRanges();
  sel.addRange(range);
}

document
  .querySelector('button')
  .addEventListener('click', putTab);
#typearea {
    overflow-x: hidden;
    margin: 8px;
    max-height: auto;
    white-space: pre;
    display: block;
    width: auto;
    line-height: 1.5;
}
<button>Insert Tab</button>

<pre id="typearea" contenteditable>
  Some predefined text.
</pre>

I hope I explained the problem clearly, thank you.

CodePudding user response:

Since the OP provides styling which makes the editable content scroll at least horizontally, the content, while appending additional characters to it, needs to be scrolled into its parent's view again.

Thus, the OP could use the content-editable container's scrollTo method. But then again the OP had to figure out when (appending content) and when not (e.g. prepending or inserting content while cursor is still perfectly aligned) to apply this method.

But using the container's scrollBy method covers any scenario.

function putTab() {
  var pre = document.getElementById("typearea");
  var doc = pre.ownerDocument.defaultView;
  var sel = doc.getSelection();
  var range = sel.getRangeAt(0);

  const scrollWidthBefore = pre.scrollWidth;

  var tabNode = document.createTextNode("    ");
  range.insertNode(tabNode);

  range.setStartAfter(tabNode);
  range.setEndAfter(tabNode);
  sel.removeAllRanges();
  sel.addRange(range);

  pre.scrollBy(pre.scrollWidth - scrollWidthBefore, pre.scrollHeight);

  // // perfect approach for appending content
  // // but leads to out of view scrolling in
  // // all other cases of perfectly visible
  // // content like prepending content or
  // // inserting it.
  //
  // pre.scrollTo(
  //  pre.scrollWidth - parseFloat(window.getComputedStyle(pre).getPropertyValue('width')),
  //  pre.scrollHeight,    
  // );
}

document
  .querySelector('button')
  .addEventListener('click', putTab);
#typearea {
  overflow-x: hidden;
  margin: 8px;
  max-height: auto;
  white-space: pre;
  display: block;
  width: auto;
  line-height: 1.5;
}
<button>Insert Tab</button>

<pre id="typearea" contenteditable>Some predefined content.</pre>

  • Related