UNPKG

suneditor

Version:

Pure JavaScript based WYSIWYG web editor

723 lines (612 loc) 32 kB
/* * wysiwyg web editor * * suneditor.js * Copyright 2017 JiHong Lee. * MIT license. */ 'use strict'; import _defaultLang from '../lang/en'; import util from './util'; export default { /** * @description document create - call _createToolBar() * @param {element} element Textarea * @param {Object} options Options * @returns {Object} */ init: function (element, options) { if (typeof options !== 'object') options = {}; const doc = document; /** --- init options --- */ this._initOptions(element, options); // suneditor div const top_div = doc.createElement('DIV'); top_div.className = 'sun-editor'; if (element.id) top_div.id = 'suneditor_' + element.id; // relative div const relative = doc.createElement('DIV'); relative.className = 'se-container'; // toolbar const tool_bar = this._createToolBar(doc, options.buttonList, options.plugins, options.lang); const arrow = doc.createElement('DIV'); arrow.className = 'se-arrow'; // sticky toolbar dummy const sticky_dummy = doc.createElement('DIV'); sticky_dummy.className = 'se-toolbar-sticky-dummy'; // inner editor div const editor_div = doc.createElement('DIV'); editor_div.className = 'se-wrapper'; /** --- init elements and create bottom bar --- */ const initHTML = util.convertContentsForEditor(element.value); const initElements = this._initElements(options, top_div, tool_bar.element, arrow, initHTML); const bottomBar = initElements.bottomBar; const wysiwyg_div = initElements.wysiwygFrame; const placeholder_span = initElements.placeholder; let textarea = initElements.codeView; // resizing bar const resizing_bar = bottomBar.resizingBar; const navigation = bottomBar.navigation; const char_counter = bottomBar.charCounter; // loading box const loading_box = doc.createElement('DIV'); loading_box.className = 'se-loading-box sun-editor-common'; loading_box.innerHTML = '<div class="se-loading-effect"></div>'; // resize operation background const resize_back = doc.createElement('DIV'); resize_back.className = 'se-resizing-back'; /** append html */ editor_div.appendChild(wysiwyg_div); editor_div.appendChild(textarea); if (placeholder_span) editor_div.appendChild(placeholder_span); relative.appendChild(tool_bar.element); relative.appendChild(sticky_dummy); relative.appendChild(editor_div); relative.appendChild(resize_back); relative.appendChild(loading_box); if (resizing_bar) relative.appendChild(resizing_bar); top_div.appendChild(relative); textarea = this._checkCodeMirror(options, textarea); return { constructed: { _top: top_div, _relative: relative, _toolBar: tool_bar.element, _editorArea: editor_div, _wysiwygArea: wysiwyg_div, _codeArea: textarea, _placeholder: placeholder_span, _resizingBar: resizing_bar, _navigation: navigation, _charCounter: char_counter, _loading: loading_box, _resizeBack: resize_back, _stickyDummy: sticky_dummy, _arrow: arrow }, options: options, plugins: tool_bar.plugins, pluginCallButtons: tool_bar.pluginCallButtons }; }, /** * @description Check the CodeMirror option to apply the CodeMirror and return the CodeMirror element. * @param {Object} options options * @param {Element} textarea textarea element * @private */ _checkCodeMirror: function(options, textarea) { if (options.codeMirror) { const cmOptions = [{ mode: 'htmlmixed', htmlMode: true, lineNumbers: true, lineWrapping: true }, (options.codeMirror.options || {})].reduce(function (init, option) { Object.keys(option).forEach(function (key) { init[key] = option[key]; }); return init; }, {}); if (options.height === 'auto') { cmOptions.viewportMargin = Infinity; cmOptions.height = 'auto'; } const cm = options.codeMirror.src.fromTextArea(textarea, cmOptions); cm.display.wrapper.style.cssText = textarea.style.cssText; options.codeMirrorEditor = cm; textarea = cm.display.wrapper; textarea.className += ' se-wrapper-code-mirror'; } return textarea; }, /** * @description Add or reset options * @param {Object} mergeOptions New options property * @param {Object} context Context object of core * @param {Object} plugins Origin plugins * @param {Object} originOptions Origin options * @returns {Object} pluginCallButtons * @private */ _setOptions: function (mergeOptions, context, plugins, originOptions) { this._initOptions(context.element.originElement, mergeOptions); const el = context.element; const relative = el.relative; const editorArea = el.editorArea; const isNewToolbar = !!mergeOptions.buttonList || mergeOptions.mode !== originOptions.mode; const isNewPlugins = !!mergeOptions.plugins; const tool_bar = this._createToolBar(document, (isNewToolbar ? mergeOptions.buttonList : originOptions.buttonList), (isNewPlugins ? mergeOptions.plugins : plugins), mergeOptions.lang); const arrow = document.createElement('DIV'); arrow.className = 'se-arrow'; if (isNewToolbar) { relative.insertBefore(tool_bar.element, el.toolbar); relative.removeChild(el.toolbar); el.toolbar = tool_bar.element; el._arrow = arrow; } const initElements = this._initElements(mergeOptions, el.topArea, (isNewToolbar ? tool_bar.element : el.toolbar), arrow, el.wysiwyg.innerHTML); const bottomBar = initElements.bottomBar; const wysiwygFrame = initElements.wysiwygFrame; const placeholder_span = initElements.placeholder; let code = initElements.codeView; if (el.resizingBar) relative.removeChild(el.resizingBar); if (bottomBar.resizingBar) relative.appendChild(bottomBar.resizingBar); el.resizingBar = bottomBar.resizingBar; el.navigation = bottomBar.navigation; el.charCounter = bottomBar.charCounter; editorArea.removeChild(el.wysiwygFrame); editorArea.removeChild(el.code); editorArea.appendChild(wysiwygFrame); editorArea.appendChild(code); if (el.placeholder) editorArea.removeChild(el.placeholder); if (placeholder_span) editorArea.appendChild(placeholder_span); code = this._checkCodeMirror(mergeOptions, code); el.wysiwygFrame = wysiwygFrame; el.code = code; el.placeholder = placeholder_span; return { callButtons: isNewToolbar ? tool_bar.pluginCallButtons : null, plugins: isNewToolbar || isNewPlugins ? tool_bar.plugins : null }; }, /** * @description Initialize property of suneditor elements * @param {Object} options Options * @param {Element} topDiv Suneditor top div * @param {Element} toolBar Tool bar * @param {Element} toolBarArrow Tool bar arrow (balloon editor) * @param {Element} initValue Code view textarea * @returns {Object} Bottom bar elements (resizingBar, navigation, charCounter) * @private */ _initElements: function (options, topDiv, toolBar, toolBarArrow, initHTML) { /** top div */ topDiv.style.width = options.width; topDiv.style.minWidth = options.minWidth; topDiv.style.maxWidth = options.maxWidth; topDiv.style.display = options.display; if (typeof options.position === 'string') topDiv.style.position = options.position; /** toolbar */ if (/inline/i.test(options.mode)) { toolBar.className += ' se-toolbar-inline'; toolBar.style.width = options.toolbarWidth; } else if (/balloon/i.test(options.mode)) { toolBar.className += ' se-toolbar-balloon'; toolBar.style.width = options.toolbarWidth; toolBar.appendChild(toolBarArrow); } /** editor */ // wysiwyg div or iframe const wysiwygDiv = document.createElement(!options.iframe ? 'DIV' : 'IFRAME'); wysiwygDiv.className = 'se-wrapper-inner se-wrapper-wysiwyg'; wysiwygDiv.style.display = 'block'; if (!options.iframe) { wysiwygDiv.setAttribute('contenteditable', true); wysiwygDiv.setAttribute('scrolling', 'auto'); wysiwygDiv.className += ' sun-editor-editable'; wysiwygDiv.innerHTML = initHTML; } else { const cssTags = (function () { const linkNames = options.iframeCSSFileName; let tagString = ''; for (let f = 0, len = linkNames.length, path; f < len; f++) { path = []; if (/^https?:\/\//.test(linkNames[f])) { path.push(linkNames[f]); } else { const CSSFileName = new RegExp('(^|.*[\\/])' + linkNames[f] + '(\\..+)?\.css(?:\\?.*|;.*)?$', 'i'); for (let c = document.getElementsByTagName('link'), i = 0, len = c.length, styleTag; i < len; i++) { styleTag = c[i].href.match(CSSFileName); if (styleTag) path.push(styleTag[0]); } } if (!path || path.length === 0) throw '[SUNEDITOR.constructor.iframe.fail] The suneditor CSS files installation path could not be automatically detected. Please set the option property "iframeCSSFileName" before creating editor instances.'; for (let i = 0, len = path.length; i < len; i++) { tagString += '<link href="' + path[i] + '" rel="stylesheet">'; } } return tagString; })() + (options.height === 'auto' ? '<style>\n/** Iframe height auto */\nbody{height: min-content; overflow: hidden;}\n</style>' : ''); wysiwygDiv.allowFullscreen = true; wysiwygDiv.frameBorder = 0; wysiwygDiv.addEventListener('load', function () { this.setAttribute('scrolling', 'auto'); this.contentDocument.head.innerHTML = '' + '<meta charset="utf-8" />' + '<meta name="viewport" content="width=device-width, initial-scale=1">' + '<title></title>' + cssTags; this.contentDocument.body.className = 'sun-editor-editable'; this.contentDocument.body.setAttribute('contenteditable', true); this.contentDocument.body.innerHTML = initHTML; }); } wysiwygDiv.style.height = options.height; wysiwygDiv.style.minHeight = options.minHeight; wysiwygDiv.style.maxHeight = options.maxHeight; // textarea for code view const textarea = document.createElement('TEXTAREA'); textarea.className = 'se-wrapper-inner se-wrapper-code'; textarea.style.display = 'none'; textarea.style.height = options.height; textarea.style.minHeight = options.minHeight; textarea.style.maxHeight = options.maxHeight; if (options.height === 'auto') textarea.style.overflow = 'hidden'; /** resize bar */ let resizingBar = null; let navigation = null; let charCounter = null; if (options.resizingBar) { resizingBar = document.createElement('DIV'); resizingBar.className = 'se-resizing-bar sun-editor-common'; /** navigation */ navigation = document.createElement('DIV'); navigation.className = 'se-navigation sun-editor-common'; resizingBar.appendChild(navigation); /** char counter */ if (options.charCounter) { const charWrapper = document.createElement('DIV'); charWrapper.className = 'se-char-counter-wrapper'; charCounter = document.createElement('SPAN'); charCounter.className = 'se-char-counter'; charCounter.textContent = '0'; charWrapper.appendChild(charCounter); if (options.maxCharCount > 0) { const char_max = document.createElement('SPAN'); char_max.textContent = ' / ' + options.maxCharCount; charWrapper.appendChild(char_max); } resizingBar.appendChild(charWrapper); } } let placeholder = null; if (options.placeholder) { placeholder = document.createElement('SPAN'); placeholder.className = 'se-placeholder'; placeholder.innerText = options.placeholder; } return { bottomBar: { resizingBar: resizingBar, navigation: navigation, charCounter: charCounter }, wysiwygFrame: wysiwygDiv, codeView: textarea, placeholder: placeholder }; }, /** * @description Initialize options * @param {Element} element Options object * @param {Object} options Options object * @private */ _initOptions: function (element, options) { /** user options */ options.lang = options.lang || _defaultLang; /** Layout */ options.mode = options.mode || 'classic'; // classic, inline, balloon options.toolbarWidth = options.toolbarWidth ? (util.isNumber(options.toolbarWidth) ? options.toolbarWidth + 'px' : options.toolbarWidth) : 'auto'; options.stickyToolbar = /balloon/i.test(options.mode) ? -1 : options.stickyToolbar === undefined ? 0 : (/^\d+/.test(options.stickyToolbar) ? util.getNumber(options.stickyToolbar, 0) : -1); // options.fullPage = options.fullPage; options.iframe = options.fullPage || options.iframe; options.iframeCSSFileName = options.iframe ? typeof options.iframeCSSFileName === 'string' ? [options.iframeCSSFileName] : (options.iframeCSSFileName || ['suneditor']) : null; options.codeMirror = options.codeMirror ? options.codeMirror.src ? options.codeMirror : {src: options.codeMirror} : null; /** Display */ // options.position = options.position; options.display = options.display || (element.style.display === 'none' || !element.style.display ? 'block' : element.style.display); options.popupDisplay = options.popupDisplay || 'full'; /** Bottom resizing bar */ options.resizingBar = options.resizingBar === undefined ? (/inline|balloon/i.test(options.mode) ? false : true) : options.resizingBar; options.showPathLabel = !options.resizingBar ? false : typeof options.showPathLabel === 'boolean' ? options.showPathLabel : true; options.charCounter = options.maxCharCount > 0 ? true : typeof options.charCounter === 'boolean' ? options.charCounter : false; options.maxCharCount = util.isNumber(options.maxCharCount) && options.maxCharCount > -1 ? options.maxCharCount * 1 : null; /** Width size */ options.width = options.width ? (util.isNumber(options.width) ? options.width + 'px' : options.width) : (element.clientWidth ? element.clientWidth + 'px' : '100%'); options.minWidth = (util.isNumber(options.minWidth) ? options.minWidth + 'px' : options.minWidth) || ''; options.maxWidth = (util.isNumber(options.maxWidth) ? options.maxWidth + 'px' : options.maxWidth) || ''; /** Height size */ options.height = options.height ? (util.isNumber(options.height) ? options.height + 'px' : options.height) : (element.clientHeight ? element.clientHeight + 'px' : 'auto'); options.minHeight = (util.isNumber(options.minHeight) ? options.minHeight + 'px' : options.minHeight) || ''; options.maxHeight = (util.isNumber(options.maxHeight) ? options.maxHeight + 'px' : options.maxHeight) || ''; /** Defining menu items */ options.font = !options.font ? null : options.font; options.fontSize = !options.fontSize ? null : options.fontSize; options.formats = !options.formats ? null : options.formats; options.colorList = !options.colorList ? null : options.colorList; options.lineHeights = !options.lineHeights ? null : options.lineHeights; options.paragraphStyles = !options.paragraphStyles ? null : options.paragraphStyles; options.textStyles = !options.textStyles ? null : options.textStyles; options.fontSizeUnit = typeof options.fontSizeUnit === 'string' ? (options.fontSizeUnit.trim() || 'px') : 'px'; /** Image */ options.imageResizing = options.imageResizing === undefined ? true : options.imageResizing; options.imageHeightShow = options.imageHeightShow === undefined ? true : !!options.imageHeightShow; options.imageWidth = !options.imageWidth ? 'auto' : util.isNumber(options.imageWidth) ? options.imageWidth + 'px' : options.imageWidth; options.imageSizeOnlyPercentage = !!options.imageSizeOnlyPercentage; options._imageSizeUnit = options.imageSizeOnlyPercentage ? '%' : 'px'; options.imageRotation = options.imageRotation !== undefined ? options.imageRotation : !(options.imageSizeOnlyPercentage || !options.imageHeightShow); options.imageFileInput = options.imageFileInput === undefined ? true : options.imageFileInput; options.imageUrlInput = (options.imageUrlInput === undefined || !options.imageFileInput) ? true : options.imageUrlInput; options.imageUploadHeader = options.imageUploadHeader || null; options.imageUploadUrl = options.imageUploadUrl || null; options.imageUploadSizeLimit = /\d+/.test(options.imageUploadSizeLimit) ? util.getNumber(options.imageUploadSizeLimit, 0) : null; /** Video */ options.videoResizing = options.videoResizing === undefined ? true : options.videoResizing; options.videoHeightShow = options.videoHeightShow === undefined ? true : !!options.videoHeightShow; options.videoRatioShow = options.videoRatioShow === undefined ? true : !!options.videoRatioShow; options.videoWidth = !options.videoWidth || !util.getNumber(options.videoWidth) ? '100%' : util.isNumber(options.videoWidth) ? options.videoWidth + 'px' : options.videoWidth; options.videoSizeOnlyPercentage = !!options.videoSizeOnlyPercentage; options._videoSizeUnit = options.videoSizeOnlyPercentage ? '%' : 'px'; options.videoRotation = options.videoRotation !== undefined ? options.videoRotation : !(options.videoSizeOnlyPercentage || !options.videoHeightShow); options.videoRatio = util.getNumber(options.videoRatio, 4) || 0.5625; // 16:9 options.videoRatioList = !options.videoRatioList ? null : options.videoRatioList; options.youtubeQuery = (options.youtubeQuery || '').replace('?', ''); /** Defining save button */ options.callBackSave = !options.callBackSave ? null : options.callBackSave; /** Templates Array */ options.templates = !options.templates ? null : options.templates; /** ETC */ options.placeholder = typeof options.placeholder === 'string' ? options.placeholder : null; /** Buttons */ options.buttonList = options.buttonList || [ ['undo', 'redo'], ['bold', 'underline', 'italic', 'strike', 'subscript', 'superscript'], ['removeFormat'], ['outdent', 'indent'], ['fullScreen', 'showBlocks', 'codeView'], ['preview', 'print'] ]; }, /** * @description Suneditor's Default button list * @private */ _defaultButtons: function (lang) { return { /** command */ bold: ['_se_command_bold', lang.toolbar.bold + ' (CTRL+B)', 'STRONG', '', '<i class="se-icon-bold"></i>' ], underline: ['_se_command_underline', lang.toolbar.underline + ' (CTRL+U)', 'INS', '', '<i class="se-icon-underline"></i>' ], italic: ['_se_command_italic', lang.toolbar.italic + ' (CTRL+I)', 'EM', '', '<i class="se-icon-italic"></i>' ], strike: ['_se_command_strike', lang.toolbar.strike + ' (CTRL+SHIFT+S)', 'DEL', '', '<i class="se-icon-strokethrough"></i>' ], subscript: ['_se_command_subscript', lang.toolbar.subscript, 'SUB', '', '<i class="se-icon-subscript"></i>' ], superscript: ['_se_command_superscript', lang.toolbar.superscript, 'SUP', '', '<i class="se-icon-superscript"></i>' ], removeFormat: ['', lang.toolbar.removeFormat, 'removeFormat', '', '<i class="se-icon-erase"></i>' ], indent: ['', lang.toolbar.indent + ' (CTRL+])', 'indent', '', '<i class="se-icon-indent-right"></i>' ], outdent: ['_se_command_outdent', lang.toolbar.outdent + ' (CTRL+[)', 'outdent', '', '<i class="se-icon-indent-left"></i>', true ], fullScreen: ['code-view-enabled', lang.toolbar.fullScreen, 'fullScreen', '', '<i class="se-icon-expansion"></i>' ], showBlocks: ['', lang.toolbar.showBlocks, 'showBlocks', '', '<i class="se-icon-showBlocks"></i>' ], codeView: ['code-view-enabled', lang.toolbar.codeView, 'codeView', '', '<i class="se-icon-code-view"></i>' ], undo: ['_se_command_undo', lang.toolbar.undo + ' (CTRL+Z)', 'undo', '', '<i class="se-icon-undo"></i>', true ], redo: ['_se_command_redo', lang.toolbar.redo + ' (CTRL+Y / CTRL+SHIFT+Z)', 'redo', '', '<i class="se-icon-redo"></i>', true ], preview: ['', lang.toolbar.preview, 'preview', '', '<i class="se-icon-preview"></i>' ], print: ['', lang.toolbar.print, 'print', '', '<i class="se-icon-print"></i>' ], save: ['_se_command_save', lang.toolbar.save, 'save', '', '<i class="se-icon-save"></i>', true ], /** plugins - submenu */ font: ['se-btn-select se-btn-tool-font _se_command_font_family', lang.toolbar.font, 'font', 'submenu', '<span class="txt">' + lang.toolbar.font + '</span><i class="se-icon-arrow-down"></i>' ], formatBlock: ['se-btn-select se-btn-tool-format', lang.toolbar.formats, 'formatBlock', 'submenu', '<span class="txt _se_command_format">' + lang.toolbar.formats + '</span><i class="se-icon-arrow-down"></i>' ], fontSize: ['se-btn-select se-btn-tool-size', lang.toolbar.fontSize, 'fontSize', 'submenu', '<span class="txt _se_command_font_size">' + lang.toolbar.fontSize + '</span><i class="se-icon-arrow-down"></i>' ], fontColor: ['', lang.toolbar.fontColor, 'fontColor', 'submenu', '<i class="se-icon-fontColor"></i>' ], hiliteColor: ['', lang.toolbar.hiliteColor, 'hiliteColor', 'submenu', '<i class="se-icon-hiliteColor"></i>' ], align: ['se-btn-align', lang.toolbar.align, 'align', 'submenu', '<i class="se-icon-align-left _se_command_align"></i>' ], list: ['_se_command_list', lang.toolbar.list, 'list', 'submenu', '<i class="se-icon-list-number"></i>' ], horizontalRule: ['btn_line', lang.toolbar.horizontalRule, 'horizontalRule', 'submenu', '<i class="se-icon-hr"></i>' ], table: ['', lang.toolbar.table, 'table', 'submenu', '<i class="se-icon-grid"></i>' ], lineHeight: ['', lang.toolbar.lineHeight, 'lineHeight', 'submenu', '<i class="se-icon-line-height"></i>' ], template: ['', lang.toolbar.template, 'template', 'submenu', '<i class="se-icon-template"></i>' ], paragraphStyle: ['', lang.toolbar.paragraphStyle, 'paragraphStyle', 'submenu', '<i class="se-icon-paragraph-style"></i>' ], textStyle: ['', lang.toolbar.textStyle, 'textStyle', 'submenu', '<i class="se-icon-text-style"></i>' ], /** plugins - dialog */ link: ['', lang.toolbar.link, 'link', 'dialog', '<i class="se-icon-link"></i>' ], image: ['', lang.toolbar.image, 'image', 'dialog', '<i class="se-icon-image"></i>' ], video: ['', lang.toolbar.video, 'video', 'dialog', '<i class="se-icon-video"></i>' ] }; }, /** * @description Create a group div containing each module * @returns {Element} * @private */ _createModuleGroup: function (oneModule) { const oDiv = util.createElement('DIV'); oDiv.className = 'se-btn-module' + (oneModule ? '' : ' se-btn-module-border'); const oUl = util.createElement('UL'); oUl.className = 'se-menu-list'; oDiv.appendChild(oUl); return { 'div': oDiv, 'ul': oUl }; }, /** * @description Create a button element * @param {string} buttonClass className in button * @param {string} title Title in button * @param {string} dataCommand The data-command property of the button * @param {string} dataDisplay The data-display property of the button ('dialog', 'submenu') * @param {string} innerHTML Html in button * @param {string} _disabled Button disabled * @returns {Element} * @private */ _createButton: function (buttonClass, title, dataCommand, dataDisplay, innerHTML, _disabled) { const oLi = util.createElement('LI'); const oButton = util.createElement('BUTTON'); oButton.setAttribute('type', 'button'); oButton.setAttribute('class', 'se-btn' + (buttonClass ? ' ' + buttonClass : '') + ' se-tooltip'); oButton.setAttribute('data-command', dataCommand); oButton.setAttribute('data-display', dataDisplay); innerHTML += '<span class="se-tooltip-inner"><span class="se-tooltip-text">' + title + '</span></span>'; if (_disabled) oButton.setAttribute('disabled', true); oButton.innerHTML = innerHTML; oLi.appendChild(oButton); return { 'li': oLi, 'button': oButton }; }, /** * @description Create editor HTML * @param {Array} doc document object * @param {Array} buttonList option.buttonList * @param {Array} lang option.lang * @private */ _createToolBar: function (doc, buttonList, _plugins, lang) { const separator_vertical = doc.createElement('DIV'); separator_vertical.className = 'se-toolbar-separator-vertical'; const tool_bar = doc.createElement('DIV'); tool_bar.className = 'se-toolbar sun-editor-common'; /** create button list */ const defaultButtonList = this._defaultButtons(lang); const pluginCallButtons = {}; const plugins = {}; if (_plugins) { const pluginsValues = _plugins.length ? _plugins : Object.keys(_plugins).map(function(name) { return _plugins[name]; }); for (let i = 0, len = pluginsValues.length, p; i < len; i++) { p = pluginsValues[i].default || pluginsValues[i]; plugins[p.name] = p; } } let module = null; let button = null; let moduleElement = null; let buttonElement = null; let pluginName = ''; let vertical = false; const oneModule = buttonList.length === 1; for (let i = 0; i < buttonList.length; i++) { const buttonGroup = buttonList[i]; moduleElement = this._createModuleGroup(oneModule); /** button object */ if (typeof buttonGroup === 'object') { for (let j = 0; j < buttonGroup.length; j++) { button = buttonGroup[j]; if (typeof button === 'object') { if (typeof button.add === 'function') { pluginName = button.name; module = defaultButtonList[pluginName]; plugins[pluginName] = button; } else { pluginName = button.name; module = [button.buttonClass, button.title, button.dataCommand, button.dataDisplay, button.innerHTML]; } } else { module = defaultButtonList[button]; pluginName = button; } buttonElement = this._createButton(module[0], module[1], module[2], module[3], module[4], module[5]); moduleElement.ul.appendChild(buttonElement.li); if (plugins[pluginName]) { pluginCallButtons[pluginName] = buttonElement.button; } } if (vertical) tool_bar.appendChild(separator_vertical.cloneNode(false)); tool_bar.appendChild(moduleElement.div); vertical = true; } /** line break */ else if (/^\/$/.test(buttonGroup)) { const enterDiv = doc.createElement('DIV'); enterDiv.className = 'se-btn-module-enter'; tool_bar.appendChild(enterDiv); vertical = false; } } const tool_cover = doc.createElement('DIV'); tool_cover.className = 'se-toolbar-cover'; tool_bar.appendChild(tool_cover); return { 'element': tool_bar, 'plugins': plugins, 'pluginCallButtons': pluginCallButtons }; } };