Files
odoo_source/addons/website/static/lib/summernote/src/js/Renderer.js
T

919 lines
32 KiB
JavaScript

define([
'summernote/core/agent', 'summernote/core/dom', 'summernote/core/func'
], function (agent, dom, func) {
/**
* renderer
*
* rendering toolbar and editable
*/
var Renderer = function () {
/**
* bootstrap button template
*
* @param {String} label
* @param {Object} [options]
* @param {String} [options.event]
* @param {String} [options.value]
* @param {String} [options.title]
* @param {String} [options.dropdown]
* @param {String} [options.hide]
*/
var tplButton = function (label, options) {
var event = options.event;
var value = options.value;
var title = options.title;
var className = options.className;
var dropdown = options.dropdown;
var hide = options.hide;
return '<button type="button"' +
' class="btn btn-default btn-sm btn-small' +
(className ? ' ' + className : '') +
(dropdown ? ' dropdown-toggle' : '') +
'"' +
(dropdown ? ' data-toggle="dropdown"' : '') +
(title ? ' title="' + title + '"' : '') +
(event ? ' data-event="' + event + '"' : '') +
(value ? ' data-value=\'' + value + '\'' : '') +
(hide ? ' data-hide=\'' + hide + '\'' : '') +
' tabindex="-1">' +
label +
(dropdown ? ' <span class="caret"></span>' : '') +
'</button>' +
(dropdown || '');
};
/**
* bootstrap icon button template
*
* @param {String} iconClassName
* @param {Object} [options]
* @param {String} [options.event]
* @param {String} [options.value]
* @param {String} [options.title]
* @param {String} [options.dropdown]
*/
var tplIconButton = function (iconClassName, options) {
var label = '<i class="' + iconClassName + '"></i>';
return tplButton(label, options);
};
/**
* bootstrap popover template
*
* @param {String} className
* @param {String} content
*/
var tplPopover = function (className, content) {
return '<div class="' + className + ' popover bottom in" style="display: none;">' +
'<div class="arrow"></div>' +
'<div class="popover-content">' +
content +
'</div>' +
'</div>';
};
/**
* bootstrap dialog template
*
* @param {String} className
* @param {String} [title]
* @param {String} body
* @param {String} [footer]
*/
var tplDialog = function (className, title, body, footer) {
return '<div class="' + className + ' modal" aria-hidden="false">' +
'<div class="modal-dialog">' +
'<div class="modal-content">' +
(title ?
'<div class="modal-header">' +
'<button type="button" class="close" aria-hidden="true" tabindex="-1">&times;</button>' +
'<h4 class="modal-title">' + title + '</h4>' +
'</div>' : ''
) +
'<form class="note-modal-form">' +
'<div class="modal-body">' + body + '</div>' +
(footer ?
'<div class="modal-footer">' + footer + '</div>' : ''
) +
'</form>' +
'</div>' +
'</div>' +
'</div>';
};
var tplButtonInfo = {
picture: function (lang) {
return tplIconButton('fa fa-picture-o', {
event: 'showImageDialog',
title: lang.image.image,
hide: true
});
},
link: function (lang) {
return tplIconButton('fa fa-link', {
event: 'showLinkDialog',
title: lang.link.link,
hide: true
});
},
table: function (lang) {
var dropdown = '<ul class="note-table dropdown-menu">' +
'<div class="note-dimension-picker">' +
'<div class="note-dimension-picker-mousecatcher" data-event="insertTable" data-value="1x1"></div>' +
'<div class="note-dimension-picker-highlighted"></div>' +
'<div class="note-dimension-picker-unhighlighted"></div>' +
'</div>' +
'<div class="note-dimension-display"> 1 x 1 </div>' +
'</ul>';
return tplIconButton('fa fa-table', {
title: lang.table.table,
dropdown: dropdown
});
},
style: function (lang, options) {
var items = options.styleTags.reduce(function (memo, v) {
var label = lang.style[v === 'p' ? 'normal' : v];
return memo + '<li><a data-event="formatBlock" href="#" data-value="' + v + '">' +
(
(v === 'p' || v === 'pre') ? label :
'<' + v + '>' + label + '</' + v + '>'
) +
'</a></li>';
}, '');
return tplIconButton('fa fa-magic', {
title: lang.style.style,
dropdown: '<ul class="dropdown-menu">' + items + '</ul>'
});
},
fontname: function (lang, options) {
var items = options.fontNames.reduce(function (memo, v) {
if (!agent.isFontInstalled(v)) { return memo; }
return memo + '<li><a data-event="fontName" href="#" data-value="' + v + '">' +
'<i class="fa fa-check"></i> ' + v +
'</a></li>';
}, '');
var label = '<span class="note-current-fontname">' +
options.defaultFontName +
'</span>';
return tplButton(label, {
title: lang.font.name,
dropdown: '<ul class="dropdown-menu">' + items + '</ul>'
});
},
color: function (lang) {
var colorButtonLabel = '<i class="fa fa-font" style="color:black;background-color:yellow;"></i>';
var colorButton = tplButton(colorButtonLabel, {
className: 'note-recent-color',
title: lang.color.recent,
event: 'color',
value: '{"backColor":"yellow"}'
});
var dropdown = '<ul class="dropdown-menu">' +
'<li>' +
'<div class="btn-group">' +
'<div class="note-palette-title">' + lang.color.background + '</div>' +
'<div class="note-color-reset" data-event="backColor"' +
' data-value="inherit" title="' + lang.color.transparent + '">' +
lang.color.setTransparent +
'</div>' +
'<div class="note-color-palette" data-target-event="backColor"></div>' +
'</div>' +
'<div class="btn-group">' +
'<div class="note-palette-title">' + lang.color.foreground + '</div>' +
'<div class="note-color-reset" data-event="foreColor" data-value="inherit" title="' + lang.color.reset + '">' +
lang.color.resetToDefault +
'</div>' +
'<div class="note-color-palette" data-target-event="foreColor"></div>' +
'</div>' +
'</li>' +
'</ul>';
var moreButton = tplButton('', {
title: lang.color.more,
dropdown: dropdown
});
return colorButton + moreButton;
},
bold: function (lang) {
return tplIconButton('fa fa-bold', {
event: 'bold',
title: lang.font.bold
});
},
italic: function (lang) {
return tplIconButton('fa fa-italic', {
event: 'italic',
title: lang.font.italic
});
},
underline: function (lang) {
return tplIconButton('fa fa-underline', {
event: 'underline',
title: lang.font.underline
});
},
clear: function (lang) {
return tplIconButton('fa fa-eraser', {
event: 'removeFormat',
title: lang.font.clear
});
},
ul: function (lang) {
return tplIconButton('fa fa-list-ul', {
event: 'insertUnorderedList',
title: lang.lists.unordered
});
},
ol: function (lang) {
return tplIconButton('fa fa-list-ol', {
event: 'insertOrderedList',
title: lang.lists.ordered
});
},
paragraph: function (lang) {
var leftButton = tplIconButton('fa fa-align-left', {
title: lang.paragraph.left,
event: 'justifyLeft'
});
var centerButton = tplIconButton('fa fa-align-center', {
title: lang.paragraph.center,
event: 'justifyCenter'
});
var rightButton = tplIconButton('fa fa-align-right', {
title: lang.paragraph.right,
event: 'justifyRight'
});
var justifyButton = tplIconButton('fa fa-align-justify', {
title: lang.paragraph.justify,
event: 'justifyFull'
});
var outdentButton = tplIconButton('fa fa-outdent', {
title: lang.paragraph.outdent,
event: 'outdent'
});
var indentButton = tplIconButton('fa fa-indent', {
title: lang.paragraph.indent,
event: 'indent'
});
var dropdown = '<div class="dropdown-menu">' +
'<div class="note-align btn-group">' +
leftButton + centerButton + rightButton + justifyButton +
'</div>' +
'<div class="note-list btn-group">' +
indentButton + outdentButton +
'</div>' +
'</div>';
return tplIconButton('fa fa-align-left', {
title: lang.paragraph.paragraph,
dropdown: dropdown
});
},
height: function (lang, options) {
var items = options.lineHeights.reduce(function (memo, v) {
return memo + '<li><a data-event="lineHeight" href="#" data-value="' + parseFloat(v) + '">' +
'<i class="fa fa-check"></i> ' + v +
'</a></li>';
}, '');
return tplIconButton('fa fa-text-height', {
title: lang.font.height,
dropdown: '<ul class="dropdown-menu">' + items + '</ul>'
});
},
help: function (lang) {
return tplIconButton('fa fa-question', {
event: 'showHelpDialog',
title: lang.options.help,
hide: true
});
},
fullscreen: function (lang) {
return tplIconButton('fa fa-arrows-alt', {
event: 'fullscreen',
title: lang.options.fullscreen
});
},
codeview: function (lang) {
return tplIconButton('fa fa-code', {
event: 'codeview',
title: lang.options.codeview
});
},
undo: function (lang) {
return tplIconButton('fa fa-undo', {
event: 'undo',
title: lang.history.undo
});
},
redo: function (lang) {
return tplIconButton('fa fa-repeat', {
event: 'redo',
title: lang.history.redo
});
},
hr: function (lang) {
return tplIconButton('fa fa-minus', {
event: 'insertHorizontalRule',
title: lang.hr.insert
});
}
};
var tplPopovers = function (lang, options) {
var tplLinkPopover = function () {
var linkButton = tplIconButton('fa fa-edit', {
title: lang.link.edit,
event: 'showLinkDialog',
hide: true
});
var unlinkButton = tplIconButton('fa fa-unlink', {
title: lang.link.unlink,
event: 'unlink'
});
var content = '<a href="http://www.google.com" target="_blank">www.google.com</a>&nbsp;&nbsp;' +
'<div class="note-insert btn-group">' +
linkButton + unlinkButton +
'</div>';
return tplPopover('note-link-popover', content);
};
var tplImagePopover = function () {
var fullButton = tplButton('<span class="note-fontsize-10">100%</span>', {
title: lang.image.resizeFull,
event: 'resize',
value: '1'
});
var halfButton = tplButton('<span class="note-fontsize-10">50%</span>', {
title: lang.image.resizeHalf,
event: 'resize',
value: '0.5'
});
var quarterButton = tplButton('<span class="note-fontsize-10">25%</span>', {
title: lang.image.resizeQuarter,
event: 'resize',
value: '0.25'
});
var leftButton = tplIconButton('fa fa-align-left', {
title: lang.image.floatLeft,
event: 'floatMe',
value: 'left'
});
var rightButton = tplIconButton('fa fa-align-right', {
title: lang.image.floatRight,
event: 'floatMe',
value: 'right'
});
var justifyButton = tplIconButton('fa fa-align-justify', {
title: lang.image.floatNone,
event: 'floatMe',
value: 'none'
});
var roundedButton = tplIconButton('fa fa-square', {
title: lang.image.shapeRounded,
event: 'imageShape',
value: 'img-rounded'
});
var circleButton = tplIconButton('fa fa-circle', {
title: lang.image.shapeCircle,
event: 'imageShape',
value: 'img-circle'
});
var thumbnailButton = tplIconButton('fa fa-picture-o', {
title: lang.image.shapeThumbnail,
event: 'imageShape',
value: 'img-thumbnail'
});
var noneButton = tplIconButton('fa fa-times', {
title: lang.image.shapeNone,
event: 'imageShape',
value: ''
});
var removeButton = tplIconButton('fa fa-trash-o', {
title: lang.image.remove,
event: 'removeMedia',
value: 'none'
});
var content = '<div class="btn-group">' + fullButton + halfButton + quarterButton + '</div>' +
'<div class="btn-group">' + leftButton + rightButton + justifyButton + '</div>' +
'<div class="btn-group">' + roundedButton + circleButton + thumbnailButton + noneButton + '</div>' +
'<div class="btn-group">' + removeButton + '</div>';
return tplPopover('note-image-popover', content);
};
var tplAirPopover = function () {
var content = '';
for (var idx = 0, len = options.airPopover.length; idx < len; idx ++) {
var group = options.airPopover[idx];
content += '<div class="note-' + group[0] + ' btn-group">';
for (var i = 0, lenGroup = group[1].length; i < lenGroup; i++) {
content += tplButtonInfo[group[1][i]](lang, options);
}
content += '</div>';
}
return tplPopover('note-air-popover', content);
};
return '<div class="note-popover">' +
tplLinkPopover() +
tplImagePopover() +
(options.airMode ? tplAirPopover() : '') +
'</div>';
};
this.tplButtonInfo = tplButtonInfo; // odoo change for overwrite
this.tplPopovers = tplPopovers; // odoo change for overwrite
var tplHandles = function () {
return '<div class="note-handle">' +
'<div class="note-control-selection">' +
'<div class="note-control-selection-bg"></div>' +
'<div class="note-control-holder note-control-nw"></div>' +
'<div class="note-control-holder note-control-ne"></div>' +
'<div class="note-control-holder note-control-sw"></div>' +
'<div class="note-control-sizing note-control-se"></div>' +
'<div class="note-control-selection-info"></div>' +
'</div>' +
'</div>';
};
/**
* shortcut table template
* @param {String} title
* @param {String} body
*/
var tplShortcut = function (title, keys) {
var keyClass = 'note-shortcut-col col-xs-6 note-shortcut-';
var body = [];
for (var i in keys) {
if (keys.hasOwnProperty(i)) {
body.push(
'<div class="' + keyClass + 'key">' + keys[i].kbd + '</div>' +
'<div class="' + keyClass + 'name">' + keys[i].text + '</div>'
);
}
}
return '<div class="note-shortcut-row row"><div class="' + keyClass + 'title col-xs-offset-6">' + title + '</div></div>' +
'<div class="note-shortcut-row row">' + body.join('</div><div class="note-shortcut-row row">') + '</div>';
};
var tplShortcutText = function (lang) {
var keys = [
{ kbd: '⌘ + B', text: lang.font.bold },
{ kbd: '⌘ + I', text: lang.font.italic },
{ kbd: '⌘ + U', text: lang.font.underline },
{ kbd: '⌘ + ⇧ + S', text: lang.font.sdivikethrough },
{ kbd: '⌘ + \\', text: lang.font.clear }
];
return tplShortcut(lang.shortcut.textFormatting, keys);
};
var tplShortcutAction = function (lang) {
var keys = [
{ kbd: '⌘ + Z', text: lang.history.undo },
{ kbd: '⌘ + ⇧ + Z', text: lang.history.redo },
{ kbd: '⌘ + ]', text: lang.paragraph.indent },
{ kbd: '⌘ + [', text: lang.paragraph.oudivent },
{ kbd: '⌘ + ENTER', text: lang.hr.insert }
];
return tplShortcut(lang.shortcut.action, keys);
};
var tplShortcutPara = function (lang) {
var keys = [
{ kbd: '⌘ + ⇧ + L', text: lang.paragraph.left },
{ kbd: '⌘ + ⇧ + E', text: lang.paragraph.center },
{ kbd: '⌘ + ⇧ + R', text: lang.paragraph.right },
{ kbd: '⌘ + ⇧ + J', text: lang.paragraph.justify },
{ kbd: '⌘ + ⇧ + NUM7', text: lang.lists.ordered },
{ kbd: '⌘ + ⇧ + NUM8', text: lang.lists.unordered }
];
return tplShortcut(lang.shortcut.paragraphFormatting, keys);
};
var tplShortcutStyle = function (lang) {
var keys = [
{ kbd: '⌘ + NUM0', text: lang.style.normal },
{ kbd: '⌘ + NUM1', text: lang.style.h1 },
{ kbd: '⌘ + NUM2', text: lang.style.h2 },
{ kbd: '⌘ + NUM3', text: lang.style.h3 },
{ kbd: '⌘ + NUM4', text: lang.style.h4 },
{ kbd: '⌘ + NUM5', text: lang.style.h5 },
{ kbd: '⌘ + NUM6', text: lang.style.h6 }
];
return tplShortcut(lang.shortcut.documentStyle, keys);
};
var tplExtraShortcuts = function (lang, options) {
var extraKeys = options.extraKeys;
var keys = [];
for (var key in extraKeys) {
if (extraKeys.hasOwnProperty(key)) {
keys.push({ kbd: key, text: extraKeys[key] });
}
}
return tplShortcut(lang.shortcut.extraKeys, keys);
};
var tplShortcutTable = function (lang, options) {
var colClass = 'class="note-shortcut note-shortcut-col col-sm-6 col-xs-12"';
var template = [
'<div ' + colClass + '>' + tplShortcutAction(lang, options) + '</div>' +
'<div ' + colClass + '>' + tplShortcutText(lang, options) + '</div>',
'<div ' + colClass + '>' + tplShortcutStyle(lang, options) + '</div>' +
'<div ' + colClass + '>' + tplShortcutPara(lang, options) + '</div>'
];
if (options.extraKeys) {
template.push('<div ' + colClass + '>' + tplExtraShortcuts(lang, options) + '</div>');
}
return '<div class="note-shortcut-row row">' +
template.join('</div><div class="note-shortcut-row row">') +
'</div>';
};
var replaceMacKeys = function (sHtml) {
return sHtml.replace(/⌘/g, 'Ctrl').replace(/⇧/g, 'Shift');
};
var tplDialogInfo = {
image: function (lang, options) {
var imageLimitation = '';
if (options.maximumImageFileSize) {
var unit = Math.floor(Math.log(options.maximumImageFileSize) / Math.log(1024));
var readableSize = (options.maximumImageFileSize / Math.pow(1024, unit)).toFixed(2) * 1 +
' ' + ' KMGTP'[unit] + 'B';
imageLimitation = '<small>' + lang.image.maximumFileSize + ' : ' + readableSize + '</small>';
}
var body = '<div class="form-group row-fluid note-group-select-from-files">' +
'<label>' + lang.image.selectFromFiles + '</label>' +
'<input class="note-image-input" type="file" name="files" accept="image/*" multiple="multiple" />' +
imageLimitation +
'</div>' +
'<div class="form-group row-fluid">' +
'<label>' + lang.image.url + '</label>' +
'<input class="note-image-url form-control span12" type="text" />' +
'</div>';
var footer = '<button href="#" class="btn btn-primary note-image-btn disabled" disabled>' + lang.image.insert + '</button>';
return tplDialog('note-image-dialog', lang.image.insert, body, footer);
},
link: function (lang, options) {
var body = '<div class="form-group row-fluid">' +
'<label>' + lang.link.textToDisplay + '</label>' +
'<input class="note-link-text form-control span12" type="text" />' +
'</div>' +
'<div class="form-group row-fluid">' +
'<label>' + lang.link.url + '</label>' +
'<input class="note-link-url form-control span12" type="text" />' +
'</div>' +
(!options.disableLinkTarget ?
'<div class="checkbox">' +
'<label>' + '<input type="checkbox" checked> ' +
lang.link.openInNewWindow +
'</label>' +
'</div>' : ''
);
var footer = '<button href="#" class="btn btn-primary note-link-btn disabled" disabled>' + lang.link.insert + '</button>';
return tplDialog('note-link-dialog', lang.link.insert, body, footer);
},
help: function (lang, options) {
var body = '<a class="modal-close pull-right" aria-hidden="true" tabindex="-1">' + lang.shortcut.close + '</a>' +
'<div class="title">' + lang.shortcut.shortcuts + '</div>' +
(agent.isMac ? tplShortcutTable(lang, options) : replaceMacKeys(tplShortcutTable(lang, options))) +
'<p class="text-center">' +
'<a href="//hackerwins.github.io/summernote/" target="_blank">Summernote @VERSION</a> · ' +
'<a href="//github.com/HackerWins/summernote" target="_blank">Project</a> · ' +
'<a href="//github.com/HackerWins/summernote/issues" target="_blank">Issues</a>' +
'</p>';
return tplDialog('note-help-dialog', '', body, '');
}
};
var tplDialogs = function (lang, options) {
var dialogs = '';
$.each(tplDialogInfo, function (idx, tplDialog) {
dialogs += tplDialog(lang, options);
});
return '<div class="note-dialog">' + dialogs + '</div>';
};
var tplStatusbar = function () {
return '<div class="note-resizebar">' +
'<div class="note-icon-bar"></div>' +
'<div class="note-icon-bar"></div>' +
'<div class="note-icon-bar"></div>' +
'</div>';
};
var representShortcut = function (str) {
if (agent.isMac) {
str = str.replace('CMD', '⌘').replace('SHIFT', '⇧');
}
return str.replace('BACKSLASH', '\\')
.replace('SLASH', '/')
.replace('LEFTBRACKET', '[')
.replace('RIGHTBRACKET', ']');
};
/**
* createTooltip
*
* @param {jQuery} $container
* @param {Object} keyMap
* @param {String} [sPlacement]
*/
var createTooltip = function ($container, keyMap, sPlacement) {
var invertedKeyMap = func.invertObject(keyMap);
var $buttons = $container.find('button');
$buttons.each(function (i, elBtn) {
var $btn = $(elBtn);
var sShortcut = invertedKeyMap[$btn.data('event')];
if (sShortcut) {
$btn.attr('title', function (i, v) {
return v + ' (' + representShortcut(sShortcut) + ')';
});
}
// bootstrap tooltip on btn-group bug
// https://github.com/twbs/bootstrap/issues/5687
}).tooltip({
container: 'body',
trigger: 'hover',
placement: sPlacement || 'top'
}).on('click', function () {
$(this).tooltip('hide');
});
};
// createPalette
var createPalette = function ($container, options) {
var colorInfo = options.colors;
$container.find('.note-color-palette').each(function () {
var $palette = $(this), eventName = $palette.attr('data-target-event');
var paletteContents = [];
for (var row = 0, lenRow = colorInfo.length; row < lenRow; row++) {
var colors = colorInfo[row];
var buttons = [];
for (var col = 0, lenCol = colors.length; col < lenCol; col++) {
var color = colors[col];
buttons.push(['<button type="button" class="note-color-btn" style="background-color:', color,
';" data-event="', eventName,
'" data-value="', color,
'" title="', color,
'" data-toggle="button" tabindex="-1"></button>'].join(''));
}
paletteContents.push('<div class="note-color-row">' + buttons.join('') + '</div>');
}
$palette.html(paletteContents.join(''));
});
};
this.createPalette = createPalette; // odoo change for overwrite
/**
* create summernote layout (air mode)
*
* @param {jQuery} $holder
* @param {Object} options
*/
this.createLayoutByAirMode = function ($holder, options) {
var langInfo = options.langInfo;
var keyMap = options.keyMap[agent.isMac ? 'mac' : 'pc'];
var id = func.uniqueId();
$holder.addClass('note-air-editor note-editable');
$holder.attr({
'data-note-id': id,
'contentEditable': true
});
var body = document.body;
// create Popover
var $popover = $(this.tplPopovers(langInfo, options)); // odoo change for overwrite
$popover.addClass('note-air-layout');
$popover.attr('id', 'note-popover-' + id);
$popover.appendTo(body);
createTooltip($popover, keyMap);
this.createPalette($popover, options); // odoo change for overwrite
// create Handle
var $handle = $(tplHandles());
$handle.addClass('note-air-layout');
$handle.attr('id', 'note-handle-' + id);
$handle.appendTo(body);
// create Dialog
var $dialog = $(tplDialogs(langInfo, options));
$dialog.addClass('note-air-layout');
$dialog.attr('id', 'note-dialog-' + id);
$dialog.find('button.close, a.modal-close').click(function () {
$(this).closest('.modal').modal('hide');
});
$dialog.appendTo(body);
};
/**
* create summernote layout (normal mode)
*
* @param {jQuery} $holder
* @param {Object} options
*/
this.createLayoutByFrame = function ($holder, options) {
var langInfo = options.langInfo;
//01. create Editor
var $editor = $('<div class="note-editor"></div>');
if (options.width) {
$editor.width(options.width);
}
//02. statusbar (resizebar)
if (options.height > 0) {
$('<div class="note-statusbar">' + (options.disableResizeEditor ? '' : tplStatusbar()) + '</div>').prependTo($editor);
}
//03. create Editable
var isContentEditable = !$holder.is(':disabled');
var $editable = $('<div class="note-editable" contentEditable="' + isContentEditable + '"></div>')
.prependTo($editor);
if (options.height) {
$editable.height(options.height);
}
if (options.direction) {
$editable.attr('dir', options.direction);
}
if (options.placeholder) {
$editable.attr('data-placeholder', options.placeholder);
}
$editable.html(dom.html($holder));
//031. create codable
$('<textarea class="note-codable"></textarea>').prependTo($editor);
//04. create Toolbar
var toolbarHTML = '';
for (var idx = 0, len = options.toolbar.length; idx < len; idx ++) {
var groupName = options.toolbar[idx][0];
var groupButtons = options.toolbar[idx][1];
toolbarHTML += '<div class="note-' + groupName + ' btn-group">';
for (var i = 0, btnLength = groupButtons.length; i < btnLength; i++) {
var buttonInfo = tplButtonInfo[groupButtons[i]];
// continue creating toolbar even if a button doesn't exist
if (!$.isFunction(buttonInfo)) { continue; }
toolbarHTML += buttonInfo(langInfo, options);
}
toolbarHTML += '</div>';
}
toolbarHTML = '<div class="note-toolbar btn-toolbar">' + toolbarHTML + '</div>';
var $toolbar = $(toolbarHTML).prependTo($editor);
var keyMap = options.keyMap[agent.isMac ? 'mac' : 'pc'];
this.createPalette($toolbar, options); // odoo change for overwrite
createTooltip($toolbar, keyMap, 'bottom');
//05. create Popover
var $popover = $(this.tplPopovers(langInfo, options)).prependTo($editor); // odoo change for overwrite
this.createPalette($popover, options); // odoo change for overwrite
createTooltip($popover, keyMap);
//06. handle(control selection, ...)
$(tplHandles()).prependTo($editor);
//07. create Dialog
var $dialog = $(tplDialogs(langInfo, options)).prependTo($editor);
$dialog.find('button.close, a.modal-close').click(function () {
$(this).closest('.modal').modal('hide');
});
//08. create Dropzone
$('<div class="note-dropzone"><div class="note-dropzone-message"></div></div>').prependTo($editor);
//09. Editor/Holder switch
$editor.insertAfter($holder);
$holder.hide();
};
this.noteEditorFromHolder = function ($holder) {
if ($holder.hasClass('note-air-editor')) {
return $holder;
} else if ($holder.next().hasClass('note-editor')) {
return $holder.next();
} else {
return $();
}
};
/**
* create summernote layout
*
* @param {jQuery} $holder
* @param {Object} options
*/
this.createLayout = function ($holder, options) {
if (this.noteEditorFromHolder($holder).length) {
return;
}
if (options.airMode) {
this.createLayoutByAirMode($holder, options);
} else {
this.createLayoutByFrame($holder, options);
}
};
/**
* returns layoutInfo from holder
*
* @param {jQuery} $holder - placeholder
* @returns {Object}
*/
this.layoutInfoFromHolder = function ($holder) {
var $editor = this.noteEditorFromHolder($holder);
if (!$editor.length) { return; }
var layoutInfo = dom.buildLayoutInfo($editor);
// cache all properties.
for (var key in layoutInfo) {
if (layoutInfo.hasOwnProperty(key)) {
layoutInfo[key] = layoutInfo[key].call();
}
}
return layoutInfo;
};
/**
* removeLayout
*
* @param {jQuery} $holder - placeholder
* @param {Object} layoutInfo
* @param {Object} options
*
*/
this.removeLayout = function ($holder, layoutInfo, options) {
if (options.airMode) {
$holder.removeClass('note-air-editor note-editable')
.removeAttr('id contentEditable');
layoutInfo.popover.remove();
layoutInfo.handle.remove();
layoutInfo.dialog.remove();
} else {
$holder.html(layoutInfo.editable.html());
layoutInfo.editor.remove();
$holder.show();
}
};
this.getTemplate = function () {
return {
button: tplButton,
iconButton: tplIconButton,
dialog: tplDialog
};
};
this.addButtonInfo = function (name, buttonInfo) {
tplButtonInfo[name] = buttonInfo;
};
this.addDialogInfo = function (name, dialogInfo) {
tplDialogInfo[name] = dialogInfo;
};
};
return Renderer;
});