admin管理员组

文章数量:1295307

We are using Summernote rich-text editor (in MVC core as it happens) and need to add a drop-down menu with different display text (in the menu) to the actual text that get's dropped into the editor (will contain placeholder text).

We have followed the helpful input from "alxmh" on this git page but don't understand it well enough to add the functionality required eg:-

Display    Inserted text
------------------------
First Name {{FirstName}}
Last Name  {{LastName}}

Here is what we have (thanks to ) :-

var EventData = function (context) {
    var ui = $.summernote.ui;

    // create button
    var event = ui.buttonGroup([
        ui.button({
            contents: 'Placeholders <i class="fa fa-caret-down" aria-hidden="true"></i>',
            `tooltip`: 'When you insert a placeholder into your email, it will get substituted with the correct contents at the time of sending',
            data: {
                toggle: 'dropdown'
            }
        }),
        ui.dropdown({
            items: [

                'First Name {{FirstName}}',
                'Last Name {{LastName}}'
            ],
            callback: function (items) {
                $(items).find('li a').on('click', function () {
                    context.invoke("editor.insertText", $(this).html())
                })
            }
        })
    ]);

    return event.render();   // return button as jquery object
}

The above works well but it will only allow the same text in the dropdown as is inserted into the body of the rich-text editor.

Any thoughts would be appreciated.

We are using Summernote rich-text editor (in MVC core as it happens) and need to add a drop-down menu with different display text (in the menu) to the actual text that get's dropped into the editor (will contain placeholder text).

We have followed the helpful input from "alxmh" on this git page but don't understand it well enough to add the functionality required eg:-

Display    Inserted text
------------------------
First Name {{FirstName}}
Last Name  {{LastName}}

Here is what we have (thanks to https://github./summernote/summernote/issues/1611) :-

var EventData = function (context) {
    var ui = $.summernote.ui;

    // create button
    var event = ui.buttonGroup([
        ui.button({
            contents: 'Placeholders <i class="fa fa-caret-down" aria-hidden="true"></i>',
            `tooltip`: 'When you insert a placeholder into your email, it will get substituted with the correct contents at the time of sending',
            data: {
                toggle: 'dropdown'
            }
        }),
        ui.dropdown({
            items: [

                'First Name {{FirstName}}',
                'Last Name {{LastName}}'
            ],
            callback: function (items) {
                $(items).find('li a').on('click', function () {
                    context.invoke("editor.insertText", $(this).html())
                })
            }
        })
    ]);

    return event.render();   // return button as jquery object
}

The above works well but it will only allow the same text in the dropdown as is inserted into the body of the rich-text editor.

Any thoughts would be appreciated.

Share Improve this question edited Aug 31, 2018 at 12:32 xnetdude asked Aug 31, 2018 at 12:26 xnetdudexnetdude 1691 silver badge13 bronze badges 3
  • Have you found a solution for this? – user3253002 Commented Sep 26, 2018 at 21:14
  • No, have not resolved. Also, since this, we have actually taken a step backwards. After moving to 0.8.9 (not sure if it's related), our own dropdown (as above) no longer works at all. Currently trying to fix. – xnetdude Commented Sep 28, 2018 at 19:06
  • if you use bootstrap 4, you have to remove the li – user3253002 Commented Sep 29, 2018 at 1:00
Add a ment  | 

6 Answers 6

Reset to default 6

Please define selector ul or select or anything you need. for example:

<ul class="attribute d-none">
    <li data-value="{First Name}">{First Name}</li>
    <li data-value="{Last Name}">{Last Name}</li>
    <li data-value="{Company Name}">{Company Name}</li>
    <li data-value="{Email}">{Email}</li>
    <li data-value="{Address}">{Address}</li>
    <li data-value="{City}">{City}</li>
    <li data-value="{State}">{State}</li>
</ul>

and provide content like this

var AttributeButton = function (context) {
            var ui = $.summernote.ui;
            var list = $('#elements-list').val();

            var button = ui.buttonGroup([
                ui.button({
                    className: 'dropdown-toggle btn-variable',
                    contents: 'Add Variable',
                    tooltip: "Add Variable",
                    data: {
                        toggle: 'dropdown'
                    }
                }),
                ui.dropdown({
                    className: 'drop-default summernote-list',
                    contents: $('.attribute').html(),
                    callback: function ($dropdown) {                    
                        $dropdown.find('li').each(function () {
                            $(this).click(function () {  
                                $('.summernote').summernote('editor.restoreRange');
                                $('.summernote').summernote('editor.focus');
                                $('.summernote').summernote('editor.insertText', $(this).data('value'));
                            });
                        });
                    }
                })
            ]);        

            return button.render();   // return button as jquery object 
        }

i hope this help

Came across this posting as I wanted to do exactly the same thing in Summernote 0.8.8.

I managed to get it working by using maps.

In the summernote options section I added the following to define my key/value pairs:

// Control keywords to display on email editor
emailControls: [
    ['Firstname', '##FIRSTNAME##'],
    ['Lastname', '##LASTNAME##'],
    ['Filename', '##FILENAME##'],
    ['Keys', '##KEYS##'],
    ['Hubcode', '##HUBCODE##'],
    ['Hubname', '##HUBNAME##'],
    ['User ID', '##USERID##'],
    ['Full site signature', '##FS_SIGNATURE##'],
    ['Mobile site signature', '##MS_SIGNATURE##'],
    ['Full site link (displayed as \'click here\')',  '##PORTAL_LINK_FS##'],
    ['Mobile site link (displayed as \'click here\')',  '##PORTAL_LINK_MS##']
],  

I then defined the dropdown:

context.memo('button.emailControls', function () {

    var keywordMap = new Map(options.emailControls);
    var list = Array.from(keywordMap.keys());

    return ui.buttonGroup([
        ui.button({
            className: 'dropdown-toggle',
            contents: ui.dropdownButtonContents(ui.icon(options.icons.emailControls), options),
            tooltip: lang.emailControls.emailControls,
            data: {
                toggle: 'dropdown'
            }
        }),
        ui.dropdown({
            items: list,
            className: 'dropdown-email-control',
            click: function (event) {
                var $button = $(event.target);
                var value = $button.data('value');
                context.invoke('editor.insertText', keywordMap.get(value));
            }
        })
    ]).render();
});
  1. I converted the defined key/value pairs into a map.
  2. Then populated an array called list with the map keys
  3. This was used to define the dropdown items
  4. Finally I used the value returned from the button click to lookup the actual value in the map and insert it into the editor.

I hope this helps someone who needs to do something similar.

It worked for me. When you click on the Address menu, "{ADDRESS}" will be inserted in the editor I just summarized some of the ments here. summernote v0.8.18

var VariableButton = function (context) {
    var ui = $.summernote.ui;
    var button = ui.buttonGroup([
        ui.button({
            className: 'dropdown-toggle',
            contents: 'Variable <span class="note-icon-caret"></span>',
            tooltip: 'Insert variable',
            data: {
                toggle: 'dropdown'
            }
        }),
        ui.dropdown({
            className: 'dropdown-variable',
            contents: '<li><a href="javascript:;" data-value="{NAME}">Name</a></li>' + '<li><a href="javascript:;" data-value="{ADDRESS}">Address</a></li>',
            callback: function (items) {
                $(items).find('li a').each(function () {
                    $(this).click(function(e) {
                        context.invoke("editor.insertText", this.dataset.value);
                        e.preventDefault();
                    });
                });
            }
        })
    ]);

    return button.render();
};

$scope.editorOptions = {
    height: 320,
    minHeight: null,
    maxHeight: null,
    placeholder: 'Please enter email template',
    toolbar: [
        //['headline', ['style']],
        ['style', ['bold', 'italic', 'underline', 'strikethrough']],
        ['fontface', ['fontname']],
        ['textsize', ['fontsize']],
        ['fontclr', ['color']],
        ['alignment', ['ul', 'ol', 'paragraph', 'lineheight']],
        ['height', ['height']],
        ['table', ['table']],
        ['insert', ['link','picture','hr']],
        ['style', ['clear']],
        //['edit',['undo','redo']]
        ['view', ['codeview']],
        ['custom', ['variable']]
    ],
    buttons: {
        variable: VariableButton
    }
};

Here's what I have working, based on the prior answers with adjustments. these worked on SM 0.8.18:

CSS:

  <style>
    div.note-dropdown-menu {
      overflow-y:auto;
      max-height:400px; /*remend keep it approx 50 px less than height of editor itself*/
      width: 180px; /*SM's setting was too narrow for its own style DDL */
    }
  </style>

And here's my javascript:

    $(document).ready(function () {

  $('#txtContent').summernote({
    placeholder: 'Content',
    tabsize: 2,
    height: 300,
    toolbar: [
      ['style', ['style']],
      ['fontface', ['fontname']],
      ['textsize', ['fontsize']],
      ['fontclr', ['color']],
      ['font', ['bold', 'underline', 'clear']],
      ['color', ['color']],
      ['para', ['ul', 'ol', 'paragraph']],
      ['table', ['table']],
      ['insert', ['link', 'picture', 'mailMergeDDL']],
      ['view', ['fullscreen', 'codeview', 'help']]
    ],
    buttons: {
      mailMergeDDL: MailMergeButton
    }
  });
});


var MailMergeButton = function (context) {
  var ui = $.summernote.ui;
  var button = ui.buttonGroup([
    ui.button({
      className: 'dropdown-toggle',
      contents: 'Merge Fields',
      tooltip: 'Inserts mail-merge tag',
      data: {
        toggle: 'dropdown'
      }
    }),
    ui.dropdown({
      className: 'dropdown-variable',
      //contents: $('.attribute').html(),
      items: ['Name', 'Address', 'Field3', 'Field4', 'Field5', 'Field6', 'Field7', 'Field8', 'Field9', 'Field10', 'Field11', 'Field12', 'Field13', 'Field14', 'Field15', 'Field16', 'Field17', 'Field18', 'Field19', 'Field20'],
      callback: function (items) {
        $(items).find('a').each(function () {
          $(this).click(function () {
            //context.summernote('editor.restoreRange');
            //context.summernote('editor.focus'); //not needed and doesn't work. the insert is injecting at the cursor
            context.invoke("editor.insertText", '{'+ this.dataset.value + '}'); 
          });
        });
      }
    }),
  ]);

  return button.render();   // return button as jquery object
}

Answer that demonstrates more clearly how to use key/value placeholders when creating the dropdown so you can insert the proper placeholder. Doesn't require an external mapping.

<script>
let placeholder_button_config = function (context) {
    let ui = $.summernote.ui;
    let button_group = ui.buttonGroup([
        ui.button({
            contents: 'Placeholders',
            className: "summernote-placeholder-button",

            // I can't get the tooltip to display. Maybe someone else can solve that.
            toolTip: "Insert placeholders into the document",

            data: {
                toggle: 'dropdown'
            }
        }),
        ui.dropdown({
            className: "summernote-placeholder-dropdown",

            // If items are objects, then "value" is a required field. Everything else is custom.
            items: [
                {value: "{{first_name}}", custom_label: "First Name", additional_custom_data: 123},
                {value: "{{last_name}}", custom_label: "Last Name", additional_custom_data: "ABC"},
            ],

            // Generates the HTML content of the dropdown option. Run for each item.
            template: function(item) { return "<b>" + item.custom_label + "</b>"; },

            callback: function (items) {
                $(items).find('a').each(function () {
                    
                    // Demonstrates using the label to facilitate accessibility
                    // Summernote stores the whole item object in a data attribute on the <a> tag.
                    let label = $(this).data("item").custom_label;
                    $(this).attr('aria-label', label);

                    $(this).click(function () {
                        console.log(this.dataset.value); // E.g. "{{last_name}}";
                        console.log($(this).data("item").additional_custom_data); // E.g. "ABC"

                        context.invoke("editor.insertText", this.dataset.value);
                    });
                });
            }
        }),
    ]);

    return button_group.render();   // return button as jquery object
};

$("#summernote").summernote({
    toolbar: [
        ['style', ['bold', 'italic', 'underline']],
        ['fontsize', ['fontsize']],
        ['color', ['color']],
        ['link', ['link']],
        ['placeholders_group', ['placeholder_button']]
    ],
    disableResizeEditor: false,
    placeholder: "Content goes here",
    minHeight: 100,
    buttons: {
        placeholder_button: placeholder_button_config
    }
});
</script>

<textarea id="summernote">Test content</textarea>

this one is work for me to set a dropdown in summernote and on change of drop down item text is printed in texteditor

var EventData = function (context) {
var ui = $.summernote.ui;
var event = ui.buttonGroup([
ui.button({
contents: 'Tags',
data: {
toggle: 'dropdown'
}
}),
ui.dropdown({
items: [
'Name', 'Address'
],
callback: function ($dropdown) {
$dropdown.find('li').each(function () {
$(this).click(function () {

                                    context.invoke("editor.insertText", '[' + $(this)[0].ariaLabel + '] ');
                                });
                            });
                        }
                  
                        
                    }),
                 
                ]);

                return event.render();   // return button as jquery object
            }
           $('#TemplateEditor').summernote({
                height: 250,
                placeholder: "write here...",
                toolbar: [
                    ['style', ['style']],
                    ['font', ['bold', 'italic', 'underline', 'clear']],
                    ['fontname', ['fontname']],
                    ['color', ['color']],
                    ['para', ['ul', 'ol', 'paragraph']],
                    ['height', ['height']],
                    ['table', ['table']],
                    ['insert', ['template', 'link', 'picture', 'hr']],
                    ['view', ['fullscreen', 'codeview']],
                    ['help', ['help']],
                    ['eventButton', ['event']]
                ],
                callbacks: {
                    onChange: function (contents, $editable) {
                        var markup = $('#TemplateEditor').summernote('code');

                    }
                },
                buttons: {
                    event: EventData
                }
            });

本文标签: javascriptSummernote dropdown menuStack Overflow