(function () { const WANG_EDITOR_VERSION = '5.7.3'; const DEFAULT_HEIGHT = 500; const DEFAULT_TOOLBAR_KEYS = [ 'headerSelect', '|', 'bold', 'underline', 'italic', '|', 'bulletedList', 'numberedList', '|', 'justifyLeft', 'justifyCenter', 'justifyRight', '|', 'insertLink', 'uploadImage', 'uploadVideo', '|', 'undo', 'redo' ]; const DEFAULT_IMAGE_HOVERBAR_KEYS = [ 'imageWidth30', 'imageWidth50', 'imageWidth100', 'editorImageSizeMenu', 'editImage', 'deleteImage' ]; const DEFAULT_VIDEO_HOVERBAR_KEYS = [ 'enter', 'editVideoSize', 'editVideoSrc' ]; function tip(message, type) { message = message || '文件上传失败'; if (window.$ && $.msg && typeof $.msg.tips === 'function') return $.msg.tips(message); if (window.layer && typeof window.layer.msg === 'function') return window.layer.msg(message); return (type === 'error' ? console.error : console.log)(message); } function firstTextarea(ele) { const $ele = $(ele).eq(0); if ($ele.length < 1) throw new Error('Editor target not found: ' + ele); return $ele; } function toNumber(value, fallback) { value = parseFloat(value); return Number.isFinite(value) ? value : fallback; } function toInteger(value, fallback) { value = parseInt(value, 10); return Number.isFinite(value) ? value : fallback; } function getConfig($ele, option) { option = option || {}; const data = $ele.data() || {}; const upload = option.upload || {}; const path = String(upload.path || option.uploadPath || data.path || 'editor').replace(/\W/g, ''); return { mode: option.mode || data.editorMode || 'default', height: toInteger(option.height || data.editorHeight || data.height, DEFAULT_HEIGHT), placeholder: option.placeholder || data.placeholder || '请输入内容...', uploadPath: path || 'editor', uploadType: upload.uptype || upload.type || option.uptype || data.uptype || '', uploadSafe: (upload.safe || option.safe || data.safe) ? 1 : 0, uploadHide: (upload.hide || option.hide || data.hload) ? 1 : 0, uploadSize: toInteger(upload.size || option.size || data.size, 0), uploadQuality: toNumber(upload.quality || option.quality || data.quality, 1), imageMaxWidth: toInteger(upload.maxWidth || option.maxWidth || data.maxWidth, 0), imageMaxHeight: toInteger(upload.maxHeight || option.maxHeight || data.maxHeight, 0), imageCutWidth: toInteger(upload.cutWidth || option.cutWidth || data.cutWidth, 0), imageCutHeight: toInteger(upload.cutHeight || option.cutHeight || data.cutHeight, 0), toolbarKeys: option.toolbarKeys || data.toolbarKeys || DEFAULT_TOOLBAR_KEYS, hoverbarKeys: option.hoverbarKeys || { image: {menuKeys: option.imageHoverbarKeys || DEFAULT_IMAGE_HOVERBAR_KEYS}, video: {menuKeys: option.videoHoverbarKeys || DEFAULT_VIDEO_HOVERBAR_KEYS} }, excludeKeys: option.excludeKeys || ['fullScreen'] }; } function uploadBySystem(file, config, type, insertFn) { if (!window.SystemUploadAdapter) { const message = '后台上传模块尚未加载,请刷新页面后重试'; tip(message, 'error'); return Promise.reject(new Error(message)); } file.path = config.uploadPath; file.quality = config.uploadQuality; file.maxWidth = type === 'image' ? config.imageMaxWidth : 0; file.maxHeight = type === 'image' ? config.imageMaxHeight : 0; file.cutWidth = type === 'image' ? config.imageCutWidth : 0; file.cutHeight = type === 'image' ? config.imageCutHeight : 0; return new Promise(function (resolve, reject) { const $scope = $(''); const fail = function (event, data) { const message = (data && data.file && data.file.xstats) || '文件上传失败'; $scope.off('upload.error', fail); tip(message, 'error'); reject(new Error(message)); }; $scope.one('upload.error', fail); new window.SystemUploadAdapter({ elem: $scope, hide: config.uploadHide, safe: config.uploadSafe, type: config.uploadType, size: config.uploadSize }).upload([file], function (url, uploadedFile) { $scope.off('upload.error', fail); uploadedFile = uploadedFile || file; if (type === 'video') { insertFn(url, ''); } else { // 第三个参数是图片链接 href,后台编辑场景不自动加链接,避免点击图片跳转导致编辑丢失。 insertFn(url, uploadedFile.name || file.name || ''); } resolve(url); }); }); } function buildMenuConfig(config) { return { uploadImage: { async customUpload(file, insertFn) { return uploadBySystem(file, config, 'image', insertFn); } }, uploadVideo: { async customUpload(file, insertFn) { return uploadBySystem(file, config, 'video', insertFn); } } }; } window.createEditor = function (ele, option) { const $ele = firstTextarea(ele); const exists = $ele.data('editorInstance'); if (exists) return exists; if (!window.wangEditor || typeof window.wangEditor.createEditor !== 'function') { throw new Error('wangEditor is not loaded.'); } const config = getConfig($ele, option); const $layout = $('
'); $layout.css({border: '1px solid #ccc', zIndex: 1001}); $layout.find('.ta-editor-toolbar').css({borderBottom: '1px solid #ccc'}); $layout.find('.ta-editor-body').css({height: config.height + 'px'}); $ele.hide().attr('data-editor-source', 'wangEditor').data('editorLayout', $layout).after($layout); const editor = window.wangEditor.createEditor({ selector: $layout.find('.ta-editor-body').get(0), html: $ele.val() || '


', config: { placeholder: config.placeholder, hoverbarKeys: config.hoverbarKeys, MENU_CONF: buildMenuConfig(config), onCreated(editor) { editor.setHtml($ele.val() || '


'); }, onChange(editor) { $ele.val(editor.getHtml()).triggerHandler('editor.change', editor); } }, mode: config.mode }); window.wangEditor.createToolbar({ editor: editor, selector: $layout.find('.ta-editor-toolbar').get(0), config: {toolbarKeys: config.toolbarKeys, excludeKeys: config.excludeKeys}, mode: config.mode }); const destroy = editor.destroy.bind(editor); editor.getData = function () { return editor.getHtml(); }; editor.setData = function (html) { return editor.setHtml(html || '


'); }; editor.updateElement = function () { $ele.val(editor.getHtml()); return editor; }; editor.destroy = function () { $ele.removeData('editorInstance').removeData('editorLayout').removeAttr('data-editor-source').show(); $layout.remove(); return destroy(); }; $ele.data('editorInstance', editor).triggerHandler('editor.init', editor); return editor; }; window.createEditor.version = WANG_EDITOR_VERSION; })();