diff options
| author | Nicolas Lempereur <nle@odoo.com> | 2015-08-28 17:22:17 +0200 |
|---|---|---|
| committer | Nicolas Lempereur <nle@odoo.com> | 2015-09-29 14:47:24 +0200 |
| commit | d33086c03fc1a0882be38ae62989b7f72df20d3b (patch) | |
| tree | 20b5776f6902916f4c67d9d356e9db2a107eb952 /addons/web_editor/static/lib/summernote/src/js/Renderer.js | |
| parent | e9ac1bff8bcef56ae09bbba3910202075f7eb89a (diff) | |
[IMP] web_editor: update summernote up to 2015-08-31
update summernote library up to revision:
https://github.com/summernote/summernote/commit/a0f26e300
see https://github.com/summernote/summernote/ for history
closes #8704
Diffstat (limited to 'addons/web_editor/static/lib/summernote/src/js/Renderer.js')
| -rw-r--r-- | addons/web_editor/static/lib/summernote/src/js/Renderer.js | 530 |
1 files changed, 317 insertions, 213 deletions
diff --git a/addons/web_editor/static/lib/summernote/src/js/Renderer.js b/addons/web_editor/static/lib/summernote/src/js/Renderer.js index 07584edc453..a6e56bedc16 100644 --- a/addons/web_editor/static/lib/summernote/src/js/Renderer.js +++ b/addons/web_editor/static/lib/summernote/src/js/Renderer.js @@ -1,7 +1,12 @@ define([ - 'summernote/core/agent', 'summernote/core/dom', 'summernote/core/func' -], function (agent, dom, func) { + 'summernote/core/agent', + 'summernote/core/dom', + 'summernote/core/func', + 'summernote/core/list' +], function (agent, dom, func, list) { /** + * @class Renderer + * * renderer * * rendering toolbar and editable @@ -10,14 +15,15 @@ define([ /** * 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] + * @private + * @param {String} label button name + * @param {Object} [options] button options + * @param {String} [options.event] data-event + * @param {String} [options.className] button's class name + * @param {String} [options.value] data-value + * @param {String} [options.title] button's title for popup + * @param {String} [options.dropdown] dropdown html + * @param {String} [options.hide] data-hide */ var tplButton = function (label, options) { var event = options.event; @@ -27,9 +33,11 @@ define([ var dropdown = options.dropdown; var hide = options.hide; - return '<button type="button"' + - ' class="btn btn-default btn-sm btn-small' + - (className ? ' ' + className : '') + + return (dropdown ? '<div class="btn-group' + + (className ? ' ' + className : '') + '">' : '') + + '<button type="button"' + + ' class="btn btn-default btn-sm' + + ((!dropdown && className) ? ' ' + className : '') + (dropdown ? ' dropdown-toggle' : '') + '"' + (dropdown ? ' data-toggle="dropdown"' : '') + @@ -38,15 +46,16 @@ define([ (value ? ' data-value=\'' + value + '\'' : '') + (hide ? ' data-hide=\'' + hide + '\'' : '') + ' tabindex="-1">' + - label + - (dropdown ? ' <span class="caret"></span>' : '') + - '</button>' + - (dropdown || ''); + label + + (dropdown ? ' <span class="caret"></span>' : '') + + '</button>' + + (dropdown || '') + + (dropdown ? '</div>' : ''); }; /** * bootstrap icon button template - * + * @private * @param {String} iconClassName * @param {Object} [options] * @param {String} [options.event] @@ -61,26 +70,28 @@ define([ /** * bootstrap popover template - * + * @private * @param {String} className * @param {String} content */ var tplPopover = function (className, content) { - return '<div class="' + className + ' popover bottom in" style="display: none;">' + + var $popover = $('<div class="' + className + ' popover bottom in" style="display: none;">' + '<div class="arrow"></div>' + '<div class="popover-content">' + - content + '</div>' + - '</div>'; + '</div>'); + + $popover.find('.popover-content').append(content); + return $popover; }; /** * bootstrap dialog template * * @param {String} className - * @param {String} [title] + * @param {String} [title=''] * @param {String} body - * @param {String} [footer] + * @param {String} [footer=''] */ var tplDialog = function (className, title, body, footer) { return '<div class="' + className + ' modal" aria-hidden="false">' + @@ -92,44 +103,60 @@ define([ '<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 class="modal-body">' + body + '</div>' + + (footer ? + '<div class="modal-footer">' + footer + '</div>' : '' + ) + '</div>' + '</div>' + '</div>'; }; + /** + * bootstrap dropdown template + * + * @param {String|String[]} contents + * @param {String} [className=''] + * @param {String} [nodeName=''] + */ + var tplDropdown = function (contents, className, nodeName) { + var classes = 'dropdown-menu' + (className ? ' ' + className : ''); + nodeName = nodeName || 'ul'; + if (contents instanceof Array) { + contents = contents.join(''); + } + + return '<' + nodeName + ' class="' + classes + '">' + contents + '</' + nodeName + '>'; + }; + var tplButtonInfo = { - picture: function (lang) { - return tplIconButton('fa fa-picture-o', { + picture: function (lang, options) { + return tplIconButton(options.iconPrefix + options.icons.image.image, { event: 'showImageDialog', title: lang.image.image, hide: true }); }, - link: function (lang) { - return tplIconButton('fa fa-link', { + link: function (lang, options) { + return tplIconButton(options.iconPrefix + options.icons.link.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', { + table: function (lang, options) { + var dropdown = [ + '<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>' + ]; + + return tplIconButton(options.iconPrefix + options.icons.table.table, { title: lang.table.table, - dropdown: dropdown + dropdown: tplDropdown(dropdown, 'note-table') }); }, style: function (lang, options) { @@ -143,28 +170,54 @@ define([ '</a></li>'; }, ''); - return tplIconButton('fa fa-magic', { + return tplIconButton(options.iconPrefix + options.icons.style.style, { title: lang.style.style, - dropdown: '<ul class="dropdown-menu">' + items + '</ul>' + dropdown: tplDropdown(items) }); }, fontname: function (lang, options) { + var realFontList = []; 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 + + if (!agent.isFontInstalled(v) && !list.contains(options.fontNamesIgnoreCheck, v)) { + return memo; + } + realFontList.push(v); + return memo + '<li><a data-event="fontName" href="#" data-value="' + v + '" style="font-family:\'' + v + '\'">' + + '<i class="' + options.iconPrefix + options.icons.misc.check + '"></i> ' + v + '</a></li>'; }, ''); + + var hasDefaultFont = agent.isFontInstalled(options.defaultFontName); + var defaultFontName = (hasDefaultFont) ? options.defaultFontName : realFontList[0]; + var label = '<span class="note-current-fontname">' + - options.defaultFontName + + defaultFontName + '</span>'; return tplButton(label, { title: lang.font.name, - dropdown: '<ul class="dropdown-menu">' + items + '</ul>' + className: 'note-fontname', + dropdown: tplDropdown(items, 'note-check') + }); + }, + fontsize: function (lang, options) { + var items = options.fontSizes.reduce(function (memo, v) { + return memo + '<li><a data-event="fontSize" href="#" data-value="' + v + '">' + + '<i class="' + options.iconPrefix + options.icons.misc.check + '"></i> ' + v + + '</a></li>'; + }, ''); + + var label = '<span class="note-current-fontsize">11</span>'; + return tplButton(label, { + title: lang.font.size, + className: 'note-fontsize', + dropdown: tplDropdown(items, 'note-check') }); }, - color: function (lang) { - var colorButtonLabel = '<i class="fa fa-font" style="color:black;background-color:yellow;"></i>'; + color: function (lang, options) { + var colorButtonLabel = '<i class="' + + options.iconPrefix + options.icons.color.recent + + '" style="color:black;background-color:yellow;"></i>'; + var colorButton = tplButton(colorButtonLabel, { className: 'note-recent-color', title: lang.color.recent, @@ -172,156 +225,168 @@ define([ 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 items = [ + '<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>' + ]; var moreButton = tplButton('', { title: lang.color.more, - dropdown: dropdown + dropdown: tplDropdown(items) }); return colorButton + moreButton; }, - bold: function (lang) { - return tplIconButton('fa fa-bold', { + bold: function (lang, options) { + return tplIconButton(options.iconPrefix + options.icons.font.bold, { event: 'bold', title: lang.font.bold }); }, - italic: function (lang) { - return tplIconButton('fa fa-italic', { + italic: function (lang, options) { + return tplIconButton(options.iconPrefix + options.icons.font.italic, { event: 'italic', title: lang.font.italic }); }, - underline: function (lang) { - return tplIconButton('fa fa-underline', { + underline: function (lang, options) { + return tplIconButton(options.iconPrefix + options.icons.font.underline, { event: 'underline', title: lang.font.underline }); }, - clear: function (lang) { - return tplIconButton('fa fa-eraser', { + strikethrough: function (lang, options) { + return tplIconButton(options.iconPrefix + options.icons.font.strikethrough, { + event: 'strikethrough', + title: lang.font.strikethrough + }); + }, + superscript: function (lang, options) { + return tplIconButton(options.iconPrefix + options.icons.font.superscript, { + event: 'superscript', + title: lang.font.superscript + }); + }, + subscript: function (lang, options) { + return tplIconButton(options.iconPrefix + options.icons.font.subscript, { + event: 'subscript', + title: lang.font.subscript + }); + }, + clear: function (lang, options) { + return tplIconButton(options.iconPrefix + options.icons.font.clear, { event: 'removeFormat', title: lang.font.clear }); }, - ul: function (lang) { - return tplIconButton('fa fa-list-ul', { + ul: function (lang, options) { + return tplIconButton(options.iconPrefix + options.icons.lists.unordered, { event: 'insertUnorderedList', title: lang.lists.unordered }); }, - ol: function (lang) { - return tplIconButton('fa fa-list-ol', { + ol: function (lang, options) { + return tplIconButton(options.iconPrefix + options.icons.lists.ordered, { event: 'insertOrderedList', title: lang.lists.ordered }); }, - paragraph: function (lang) { - var leftButton = tplIconButton('fa fa-align-left', { + paragraph: function (lang, options) { + var leftButton = tplIconButton(options.iconPrefix + options.icons.paragraph.left, { title: lang.paragraph.left, event: 'justifyLeft' }); - var centerButton = tplIconButton('fa fa-align-center', { + var centerButton = tplIconButton(options.iconPrefix + options.icons.paragraph.center, { title: lang.paragraph.center, event: 'justifyCenter' }); - var rightButton = tplIconButton('fa fa-align-right', { + var rightButton = tplIconButton(options.iconPrefix + options.icons.paragraph.right, { title: lang.paragraph.right, event: 'justifyRight' }); - var justifyButton = tplIconButton('fa fa-align-justify', { + var justifyButton = tplIconButton(options.iconPrefix + options.icons.paragraph.justify, { title: lang.paragraph.justify, event: 'justifyFull' }); - var outdentButton = tplIconButton('fa fa-outdent', { + var outdentButton = tplIconButton(options.iconPrefix + options.icons.paragraph.outdent, { title: lang.paragraph.outdent, event: 'outdent' }); - var indentButton = tplIconButton('fa fa-indent', { + var indentButton = tplIconButton(options.iconPrefix + options.icons.paragraph.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>'; + var dropdown = [ + '<div class="note-align btn-group">', + leftButton + centerButton + rightButton + justifyButton, + '</div><div class="note-list btn-group">', + indentButton + outdentButton, + '</div>' + ]; - return tplIconButton('fa fa-align-left', { + return tplIconButton(options.iconPrefix + options.icons.paragraph.paragraph, { title: lang.paragraph.paragraph, - dropdown: dropdown + dropdown: tplDropdown(dropdown, '', 'div') }); }, 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 + + '<i class="' + options.iconPrefix + options.icons.misc.check + '"></i> ' + v + '</a></li>'; }, ''); - return tplIconButton('fa fa-text-height', { + return tplIconButton(options.iconPrefix + options.icons.font.height, { title: lang.font.height, - dropdown: '<ul class="dropdown-menu">' + items + '</ul>' + dropdown: tplDropdown(items, 'note-check') }); }, - help: function (lang) { - return tplIconButton('fa fa-question', { + help: function (lang, options) { + return tplIconButton(options.iconPrefix + options.icons.options.help, { event: 'showHelpDialog', title: lang.options.help, hide: true }); }, - fullscreen: function (lang) { - return tplIconButton('fa fa-arrows-alt', { + fullscreen: function (lang, options) { + return tplIconButton(options.iconPrefix + options.icons.options.fullscreen, { event: 'fullscreen', title: lang.options.fullscreen }); }, - codeview: function (lang) { - return tplIconButton('fa fa-code', { + codeview: function (lang, options) { + return tplIconButton(options.iconPrefix + options.icons.options.codeview, { event: 'codeview', title: lang.options.codeview }); }, - undo: function (lang) { - return tplIconButton('fa fa-undo', { + undo: function (lang, options) { + return tplIconButton(options.iconPrefix + options.icons.history.undo, { event: 'undo', title: lang.history.undo }); }, - redo: function (lang) { - return tplIconButton('fa fa-repeat', { + redo: function (lang, options) { + return tplIconButton(options.iconPrefix + options.icons.history.redo, { event: 'redo', title: lang.history.redo }); }, - hr: function (lang) { - return tplIconButton('fa fa-minus', { + hr: function (lang, options) { + return tplIconButton(options.iconPrefix + options.icons.hr.insert, { event: 'insertHorizontalRule', title: lang.hr.insert }); @@ -330,12 +395,12 @@ define([ var tplPopovers = function (lang, options) { var tplLinkPopover = function () { - var linkButton = tplIconButton('fa fa-edit', { + var linkButton = tplIconButton(options.iconPrefix + options.icons.link.edit, { title: lang.link.edit, event: 'showLinkDialog', hide: true }); - var unlinkButton = tplIconButton('fa fa-unlink', { + var unlinkButton = tplIconButton(options.iconPrefix + options.icons.link.unlink, { title: lang.link.unlink, event: 'unlink' }); @@ -363,50 +428,50 @@ define([ value: '0.25' }); - var leftButton = tplIconButton('fa fa-align-left', { + var leftButton = tplIconButton(options.iconPrefix + options.icons.image.floatLeft, { title: lang.image.floatLeft, event: 'floatMe', value: 'left' }); - var rightButton = tplIconButton('fa fa-align-right', { + var rightButton = tplIconButton(options.iconPrefix + options.icons.image.floatRight, { title: lang.image.floatRight, event: 'floatMe', value: 'right' }); - var justifyButton = tplIconButton('fa fa-align-justify', { + var justifyButton = tplIconButton(options.iconPrefix + options.icons.image.floatNone, { title: lang.image.floatNone, event: 'floatMe', value: 'none' }); - var roundedButton = tplIconButton('fa fa-square', { + var roundedButton = tplIconButton(options.iconPrefix + options.icons.image.shapeRounded, { title: lang.image.shapeRounded, event: 'imageShape', value: 'img-rounded' }); - var circleButton = tplIconButton('fa fa-circle', { + var circleButton = tplIconButton(options.iconPrefix + options.icons.image.shapeCircle, { title: lang.image.shapeCircle, event: 'imageShape', value: 'img-circle' }); - var thumbnailButton = tplIconButton('fa fa-picture-o', { + var thumbnailButton = tplIconButton(options.iconPrefix + options.icons.image.shapeThumbnail, { title: lang.image.shapeThumbnail, event: 'imageShape', value: 'img-thumbnail' }); - var noneButton = tplIconButton('fa fa-times', { + var noneButton = tplIconButton(options.iconPrefix + options.icons.image.shapeNone, { title: lang.image.shapeNone, event: 'imageShape', value: '' }); - var removeButton = tplIconButton('fa fa-trash-o', { + var removeButton = tplIconButton(options.iconPrefix + options.icons.image.remove, { title: lang.image.remove, event: 'removeMedia', value: 'none' }); - var content = '<div class="btn-group">' + fullButton + halfButton + quarterButton + '</div>' + + var content = (options.disableResizeImage ? '' : '<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>'; @@ -414,38 +479,50 @@ define([ }; var tplAirPopover = function () { - var content = ''; + var $content = $('<div />'); for (var idx = 0, len = options.airPopover.length; idx < len; idx ++) { var group = options.airPopover[idx]; - content += '<div class="note-' + group[0] + ' btn-group">'; + + var $group = $('<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); + var $button = $(tplButtonInfo[group[1][i]](lang, options)); + + $button.attr('data-name', group[1][i]); + + $group.append($button); } - content += '</div>'; + $content.append($group); } - return tplPopover('note-air-popover', content); + return tplPopover('note-air-popover', $content.children()); }; - return '<div class="note-popover">' + - tplLinkPopover() + - tplImagePopover() + - (options.airMode ? tplAirPopover() : '') + - '</div>'; + var $notePopover = $('<div class="note-popover" />'); + + $notePopover.append(tplLinkPopover()); + $notePopover.append(tplImagePopover()); + + if (options.airMode) { + $notePopover.append(tplAirPopover()); + } + + return $notePopover; }; - this.tplButtonInfo = tplButtonInfo; // odoo change for overwrite - this.tplPopovers = tplPopovers; // odoo change for overwrite + this.tplButtonInfo = tplButtonInfo; // ODOO: allow access for override + this.tplPopovers = tplPopovers; // ODOO: allow access for override - var tplHandles = function () { + var tplHandles = function (options) { 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 class="' + + (options.disableResizeImage ? 'note-control-holder' : 'note-control-sizing') + + ' note-control-se"></div>' + + (options.disableResizeImage ? '' : '<div class="note-control-selection-info"></div>') + '</div>' + '</div>'; }; @@ -477,7 +554,6 @@ define([ { 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 } ]; @@ -489,7 +565,7 @@ define([ { kbd: '⌘ + Z', text: lang.history.undo }, { kbd: '⌘ + ⇧ + Z', text: lang.history.redo }, { kbd: '⌘ + ]', text: lang.paragraph.indent }, - { kbd: '⌘ + [', text: lang.paragraph.oudivent }, + { kbd: '⌘ + [', text: lang.paragraph.outdent }, { kbd: '⌘ + ENTER', text: lang.hr.insert } ]; @@ -568,27 +644,27 @@ define([ imageLimitation = '<small>' + lang.image.maximumFileSize + ' : ' + readableSize + '</small>'; } - var body = '<div class="form-group row-fluid note-group-select-from-files">' + + var body = '<div class="form-group row note-group-select-from-files">' + '<label>' + lang.image.selectFromFiles + '</label>' + - '<input class="note-image-input" type="file" name="files" accept="image/*" multiple="multiple" />' + + '<input class="note-image-input form-control" type="file" name="files" accept="image/*" multiple="multiple" />' + imageLimitation + '</div>' + - '<div class="form-group row-fluid">' + + '<div class="form-group row">' + '<label>' + lang.image.url + '</label>' + - '<input class="note-image-url form-control span12" type="text" />' + + '<input class="note-image-url form-control col-md-12" 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">' + + var body = '<div class="form-group row">' + '<label>' + lang.link.textToDisplay + '</label>' + - '<input class="note-link-text form-control span12" type="text" />' + + '<input class="note-link-text form-control col-md-12" type="text" />' + '</div>' + - '<div class="form-group row-fluid">' + + '<div class="form-group row">' + '<label>' + lang.link.url + '</label>' + - '<input class="note-link-url form-control span12" type="text" />' + + '<input class="note-link-url form-control col-md-12" type="text" value="http://" />' + '</div>' + (!options.disableLinkTarget ? '<div class="checkbox">' + @@ -606,9 +682,9 @@ define([ '<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>' + + '<a href="//summernote.org/" target="_blank">Summernote @VERSION</a> · ' + + '<a href="//github.com/summernote/summernote" target="_blank">Project</a> · ' + + '<a href="//github.com/summernote/summernote/issues" target="_blank">Issues</a>' + '</p>'; return tplDialog('note-help-dialog', '', body, ''); } @@ -696,7 +772,7 @@ define([ }); }; - this.createPalette = createPalette; // odoo change for overwrite + this.createPalette = createPalette; // ODOO: allow access for override /** * create summernote layout (air mode) @@ -709,24 +785,25 @@ define([ var keyMap = options.keyMap[agent.isMac ? 'mac' : 'pc']; var id = func.uniqueId(); - $holder.addClass('note-air-editor note-editable'); + $holder.addClass('note-air-editor note-editable panel-body'); $holder.attr({ - 'data-note-id': id, + 'data-note-id': id, // ODOO: we use [data-note-id="{id}"] instead of [id="{id}"] + // 'id': 'note-editor-' + id, 'contentEditable': true }); var body = document.body; // create Popover - var $popover = $(this.tplPopovers(langInfo, options)); // odoo change for overwrite + var $popover = $(this.tplPopovers(langInfo, options)); // ODOO: user (maybe) overrided method $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 + this.createPalette($popover, options); // ODOO: use (maybe) overrided method // create Handle - var $handle = $(tplHandles()); + var $handle = $(tplHandles(options)); $handle.addClass('note-air-layout'); $handle.attr('id', 'note-handle-' + id); $handle.appendTo(body); @@ -751,7 +828,7 @@ define([ var langInfo = options.langInfo; //01. create Editor - var $editor = $('<div class="note-editor"></div>'); + var $editor = $('<div class="note-editor panel panel-default" />'); if (options.width) { $editor.width(options.width); } @@ -761,70 +838,81 @@ define([ $('<div class="note-statusbar">' + (options.disableResizeEditor ? '' : tplStatusbar()) + '</div>').prependTo($editor); } - //03. create Editable + //03 editing area + var $editingArea = $('<div class="note-editing-area" />'); + //03. create editable var isContentEditable = !$holder.is(':disabled'); - var $editable = $('<div class="note-editable" contentEditable="' + isContentEditable + '"></div>') - .prependTo($editor); + var $editable = $('<div class="note-editable panel-body" contentEditable="' + isContentEditable + '"></div>').prependTo($editingArea); + if (options.height) { $editable.height(options.height); } if (options.direction) { $editable.attr('dir', options.direction); } - if (options.placeholder) { - $editable.attr('data-placeholder', options.placeholder); + var placeholder = $holder.attr('placeholder') || options.placeholder; + if (placeholder) { + $editable.attr('data-placeholder', placeholder); } - $editable.html(dom.html($holder)); + $editable.html(dom.html($holder) || dom.emptyPara); //031. create codable - $('<textarea class="note-codable"></textarea>').prependTo($editor); + $('<textarea class="note-codable"></textarea>').prependTo($editingArea); + + //04. create Popover + var $popover = $(this.tplPopovers(langInfo, options)).prependTo($editingArea); // ODOO: use (maybe) overrided method + this.createPalette($popover, options); // ODOO: use (maybe) overrided method + createTooltip($popover, keyMap); + + //05. handle(control selection, ...) + $(tplHandles(options)).prependTo($editingArea); - //04. create Toolbar - var toolbarHTML = ''; + $editingArea.prependTo($editor); + + //06. create Toolbar + var $toolbar = $('<div class="note-toolbar panel-heading" />'); 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">'; + var $group = $('<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); + + var $button = $(buttonInfo(langInfo, options)); + $button.attr('data-name', groupButtons[i]); // set button's alias, becuase to get button element from $toolbar + $group.append($button); } - toolbarHTML += '</div>'; + $toolbar.append($group); } - 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 + this.createPalette($toolbar, options); // ODOO: use (maybe) overrided method createTooltip($toolbar, keyMap, 'bottom'); + $toolbar.prependTo($editor); - //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 Dropzone + $('<div class="note-dropzone"><div class="note-dropzone-message"></div></div>').prependTo($editor); - //07. create Dialog - var $dialog = $(tplDialogs(langInfo, options)).prependTo($editor); + //08. create Dialog + var $dialogContainer = options.dialogsInBody ? $(document.body) : $editor; + var $dialog = $(tplDialogs(langInfo, options)).prependTo($dialogContainer); $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.hasNoteEditor = function ($holder) { + return this.noteEditorFromHolder($holder).length > 0; + }; + this.noteEditorFromHolder = function ($holder) { if ($holder.hasClass('note-air-editor')) { return $holder; @@ -842,10 +930,6 @@ define([ * @param {Object} options */ this.createLayout = function ($holder, options) { - if (this.noteEditorFromHolder($holder).length) { - return; - } - if (options.airMode) { this.createLayoutByAirMode($holder, options); } else { @@ -857,20 +941,18 @@ define([ * returns layoutInfo from holder * * @param {jQuery} $holder - placeholder - * @returns {Object} + * @return {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(); - } + if (!$editor.length) { + return; } - return layoutInfo; + + // connect $holder to $editor + $editor.data('holder', $holder); + + return dom.buildLayoutInfo($editor); }; /** @@ -884,31 +966,53 @@ define([ this.removeLayout = function ($holder, layoutInfo, options) { if (options.airMode) { $holder.removeClass('note-air-editor note-editable') - .removeAttr('contentEditable'); + .removeAttr('contentEditable'); // ODOO: removed id 'id contentEditable' - layoutInfo.popover.remove(); - layoutInfo.handle.remove(); - layoutInfo.dialog.remove(); + layoutInfo.popover().remove(); + layoutInfo.handle().remove(); + layoutInfo.dialog().remove(); } else { - $holder.html(layoutInfo.editable.html()); + $holder.html(layoutInfo.editable().html()); - layoutInfo.editor.remove(); + if (options.dialogsInBody) { + layoutInfo.dialog().remove(); + } + layoutInfo.editor().remove(); $holder.show(); } }; + /** + * + * @return {Object} + * @return {function(label, options=):string} return.button {@link #tplButton function to make text button} + * @return {function(iconClass, options=):string} return.iconButton {@link #tplIconButton function to make icon button} + * @return {function(className, title=, body=, footer=):string} return.dialog {@link #tplDialog function to make dialog} + */ this.getTemplate = function () { return { button: tplButton, iconButton: tplIconButton, - dialog: tplDialog + dialog: tplDialog, + dropdown: tplDropdown // ODOO: suggest upstream }; }; + /** + * add button information + * + * @param {String} name button name + * @param {Function} buttonInfo function to make button, reference to {@link #tplButton},{@link #tplIconButton} + */ this.addButtonInfo = function (name, buttonInfo) { tplButtonInfo[name] = buttonInfo; }; + /** + * + * @param {String} name + * @param {Function} dialogInfo function to make dialog, reference to {@link #tplDialog} + */ this.addDialogInfo = function (name, dialogInfo) { tplDialogInfo[name] = dialogInfo; }; |
