简体   繁体   English

将光标(插入符号)放置在特定位置 <pre> 内容可编辑元素

[英]Place cursor(caret) in specific position in <pre> contenteditable element

I'm making a web application to test regular expressions. 我正在制作一个Web应用程序来测试正则表达式。 I have an input where I enter the regexp and a contenteditable pre element where I enter the text where the matches are found and highlighted. 在输入正则表达式时有一个输入,在输入要查找并突出显示匹配项的文本时输入一个contenteditable pre元素。

Example: asuming the regexp is ab, if the user types abcab in the pre element, both regexp and text are sent to an api I implemented which returns 示例:假设正则表达式为ab,如果用户在pre元素中输入abcab,则正则表达式和文本都会发送到我实现的api中,该api返回


  
 
  
  
  
    <span style='background-color: lightgreen'>ab</span>c<span style='background-color: lightgreen'>ab</span>

and this string is set as the innerHTML of the pre element 并将此字符串设置为pre元素的innerHTML

This operation is made each time the user edites the content of the pre element (keyup event to be exact). 每次用户编辑pre元素的内容时都会执行此操作(确切地说是keyup事件)。 The problem I have (and I hope you can solve) is that each time the innterHTML is set, the caret is placed at the beginning, and I want it to be placed right after the last character input by de user. 我遇到的问题(我希望您能解决)是,每次设置intterHTML时,都会将插入号放在开头,并且我希望将其插入到de user输入的最后一个字符之后。 Any suggestions on how to know where the caret is placed and how to place it in a desired position? 关于如何知道插入标记的位置以及如何将其放置在所需位置的任何建议? Thanks. 谢谢。

UPDATE For better understanding...A clear case: Regexp is ab and in the contenteditable element we have: 更新为了更好地理解...一个明显的情况:正则表达式为ab,在contenteditable元素中,我们具有:


  
 
  
  
  
    <span style='background-color: lightgreen'>ab</span>c<span style='background-color: lightgreen'>ab</span>

Then I type ac between the first a and the first b, so now we have: 然后我在第一个a和第一个b之间输入ac,所以现在我们有了:


  
 
  
  
  
    acbc<span style='background-color: lightgreen'>ab</span>

At this moment the caret has returned to the beginning of the contenteditable element, and it should be placed right after the c I typed. 此时,插入记号已返回到contenteditable元素的开头,应将其放置在我键入的c之后。 That's what I want to achieve, hope now it's more clear. 这就是我要实现的目标,希望现在更加清楚。

UPDATE2 更新2

 function refreshInnerHtml() { document.getElementById('textInput').innerHTML = "<span style='background-color: lightgreen'>ab</span>c<span style='background-color: lightgreen'>ab</span>"; } 
  <pre contenteditable onkeyup="refreshInnerHtml()" id="textInput" style="border: 1px solid black;" ></pre> 

 <html> <head> <script> function test(inp){ document.getElementById(inp).value = document.getElementById(inp).value; } </script> </head> <body> <input id="search" type="text" value="mycurrtext" size="30" onfocus="test(this.id);" onclick="test(this.id);" name="search"/> </body> </html> 

I quickly made this and it places the cursor at the end of the string in the input box. 我很快就做到了,它将光标放在输入框中字符串的末尾。 The onclick is for when the user manually clicks on the input and the onfocus is for when the user tabs on the input. onclick用于用户手动单击输入,而onfocus用于用户在输入上制表。

<input id="search" type="text" value="mycurrtext" size="30" 
   onfocus="test(this.id);" onclick="test(this.id);" name="search"/>

function test(inp){
        document.getElementById(inp).value = document.getElementById(inp).value;  
    }

Here to make selection easy, I've added another span tag with nothing in it, and given it a data-end attribute to make it easy to select. 在这里,为了使选择变得容易,我添加了一个没有任何内容的span标签,并为其赋予了data-end属性以使其易于选择。

I then simply create a range from this and use window.getSelection addRange to apply it. 然后,我从此简单地创建一个范围,并使用window.getSelection addRange应用它。

Update: modified to place caret after the first ab 更新:修改为在第一个ab之后放置插入符号

 var e = document.querySelector('[data-end]'); var range = document.createRange(); range.setStart(e, 0); range.setEnd(e, 0); document.querySelector('[contenteditable]').focus(); var sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(range); 
 <div contenteditable="true"> <span style='background-color: lightgreen'>ab</span><span data-end></span>c<span style='background-color: lightgreen'>ab</span> </div> 

With some help from these functions from here -> 在这些功能的帮助下->

Add element before/after text selection 在文本选择之前/之后添加元素

I've created something I think your after. 我创造了一些我想成为你的东西。 I basically place some temporary tags into the html where the current cursor is. 我基本上将一些临时标签放入当前光标所在的html中。 I then render the new HTML, I then replace the tags with the span with a data-cpos attribute. 然后渲染新的HTML,然后用data-cpos属性用span替换标记。 Using this I then re-select the cursor. 然后我使用它重新选择光标。

 var insertHtmlBeforeSelection, insertHtmlAfterSelection; (function() { function createInserter(isBefore) { return function(html) { var sel, range, node; if (window.getSelection) { // IE9 and non-IE sel = window.getSelection(); if (sel.getRangeAt && sel.rangeCount) { range = window.getSelection().getRangeAt(0); range.collapse(isBefore); // Range.createContextualFragment() would be useful here but is // non-standard and not supported in all browsers (IE9, for one) var el = document.createElement("div"); el.innerHTML = html; var frag = document.createDocumentFragment(), node, lastNode; while ( (node = el.firstChild) ) { lastNode = frag.appendChild(node); } range.insertNode(frag); } } else if (document.selection && document.selection.createRange) { // IE < 9 range = document.selection.createRange(); range.collapse(isBefore); range.pasteHTML(html); } } } insertHtmlBeforeSelection = createInserter(true); insertHtmlAfterSelection = createInserter(false); })(); function refreshInnerHtml() { var tag_start = '⇷', //lets use some unicode chars unlikely to ever use.. tag_end = '⇸', sel = document.getSelection(), input = document.getElementById('textInput'); //remove old data-cpos [].forEach.call( input.querySelectorAll('[data-cpos]'), function(e) { e.remove() }); //insert the tags at current cursor position insertHtmlBeforeSelection(tag_start); insertHtmlAfterSelection(tag_end); //now do our replace let html = input.innerText.replace(/(ab)/g, '<span style="background-color: lightgreen">$1</span>'); input.innerHTML = html.replace(tag_start,'<span data-cpos>').replace(tag_end,'</span>'); //now put cursor back var e = input.querySelector('[data-cpos]'); if (e) { var range = document.createRange(); range.setStart(e, 0); range.setEnd(e, 0); sel.removeAllRanges(); sel.addRange(range); } } refreshInnerHtml(); 
 Type some text below, with the letters 'ab' somewhere within it. <br> <pre contenteditable onkeyup="refreshInnerHtml()" id="textInput" style="border: 1px solid black;" >It's about time.. above and beyond</pre> 

暂无
暂无

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

相关问题 如何在特定的contenteditable div上设置插入符/光标位置? - How do I set the caret/cursor position on a specific contenteditable div? 将插入号(光标)放置在可内容编辑的字段中的特定位置-单击时出现问题 - Placing the caret (cursor) in a specific position in a contenteditable field — problems during click 如何在 contenteditable 元素(div)中设置插入符号(光标)position? - How to set the caret (cursor) position in a contenteditable element (div)? 如何将光标位置放在contenteditable元素的中心对齐占位符的开头? - How to place cursor position at the start of center aligned placeholder of contenteditable element? 将插入号/光标位置设置为可编辑div的末尾 - setting the caret/cursor position to the end of a contenteditable div 将插入符号位置设置在contenteditable div中的特定位置 - Set caret position at a specific position in contenteditable div 如何保持插入符号在 contenteditable 元素中的位置 - How to keep the position of the caret in contenteditable element 获取包含HTML内容的contentEditable区域中的插入符(光标)位置 - Get caret (cursor) position in contentEditable area containing HTML content 修改contenteditable div中的文本而不重置插入符(光标)位置 - Modify text in a contenteditable div without resetting the caret (cursor) position 将插入符号(光标)设置在可疑段落中的粗体元素内 - setting caret (cursor) inside bold element present inside contenteditable paragraph
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM