question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Inserting an HTML - appends it outside when selecting outside editor

See original GitHub issue

Hello,

i made a summernote plugin to add my custom blocs, it works fine but when i select outside editor, it appends the bloc where i selected,

to insert the bloc i use context.invoke('editor.pasteHTML', $bloc_menu_content.prop('outerHTML'));

screen

Issue Analytics

  • State:closed
  • Created 8 years ago
  • Reactions:1
  • Comments:6

github_iconTop GitHub Comments

4reactions
eissasoubhicommented, Mar 8, 2016

ok, for other programmers who encountered the same issue. here is my problems and how i solved them :

the issue

like described above i created summernote to add custom blocs to the editor. when i try to insert simple HTML content to the editor with context.invoke('editor.pasteHTML', '<div></div>' it goes well. but when it comes to a bloc with options where i have to show the modal (like the gif demo above) the bloc is inserted to the last area where i clicked (even outside of the editor) before i opened the modal , and sometime is inserted to the modal body itself and somtimes is not inserted anywhere at all.

the solution

my code was like the following :

self.modalSaveEvent = function()
{
    self.$modal.find("button#save").click(function(event)
    {

        var bloc_menu_content = $.parseHTML(self.bloc_menu_content_html);

        $bloc_menu_content = $(bloc_menu_content).clone(); // make a copy

        $ul = $bloc_menu_content.find('ul.navbar-nav');

        $ul.html("");

        var $menu_items = self.$modal.find('.menu-item'); // get inserted menu tabs

        $menu_items.each(function(index, el)
        {
            // make a copy from the menu item model to insert to the editor
            var $bloc_menu_item = self.$bloc_menu_item.clone();
            //get inserted menu items values to insert to the model
            var url = $(this).find('input.item-menu-url').val();
            var label = $(this).find('input.item-menu-label').val();
            var li_class = $(this).find('.current-item').prop("checked") ? "active" : "";
            //insert menu items values to the model
            $bloc_menu_item.find('a span').text(label);
            $bloc_menu_item.find('a').attr('title', label);
            $bloc_menu_item.find('a').attr('href', url);
            $bloc_menu_item.addClass(li_class);

            $ul.append($bloc_menu_item);
        });

        var editor_content = $(self.editor).summernote('code');

        if (!$(editor_content).find('style#bloc_' + bloc_name + '_style').length)
        {   // add the [bloc_name] style if is not lready inserted
            context.invoke('editor.pasteHTML', self.bloc_menu_style);
        };
        // insert the generated menu items to the [bloc_name] html
        $bloc_menu_content.find('ul').html($ul.html());

        // add [bloc_name] html to the editor
        var bloc_menu_html = $bloc_menu_content.prop('outerHTML');

        context.invoke('editor.pasteHTML', bloc_menu_html);
        context.invoke('editor.pasteHTML', '&nbsp;'); //next line

        self.$modal.modal('hide');

    });
}

note the last three lines of code, i insert the html to the editor and then i hide the modal.

solution part 1

to resolve that issue i insert HTML to the editor after i hided the modal .

self.modalSaveEvent = function()
{
    self.$modal.find("button#save").click(function(event)
    {

       /*...*/

        self.$modal.modal('hide');

        // var editor_content = $(self.editor).summernote('code');

        // if (!$(editor_content).find('style#bloc_' + bloc_name + '_style').length)
        // {   // add the [bloc_name] style if is not already inserted
        //     context.invoke('editor.pasteHTML', self.bloc_menu_style);
        // };
        // // insert the generated menu items to the [bloc_name] html
        // $bloc_menu_content.find('ul').html($ul.html());

        // // editor_content = $(self.editor).summernote('code');

        // // add [bloc_name] html to the editor
        // var bloc_menu_html = $bloc_menu_content.prop('outerHTML');

        // context.invoke('editor.pasteHTML', bloc_menu_html);
        // context.invoke('editor.pasteHTML', '&nbsp;');

    });
}

now the bloc is inserted inside the editor but it always ends up on top.

solution part 2

to make the plugin insert the bloc to the last clicked area inside the editor i created function to do that, so before i insert the bloc i hide the modal and put the cursor in the last clicked area inside the editor but first i have to save where was the cursor last position .

save the last clicked area inside the editor

i used 3 summernote events : keypress, mousemove and keyup,

self.editorEvents = function () {
    $(self.editable).on('keypress, mousemove', function()
    {
        var focused_element = window.getSelection().focusNode; 
        var parent = $(self.editable).get(0); // contenteditable used by summernote
        if ($.contains(parent, focused_element))
        {   // the clicked element is inside the editor
            $(self.editor).data('last_focused_element', focused_element) // save the element in summernote data
        };
    })
}

'summernote.keyup': function (we, e) {
    // same thing in here
}

recovering editor last focus

 self.recoverEditorFocus = function ()
{
    var last_focused_el = $(self.editor).data('last_focused_element'); // retrieve last focused element from summernote data
    if(typeof last_focused_el !== "undefined")
    {
        var editor = self.editable; // contenteditable used by summernote
        var range = document.createRange();
        var sel = window.getSelection();

        range.setStart(last_focused_el, last_focused_el.length); // put the cursor in last position of the element
        range.collapse(true);
        sel.removeAllRanges();
        sel.addRange(range);
        editor.focus();
    }
}

using all of that

hide modal then recover editor last focus then insert the bloc

self.modalSaveEvent = function()
{
    self.$modal.find("button#save").click(function(event)
    {

       /*...*/

        self.$modal.modal('hide');

        self.recoverEditorFocus();

        // var editor_content = $(self.editor).summernote('code');

        // if (!$(editor_content).find('style#bloc_' + bloc_name + '_style').length)
        // {   // add the [bloc_name] style if is not lready inserted
        //     context.invoke('editor.pasteHTML', self.bloc_menu_style);
        // };
        // // insert the generated menu items to the [bloc_name] html
        // $bloc_menu_content.find('ul').html($ul.html());

        // // editor_content = $(self.editor).summernote('code');

        // // add [bloc_name] html to the editor
        // var bloc_menu_html = $bloc_menu_content.prop('outerHTML');

        context.invoke('editor.pasteHTML', bloc_menu_html);
         context.invoke('editor.pasteHTML', '&nbsp;');

    });
}

that worked for me i hope the same for you as well 😃 .

NB : tested on Chrome only.

0reactions
eissasoubhicommented, Mar 2, 2016

so did i, in both ways context.invoke('editor.focus'); $(editor).summernote('focus'); but it didn work for me either. i think summernote tried already to keep the focus inside the editor before every command execution : var beforeCommand = this.beforeCommand = function () { context.triggerEvent('before.command', $editable.html()); // keep focus on editable before command execution self.focus(); };

Read more comments on GitHub >

github_iconTop Results From Across the Web

Append HTML to container element without innerHTML
Check out the insertAdjacentHTML() method. The first parameter is where you want the string appended and takes ("beforebegin", "afterbegin", ...
Read more >
CRUD in HTML, JavaScript, and jQuery - CODE Magazine
In this first article of a series on working within HTML and the Web API, I'll show you how to add, edit, and...
Read more >
.insertBefore() | jQuery API Documentation
A selector, element, array of elements, HTML string, or jQuery object; the matched set of elements will be inserted before the element(s) specified...
Read more >
The Embed External Content element - HTML - MDN Web Docs
The HTML element embeds external content at the specified point in the document. This content is provided by an external application or ...
Read more >
Defining editable regions in your HTML | Articles - CloudCannon
The value is the class name the editor should add to justify the text. The styles for this class need to be listed...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found