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

igg
  • 2,172
  • 3
  • 10
  • 33
  • https://github.com/summernote/summernote/issues/3125 – x00 Apr 05 '20 at 11:58
  • @x00 This is a similar issue, but so solution is provided. – igg Apr 06 '20 at 08:04
  • 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. – x00 Apr 06 '20 at 08:40
  • @x00 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! – igg Apr 06 '20 at 09:01
  • I would suggest seeing in which paragraph they are, and putting the cursor at the start of that paragraph as a in between solution. – Tschallacka Apr 06 '20 at 13:03

1 Answers1

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

x00
  • 13,643
  • 3
  • 16
  • 40
  • 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 you – igg Apr 06 '20 at 13:28