javascript - 如何设置包含文本和元素节点组合的 contenteditable div 的插入符号位置

标签 javascript contenteditable caret

我的 HTML:

<div id="text" contenteditable="true">abcd<img src="icon.gif"/>efgh</div>

我的 caret = 5; 所以我想将插入符号位置设置为紧跟在图像之后,因为图像被视为 1 个字符。

所以我写了这个代码:

var node = document.querySelector("div");
node.focus();
var textNode = node.firstChild;
var caret = 5; 
var range = document.createRange();
range.setStart(textNode, caret);
range.setEnd(textNode, caret);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);

但是我得到这个错误:

Uncaught DOMException: Failed to execute 'setStart' on 'Range': The offset 5 is larger than or equal to the node's length (4).

请建议我如何实现这一目标?我可能在我想要的插入符号位置之前有几张图片,每张图片都将被视为 1 个字符。

最佳答案

你的 textNode有 3 个子项(1 个文本、1 个元素、1 个文本),因此您不能只使用 firstChild .

您需要遍历 childNodes<div>并跟踪 nodeType 所在的字符数的 childNode等于 Node.TEXT_NODE (参见 MDN 上的 here)。其中字符数小于 caret 的值你可以从caret中扣除并移动到下一个文本节点。

根据您的条件:

I desire and each image would be treated as 1 character

代码将从caret中减去1其中 nodeType == 1Node.ELEMENT_NODE

这是一个包含多个图标的代码示例:

var node = document.querySelector("div");
node.focus();
var caret = 24; 

var child;
var childNodeIndex = 0;
for(var i=0; i<node.childNodes.length; i++) {
  child = node.childNodes[i];
  // Node.ELEMENT_NODE == 1
  // Node.TEXT_NODE == 3
  if(child.nodeType == Node.TEXT_NODE) {
    // keep track of caret across text childNodes
    if(child.length <= caret) {
      caret -= child.length;
    } else {
      break;
    }
  } else if (child.nodeType == Node.ELEMENT_NODE) {
    // condition that 'each image would be treated as 1 character'
    if(caret > 0) {
      caret -= 1;
    } else {
    	break;
    }
  };
  childNodeIndex += 1;
}

var textNode = node.childNodes[childNodeIndex];

// your original code continues here...
var range = document.createRange();
range.setStart(textNode, caret);
range.setEnd(textNode, caret);
var sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
<div id="text" contenteditable="true">a<img src="https://www.splitbrain.org/_static/ico/circular/ico/add.png"/><img src="https://www.splitbrain.org/_static/ico/circular/ico/add.png"/><img src="https://www.splitbrain.org/_static/ico/circular/ico/add.png"/><img src="https://www.splitbrain.org/_static/ico/circular/ico/add.png"/>b<img src="https://www.splitbrain.org/_static/ico/circular/ico/add.png"/>cdefghijkl<img src="https://www.splitbrain.org/_static/ico/circular/ico/add.png"/>mnopq<img src="https://www.splitbrain.org/_static/ico/circular/ico/add.png"/>rst<img src="https://www.splitbrain.org/_static/ico/circular/ico/add.png"/>uvw<img src="https://www.splitbrain.org/_static/ico/circular/ico/add.png"/>xyz<img src="https://www.splitbrain.org/_static/ico/circular/ico/add.png"/></div>

关于javascript - 如何设置包含文本和元素节点组合的 contenteditable div 的插入符号位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40781179/

相关文章:

javascript - 如果我对 contenteditable 项目执行 "jquery sortable",那么我将无法再将鼠标聚焦在 contenteditable 文本内的任何位置

javascript - 在 contentEditable 中将 HTML 转换为纯文本

css - Select2 需要点击 2 次才能从搜索字段中移除焦点

autohotkey - 使用 AutoHotkey 选择插入符号之前的最后 N 个字符

javascript - 检查 div 内是否有两个选中的复选框

javascript - 我将如何在 svelte reactive 中创建一个 each 循环

asp.net - 当子页面关闭时,是否可以在父页面上调用服务器端事件?

iphone - 将 web 内容从 safari 复制到 contenteditable UIWebView 时过滤 UIPasteboard

javascript - 将 html 数据附加到 Bootstrap 模式 javascript

java - 有没有办法将 JTextArea 的插入符垂直向上移动?