Insert Text at Caret Position in Summernote Editor for Bootstrap

Problem

Using the very useful Summernote Editor component for Bootstrap, you would like to insert some text at the current caret position programmatically.

Solution

The Summernote API does not provide any dedicated methods for inserting text. However, that’s not a problem since we can use the JQuery/native DOM API to insert text into the editor. Thankfully, the content of the Summernote editor is nothing but vanilla HTML/DOM elements. Thus, we can insert text at the current cursor position as follows (if the Summernote editor is focused):

To Insert at the End of the Current Paragraph

$(document.getSelection().anchorNode.parentNode).append(“appended!”);

To Insert at the Current Cursor Position

var selection = document.getSelection();
var cursorPos = selection.anchorOffset;
var oldContent = selection.anchorNode.nodeValue;
var toInsert = "InsertMe!";
var newContent = oldContent.substring(0, cursorPos) + toInsert + oldContent.substring(cursorPos);
selection.anchorNode.nodeValue = newContent;

Note: You probably will have to work some magic with the document.getSelection() call. The problem is that once you would click a button or trigger the action in some other way, the selection would change. Thus, I save a reference to the document.getSelection() upon every focus and key press event on the editor.

Insert at Current Position (Alternative)

As suggested by Dexter in the comments below, you can also insert text as follows:

$(‘#summernote’).summernote('editor.saveRange');

// Editor loses selected range (e.g after blur)

$(‘#summernote’).summernote('editor.restoreRange');
$(‘#summernote’).summernote('editor.focus');
$(‘#summernote’).summernote('editor.insertText', 'This text should appear at the cursor');

References

MDN – Selection.anchorNode

Stackoverflow – Get caret position in contentEditable div

Stackoverflow – Inserting Text at Cursor Position using JS/JQuery

Stackoverflow – JQuery Plugin for Inserting Text at Caret

14 thoughts on “Insert Text at Caret Position in Summernote Editor for Bootstrap

  1. This is really cool. Thanks for posting.

    This works great with plain text, but I’ve run into a problem using this technique when inserting into a rich text document. It looks like the additional HTML formatting is throwing off the math.

    Have you had this same problem? And, any suggestions on working around it?

  2. Hi Max,

    No, I never did get this to work, and now I’ve put it to the side to make progress on other things. I am using a summernote connector to AngularJS, which *should* not be interfering with the code here.

    Thanks again for any insights you have on this.

    Best wishes!

    1. Just tried the example with formatted code. For me, it seems to work and inserts the text at the correct location.

      Maybe it has something to do with the AngularJs connector?

      1. Hey Max, It took me a while to get back on this particular issue. But, it DID work correctly when I bypassed AngularJS. So, going straight to the DOM nodes looks like the way to go. Thanks for your help!

  3. Hi ,
    I tried your solution . It works for me for plain text . But for formatted text it is not replacing text at selected position .
    Here is my code.
    var selection = document.getSelection();

    var endPos = selection.focusOffset;

    var cursorPos = selection.anchorOffset;
    var fieldId = $(e).attr(“data-id”).trim();
    var desc = $(e).attr(“data-desc”).trim();
    fieldId = fieldId.replace(” “, “”);

    var toInsert = ‘{‘+fieldId+”:”+desc+’}’;

    var newContent = “”;
    if (endPos == cursorPos) {
    var oldContent = $(‘.note-editable’).text();
    newContent = oldContent.substring(0, cursorPos) + toInsert + oldContent.substring(cursorPos);

    }
    else {
    var oldContent = $(‘.note-editable’).text();
    newContent = oldContent.replace(oldContent.substring(cursorPos,endPos), toInsert);

    }

    selection.anchorNode.nodeValue = newContent

    Cursor offset is getting wrong in above code.

  4. $(‘#summernote’).summernote(‘editor.saveRange’);

    // Editor loses selected range (e.g after blur)

    $(‘#summernote’).summernote(‘editor.restoreRange’);
    $(‘#summernote’).summernote(‘editor.focus’);
    $(‘#summernote’).summernote(‘editor.insertText’, ‘This text should appear at the cursor’);

    Alternatively, you can invoke directly from the context variable

    context.invoke(‘editor.saveRange’);

    // Editor loses selected range (e.g after blur)

    context.invoke(‘editor.restoreRange’);
    context.invoke(‘editor.focus’);
    context.invoke(‘editor.insertText’, ‘This text should appear at the cursor’);

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s