`textNode.splitText(pos)` 弄乱了 Safari 中的插入符位置,将其移动到新节点之前。漏洞?

`textNode.splitText(pos)` messes up caret position in Safari, moves it BEFORE the new node. Bug?

在 Safari 中使用 .splitText() 拆分文本节点(在键入时)时,插入符号会移动到新创建的节点之前 - 在 Chrome 和 Firefox 中它会保持其在行尾的位置, 符合预期。

我想知道,我是不是遇到了错误,什么是干净的解决方法?

function wrapWorld({target}) {
  const node = target.childNodes[0];
  const pos = node.nodeValue.indexOf('world');
  console.log(pos);
  
  if (pos > 0) {
    //watch the caret in Safari jump before "world" when split :(
    const newNode = node.splitText(pos);
  }
}
#editor {
  width: 300px;
  height: 130px;
  border: 1px solid #ccc;
}
<p>Type "hello world" in Safari, watch the caret jump before "world" when it gets split</p>

<div id="editor" 
     contenteditable="true"
     oninput="wrapWorld(event)">
</div>

我不能确定这是否真的是一个错误,我没有在规范中进行广泛搜索以了解这里应该发生什么(内容可编辑通常是未指定的...) ,但这两种行为对我来说听起来都很合乎逻辑,就像我希望如果内容刚刚被删除,光标会返回。

现在,您实际上可以强制 Chrome 和 Firefox 的行为,无论如何这可能是个好主意。

为此,使用 Selection API 了解您的光标当前位置,然后在您完成拆分后,将其设置到新位置,您可以使用您的拆分索引计算该位置。

function wrapWorld( { target } ) {
  const sel = getSelection(); // get current selection
  const range = sel.getRangeAt( 0 ); // extract active Range
  const node = range.endContainer; // we should be collapsed, so startContainer === endContainer
  const cursor_pos = range.endOffset; // the position of our cursor in the whole node
  const txt_pos = node.nodeValue.indexOf( 'world' );

  if ( txt_pos > -1 ) {
    const new_node = node.splitText( txt_pos );
    const new_pos = cursor_pos - txt_pos;
    if( new_pos > -1 ) {
      range.setStart( new_node, new_pos ); // update our range
      sel.removeAllRanges();
      sel.addRange( range ); // update the Selection
    }
  }
}
#editor {
  width: 300px;
  height: 130px;
  border: 1px solid #ccc;
}
<p>Type "hello world" in Safari, watch the caret stay where it belongs</p>

<div id="editor" 
     contenteditable="true"
     oninput="wrapWorld(event)">
</div>