diff --git a/src/js/bs3/module/Button.js b/src/js/bs3/module/Button.js new file mode 100644 index 000000000..ad79bbf5b --- /dev/null +++ b/src/js/bs3/module/Button.js @@ -0,0 +1,586 @@ +define([ + 'jquery', + 'summernote/base/core/func', + 'summernote/base/core/list', + 'summernote/base/core/agent' +], function ($, func, list, agent) { + + var Button = function (summernote) { + var self = this; + var ui = $.summernote.ui; + + var $toolbar = summernote.layoutInfo.toolbar; + var options = summernote.options; + var lang = options.langInfo; + + + var invertedKeyMap = func.invertObject(options.keyMap[agent.isMac ? 'mac' : 'pc']); + + var representShortcut = this.representShortcut = function (editorMethod) { + var shortcut = invertedKeyMap[editorMethod]; + if (agent.isMac) { + shortcut = shortcut.replace('CMD', '⌘').replace('SHIFT', '⇧'); + } + + shortcut = shortcut.replace('BACKSLASH', '\\') + .replace('SLASH', '/') + .replace('LEFTBRACKET', '[') + .replace('RIGHTBRACKET', ']'); + + return ' (' + shortcut + ')'; + }; + + this.initialize = function () { + + this.makeToolbarButton(); + this.makeImagePopoverButton(); + this.makeLinkPopoverButton(); + }; + + this.makeToolbarButton = function () { + summernote.addButton('style', function () { + return ui.buttonGroup([ + ui.button({ + className: 'dropdown-toggle', + contents: ' ', + tooltip: lang.style.style, + data: { + toggle: 'dropdown' + } + }), + ui.dropdown({ + className: 'dropdown-style', + items: summernote.options.styleTags, + click: summernote.createInvokeHandler('editor.formatBlock') + }) + ]).render(); + }); + + summernote.addButton('bold', function () { + return ui.button({ + className: 'note-btn-bold', + contents: '', + tooltip: lang.font.bold + representShortcut('bold'), + click: summernote.createInvokeHandler('editor.bold') + }).render(); + }); + + summernote.addButton('italic', function () { + return ui.button({ + className: 'note-btn-italic', + contents: '', + tooltip: lang.font.italic + representShortcut('italic'), + click: summernote.createInvokeHandler('editor.italic') + }).render(); + }); + + summernote.addButton('underline', function () { + return ui.button({ + className: 'note-btn-underline', + contents: '', + tooltip: lang.font.underline + representShortcut('underline'), + click: summernote.createInvokeHandler('editor.underline') + }).render(); + }); + + summernote.addButton('clear', function () { + return ui.button({ + contents: '', + tooltip: lang.font.clear + representShortcut('removeFormat'), + click: summernote.createInvokeHandler('editor.removeFormat') + }).render(); + }); + + summernote.addButton('fontname', function () { + return ui.buttonGroup([ + ui.button({ + className: 'dropdown-toggle', + contents: ' ', + tooltip: lang.font.name, + data: { + toggle: 'dropdown' + } + }), + ui.dropdownCheck({ + className: 'dropdown-fontname', + items: options.fontNames.filter(function (name) { + return agent.isFontInstalled(name) || + list.contains(options.fontNamesIgnoreCheck, name); + }), + click: summernote.createInvokeHandler('editor.fontName') + }) + ]).render(); + }); + + summernote.addButton('fontsize', function () { + return ui.buttonGroup([ + ui.button({ + className: 'dropdown-toggle', + contents: ' ', + tooltip: lang.font.size, + data: { + toggle: 'dropdown' + } + }), + ui.dropdownCheck({ + className: 'dropdown-fontsize', + items: options.fontSizes, + click: summernote.createInvokeHandler('editor.fontSize') + }) + ]).render(); + }); + + summernote.addButton('color', function () { + return ui.buttonGroup({ + className: 'note-color', + children: [ + ui.button({ + className : 'note-current-color-button', + contents: '', + tooltip: lang.color.recent, + click: summernote.createInvokeHandler('editor.color'), + callback: function ($button) { + var $recentColor = $button.find('.note-recent-color'); + $recentColor.css({ + 'background-color': 'yellow' + }); + + $button.data('value', { + backColor: 'yellow' + }); + } + }), + ui.button({ + className: 'dropdown-toggle', + contents: '', + tooltip: lang.color.more, + data: { + toggle: 'dropdown' + } + }), + ui.dropdown({ + items: [ + '
  • ', + '
    ', + '
    ' + lang.color.background + '
    ', + '
    ' + lang.color.transparent + '
    ', + '
    ', + '
    ', + '
    ', + '
    ' + lang.color.foreground + '
    ', + '
    ' + lang.color.resetToDefault + '
    ', + '
    ', + '
    ', + '
  • ' + ].join(''), + callback: function ($dropdown) { + $dropdown.find('.note-holder').each(function () { + var $holder = $(this); + $holder.append(ui.palette({ + colors: options.colors, + eventName: $holder.data('event') + }).render()); + }); + }, + click: function (event) { + var $button = $(event.target); + var eventName = $button.data('event'); + var value = $button.data('value'); + + if (eventName && value) { + var key = eventName === 'backColor' ? 'background-color' : 'color'; + var $color = $button.closest('.note-color').find('.note-recent-color'); + var $currentButton = $button.closest('.note-color').find('.note-current-color-button'); + + var colorInfo = $currentButton.data('value'); + colorInfo[eventName] = value; + $color.css(key, value); + $currentButton.data('value', colorInfo); + + summernote.invoke('editor.' + eventName, value); + } + } + }) + ] + }).render(); + }); + + summernote.addButton('ol', function () { + return ui.button({ + contents: '', + tooltip: lang.lists.unordered + representShortcut('insertUnorderedList'), + click: summernote.createInvokeHandler('editor.insertUnorderedList') + }).render(); + }); + + summernote.addButton('ul', function () { + return ui.button({ + contents: '', + tooltip: lang.lists.ordered + representShortcut('insertOrderedList'), + click: summernote.createInvokeHandler('editor.insertOrderedList') + }).render(); + }); + + summernote.addButton('paragraph', function () { + return ui.buttonGroup([ + ui.button({ + className: 'dropdown-toggle', + contents: ' ', + tooltip: lang.paragraph.paragraph, + data: { + toggle: 'dropdown' + } + }), + ui.dropdown([ + ui.buttonGroup({ + className: 'note-align', + children: [ + ui.button({ + contents: '', + tooltip: lang.paragraph.left + representShortcut('justifyLeft'), + click: summernote.createInvokeHandler('editor.justifyLeft') + }), + ui.button({ + contents: '', + tooltip: lang.paragraph.center + representShortcut('justifyCenter'), + click: summernote.createInvokeHandler('editor.justifyCenter') + }), + ui.button({ + contents: '', + tooltip: lang.paragraph.right + representShortcut('justifyRight'), + click: summernote.createInvokeHandler('editor.justifyRight') + }), + ui.button({ + contents: '', + tooltip: lang.paragraph.justify + representShortcut('justifyFull'), + click: summernote.createInvokeHandler('editor.justifyFull') + }) + ] + }), + ui.buttonGroup({ + className: 'note-list', + children: [ + ui.button({ + contents: '', + tooltip: lang.paragraph.outdent + representShortcut('outdent'), + click: summernote.createInvokeHandler('editor.outdent') + }), + ui.button({ + contents: '', + tooltip: lang.paragraph.indent + representShortcut('indent'), + click: summernote.createInvokeHandler('editor.indent') + }) + ] + }) + ]) + ]).render(); + }); + + summernote.addButton('height', function () { + return ui.buttonGroup([ + ui.button({ + className: 'dropdown-toggle', + contents: ' ', + tooltip: lang.font.height, + data: { + toggle: 'dropdown' + } + }), + ui.dropdownCheck({ + items: options.lineHeights, + className: 'dropdown-line-height', + click: summernote.createInvokeHandler('editor.lineHeight') + }) + ]).render(); + }); + + summernote.addButton('table', function () { + return ui.buttonGroup([ + ui.button({ + className: 'dropdown-toggle', + contents: ' ', + tooltip: lang.table.table, + data: { + toggle: 'dropdown' + } + }), + ui.dropdown({ + className: 'note-table', + items: [ + '
    ', + '
    ', + '
    ', + '
    ', + '
    ', + '
    1 x 1
    ' + ].join('') + }) + ], { + callback: function ($node) { + var $catcher = $node.find('.note-dimension-picker-mousecatcher'); + $catcher.css({ + width: options.insertTableMaxSize.col + 'em', + height: options.insertTableMaxSize.row + 'em' + }).click(summernote.createInvokeHandler('editor.insertTable')) + .on('mousemove', self.tableMoveHandler); + } + }).render(); + }); + + summernote.addButton('link', function () { + return ui.button({ + contents: '', + tooltip: lang.link.link, + click: summernote.createInvokeHandler('linkDialog.show') + }).render(); + }); + + summernote.addButton('picture', function () { + return ui.button({ + contents: '', + tooltip: lang.image.image, + click: summernote.createInvokeHandler('imageDialog.show') + }).render(); + }); + + summernote.addButton('hr', function () { + return ui.button({ + contents: '', + tooltip: lang.hr.insert + representShortcut('insertHorizontalRule'), + click: summernote.createInvokeHandler('editor.insertHorizontalRule') + }).render(); + }); + + summernote.addButton('fullscreen', function () { + return ui.button({ + className: 'btn-fullscreen', + contents: '', + tooltip: lang.options.fullscreen, + click: summernote.createInvokeHandler('fullscreen.toggle') + }).render(); + }); + + summernote.addButton('codeview', function () { + return ui.button({ + className: 'btn-codeview', + contents: '', + tooltip: lang.options.codeview, + click: summernote.createInvokeHandler('codeview.toggle') + }).render(); + }); + + }; + + /** + * image : [ + ['imagesize', ['imageSize100', 'imageSize50', 'imageSize25']], + ['float', ['floatLeft', 'floatRight', 'floatNone' ]], + ['remove', ['removeMedia']] + ], + */ + this.makeImagePopoverButton = function () { + + // Image Size Buttons + summernote.addButton('imageSize100', function (summernote) { + return ui.button({ + contents: '100%', + tooltip: lang.image.resizeFull, + click: summernote.createInvokeHandler('editor.resize', '1') + }).render(); + }); + summernote.addButton('imageSize50', function (summernote) { + return ui.button({ + contents: '50%', + tooltip: lang.image.resizeHalf, + click: summernote.createInvokeHandler('editor.resize', '0.5') + }).render(); + }); + summernote.addButton('imageSize25', function (summernote) { + return ui.button({ + contents: '25%', + tooltip: lang.image.resizeQuarter, + click: summernote.createInvokeHandler('editor.resize', '0.25') + }).render(); + }); + + // Float Buttons + summernote.addButton('floatLeft', function (summernote) { + return ui.button({ + contents: '', + tooltip: lang.image.floatLeft, + click: summernote.createInvokeHandler('editor.floatMe', 'left') + }).render(); + }); + + summernote.addButton('floatRight', function (summernote) { + return ui.button({ + contents: '', + tooltip: lang.image.floatRight, + click: summernote.createInvokeHandler('editor.floatMe', 'right') + }).render(); + }); + + summernote.addButton('floatNone', function (summernote) { + return ui.button({ + contents: '', + tooltip: lang.image.floatNone, + click: summernote.createInvokeHandler('editor.floatMe', 'none') + }).render(); + }); + + // Remove Buttons + + summernote.addButton('removeMedia', function (summernote) { + return ui.button({ + contents: '', + tooltip: lang.image.remove, + click: summernote.createInvokeHandler('editor.removeMedia') + }).render(); + }); + }; + + this.makeLinkPopoverButton = function () { + summernote.addButton('linkDialogShow', function (summernote) { + return ui.button({ + contents: '', + tooltip: lang.link.edit, + click: summernote.createInvokeHandler('linkDialog.show') + }).render(); + }); + + summernote.addButton('unlink', function (summernote) { + return ui.button({ + contents: '', + tooltip: lang.link.unlink, + click: summernote.createInvokeHandler('editor.unlink') + }).render(); + }); + }; + + this.updateCurrentStyle = function () { + var styleInfo = summernote.invoke('editor.currentStyle'); + this.updateBtnStates({ + '.note-btn-bold': function () { + return styleInfo['font-bold'] === 'bold'; + }, + '.note-btn-italic': function () { + return styleInfo['font-italic'] === 'italic'; + }, + '.note-btn-underline': function () { + return styleInfo['font-underline'] === 'underline'; + } + }); + + if (styleInfo['font-family']) { + var fontNames = styleInfo['font-family'].split(',').map(function (name) { + return name.replace(/[\'\"]/g, '') + .replace(/\s+$/, '') + .replace(/^\s+/, ''); + }); + var fontName = list.find(fontNames, function (name) { + return agent.isFontInstalled(name) || + list.contains(options.fontNamesIgnoreCheck, name); + }); + + $toolbar.find('.dropdown-fontname li a').each(function () { + // always compare string to avoid creating another func. + var isChecked = ($(this).data('value') + '') === (fontName + ''); + this.className = isChecked ? 'checked' : ''; + }); + $toolbar.find('.note-current-fontname').text(fontName); + } + + if (styleInfo['font-size']) { + var fontSize = styleInfo['font-size']; + $toolbar.find('.dropdown-fontsize li a').each(function () { + // always compare with string to avoid creating another func. + var isChecked = ($(this).data('value') + '') === (fontSize + ''); + this.className = isChecked ? 'checked' : ''; + }); + $toolbar.find('.note-current-fontsize').text(fontSize); + } + + if (styleInfo['line-height']) { + var lineHeight = styleInfo['line-height']; + $toolbar.find('.dropdown-line-height li a').each(function () { + // always compare with string to avoid creating another func. + var isChecked = ($(this).data('value') + '') === (lineHeight + ''); + this.className = isChecked ? 'checked' : ''; + }); + } + }; + + this.updateBtnStates = function (infos) { + $.each(infos, function (selector, pred) { + ui.toggleBtnActive($toolbar.find(selector), pred()); + }); + }; + + this.tableMoveHandler = function (event) { + var PX_PER_EM = 18; + var $picker = $(event.target.parentNode); // target is mousecatcher + var $dimensionDisplay = $picker.next(); + var $catcher = $picker.find('.note-dimension-picker-mousecatcher'); + var $highlighted = $picker.find('.note-dimension-picker-highlighted'); + var $unhighlighted = $picker.find('.note-dimension-picker-unhighlighted'); + + var posOffset; + // HTML5 with jQuery - e.offsetX is undefined in Firefox + if (event.offsetX === undefined) { + var posCatcher = $(event.target).offset(); + posOffset = { + x: event.pageX - posCatcher.left, + y: event.pageY - posCatcher.top + }; + } else { + posOffset = { + x: event.offsetX, + y: event.offsetY + }; + } + + var dim = { + c: Math.ceil(posOffset.x / PX_PER_EM) || 1, + r: Math.ceil(posOffset.y / PX_PER_EM) || 1 + }; + + $highlighted.css({ width: dim.c + 'em', height: dim.r + 'em' }); + $catcher.data('value', dim.c + 'x' + dim.r); + + if (3 < dim.c && dim.c < options.insertTableMaxSize.col) { + $unhighlighted.css({ width: dim.c + 1 + 'em'}); + } + + if (3 < dim.r && dim.r < options.insertTableMaxSize.row) { + $unhighlighted.css({ height: dim.r + 1 + 'em'}); + } + + $dimensionDisplay.html(dim.c + ' x ' + dim.r); + }; + + this.updateFullscreen = function (isFullscreen) { + ui.toggleBtnActive($toolbar.find('.btn-fullscreen'), isFullscreen); + }; + + this.updateCodeview = function (isCodeview) { + ui.toggleBtnActive($toolbar.find('.btn-codeview'), isCodeview); + if (isCodeview) { + this.deactivate(); + } else { + this.activate(); + } + }; + + this.activate = function () { + var $btn = $toolbar.find('button').not('.btn-codeview'); + ui.toggleBtn($btn, true); + }; + + this.deactivate = function () { + var $btn = $toolbar.find('button').not('.btn-codeview'); + ui.toggleBtn($btn, false); + }; + }; + + return Button; +}); diff --git a/src/js/bs3/module/ImageDialog.js b/src/js/bs3/module/ImageDialog.js index 701fc1a84..e597eb7f2 100644 --- a/src/js/bs3/module/ImageDialog.js +++ b/src/js/bs3/module/ImageDialog.js @@ -26,7 +26,7 @@ define([ '' + imageLimitation + '
    ' + - '
    ' + + '
    ' + '' + '' + '
    '; diff --git a/src/js/bs3/module/ImagePopover.js b/src/js/bs3/module/ImagePopover.js index 1a8b2d314..cdaacd0c4 100644 --- a/src/js/bs3/module/ImagePopover.js +++ b/src/js/bs3/module/ImagePopover.js @@ -9,63 +9,24 @@ define([ var $note = summernote.layoutInfo.note; var $editingArea = summernote.layoutInfo.editingArea; - var lang = summernote.options.langInfo; + var options = summernote.options; var $popover = ui.popover({ - className: 'note-image-popover', - children: [ - ui.buttonGroup([ - ui.button({ - contents: '100%', - tooltip: lang.image.resizeFull, - click: summernote.createInvokeHandler('editor.resize', '1') - }), - ui.button({ - contents: '50%', - tooltip: lang.image.resizeHalf, - click: summernote.createInvokeHandler('editor.resize', '0.5') - }), - ui.button({ - contents: '25%', - tooltip: lang.image.resizeQuarter, - click: summernote.createInvokeHandler('editor.resize', '0.25') - }) - ]), - ui.buttonGroup([ - ui.button({ - contents: '', - tooltip: lang.image.floatLeft, - click: summernote.createInvokeHandler('editor.floatMe', 'left') - }), - ui.button({ - contents: '', - tooltip: lang.image.floatRight, - click: summernote.createInvokeHandler('editor.floatMe', 'right') - }), - ui.button({ - contents: '', - tooltip: lang.image.floatNone, - click: summernote.createInvokeHandler('editor.floatMe', 'none') - }) - ]), - ui.buttonGroup([ - ui.button({ - contents: '', - tooltip: lang.image.remove, - click: summernote.createInvokeHandler('editor.removeMedia') - }) - ]) - ] + className: 'note-image-popover' }).render(); $editingArea.append($popover); this.initialize = function () { + + summernote.generateButtons($popover.find('.popover-content'), options.popover.image); + $note.on('summernote.keyup summernote.mouseup summernote.change', function (customEvent, event) { self.update(event.target); }).on('summernote.scroll', function () { self.update(summernote.invoke('editor.restoreTarget')); }); + }; this.posFromPlaceholder = function (placeholder) { diff --git a/src/js/bs3/module/LinkPopover.js b/src/js/bs3/module/LinkPopover.js index 919eb94ab..d80e4e562 100644 --- a/src/js/bs3/module/LinkPopover.js +++ b/src/js/bs3/module/LinkPopover.js @@ -9,28 +9,18 @@ define([ var $note = summernote.layoutInfo.note; var $editingArea = summernote.layoutInfo.editingArea; - var lang = summernote.options.langInfo; + var options = summernote.options; var $popover = ui.popover({ - children: [ - ui.buttonGroup([ - ui.button({ - contents: '', - tooltip: lang.link.edit, - click: summernote.createInvokeHandler('linkDialog.show') - }), - ui.button({ - contents: '', - tooltip: lang.link.unlink, - click: summernote.createInvokeHandler('editor.unlink') - }) - ]) - ] + className: 'note-link-popover' }).render(); $editingArea.append($popover); this.initialize = function () { + + summernote.generateButtons($popover.find('.popover-content'), options.popover.link); + $note.on('summernote.keyup summernote.mouseup summernote.change', function (customEvent, event) { self.update(event.target); }).on('summernote.scroll', function () { diff --git a/src/js/bs3/module/Toolbar.js b/src/js/bs3/module/Toolbar.js index 050ed84b2..441b24fac 100644 --- a/src/js/bs3/module/Toolbar.js +++ b/src/js/bs3/module/Toolbar.js @@ -1,462 +1,29 @@ -define([ - 'jquery', - 'summernote/base/core/func', - 'summernote/base/core/list', - 'summernote/base/core/agent' -], function ($, func, list, agent) { +define([ ], function () { var Toolbar = function (summernote) { - var self = this; - var ui = $.summernote.ui; - var $note = summernote.layoutInfo.note; var $toolbar = summernote.layoutInfo.toolbar; var options = summernote.options; - var lang = options.langInfo; - - var invertedKeyMap = func.invertObject(options.keyMap[agent.isMac ? 'mac' : 'pc']); - - this.representShortcut = function (editorMethod) { - var shortcut = invertedKeyMap[editorMethod]; - if (agent.isMac) { - shortcut = shortcut.replace('CMD', '⌘').replace('SHIFT', '⇧'); - } - shortcut = shortcut.replace('BACKSLASH', '\\') - .replace('SLASH', '/') - .replace('LEFTBRACKET', '[') - .replace('RIGHTBRACKET', ']'); + this.initialize = function () { - return ' (' + shortcut + ')'; - }; + options.toolbar = options.toolbar || []; - this.initialize = function () { + if (!options.toolbar.length) { + $toolbar.hide(); + } else { + summernote.generateButtons($toolbar, options.toolbar); + } $note.on('summernote.keyup summernote.mouseup summernote.change', function () { - self.updateCurrentStyle(); + summernote.invoke('button.updateCurrentStyle'); }); - $toolbar.append(ui.buttonGroup([ - ui.button({ - className: 'dropdown-toggle', - contents: ' ', - tooltip: lang.style.style, - data: { - toggle: 'dropdown' - } - }), - ui.dropdown({ - className: 'dropdown-style', - items: options.styleTags, - click: summernote.createInvokeHandler('editor.formatBlock') - }) - ]).render()); - - $toolbar.append(ui.buttonGroup([ - ui.button({ - className: 'note-btn-bold', - contents: '', - tooltip: lang.font.bold + this.representShortcut('bold'), - click: summernote.createInvokeHandler('editor.bold') - }), - ui.button({ - className: 'note-btn-italic', - contents: '', - tooltip: lang.font.italic + this.representShortcut('italic'), - click: summernote.createInvokeHandler('editor.italic') - }), - ui.button({ - className: 'note-btn-underline', - contents: '', - tooltip: lang.font.underline + this.representShortcut('underline'), - click: summernote.createInvokeHandler('editor.underline') - }), - ui.button({ - contents: '', - tooltip: lang.font.clear + this.representShortcut('removeFormat'), - click: summernote.createInvokeHandler('editor.removeFormat') - }) - ]).render()); - - $toolbar.append(ui.buttonGroup([ - ui.button({ - className: 'dropdown-toggle', - contents: ' ', - tooltip: lang.font.name, - data: { - toggle: 'dropdown' - } - }), - ui.dropdownCheck({ - className: 'dropdown-fontname', - items: options.fontNames.filter(function (name) { - return agent.isFontInstalled(name) || - list.contains(options.fontNamesIgnoreCheck, name); - }), - click: summernote.createInvokeHandler('editor.fontName') - }) - ]).render()); - - $toolbar.append(ui.buttonGroup([ - ui.button({ - className: 'dropdown-toggle', - contents: ' ', - tooltip: lang.font.size, - data: { - toggle: 'dropdown' - } - }), - ui.dropdownCheck({ - className: 'dropdown-fontsize', - items: options.fontSizes, - click: summernote.createInvokeHandler('editor.fontSize') - }) - ]).render()); - - $toolbar.append(ui.buttonGroup({ - className: 'note-color', - children: [ - ui.button({ - contents: '', - tooltip: lang.color.recent, - click: summernote.createInvokeHandler('editor.color'), - callback: function ($button) { - var $recentColor = $button.find('.note-recent-color'); - $recentColor.css({ - 'background-color': 'yellow' - }).data('value', { - backColor: 'yellow' - }); - } - }), - ui.button({ - className: 'dropdown-toggle', - contents: '', - tooltip: lang.color.more, - data: { - toggle: 'dropdown' - } - }), - ui.dropdown({ - items: [ - '
  • ', - '
    ', - '
    ' + lang.color.background + '
    ', - '
    ' + lang.color.transparent + '
    ', - '
    ', - '
    ', - '
    ', - '
    ' + lang.color.foreground + '
    ', - '
    ' + lang.color.resetToDefault + '
    ', - '
    ', - '
    ', - '
  • ' - ].join(''), - callback: function ($dropdown) { - $dropdown.find('.note-holder').each(function () { - var $holder = $(this); - $holder.append(ui.palette({ - colors: options.colors, - eventName: $holder.data('event') - }).render()); - }); - }, - click: function (event) { - var $button = $(event.target); - var eventName = $button.data('event'); - var value = $button.data('value'); - - if (eventName && value) { - var key = eventName === 'backColor' ? 'background-color' : 'color'; - var $color = $button.closest('.note-color').find('.note-recent-color'); - - var colorInfo = $color.data('value'); - colorInfo[eventName] = value; - $color.data('value', colorInfo).css(key, value); - - summernote.invoke('editor.' + eventName, value); - } - } - }) - ] - }).render()); - - $toolbar.append(ui.buttonGroup({ - className: 'note-para', - children: [ - ui.button({ - contents: '', - tooltip: lang.lists.unordered + this.representShortcut('insertUnorderedList'), - click: summernote.createInvokeHandler('editor.insertUnorderedList') - }), - ui.button({ - contents: '', - tooltip: lang.lists.ordered + this.representShortcut('insertOrderedList'), - click: summernote.createInvokeHandler('editor.insertOrderedList') - }), - ui.buttonGroup([ - ui.button({ - className: 'dropdown-toggle', - contents: ' ', - tooltip: lang.paragraph.paragraph, - data: { - toggle: 'dropdown' - } - }), - ui.dropdown([ - ui.buttonGroup({ - className: 'note-align', - children: [ - ui.button({ - contents: '', - tooltip: lang.paragraph.left + this.representShortcut('justifyLeft'), - click: summernote.createInvokeHandler('editor.justifyLeft') - }), - ui.button({ - contents: '', - tooltip: lang.paragraph.center + this.representShortcut('justifyCenter'), - click: summernote.createInvokeHandler('editor.justifyCenter') - }), - ui.button({ - contents: '', - tooltip: lang.paragraph.right + this.representShortcut('justifyRight'), - click: summernote.createInvokeHandler('editor.justifyRight') - }), - ui.button({ - contents: '', - tooltip: lang.paragraph.justify + this.representShortcut('justifyFull'), - click: summernote.createInvokeHandler('editor.justifyFull') - }) - ] - }), - ui.buttonGroup({ - className: 'note-list', - children: [ - ui.button({ - contents: '', - tooltip: lang.paragraph.outdent + this.representShortcut('outdent'), - click: summernote.createInvokeHandler('editor.outdent') - }), - ui.button({ - contents: '', - tooltip: lang.paragraph.indent + this.representShortcut('indent'), - click: summernote.createInvokeHandler('editor.indent') - }) - ] - }) - ]) - ]) - ] - }).render()); - - $toolbar.append(ui.buttonGroup([ - ui.button({ - className: 'dropdown-toggle', - contents: ' ', - tooltip: lang.font.height, - data: { - toggle: 'dropdown' - } - }), - ui.dropdownCheck({ - items: options.lineHeights, - className: 'dropdown-line-height', - click: summernote.createInvokeHandler('editor.lineHeight') - }) - ]).render()); - - $toolbar.append(ui.buttonGroup([ - ui.button({ - className: 'dropdown-toggle', - contents: ' ', - tooltip: lang.table.table, - data: { - toggle: 'dropdown' - } - }), - ui.dropdown({ - className: 'note-table', - items: [ - '
    ', - '
    ', - '
    ', - '
    ', - '
    ', - '
    1 x 1
    ' - ].join('') - }) - ], { - callback: function ($node) { - var $catcher = $node.find('.note-dimension-picker-mousecatcher'); - $catcher.css({ - width: options.insertTableMaxSize.col + 'em', - height: options.insertTableMaxSize.row + 'em' - }).click(summernote.createInvokeHandler('editor.insertTable')) - .on('mousemove', self.tableMoveHandler); - } - }).render()); - - $toolbar.append(ui.buttonGroup([ - ui.button({ - contents: '', - tooltip: lang.link.link, - click: summernote.createInvokeHandler('linkDialog.show') - }), - ui.button({ - contents: '', - tooltip: lang.image.image, - click: summernote.createInvokeHandler('imageDialog.show') - }), - ui.button({ - contents: '', - tooltip: lang.hr.insert + this.representShortcut('insertHorizontalRule'), - click: summernote.createInvokeHandler('editor.insertHorizontalRule') - }) - ]).render()); - - $toolbar.append(ui.buttonGroup([ - ui.button({ - className: 'btn-fullscreen', - contents: '', - tooltip: lang.options.fullscreen, - click: summernote.createInvokeHandler('fullscreen.toggle') - }), - ui.button({ - className: 'btn-codeview', - contents: '', - tooltip: lang.options.codeview, - click: summernote.createInvokeHandler('codeview.toggle') - }) - ]).render()); - - this.updateCurrentStyle(); + summernote.invoke('button.updateCurrentStyle'); }; this.destroy = function () { $toolbar.children().remove(); }; - this.updateCurrentStyle = function () { - var styleInfo = summernote.invoke('editor.currentStyle'); - this.updateBtnStates({ - '.note-btn-bold': function () { - return styleInfo['font-bold'] === 'bold'; - }, - '.note-btn-italic': function () { - return styleInfo['font-italic'] === 'italic'; - }, - '.note-btn-underline': function () { - return styleInfo['font-underline'] === 'underline'; - } - }); - - if (styleInfo['font-family']) { - var fontNames = styleInfo['font-family'].split(',').map(function (name) { - return name.replace(/[\'\"]/g, '') - .replace(/\s+$/, '') - .replace(/^\s+/, ''); - }); - var fontName = list.find(fontNames, function (name) { - return agent.isFontInstalled(name) || - list.contains(options.fontNamesIgnoreCheck, name); - }); - - $toolbar.find('.dropdown-fontname li a').each(function () { - // always compare string to avoid creating another func. - var isChecked = ($(this).data('value') + '') === (fontName + ''); - this.className = isChecked ? 'checked' : ''; - }); - $toolbar.find('.note-current-fontname').text(fontName); - } - - if (styleInfo['font-size']) { - var fontSize = styleInfo['font-size']; - $toolbar.find('.dropdown-fontsize li a').each(function () { - // always compare with string to avoid creating another func. - var isChecked = ($(this).data('value') + '') === (fontSize + ''); - this.className = isChecked ? 'checked' : ''; - }); - $toolbar.find('.note-current-fontsize').text(fontSize); - } - - if (styleInfo['line-height']) { - var lineHeight = styleInfo['line-height']; - $toolbar.find('.dropdown-line-height li a').each(function () { - // always compare with string to avoid creating another func. - var isChecked = ($(this).data('value') + '') === (lineHeight + ''); - this.className = isChecked ? 'checked' : ''; - }); - } - }; - - this.updateBtnStates = function (infos) { - $.each(infos, function (selector, pred) { - ui.toggleBtnActive($toolbar.find(selector), pred()); - }); - }; - - this.tableMoveHandler = function (event) { - var PX_PER_EM = 18; - var $picker = $(event.target.parentNode); // target is mousecatcher - var $dimensionDisplay = $picker.next(); - var $catcher = $picker.find('.note-dimension-picker-mousecatcher'); - var $highlighted = $picker.find('.note-dimension-picker-highlighted'); - var $unhighlighted = $picker.find('.note-dimension-picker-unhighlighted'); - - var posOffset; - // HTML5 with jQuery - e.offsetX is undefined in Firefox - if (event.offsetX === undefined) { - var posCatcher = $(event.target).offset(); - posOffset = { - x: event.pageX - posCatcher.left, - y: event.pageY - posCatcher.top - }; - } else { - posOffset = { - x: event.offsetX, - y: event.offsetY - }; - } - - var dim = { - c: Math.ceil(posOffset.x / PX_PER_EM) || 1, - r: Math.ceil(posOffset.y / PX_PER_EM) || 1 - }; - - $highlighted.css({ width: dim.c + 'em', height: dim.r + 'em' }); - $catcher.data('value', dim.c + 'x' + dim.r); - - if (3 < dim.c && dim.c < options.insertTableMaxSize.col) { - $unhighlighted.css({ width: dim.c + 1 + 'em'}); - } - - if (3 < dim.r && dim.r < options.insertTableMaxSize.row) { - $unhighlighted.css({ height: dim.r + 1 + 'em'}); - } - - $dimensionDisplay.html(dim.c + ' x ' + dim.r); - }; - - this.updateFullscreen = function (isFullscreen) { - ui.toggleBtnActive($toolbar.find('.btn-fullscreen'), isFullscreen); - }; - - this.updateCodeview = function (isCodeview) { - ui.toggleBtnActive($toolbar.find('.btn-codeview'), isCodeview); - if (isCodeview) { - this.deactivate(); - } else { - this.activate(); - } - }; - - this.activate = function () { - var $btn = $toolbar.find('button').not('.btn-codeview'); - ui.toggleBtn($btn, true); - }; - - this.deactivate = function () { - var $btn = $toolbar.find('button').not('.btn-codeview'); - ui.toggleBtn($btn, false); - }; }; return Toolbar; diff --git a/src/js/bs3/settings.js b/src/js/bs3/settings.js index 6433a8d5d..b726cc985 100644 --- a/src/js/bs3/settings.js +++ b/src/js/bs3/settings.js @@ -7,6 +7,7 @@ define([ 'summernote/base/module/Statusbar', 'summernote/base/module/Fullscreen', 'summernote/base/module/Handle', + 'summernote/bs3/module/Button', 'summernote/bs3/module/Toolbar', 'summernote/bs3/module/LinkDialog', 'summernote/bs3/module/LinkPopover', @@ -15,7 +16,7 @@ define([ ], function ( ui, Editor, Clipboard, Dropzone, Codeview, Statusbar, Fullscreen, Handle, - Toolbar, LinkDialog, LinkPopover, ImageDialog, ImagePopover + Button, Toolbar, LinkDialog, LinkPopover, ImageDialog, ImagePopover ) { $.summernote = $.extend($.summernote, { @@ -137,15 +138,45 @@ define([ 'statusbar': Statusbar, 'fullscreen': Fullscreen, 'handle': Handle, + 'button' : Button, 'toolbar': Toolbar, 'linkDialog': LinkDialog, 'linkPopover': LinkPopover, 'imageDialog': ImageDialog, 'imagePopover': ImagePopover }, + + buttons : { }, lang: 'en-US', + // toolbar + toolbar: [ + ['style', ['style']], + ['font', ['bold', 'italic', 'underline', 'clear']], + // ['font', ['bold', 'italic', 'underline', 'strikethrough', 'superscript', 'subscript', 'clear']], + ['fontname', ['fontname']], + ['fontsize', ['fontsize']], + ['color', ['color']], + ['para', ['ul', 'ol', 'paragraph']], + ['height', ['height']], + ['table', ['table']], + ['insert', ['link', 'picture', 'hr']], + ['view', ['fullscreen', 'codeview']], + ['help', ['help']] + ], + + popover : { + image : [ + ['imagesize', ['imageSize100', 'imageSize50', 'imageSize25']], + ['float', ['floatLeft', 'floatRight', 'floatNone' ]], + ['remove', ['removeMedia']] + ], + link : [ + ['link', ['linkDialogShow', 'unlink']] + ] + }, + width: null, height: null, diff --git a/src/js/lite/settings.js b/src/js/lite/settings.js index 7deb9fcc4..982e55903 100644 --- a/src/js/lite/settings.js +++ b/src/js/lite/settings.js @@ -13,6 +13,8 @@ define([ 'toolbar': Toolbar }, + buttons : { }, + width: null, height: null, diff --git a/src/js/summernote.js b/src/js/summernote.js index afe76cda5..edc299957 100644 --- a/src/js/summernote.js +++ b/src/js/summernote.js @@ -15,12 +15,18 @@ define([ var ui = $.summernote.ui; this.modules = {}; + this.buttons = {}; this.layoutInfo = {}; this.options = options; this.initialize = function () { this.layoutInfo = ui.createLayout($note); + Object.keys(this.options.buttons).forEach(function (key) { + var button = self.options.buttons[key]; + self.addButton(key, button); + }); + Object.keys(this.options.modules).forEach(function (key) { var module = new self.options.modules[key](self); if (module.initialize) { @@ -78,10 +84,46 @@ define([ delete this.modules[key]; }; + this.addButton = function (key, createHandler) { + this.buttons[key] = createHandler; + }; + + this.removeButton = function (key) { + if (this.buttons[key].destroy) { + this.buttons[key].destroy(); + } + delete this.buttons[key]; + }; + + this.generateButtons = function ($container, buttonArray) { + buttonArray = buttonArray || []; + + for (var groupIndex = 0, groupLength = buttonArray.length; groupIndex < groupLength; groupIndex++) { + var group = buttonArray[groupIndex]; + var groupName = group[0]; + var buttonList = group[1]; + + var $groupElement = ui.buttonGroup().render(); + $groupElement.addClass('note-' + groupName); + + for (var buttonIndex = 0, buttonLength = buttonList.length; buttonIndex < buttonLength; buttonIndex++) { + var buttonName = buttonList[buttonIndex]; + var button = this.buttons[buttonName]; + + if (button) { + $groupElement.append(typeof button === 'function' ? button.call(this, this) : button); + } + + } + $container.append($groupElement); + } + + }; + this.createInvokeHandler = function (namespace, value) { return function (event) { event.preventDefault(); - self.invoke(namespace, value || $(event.target).data('value')); + self.invoke(namespace, value || $(event.target).data('value') || $(event.currentTarget).data('value')); }; };