简体   繁体   English

如何在更换一个可疑的div的html之后将插入符号放在以前的位置?

[英]How to place the caret where it previously was after replacing the html of a contenteditable div?

I have a contenteditable div where I replace hashtags with clickable links when the user clicks on space or on enter. 我有一个contenteditable div,当用户点击空格或输入时,我用可点击的链接替换主题标签。 The user writes down: 用户写下:

I love but there is no fish at home| 我爱,但家里没有鱼

He then realizes he made a mistake and then decides to go back and write 然后他意识到他犯了一个错误然后决定回去写

I love #sushi | 我喜欢#sushi | but there is no fish at home 但家里没有鱼

#sushi 

gets replaced by: 被替换为:

 <a href="https://google.com/sushi>#sushi</a>

Notice that the | 请注意| shows the position of where I want the caret to be when the user presses spacebar. 显示当用户按空格键时我想要插入符号的位置。 My current "placeCaretAtEnd" function places the caret at the end of the div and NOT behind the link that I just replaced sushi with. 我当前的“placeCaretAtEnd”函数将插入符号放在div的末尾,而不是在我刚刚替换寿司的链接后面。 Is there a way to alter my current function to place the caret behind the link I just replaced in the text on the position shown above, so that the user can continue typing carelessly? 有没有办法改变我当前的功能,将插入符号放在我刚刚在上面显示的位置文本中替换的链接后面,这样用户可以继续不小心输入? So in raw html: 所以在原始的HTML:

I love < a> #sushi< /a> | 我爱<a> #sushi </ a> | but there is no fish at home 但家里没有鱼

 /** * Trigger when someone releases a key on the field where you can post remarks, posts or reactions */ $(document).on("keyup", ".post-input-field", function (event) { // if the user has pressed the spacebar (32) or the enter key (13) if (event.keyCode === 32 || event.keyCode === 13) { let html = $(this).html(); html = html.replace(/(^|\\s)(#\\w+)/g, " <a href=#>$2</a>").replace("<br>", ""); $(this).html(html); placeCaretAtEnd($(this)[0]); } }); /** * Place the caret at the end of the textfield * @param {object} el - the DOM element where the caret should be placed */ function placeCaretAtEnd(el) { el.focus(); if (typeof window.getSelection != "undefined" && typeof document.createRange != "undefined") { var range = document.createRange(); range.selectNodeContents(el); range.collapse(false); var sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); } else if (typeof document.body.createTextRange != "undefined"){ var textRange = document.body.createTextRange(); textRange.moveToElementText(el); textRange.collapse(false); textRange.select(); } } 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <div contenteditable="true" class="post-input-field"> I love (replace this with #sushi and type space) but there is no fish at home </div> 

rangy.js has a text range module that lets you save selection as indices of the characters that are selected, and then restore it. rangy.js有一个文本范围模块 ,可以将选择保存为所选字符的索引,然后将其还原。 Since your modifications do not alter innerText , this looks like a perfect fit: 由于您的修改不会改变innerText ,因此这看起来非常合适:

      var sel = rangy.getSelection();
      var savedSel = sel.saveCharacterRanges(this);
      $(this).html(html);
      sel.restoreCharacterRanges(this, savedSel);

Implementing this manually requires careful traversal of the DOM inside contenteditable and careful arithmetics with the indices; 手动实现这个需要仔细遍历DOM内部的contenteditable和谨慎的算法与索引; this can't be done with a few lines of code. 用几行代码就无法做到这一点。

Your placeCaretAtEnd can't possibly place the caret after the link you've inserted, since it doesn't "know" which (of the possibly multiple) link it is. 您的placeCaretAtEnd不能将插入符号放在您插入的链接之后,因为它不“知道”它(可能是多个)链接。 You have to save this information beforehand. 您必须事先保存此信息。

 /** * Trigger when someone releases a key on the field where you can post remarks, posts or reactions */ $(document).on("keyup", ".post-input-field", function (event) { // if the user has pressed the spacebar (32) or the enter key (13) if (event.keyCode === 32 || event.keyCode === 13) { let html = $(this).html(); html = html.replace(/(^|\\s)(#\\w+)/g, " <a href=#>$2</a>").replace("<br>", ""); var sel = rangy.getSelection(); var savedSel = sel.saveCharacterRanges(this); $(this).html(html); sel.restoreCharacterRanges(this, savedSel); } }); 
 <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/rangy/1.3.0/rangy-core.js"></script> <script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/rangy/1.3.0/rangy-textrange.js"></script> <div contenteditable="true" class="post-input-field"> I love (replace this with #sushi and type space) but there is no fish at home </div> 

暂无
暂无

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

相关问题 用HTML替换文本后,可内容编辑的div设置插入记号 - Contenteditable div set caret after replacing text with HTML 更改 contenteditable 元素的 innerHTML 后,将插入符号放回原来的位置 - Place caret back where it was after changing innerHTML of a contenteditable element 在一个可信的div中插入插入符号的html - Insert html at caret in a contenteditable div 如何在原始文本中间粘贴HTML单词后,防止插入符号在contenteditable div中跳到整个文本的末尾? - How to prevent the caret jumping to the end of the whole text in contenteditable div after pasting the HTML words in the middle of the original text? 将插入符放置在ContentEditable Div的末尾不起作用 - Place Caret at end of ContentEditable Div does not work 如何在忽略HTML标签的情况下将插入符号放置在contenteditable div中? - How to position a caret in a contenteditable div while ignoring the HTML tags? 如何使用 html 子元素在 contenteditable div 中获取插入符号 position? - How to get caret position within contenteditable div with html child elements? 在内容可编辑的图像之前/之后放置插入号 - Place caret before / after image in contenteditable 如何在contenteditable div中查找插入符号前后的字符长度? - How to find the length of characters before and after the caret in contenteditable div? HTML节点位于contenteditable中的插入符位置<div> - HTML node at caret position in contenteditable <div>
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM