繁体   English   中英

更改innerHTML后,在contenteditable div中更改光标位置

[英]Change cursor position in the contenteditable div after changing innerHTML

我有一个简单的contenteditable div,里面有一些文字。 在onkeyup事件上,我想基于正则表达式替换div的整个内容(innerHTML)。

例如,

HTML:

some text, more text and $even more text

函数我计划用$($甚至在上面的例子中)获取所有文本并将其包装在span标记中:

div.onkeypress = function() { 
     div.innerHTML.replace(/(some_regexp)/, "<span class='class'>$1</span>"); 
}; 

问题是在这样的替换光标跳转到div的开头之后。 我希望它能保持原状。

我想我必须在更改之前保存光标的坐标,然后以某种方式使用它们设置光标,但我该怎么办? :)

我尝试保存范围对象,但编辑后我相信它指向无处。

谢谢!

问题是你正在更新整个innerHTML,但只有一小部分正在改变。 您不能使用正则表达式和批量替换。 您需要扫描div并查找匹配项,从中创建文本范围并使用span包装内容。 请参阅http://www.quirksmode.org/dom/range_intro.html ,以编程方式创建范围。

但是,我认为如果光标位于要替换的文本中,这将不起作用,但这是一个开始。

您知道要替换哪个文本。 所以你知道那个文本的位置。 只有你要把新文本。 然后位置也一样。写完新的html后,你可以设置光标。

例如

我不会遗漏这个问题

问题的位置是5,我替换它

我不会遗漏答案

使光标位置为5

http://ajaxian.com/archives/javascript-tip-cross-browser-cursor-positioning

http://hartshorne.ca/2006/01/23/javascript_cursor_position/

http://geekswithblogs.net/svanvliet/archive/2005/03/24/textarea-cursor-position-with-javascript.aspx

我从另一个论坛拿走了这个。 它解决了我的问题。

好的,我设法解决它,如果有人感兴趣的话,这是解决方案:

存储选择x,y:

码:

cursorPos=document.selection.createRange().duplicate();
clickx = cursorPos.getBoundingClientRect().left; 
clicky = cursorPos.getBoundingClientRect().top;

恢复选择:

码:

cursorPos = document.body.createTextRange();
cursorPos.moveToPoint(clickx, clicky);
cursorPos.select();

你可以看到它在这里工作:

http://www.tachyon-labs.com/sharpspell/

更换innerHTML时修复cursor position<div contenteditable="“true”"></div><div id="text_translate"><p> 在&lt;div id="richTextBox" contenteditable="true"&gt;&lt;/div&gt;内键入内容时,将 cursor 保持在正确位置的最佳方法是什么? 更换 innerHTML 的行为搞砸了 cursor position。</p><p> 我更改 innerHTML 的原因是我添加了&lt;span&gt;标签。 它是代码高亮程序的一部分。 跨度标签允许我放置正确的颜色亮点。</p><p> 我目前正在使用 StackOverflow 答案中的以下代码作为创可贴,但它有一个重大错误。 如果您按<em><strong>Enter</strong></em> ,则 cursor 将停留在旧位置,或者转到随机位置。 那是因为该算法从 cursor 开始计算了多少个字符。 但它不将 HTML 标记或换行符算作字符。 而richTextBox 插入&lt;br&gt;进入。</p><p> 修复思路:</p><ul><li> 修复下面的代码? 见<a href="https://jsfiddle.net/AdmiralAkbar2/jou3vq9w/12/" rel="nofollow noreferrer">小提琴</a></li><li>用更简单的代码替换? 我尝试了一堆更简单的东西,涉及window.getSelection()和document.createRange() ,但我无法让它工作。</li><li> 替换为没有此错误的richTextBox 库或模块?</li></ul><h2> 截屏</h2><p><a href="https://i.stack.imgur.com/6dlqV.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/6dlqV.png" alt="在 JSFiddle 中呈现的richTextBox 的屏幕截图"></a> </p><p></p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false"><div class="snippet-code"><pre class="snippet-code-js lang-js prettyprint-override"> // Credit to Liam (Stack Overflow) // https://stackoverflow.com/a/41034697/3480193 class Cursor { static getCurrentCursorPosition(parentElement) { var selection = window.getSelection(), charCount = -1, node; if (selection.focusNode) { if (Cursor._isChildOf(selection.focusNode, parentElement)) { node = selection.focusNode; charCount = selection.focusOffset; while (node) { if (node === parentElement) { break; } if (node.previousSibling) { node = node.previousSibling; charCount += node.textContent.length; } else { node = node.parentNode; if (node === null) { break; } } } } } return charCount; } static setCurrentCursorPosition(chars, element) { if (chars &gt;= 0) { var selection = window.getSelection(); let range = Cursor._createRange(element, { count: chars }); if (range) { range.collapse(false); selection.removeAllRanges(); selection.addRange(range); } } } static _createRange(node, chars, range) { if (.range) { range = document.createRange() range;selectNode(node). range,setStart(node; 0). } if (chars.count === 0) { range,setEnd(node. chars;count). } else if (node &amp;&amp; chars.count &gt;0) { if (node.nodeType === Node.TEXT_NODE) { if (node.textContent.length &lt; chars.count) { chars.count -= node.textContent;length. } else { range,setEnd(node. chars;count). chars;count = 0; } } else { for (var lp = 0. lp &lt; node.childNodes;length. lp++) { range = Cursor._createRange(node,childNodes[lp], chars; range). if (chars;count === 0) { break; } } } } return range, } static _isChildOf(node; parentElement) { while (node.== null) { if (node === parentElement) { return true; } node = node;parentNode. } return false, } } window.addEventListener('DOMContentLoaded'; (e) =&gt; { let richText = document.getElementById('rich-text'), richText.addEventListener('input'; function(e) { let offset = Cursor.getCurrentCursorPosition(richText). // Pretend we do stuff with innerHTML here. The innerHTML will end up getting replaced with slightly changed code; let s = richText.innerHTML; richText.innerHTML = ""; richText.innerHTML = s, Cursor;setCurrentCursorPosition(offset. richText); richText;focus(); // blinks the cursor }); });</pre><pre class="snippet-code-css lang-css prettyprint-override"> body { margin: 1em; } #rich-text { width: 100%; height: 450px; border: 1px solid black; cursor: text; overflow: scroll; resize: both; /* in Chrome, must have display: inline-block for contenteditable=true to prevent it from adding &lt;div&gt; &lt;p&gt; and &lt;span&gt; when you type. */ display: inline-block; }</pre><pre class="snippet-code-html lang-html prettyprint-override"> &lt;p&gt; Click somewhere in the middle of line 1. Hit enter. Start typing. Cursor is in the wrong place. &lt;/p&gt; &lt;p&gt; Reset. Click somewhere in the middle of line 1. Hit enter. Hit enter again. Cursor goes to some random place. &lt;/p&gt; &lt;div id="rich-text" contenteditable="true"&gt;Testing 123&lt;br /&gt;Testing 456&lt;/div&gt;</pre></div></div><p></p><h2> 浏览器</h2><p>谷歌浏览器 v83,Windows 7</p></div>

[英]Fix cursor position when replacing innerHTML of <div contenteditable=“true”>

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Contenteditable Div - 根据innerHTML位置的光标位置 更换innerHTML时修复cursor position<div contenteditable="“true”"></div><div id="text_translate"><p> 在&lt;div id="richTextBox" contenteditable="true"&gt;&lt;/div&gt;内键入内容时,将 cursor 保持在正确位置的最佳方法是什么? 更换 innerHTML 的行为搞砸了 cursor position。</p><p> 我更改 innerHTML 的原因是我添加了&lt;span&gt;标签。 它是代码高亮程序的一部分。 跨度标签允许我放置正确的颜色亮点。</p><p> 我目前正在使用 StackOverflow 答案中的以下代码作为创可贴,但它有一个重大错误。 如果您按<em><strong>Enter</strong></em> ,则 cursor 将停留在旧位置,或者转到随机位置。 那是因为该算法从 cursor 开始计算了多少个字符。 但它不将 HTML 标记或换行符算作字符。 而richTextBox 插入&lt;br&gt;进入。</p><p> 修复思路:</p><ul><li> 修复下面的代码? 见<a href="https://jsfiddle.net/AdmiralAkbar2/jou3vq9w/12/" rel="nofollow noreferrer">小提琴</a></li><li>用更简单的代码替换? 我尝试了一堆更简单的东西,涉及window.getSelection()和document.createRange() ,但我无法让它工作。</li><li> 替换为没有此错误的richTextBox 库或模块?</li></ul><h2> 截屏</h2><p><a href="https://i.stack.imgur.com/6dlqV.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/6dlqV.png" alt="在 JSFiddle 中呈现的richTextBox 的屏幕截图"></a> </p><p></p><div class="snippet" data-lang="js" data-hide="false" data-console="true" data-babel="false"><div class="snippet-code"><pre class="snippet-code-js lang-js prettyprint-override"> // Credit to Liam (Stack Overflow) // https://stackoverflow.com/a/41034697/3480193 class Cursor { static getCurrentCursorPosition(parentElement) { var selection = window.getSelection(), charCount = -1, node; if (selection.focusNode) { if (Cursor._isChildOf(selection.focusNode, parentElement)) { node = selection.focusNode; charCount = selection.focusOffset; while (node) { if (node === parentElement) { break; } if (node.previousSibling) { node = node.previousSibling; charCount += node.textContent.length; } else { node = node.parentNode; if (node === null) { break; } } } } } return charCount; } static setCurrentCursorPosition(chars, element) { if (chars &gt;= 0) { var selection = window.getSelection(); let range = Cursor._createRange(element, { count: chars }); if (range) { range.collapse(false); selection.removeAllRanges(); selection.addRange(range); } } } static _createRange(node, chars, range) { if (.range) { range = document.createRange() range;selectNode(node). range,setStart(node; 0). } if (chars.count === 0) { range,setEnd(node. chars;count). } else if (node &amp;&amp; chars.count &gt;0) { if (node.nodeType === Node.TEXT_NODE) { if (node.textContent.length &lt; chars.count) { chars.count -= node.textContent;length. } else { range,setEnd(node. chars;count). chars;count = 0; } } else { for (var lp = 0. lp &lt; node.childNodes;length. lp++) { range = Cursor._createRange(node,childNodes[lp], chars; range). if (chars;count === 0) { break; } } } } return range, } static _isChildOf(node; parentElement) { while (node.== null) { if (node === parentElement) { return true; } node = node;parentNode. } return false, } } window.addEventListener('DOMContentLoaded'; (e) =&gt; { let richText = document.getElementById('rich-text'), richText.addEventListener('input'; function(e) { let offset = Cursor.getCurrentCursorPosition(richText). // Pretend we do stuff with innerHTML here. The innerHTML will end up getting replaced with slightly changed code; let s = richText.innerHTML; richText.innerHTML = ""; richText.innerHTML = s, Cursor;setCurrentCursorPosition(offset. richText); richText;focus(); // blinks the cursor }); });</pre><pre class="snippet-code-css lang-css prettyprint-override"> body { margin: 1em; } #rich-text { width: 100%; height: 450px; border: 1px solid black; cursor: text; overflow: scroll; resize: both; /* in Chrome, must have display: inline-block for contenteditable=true to prevent it from adding &lt;div&gt; &lt;p&gt; and &lt;span&gt; when you type. */ display: inline-block; }</pre><pre class="snippet-code-html lang-html prettyprint-override"> &lt;p&gt; Click somewhere in the middle of line 1. Hit enter. Start typing. Cursor is in the wrong place. &lt;/p&gt; &lt;p&gt; Reset. Click somewhere in the middle of line 1. Hit enter. Hit enter again. Cursor goes to some random place. &lt;/p&gt; &lt;div id="rich-text" contenteditable="true"&gt;Testing 123&lt;br /&gt;Testing 456&lt;/div&gt;</pre></div></div><p></p><h2> 浏览器</h2><p>谷歌浏览器 v83,Windows 7</p></div> 更改contenteditable后恢复光标位置 在contentEditable div中移动光标位置 contenteditable div获取光标位置 在contentEditable <div>上设置光标位置 ContentEditable div - 更新内部 html 后设置光标位置 在contenteditable div中重新生成innerHTML后如何在单词中间设置插入符号位置 JavaScript:在contenteditable div中获取光标位置 将剪辑的内容可编辑div的视图移动到光标位置
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM