将字符插入 contenteditable 元素时出现文本光标问题

Text cursor problem when inserting characters into a contenteditable element

有一个 contenteditable 的 pre 元素。我想通过 TAB 按钮添加制表符。所以,我添加了名为 putTab 的 js 方法。这种方法工作正常。但是有一个关于文本光标的问题。 正常输入时,视图不断向右移动。但是当按下tab键时,view在行尾后并没有继续向右滑动。然后比如我按下'A'键的时候突然向右滑动得到了预期的view

在JS方法中添加字符后,我找不到任何关于跟随文本光标的明确信息:

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>

希望我把问题说清楚了,谢谢

由于 OP 提供了使可编辑内容至少水平滚动的样式,因此内容在向其附加额外字符时需要再次滚动到其父视图中。

因此,OP 可以使用 content-editable 容器的 scrollTo 方法。但话又说回来,OP 必须弄清楚何时(附加内容)和何时不(例如,在光标仍然完全对齐时预先添加或插入内容)来应用此方法。

但是使用容器的scrollBy方法涵盖任何场景。

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>