簡體   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