如何获取ContentEditable元素中相对于innerText的光标位置?
ContentEditable元素相对innerText的光标位置获取方案需求
目前已有大量关于获取ContentEditable元素光标位置的相关问题,几乎所有现有方案给出的都是相对于textContent的光标位置。
我们正在开发两款实现打字自动更正功能的Web扩展,例如用户输入:)时自动替换为😀。要实现自动更正功能,需要获取相对于innerText的光标位置,而textContent会包含文本渲染时不会实际显示的空白字符及其他和实际渲染结果的差异,会导致自动更正功能失效。
我们当前使用的方案部分改编自公开技术回答,原方案提供相对于innerHTML的光标位置,原理为克隆元素、插入空字符、计算索引后再移除空字符,代码如下:
// document.designMode 场景处理逻辑一致 if (target.isContentEditable || document.designMode === "on") { target.focus(); const _range = document.getSelection().getRangeAt(0); if (!_range.collapsed) { return null; } const range = _range.cloneRange(); const temp = document.createTextNode("\0"); range.insertNode(temp); const caretposition = target.innerText.indexOf("\0"); temp.parentNode.removeChild(temp); return caretposition; }
该方案在99%的站点上运行正常,但在Twitter上会失效:用户打字时光标会不断被重置到行首,导致文本错乱。我们最初猜测是Twitter对空字符做了限制,但更换其他非打印字符测试后仍存在相同问题。
2025年更新: 目前发现该方案还会在更多主流站点上失效,包括Facebook Messenger和Google Docs,其中Google Docs不会出现全站功能异常,仅光标位置获取功能无法正常使用。
我们希望找到其他可在所有站点正常运行的方案,来获取相对于innerText的光标位置。方案需要兼容Firefox和Chrome的最新版本(包括Firefox ESR版本),同时需要有足够高的性能,支持在每次按键触发时运行。
内容的提问来源于stack exchange,提问作者rugk
相关产品推荐
相关产品推荐

