: str_replace(): Passing null to parameter #2 ($replace) of type array|string is deprecated in
this.initialize = function () {
this.layoutInfo = ui.createLayout($note, options);
* destroy modules and other resources and remove layout
this.destroy = function () {
$note.removeData('summernote');
ui.removeLayout($note, this.layoutInfo);
* destory modules and other resources and initialize it again
this.reset = function () {
this.code(dom.emptyPara);
this._initialize = function () {
var buttons = $.extend({}, this.options.buttons);
Object.keys(buttons).forEach(function (key) {
self.memo('button.' + key, buttons[key]);
var modules = $.extend({}, this.options.modules, $.summernote.plugins || {});
// add and initialize modules
Object.keys(modules).forEach(function (key) {
self.module(key, modules[key], true);
Object.keys(this.modules).forEach(function (key) {
self.initializeModule(key);
this._destroy = function () {
// destroy modules with reversed order
Object.keys(this.modules).reverse().forEach(function (key) {
Object.keys(this.memos).forEach(function (key) {
this.code = function (html) {
var isActivated = this.invoke('codeview.isActivated');
if (html === undefined) {
this.invoke('codeview.sync');
return isActivated ? this.layoutInfo.codable.val() : this.layoutInfo.editable.html();
this.layoutInfo.codable.val(html);
this.layoutInfo.editable.html(html);
this.triggerEvent('change', html);
this.isDisabled = function () {
return this.layoutInfo.editable.attr('contenteditable') === 'false';
this.enable = function () {
this.layoutInfo.editable.attr('contenteditable', true);
this.invoke('toolbar.activate', true);
this.disable = function () {
// close codeview if codeview is opend
if (this.invoke('codeview.isActivated')) {
this.invoke('codeview.deactivate');
this.layoutInfo.editable.attr('contenteditable', false);
this.invoke('toolbar.deactivate', true);
this.triggerEvent = function () {
var namespace = list.head(arguments);
var args = list.tail(list.from(arguments));
var callback = this.options.callbacks[func.namespaceToCamel(namespace, 'on')];
callback.apply($note[0], args);
$note.trigger('summernote.' + namespace, args);
this.initializeModule = function (key) {
var module = this.modules[key];
module.shouldInitialize = module.shouldInitialize || func.ok;
if (!module.shouldInitialize()) {
dom.attachEvents($note, module.events);
this.module = function (key, ModuleClass, withoutIntialize) {
if (arguments.length === 1) {
return this.modules[key];
this.modules[key] = new ModuleClass(this);
this.initializeModule(key);
this.removeModule = function (key) {
var module = this.modules[key];
if (module.shouldInitialize()) {
dom.detachEvents($note, module.events);
delete this.modules[key];
this.memo = function (key, obj) {
if (arguments.length === 1) {
this.removeMemo = function (key) {
if (this.memos[key] && this.memos[key].destroy) {
this.memos[key].destroy();
this.createInvokeHandler = function (namespace, value) {
return function (event) {
self.invoke(namespace, value || $(event.target).data('value') || $(event.currentTarget).data('value'));
this.invoke = function () {
var namespace = list.head(arguments);
var args = list.tail(list.from(arguments));
var splits = namespace.split('.');
var hasSeparator = splits.length > 1;
var moduleName = hasSeparator && list.head(splits);
var methodName = hasSeparator ? list.last(splits) : list.head(splits);
var module = this.modules[moduleName || 'editor'];
if (!moduleName && this[methodName]) {
return this[methodName].apply(this, args);
} else if (module && module[methodName] && module.shouldInitialize()) {
return module[methodName].apply(module, args);
return this.initialize();
$.summernote = $.summernote || {
summernote: function () {
var type = $.type(list.head(arguments));
var isExternalAPICalled = type === 'string';
var hasInitOptions = type === 'object';
var options = hasInitOptions ? list.head(arguments) : {};
options = $.extend({}, $.summernote.options, options);
options.langInfo = $.extend(true, {}, $.summernote.lang['en-US'], $.summernote.lang[options.lang]);
this.each(function (idx, note) {
if (!$note.data('summernote')) {
var context = new Context($note, options);
$note.data('summernote', context);
$note.data('summernote').triggerEvent('init', context.layoutInfo);
var $note = this.first();
var context = $note.data('summernote');
if (isExternalAPICalled) {
return context.invoke.apply(context, list.from(arguments));
} else if (options.focus) {
context.invoke('editor.focus');
var Renderer = function (markup, children, options, callback) {
this.render = function ($parent) {
if (options && options.contents) {
$node.html(options.contents);
if (options && options.className) {
$node.addClass(options.className);
if (options && options.data) {
$.each(options.data, function (k, v) {
$node.attr('data-' + k, v);
if (options && options.click) {
$node.on('click', options.click);
var $container = $node.find('.note-children-container');
children.forEach(function (child) {
child.render($container.length ? $container : $node);
callback($node, options);
if (options && options.callback) {
create: function (markup, callback) {
var children = $.isArray(arguments[0]) ? arguments[0] : [];
var options = typeof arguments[1] === 'object' ? arguments[1] : arguments[0];
if (options && options.children) {
children = options.children;
return new Renderer(markup, children, options, callback);
var editor = renderer.create('<div class="note-editor note-frame panel panel-default"/>');
var toolbar = renderer.create('<div class="note-toolbar panel-heading"/>');
var editingArea = renderer.create('<div class="note-editing-area"/>');
var codable = renderer.create('<textarea class="note-codable"/>');
var editable = renderer.create('<div class="note-editable panel-body" contentEditable="true"/>');
var statusbar = renderer.create([
'<div class="note-statusbar">',
' <div class="note-resizebar">',
' <div class="note-icon-bar"/>',
' <div class="note-icon-bar"/>',
' <div class="note-icon-bar"/>',
var airEditor = renderer.create('<div class="note-editor"/>');
var airEditable = renderer.create('<div class="note-editable" contentEditable="true"/>');
var buttonGroup = renderer.create('<div class="note-btn-group btn-group">');
var button = renderer.create('<button type="button" class="note-btn btn btn-default btn-sm">', function ($node, options) {
if (options && options.tooltip) {
var dropdown = renderer.create('<div class="dropdown-menu">', function ($node, options) {
var markup = $.isArray(options.items) ? options.items.map(function (item) {
return '<li><a href="#" data-value="' + item + '">' + item + '</a></li>';
}).join('') : options.items;
var dropdownCheck = renderer.create('<div class="dropdown-menu note-check">', function ($node, options) {
var markup = $.isArray(options.items) ? options.items.map(function (item) {
return '<li><a href="#" data-value="' + item + '">' + icon(options.checkClassName) + ' ' + item + '</a></li>';
}).join('') : options.items;
var palette = renderer.create('<div class="note-color-palette"/>', function ($node, options) {
for (var row = 0, rowSize = options.colors.length; row < rowSize; row++) {
var eventName = options.eventName;
var colors = options.colors[row];
for (var col = 0, colSize = colors.length; col < colSize; col++) {
'<button type="button" class="note-color-btn"',
'style="background-color:', color, '" ',
'data-event="', eventName, '" ',
'data-value="', color, '" ',
'data-toggle="button" tabindex="-1"></button>'
contents.push('<div class="note-color-row">' + buttons.join('') + '</div>');
$node.html(contents.join(''));
$node.find('.note-color-btn').tooltip({
var dialog = renderer.create('<div class="modal" aria-hidden="false"/>', function ($node, options) {
'<div class="modal-dialog">',
' <div class="modal-content">',
' <div class="modal-header">' +
' <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>' +
' <h4 class="modal-title">' + options.title + '</h4>' +
' <div class="modal-body">' + options.body + '</div>',
' <div class="modal-footer">' + options.footer + '</div>' : ''
var popover = renderer.create([
'<div class="note-popover popover bottom in">',
' <div class="popover-content note-children-container"/>',
var icon = function (iconClassName, tagName) {
tagName = tagName || 'i';
return '<' + tagName + ' class="' + iconClassName + '"/>';
editingArea: editingArea,
airEditable: airEditable,
buttonGroup: buttonGroup,
dropdownCheck: dropdownCheck,
toggleBtn: function ($btn, isEnable) {
$btn.toggleClass('disabled', !isEnable);
$btn.attr('disabled', !isEnable);
toggleBtnActive: function ($btn, isActive) {
$btn.toggleClass('active', isActive);
onDialogShown: function ($dialog, handler) {
$dialog.one('shown.bs.modal', handler);
onDialogHidden: function ($dialog, handler) {
$dialog.one('hidden.bs.modal', handler);
showDialog: function ($dialog) {
hideDialog: function ($dialog) {
createLayout: function ($note, options) {
var $editor = (options.airMode ? ui.airEditor([
$editor.insertAfter($note);
toolbar: $editor.find('.note-toolbar'),
editingArea: $editor.find('.note-editing-area'),
editable: $editor.find('.note-editable'),
codable: $editor.find('.note-codable'),
statusbar: $editor.find('.note-statusbar')
removeLayout: function ($note, layoutInfo) {
$note.html(layoutInfo.editable.html());
layoutInfo.editor.remove();
$.extend($.summernote.lang, {
clear: 'Remove Font Style',
strikethrough: 'Strikethrough',
superscript: 'Superscript',
resizeFull: 'Resize Full',
resizeHalf: 'Resize Half',
resizeQuarter: 'Resize Quarter',
floatRight: 'Float Right',
shapeRounded: 'Shape: Rounded',