首页 > 解决方案 > 重置内容可编辑的插入符号位置

问题描述

我目前正在尝试为Javascript创建一个语法荧光笔,我目前面临的问题是我发现创建类似这样的东西很常见,即在用户键入或编辑 contentEditable 文本时将插入符号位置设置到末尾。

我在 SO 上研究并发现了这个和许多其他解决方案,但没有一个有效。它获取插入符号的位置,但从不重置它,所以我试图找到解决这个问题的方法。

下面是我想出的代码。

html

<div id="editor" contentEditable="true" onkeyup="resetPosition(this)"></div>

<input type="text" onkeyup="resetPosition(this)" />

js

function getPos(e) {
    // for contentedit field
  if (e.isContentEditable) {
    e.focus()
    let _range = document.getSelection().getRangeAt(0)
    let range = _range.cloneRange()
    range.selectNodeContents(e)
    range.setEnd(_range.endContainer, _range.endOffset)

    return range.toString().length;
  }
  // for texterea/input element
  return e.target.selectionStart
}


function setPos(pos, e) {
  // for contentedit field
  if (e.isContentEditable) {
      e.focus()
      document.getSelection().collapse(e, pos);
      return
  }
  e.setSelectionRange(pos, pos)
}

function resetPosition(e) {
  if(e.isContentEditable) {
  let currentPosition = getPos(e);
  e.innerHTML=e.innerHTML.replace(/[0-9]/g, "a");
  setPos(currentPosition, e);

  return;
}

  e.value = e.value.replace(/[0-9]/g, "a");
  setPos(currentPosition, e);

}     

这适用于文本输入,但不适用于 contentEditable divs

当我输入类似的东西时function,我得到otincfun.

更新:我能够setPos通过将这一行从更改为来修复该功能,document.getSelection().collapse(e, pos);document.getSelection().collapse(e.firstChild, pos);出现了一个新错误。

当我按 ENTER 键时,插入符号返回到第一行和第一个字符。请问我该如何解决?


下面是小提琴链接

https://jsfiddle.net/oketega/bfeh9nm5/35/

谢谢。

标签: javascripthtmlcaret

解决方案


问题

document.getSelection().collapse(element, index)将光标折叠到指向的子节点,index而不是字符索引。

setPos我可以通过将此行从更改为document.getSelection().collapse(e, pos);来修复该功能document.getSelection().collapse(e.firstChild, pos);

如果您只替换字符,这将起作用,但如果您正在创建语法荧光笔,您将希望将字符包含在span元素中以设置它们的样式。 e.firstChild然后只会将位置设置为第一个孩子中的索引,e不包括后者span

要考虑的另一件事是您可能希望自动完成某些字符。操作文本之前的插入符号位置可能与操作之后不同。

解决方案

我建议创建一个<span id="caret-position"></span>元素来跟踪插入符号的位置。

它会像这样工作:

function textChanged(element) {
    // 1
    const text = setCursorMarker(element.innerText, element);

    // 2
    const html = manipulate(text);
    element.innerHTML = html;

    // 3
    const index = findCursorIndex(element);
    document.getSelection().collapse(element, index)
}

  1. 每次用户键入时,您都可以获得当前插入符号的位置并滑入其中的#caret-position元素。
  2. 用语法高亮文本覆盖现有的 html
  3. 找出在哪里#caret-position并将插入符号放在那里。

注意:当用户在 content-editable 元素中键入内容时,推荐的监听方式是使用oninput监听器,而不是onkeyup. 按住一个键可以插入许多字符。

例子

这里有一个工作js小提琴:https ://jsfiddle.net/Vehmloewff/0j8hzevm/132/

已知问题:点击Enter两次后,它会丢失插入符号的位置。我不太确定它为什么会这样做。


推荐阅读