Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Maintain cursor location when switching between normal and code view

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

like image 678
igg Avatar asked Apr 02 '20 08:04

igg


1 Answers

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

like image 155
x00 Avatar answered Oct 20 '22 04:10

x00