在普通视图和代码视图之间切换时保持光标位置

Posted

技术标签:

【中文标题】在普通视图和代码视图之间切换时保持光标位置【英文标题】:Maintain cursor location when switching between normal and code view 【发布时间】:2020-07-14 04:44:21 【问题描述】:

在 Summernote 中切换到代码视图时,光标总是一直移动到文档末尾。切换时有什么方法可以保持光标位置吗?有时使用它的人想要编写一些自定义 html,因为它比使用编辑器的按钮更快,但是在切换到代码视图后,他们必须向上滚动并尝试找到之前的位置。不太实用。

这是一个简单的stackblitz。

基本上,我需要实现的是:当光标在这里

我想单击“代码查看”按钮并转到此处:

【问题讨论】:

github.com/summernote/summernote/issues/3125 @x00 这是一个类似的问题,但提供了解决方案。 抱歉,帮不上忙。我试图在note-editable 中获取光标位置并将其镜像到note-codable,但这并不是微不足道的。我从来没有达到过一对一通信的地步。光标总是一个几个符号关闭。您还需要将光标镜像到相反的方向——从note-codablenote-editable——我什至没有尝试过。所以我刚刚发布了可以将您推向正确方向的链接。 @x00 如果您的解决方案是“关闭几个符号”,那实际上非常好。我不需要 100% 的准确率,我的主要问题是用户必须向上滚动才能找到他们正在输入的内容。与之前的位置“足够接近”将是一个显着的改进。请将您的解决方案发布为 stackblitz! 我建议查看它们在哪个段落中,并将光标放在该段落的开头作为中间解决方案。 【参考方案1】:

我发布了一个不完整肮脏回答您的问题,正如您在 cmets 中要求的那样:

 function getCaretCharacterOffsetWithin(element) 
     var caretOffset = 0;
     var doc = element.ownerDocument || element.document;
     var win = doc.defaultView || doc.parentWindow;
     var sel;
     if (typeof win.getSelection != "undefined") 
         sel = win.getSelection();
         if (sel.rangeCount > 0) 
             var range = win.getSelection().getRangeAt(0);
             var preCaretRange = range.cloneRange();
             preCaretRange.selectNodeContents(element);
             preCaretRange.setEnd(range.endContainer, range.endOffset);
             caretOffset = preCaretRange.toString().length;
         
      else if ( (sel = doc.selection) && sel.type != "Control") 
         var textRange = sel.createRange();
         var preCaretTextRange = doc.body.createTextRange();
         preCaretTextRange.moveToElementText(element);
         preCaretTextRange.setEndPoint("EndToEnd", textRange);
         caretOffset = preCaretTextRange.text.length;
     
     return caretOffset;
 

 $(document).ready(function() 
   $('#summernote').summernote(
       callbacks: 
         onKeydown: function(e) 
           const editable = document.getElementsByClassName('note-editable')[0]
           const pos = getCaretCharacterOffsetWithin(editable)
           console.log(pos)
           const codable = document.getElementsByClassName('note-codable')[0]
           codable.setSelectionRange(pos,pos)
         
       
   )
   $('#summernote').summernote('fullscreen.toggle');
 );

getCaretCharacterOffsetWithin 的学分归Tim Down

getCaretCharacterOffsetWithin().note-editable 中获得插入符号位置,但并不完全正确,当您在段落边界上来回移动时,该值甚至不一致(正如蒂姆在他的原始帖子中警告的那样)。

setSelectionRange(pos,pos).note-editable 中的位置镜像到.note-codable

还有

    您需要切换到code view 并在它开始工作之前返回。并以某种方式解决了这个问题。 您需要设置鼠标回调 & Co. 以反映鼠标单击时的插入符号位置等。现在它仅适用于 onKeydown。 您需要滚动到textarea 中的插入符号位置

这里是https://js-pvbgkh.stackblitz.io

【讨论】:

谢谢,我想我可以用这个。我会将赏金继续开放几天,以防其他人提出更好的解决方案。如果没有其他人回答,我会将赏金奖励给你

以上是关于在普通视图和代码视图之间切换时保持光标位置的主要内容,如果未能解决你的问题,请参考以下文章

计算在鼠标光标位置放大的视图偏移

带有光标适配器滚动问题的android列表视图

iOS:滚动视图到文本视图中的当前光标位置

自动提交后如何将光标保持在 textarea 中的位置?

使用 glm 根据光标位置旋转模型视图矩阵

UITextview 光标移动到行尾