Maintain cursor location when switching between normal and code view
Asked Answered
P

1

7

When switching to code view in Summernote, the cursor is always moved all the way to end of the document. Is there any way to keep the cursor location when switching? Sometimes the people who use it want to write some custom HTML because it's faster than using the editor's buttons, but after switching to code view, they have to scroll up and try to find where they were before. It's not very practical.

Here's a simple stackblitz for this.

Basically, what I need to achieve is: when the cursor is here enter image description here

I want to click the "code view" button and go here: enter image description here

Pennebaker answered 2/4, 2020 at 8:57 Comment(5)
github.com/summernote/summernote/issues/3125Sulfanilamide
@Sulfanilamide This is a similar issue, but so solution is provided.Pennebaker
Sorry, can't help. I've tried to get the cursor position in the note-editable and mirror it for note-codable, but it's not trivial. I never got to the point of one-to-one correspondence. Cursor is always a several symbols off. Also you need to mirror cursor in the opposite direction - from note-codable to note-editable - this I didn't even tried. So I just posted the link that can push you in the right direction.Sulfanilamide
@Sulfanilamide If your solution is "several symbols off", that's pretty good actually. I don't need 100% accuracy, my main problem is that users have to scroll up to find what they were typing. Being "close enough" to where they were before will be a noticeable improvement. Please post your solution as a stackblitz!Pennebaker
I would suggest seeing in which paragraph they are, and putting the cursor at the start of that paragraph as a in between solution.Gabbro
S
3

I post an incomplete and dirty answer to your question, as you asked for it in the comments:

 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');
 });

The credits for getCaretCharacterOffsetWithin goes to Tim Down

getCaretCharacterOffsetWithin() gets caret position in .note-editable, but not quite right, and the value is not even consistent when you move over paragraph borders back and forth (as Tim warns in his original post).

setSelectionRange(pos,pos) mirrors the position in .note-editable to .note-codable.

Also

  1. You need to switch to the code view and back before it starts to work. And somehow fix this issue.
  2. You'll need to set mouse callbacks & Co. to mirror caret position on mouse clicks, etc. Now it works only on onKeydown.
  3. You will need to scroll to caret position in textarea

Here is https://js-pvbgkh.stackblitz.io

Sulfanilamide answered 6/4, 2020 at 12:58 Comment(1)
Thanks, I think I can use this. I'll keep the bounty open for a few more days in case someone else can come up with a better solution. If no one else answers, I'll award the bounty to youPennebaker

© 2022 - 2024 — McMap. All rights reserved.