vue 项目中使用wangEditor上传图片视频到oos

废话:

最近在做商城后台管理的项目, 商品详情需要使用富文本编辑器, 需要上传图片和上传视频的功能.

关于富文本:

富文本选择: wangEditor , froalaEditor 我个人是喜欢froala的,图片和视频都是可以调整大小还可以粘贴图片,无奈需要收费, 公司也不会同意破解, 客户估计也不会出这个钱, 所以没办法只能使用wangEditor.

效果预览

vue 项目中使用wangEditor上传图片视频到oos_第1张图片

结构

我是把wangeditor 封装成一个组件,这些都不用细说了. oos 上传服务 也都封装好的.
主要是要修改wangeditor 的源码,达到oos上传的目的

(function (global, factory) {
	typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
	typeof define === 'function' && define.amd ? define(factory) :
	(global.wangEditor = factory());
}(this, (function () { 'use strict';

/*
    poly-fill
*/

var polyfill = function () {

    // Object.assign
    if (typeof Object.assign != 'function') {
        Object.assign = function (target, varArgs) {
            // .length of function is 2
            if (target == null) {
                // TypeError if undefined or null
                throw new TypeError('Cannot convert undefined or null to object');
            }

            var to = Object(target);

            for (var index = 1; index < arguments.length; index++) {
                var nextSource = arguments[index];

                if (nextSource != null) {
                    // Skip over if undefined or null
                    for (var nextKey in nextSource) {
                        // Avoid bugs when hasOwnProperty is shadowed
                        if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
                            to[nextKey] = nextSource[nextKey];
                        }
                    }
                }
            }
            return to;
        };
    }

    // IE 中兼容 Element.prototype.matches
    if (!Element.prototype.matches) {
        Element.prototype.matches = Element.prototype.matchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector || Element.prototype.oMatchesSelector || Element.prototype.webkitMatchesSelector || function (s) {
            var matches = (this.document || this.ownerDocument).querySelectorAll(s),
                i = matches.length;
            while (--i >= 0 && matches.item(i) !== this) {}
            return i > -1;
        };
    }
};

/*
    DOM 操作 API
*/

// 根据 html 代码片段创建 dom 对象
function createElemByHTML(html) {
    var div = void 0;
    div = document.createElement('div');
    div.innerHTML = html;
    return div.children;
}

// 是否是 DOM List
function isDOMList(selector) {
    if (!selector) {
        return false;
    }
    if (selector instanceof HTMLCollection || selector instanceof NodeList) {
        return true;
    }
    return false;
}

// 封装 document.querySelectorAll
function querySelectorAll(selector) {
    var result = document.querySelectorAll(selector);
    if (isDOMList(result)) {
        return result;
    } else {
        return [result];
    }
}

// 记录所有的事件绑定
var eventList = [];

// 创建构造函数
function DomElement(selector) {
    if (!selector) {
        return;
    }

    // selector 本来就是 DomElement 对象,直接返回
    if (selector instanceof DomElement) {
        return selector;
    }

    this.selector = selector;
    var nodeType = selector.nodeType;

    // 根据 selector 得出的结果(如 DOM,DOM List)
    var selectorResult = [];
    if (nodeType === 9) {
        // document 节点
        selectorResult = [selector];
    } else if (nodeType === 1) {
        // 单个 DOM 节点
        selectorResult = [selector];
    } else if (isDOMList(selector) || selector instanceof Array) {
        // DOM List 或者数组
        selectorResult = selector;
    } else if (typeof selector === 'string') {
        // 字符串
        selector = selector.replace('/\n/mg', '').trim();
        if (selector.indexOf('<') === 0) {
            // 如 
selectorResult = createElemByHTML(selector); } else { // 如 #id .class selectorResult = querySelectorAll(selector); } } var length = selectorResult.length; if (!length) { // 空数组 return this; } // 加入 DOM 节点 var i = void 0; for (i = 0; i < length; i++) { this[i] = selectorResult[i]; } this.length = length; } // 修改原型 DomElement.prototype = { constructor: DomElement, // 类数组,forEach forEach: function forEach(fn) { var i = void 0; for (i = 0; i < this.length; i++) { var elem = this[i]; var result = fn.call(elem, elem, i); if (result === false) { break; } } return this; }, // clone clone: function clone(deep) { var cloneList = []; this.forEach(function (elem) { cloneList.push(elem.cloneNode(!!deep)); }); return $(cloneList); }, // 获取第几个元素 get: function get(index) { var length = this.length; if (index >= length) { index = index % length; } return $(this[index]); }, // 第一个 first: function first() { return this.get(0); }, // 最后一个 last: function last() { var length = this.length; return this.get(length - 1); }, // 绑定事件 on: function on(type, selector, fn) { // selector 不为空,证明绑定事件要加代理 if (!fn) { fn = selector; selector = null; } // type 是否有多个 var types = []; types = type.split(/\s+/); return this.forEach(function (elem) { types.forEach(function (type) { if (!type) { return; } // 记录下,方便后面解绑 eventList.push({ elem: elem, type: type, fn: fn }); if (!selector) { // 无代理 elem.addEventListener(type, fn); return; } // 有代理 elem.addEventListener(type, function (e) { var target = e.target; if (target.matches(selector)) { fn.call(target, e); } }); }); }); }, // 取消事件绑定 off: function off(type, fn) { return this.forEach(function (elem) { elem.removeEventListener(type, fn); }); }, // 获取/设置 属性 attr: function attr(key, val) { if (val == null) { // 获取值 return this[0].getAttribute(key); } else { // 设置值 return this.forEach(function (elem) { elem.setAttribute(key, val); }); } }, // 添加 class addClass: function addClass(className) { if (!className) { return this; } return this.forEach(function (elem) { var arr = void 0; if (elem.className) { // 解析当前 className 转换为数组 arr = elem.className.split(/\s/); arr = arr.filter(function (item) { return !!item.trim(); }); // 添加 class if (arr.indexOf(className) < 0) { arr.push(className); } // 修改 elem.class elem.className = arr.join(' '); } else { elem.className = className; } }); }, // 删除 class removeClass: function removeClass(className) { if (!className) { return this; } return this.forEach(function (elem) { var arr = void 0; if (elem.className) { // 解析当前 className 转换为数组 arr = elem.className.split(/\s/); arr = arr.filter(function (item) { item = item.trim(); // 删除 class if (!item || item === className) { return false; } return true; }); // 修改 elem.class elem.className = arr.join(' '); } }); }, // 修改 css css: function css(key, val) { var currentStyle = key + ':' + val + ';'; return this.forEach(function (elem) { var style = (elem.getAttribute('style') || '').trim(); var styleArr = void 0, resultArr = []; if (style) { // 将 style 按照 ; 拆分为数组 styleArr = style.split(';'); styleArr.forEach(function (item) { // 对每项样式,按照 : 拆分为 key 和 value var arr = item.split(':').map(function (i) { return i.trim(); }); if (arr.length === 2) { resultArr.push(arr[0] + ':' + arr[1]); } }); // 替换或者新增 resultArr = resultArr.map(function (item) { if (item.indexOf(key) === 0) { return currentStyle; } else { return item; } }); if (resultArr.indexOf(currentStyle) < 0) { resultArr.push(currentStyle); } // 结果 elem.setAttribute('style', resultArr.join('; ')); } else { // style 无值 elem.setAttribute('style', currentStyle); } }); }, // 显示 show: function show() { return this.css('display', 'block'); }, // 隐藏 hide: function hide() { return this.css('display', 'none'); }, // 获取子节点 children: function children() { var elem = this[0]; if (!elem) { return null; } return $(elem.children); }, // 获取子节点(包括文本节点) childNodes: function childNodes() { var elem = this[0]; if (!elem) { return null; } return $(elem.childNodes); }, // 增加子节点 append: function append($children) { return this.forEach(function (elem) { $children.forEach(function (child) { elem.appendChild(child); }); }); }, // 移除当前节点 remove: function remove() { return this.forEach(function (elem) { if (elem.remove) { elem.remove(); } else { var parent = elem.parentElement; parent && parent.removeChild(elem); } }); }, // 是否包含某个子节点 isContain: function isContain($child) { var elem = this[0]; var child = $child[0]; return elem.contains(child); }, // 尺寸数据 getSizeData: function getSizeData() { var elem = this[0]; return elem.getBoundingClientRect(); // 可得到 bottom height left right top width 的数据 }, // 封装 nodeName getNodeName: function getNodeName() { var elem = this[0]; return elem.nodeName; }, // 从当前元素查找 find: function find(selector) { var elem = this[0]; return $(elem.querySelectorAll(selector)); }, // 获取当前元素的 text text: function text(val) { if (!val) { // 获取 text var elem = this[0]; return elem.innerHTML.replace(/<.*?>/g, function () { return ''; }); } else { // 设置 text return this.forEach(function (elem) { elem.innerHTML = val; }); } }, // 获取 html html: function html(value) { var elem = this[0]; if (value == null) { return elem.innerHTML; } else { elem.innerHTML = value; return this; } }, // 获取 value val: function val() { var elem = this[0]; return elem.value.trim(); }, // focus focus: function focus() { return this.forEach(function (elem) { elem.focus(); }); }, // parent parent: function parent() { var elem = this[0]; return $(elem.parentElement); }, // parentUntil 找到符合 selector 的父节点 parentUntil: function parentUntil(selector, _currentElem) { var results = document.querySelectorAll(selector); var length = results.length; if (!length) { // 传入的 selector 无效 return null; } var elem = _currentElem || this[0]; if (elem.nodeName === 'BODY') { return null; } var parent = elem.parentElement; var i = void 0; for (i = 0; i < length; i++) { if (parent === results[i]) { // 找到,并返回 return $(parent); } } // 继续查找 return this.parentUntil(selector, parent); }, // 判断两个 elem 是否相等 equal: function equal($elem) { if ($elem.nodeType === 1) { return this[0] === $elem; } else { return this[0] === $elem[0]; } }, // 将该元素插入到某个元素前面 insertBefore: function insertBefore(selector) { var $referenceNode = $(selector); var referenceNode = $referenceNode[0]; if (!referenceNode) { return this; } return this.forEach(function (elem) { var parent = referenceNode.parentNode; parent.insertBefore(elem, referenceNode); }); }, // 将该元素插入到某个元素后面 insertAfter: function insertAfter(selector) { var $referenceNode = $(selector); var referenceNode = $referenceNode[0]; if (!referenceNode) { return this; } return this.forEach(function (elem) { var parent = referenceNode.parentNode; if (parent.lastChild === referenceNode) { // 最后一个元素 parent.appendChild(elem); } else { // 不是最后一个元素 parent.insertBefore(elem, referenceNode.nextSibling); } }); } }; // new 一个对象 function $(selector) { return new DomElement(selector); } // 解绑所有事件,用于销毁编辑器 $.offAll = function () { eventList.forEach(function (item) { var elem = item.elem; var type = item.type; var fn = item.fn; // 解绑 elem.removeEventListener(type, fn); }); }; /* 配置信息 */ var config = { // 默认菜单配置 menus: ['head', 'bold', 'fontSize', 'fontName', 'italic', 'underline', 'strikeThrough', 'foreColor', 'backColor', 'link', 'list', 'justify', 'quote', 'emoticon', 'image', 'table', 'video', 'code', 'undo', 'redo'], fontNames: ['宋体', '微软雅黑', 'Arial', 'Tahoma', 'Verdana'], colors: ['#000000', '#eeece0', '#1c487f', '#4d80bf', '#c24f4a', '#8baa4a', '#7b5ba1', '#46acc8', '#f9963b', '#ffffff'], // // 语言配置 // lang: { // '设置标题': 'title', // '正文': 'p', // '链接文字': 'link text', // '链接': 'link', // '插入': 'insert', // '创建': 'init' // }, // 表情 emotions: [{ // tab 的标题 title: '默认', // type -> 'emoji' / 'image' type: 'image', // content -> 数组 content: [{ alt: '[坏笑]', src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/50/pcmoren_huaixiao_org.png' }, { alt: '[舔屏]', src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/40/pcmoren_tian_org.png' }, { alt: '[污]', src: 'http://img.t.sinajs.cn/t4/appstyle/expression/ext/normal/3c/pcmoren_wu_org.png' }] }, { // tab 的标题 title: '新浪', // type -> 'emoji' / 'image' type: 'image', // content -> 数组 content: [{ src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/7a/shenshou_thumb.gif', alt: '[草泥马]' }, { src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/60/horse2_thumb.gif', alt: '[神马]' }, { src: 'http://img.t.sinajs.cn/t35/style/images/common/face/ext/normal/bc/fuyun_thumb.gif', alt: '[浮云]' }] }, { // tab 的标题 title: 'emoji', // type -> 'emoji' / 'image' type: 'emoji', // content -> 数组 content: '? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?'.split(/\s/) }], // 编辑区域的 z-index zIndex: 10000, // 是否开启 debug 模式(debug 模式下错误会 throw error 形式抛出) debug: false, // 插入链接时候的格式校验 linkCheck: function linkCheck(text, link) { // text 是插入的文字 // link 是插入的链接 return true; // 返回 true 即表示成功 // return '校验失败' // 返回字符串即表示失败的提示信息 }, // 插入网络图片的校验 linkImgCheck: function linkImgCheck(src) { // src 即图片的地址 return true; // 返回 true 即表示成功 // return '校验失败' // 返回字符串即表示失败的提示信息 }, // 粘贴过滤样式,默认开启 pasteFilterStyle: true, // 粘贴内容时,忽略图片。默认关闭 pasteIgnoreImg: false, // 对粘贴的文字进行自定义处理,返回处理后的结果。编辑器会将处理后的结果粘贴到编辑区域中。 // IE 暂时不支持 pasteTextHandle: function pasteTextHandle(content) { // content 即粘贴过来的内容(html 或 纯文本),可进行自定义处理然后返回 return content; }, // onchange 事件 // onchange: function (html) { // // html 即变化之后的内容 // console.log(html) // }, // 是否显示添加网络图片的 tab showLinkImg: true, // 插入网络图片的回调 linkImgCallback: function linkImgCallback(url) { // console.log(url) // url 即插入图片的地址 }, // 默认上传图片 max size: 5M uploadImgMaxSize: 5 * 1024 * 1024, // 配置一次最多上传几个图片 // uploadImgMaxLength: 5, // 上传图片,是否显示 base64 格式 uploadImgShowBase64: false, // 上传图片,server 地址(如果有值,则 base64 格式的配置则失效) // uploadImgServer: '/upload', // 自定义配置 filename uploadFileName: '', // 上传图片的自定义参数 uploadImgParams: { // token: 'abcdef12345' }, // 上传图片的自定义header uploadImgHeaders: { // 'Accept': 'text/x-json' }, // 配置 XHR withCredentials withCredentials: false, // 自定义上传图片超时时间 ms uploadImgTimeout: 10000, // 上传图片 hook uploadImgHooks: { // customInsert: function (insertLinkImg, result, editor) { // console.log('customInsert') // // 图片上传并返回结果,自定义插入图片的事件,而不是编辑器自动插入图片 // const data = result.data1 || [] // data.forEach(link => { // insertLinkImg(link) // }) // }, before: function before(xhr, editor, files) { // 图片上传之前触发 // 如果返回的结果是 {prevent: true, msg: 'xxxx'} 则表示用户放弃上传 // return { // prevent: true, // msg: '放弃上传' // } }, success: function success(xhr, editor, result) { // 图片上传并返回结果,图片插入成功之后触发 }, fail: function fail(xhr, editor, result) { // 图片上传并返回结果,但图片插入错误时触发 }, error: function error(xhr, editor) { // 图片上传出错时触发 }, timeout: function timeout(xhr, editor) { // 图片上传超时时触发 } }, // 是否上传七牛云,默认为 false qiniu: false }; /* 工具 */ // 和 UA 相关的属性 var UA = { _ua: navigator.userAgent, // 是否 webkit isWebkit: function isWebkit() { var reg = /webkit/i; return reg.test(this._ua); }, // 是否 IE isIE: function isIE() { return 'ActiveXObject' in window; } }; // 遍历对象 function objForEach(obj, fn) { var key = void 0, result = void 0; for (key in obj) { if (obj.hasOwnProperty(key)) { result = fn.call(obj, key, obj[key]); if (result === false) { break; } } } } // 遍历类数组 function arrForEach(fakeArr, fn) { var i = void 0, item = void 0, result = void 0; var length = fakeArr.length || 0; for (i = 0; i < length; i++) { item = fakeArr[i]; result = fn.call(fakeArr, item, i); if (result === false) { break; } } } // 获取随机数 function getRandom(prefix) { return prefix + Math.random().toString().slice(2); } // 替换 html 特殊字符 function replaceHtmlSymbol(html) { if (html == null) { return ''; } return html.replace(//gm, '>').replace(/"/gm, '"').replace(/(\r\n|\r|\n)/g, '
'); } // 返回百分比的格式 // 判断是不是 function function isFunction(fn) { return typeof fn === 'function'; } /* bold-menu */ // 构造函数 function Bold(editor) { this.editor = editor; this.$elem = $('
\n \n
'); this.type = 'click'; // 当前是否 active 状态 this._active = false; } // 原型 Bold.prototype = { constructor: Bold, // 点击事件 onClick: function onClick(e) { // 点击菜单将触发这里 var editor = this.editor; var isSeleEmpty = editor.selection.isSelectionEmpty(); if (isSeleEmpty) { // 选区是空的,插入并选中一个“空白” editor.selection.createEmptyRange(); } // 执行 bold 命令 editor.cmd.do('bold'); if (isSeleEmpty) { // 需要将选取折叠起来 editor.selection.collapseRange(); editor.selection.restoreSelection(); } }, // 试图改变 active 状态 tryChangeActive: function tryChangeActive(e) { var editor = this.editor; var $elem = this.$elem; if (editor.cmd.queryCommandState('bold')) { this._active = true; $elem.addClass('w-e-active'); } else { this._active = false; $elem.removeClass('w-e-active'); } } }; /* 替换多语言 */ var replaceLang = function (editor, str) { var langArgs = editor.config.langArgs || []; var result = str; langArgs.forEach(function (item) { var reg = item.reg; var val = item.val; if (reg.test(result)) { result = result.replace(reg, function () { return val; }); } }); return result; }; /* droplist */ var _emptyFn = function _emptyFn() {}; // 构造函数 function DropList(menu, opt) { var _this = this; // droplist 所依附的菜单 var editor = menu.editor; this.menu = menu; this.opt = opt; // 容器 var $container = $('
'); // 标题 var $title = opt.$title; var titleHtml = void 0; if ($title) { // 替换多语言 titleHtml = $title.html(); titleHtml = replaceLang(editor, titleHtml); $title.html(titleHtml); $title.addClass('w-e-dp-title'); $container.append($title); } var list = opt.list || []; var type = opt.type || 'list'; // 'list' 列表形式(如“标题”菜单) / 'inline-block' 块状形式(如“颜色”菜单) var onClick = opt.onClick || _emptyFn; // 加入 DOM 并绑定事件 var $list = $('
    '); $container.append($list); list.forEach(function (item) { var $elem = item.$elem; // 替换多语言 var elemHtml = $elem.html(); elemHtml = replaceLang(editor, elemHtml); $elem.html(elemHtml); var value = item.value; var $li = $('
  • '); if ($elem) { $li.append($elem); $list.append($li); $li.on('click', function (e) { onClick(value); // 隐藏 _this.hideTimeoutId = setTimeout(function () { _this.hide(); }, 0); }); } }); // 绑定隐藏事件 $container.on('mouseleave', function (e) { _this.hideTimeoutId = setTimeout(function () { _this.hide(); }, 0); }); // 记录属性 this.$container = $container; // 基本属性 this._rendered = false; this._show = false; } // 原型 DropList.prototype = { constructor: DropList, // 显示(插入DOM) show: function show() { if (this.hideTimeoutId) { // 清除之前的定时隐藏 clearTimeout(this.hideTimeoutId); } var menu = this.menu; var $menuELem = menu.$elem; var $container = this.$container; if (this._show) { return; } if (this._rendered) { // 显示 $container.show(); } else { // 加入 DOM 之前先定位位置 var menuHeight = $menuELem.getSizeData().height || 0; var width = this.opt.width || 100; // 默认为 100 $container.css('margin-top', menuHeight + 'px').css('width', width + 'px'); // 加入到 DOM $menuELem.append($container); this._rendered = true; } // 修改属性 this._show = true; }, // 隐藏(移除DOM) hide: function hide() { if (this.showTimeoutId) { // 清除之前的定时显示 clearTimeout(this.showTimeoutId); } var $container = this.$container; if (!this._show) { return; } // 隐藏并需改属性 $container.hide(); this._show = false; } }; /* menu - header */ // 构造函数 function Head(editor) { var _this = this; this.editor = editor; this.$elem = $('
    '); this.type = 'droplist'; // 当前是否 active 状态 this._active = false; // 初始化 droplist this.droplist = new DropList(this, { width: 100, $title: $('

    设置标题

    '), type: 'list', // droplist 以列表形式展示 list: [{ $elem: $('

    H1

    '), value: '

    ' }, { $elem: $('

    H2

    '), value: '

    ' }, { $elem: $('

    H3

    '), value: '

    ' }, { $elem: $('

    H4

    '), value: '

    ' }, { $elem: $('

    H5
    '), value: '
    ' }, { $elem: $('

    正文

    '), value: '

    ' }], onClick: function onClick(value) { // 注意 this 是指向当前的 Head 对象 _this._command(value); } }); } // 原型 Head.prototype = { constructor: Head, // 执行命令 _command: function _command(value) { var editor = this.editor; var $selectionElem = editor.selection.getSelectionContainerElem(); if (editor.$textElem.equal($selectionElem)) { // 不能选中多行来设置标题,否则会出现问题 // 例如选中的是

    xxx

    yyy

    来设置标题,设置之后会成为

    xxx
    yyy

    不符合预期 return; } editor.cmd.do('formatBlock', value); }, // 试图改变 active 状态 tryChangeActive: function tryChangeActive(e) { var editor = this.editor; var $elem = this.$elem; var reg = /^h/i; var cmdValue = editor.cmd.queryCommandValue('formatBlock'); if (reg.test(cmdValue)) { this._active = true; $elem.addClass('w-e-active'); } else { this._active = false; $elem.removeClass('w-e-active'); } } }; /* menu - fontSize */ // 构造函数 function FontSize(editor) { var _this = this; this.editor = editor; this.$elem = $('
    '); this.type = 'droplist'; // 当前是否 active 状态 this._active = false; // 初始化 droplist this.droplist = new DropList(this, { width: 160, $title: $('

    字号

    '), type: 'list', // droplist 以列表形式展示 list: [{ $elem: $('x-small'), value: '1' }, { $elem: $('small'), value: '2' }, { $elem: $('normal'), value: '3' }, { $elem: $('large'), value: '4' }, { $elem: $('x-large'), value: '5' }, { $elem: $('xx-large'), value: '6' }], onClick: function onClick(value) { // 注意 this 是指向当前的 FontSize 对象 _this._command(value); } }); } // 原型 FontSize.prototype = { constructor: FontSize, // 执行命令 _command: function _command(value) { var editor = this.editor; editor.cmd.do('fontSize', value); } }; /* menu - fontName */ // 构造函数 function FontName(editor) { var _this = this; this.editor = editor; this.$elem = $('
    '); this.type = 'droplist'; // 当前是否 active 状态 this._active = false; // 获取配置的字体 var config = editor.config; var fontNames = config.fontNames || []; // 初始化 droplist this.droplist = new DropList(this, { width: 100, $title: $('

    字体

    '), type: 'list', // droplist 以列表形式展示 list: fontNames.map(function (fontName) { return { $elem: $('' + fontName + ''), value: fontName }; }), onClick: function onClick(value) { // 注意 this 是指向当前的 FontName 对象 _this._command(value); } }); } // 原型 FontName.prototype = { constructor: FontName, _command: function _command(value) { var editor = this.editor; editor.cmd.do('fontName', value); } }; /* panel */ var emptyFn = function emptyFn() {}; // 记录已经显示 panel 的菜单 var _isCreatedPanelMenus = []; // 构造函数 function Panel(menu, opt) { this.menu = menu; this.opt = opt; } // 原型 Panel.prototype = { constructor: Panel, // 显示(插入DOM) show: function show() { var _this = this; var menu = this.menu; if (_isCreatedPanelMenus.indexOf(menu) >= 0) { // 该菜单已经创建了 panel 不能再创建 return; } var editor = menu.editor; var $body = $('body'); var $textContainerElem = editor.$textContainerElem; var opt = this.opt; // panel 的容器 var $container = $('
    '); var width = opt.width || 300; // 默认 300px $container.css('width', width + 'px').css('margin-left', (0 - width) / 2 + 'px'); // 添加关闭按钮 var $closeBtn = $(''); $container.append($closeBtn); $closeBtn.on('click', function () { _this.hide(); }); // 准备 tabs 容器 var $tabTitleContainer = $('
      '); var $tabContentContainer = $('
      '); $container.append($tabTitleContainer).append($tabContentContainer); // 设置高度 var height = opt.height; if (height) { $tabContentContainer.css('height', height + 'px').css('overflow-y', 'auto'); } // tabs var tabs = opt.tabs || []; var tabTitleArr = []; var tabContentArr = []; tabs.forEach(function (tab, tabIndex) { if (!tab) { return; } var title = tab.title || ''; var tpl = tab.tpl || ''; // 替换多语言 title = replaceLang(editor, title); tpl = replaceLang(editor, tpl); // 添加到 DOM var $title = $('
    • ' + title + '
    • '); $tabTitleContainer.append($title); var $content = $(tpl); $tabContentContainer.append($content); // 记录到内存 $title._index = tabIndex; tabTitleArr.push($title); tabContentArr.push($content); // 设置 active 项 if (tabIndex === 0) { $title._active = true; $title.addClass('w-e-active'); } else { $content.hide(); } // 绑定 tab 的事件 $title.on('click', function (e) { if ($title._active) { return; } // 隐藏所有的 tab tabTitleArr.forEach(function ($title) { $title._active = false; $title.removeClass('w-e-active'); }); tabContentArr.forEach(function ($content) { $content.hide(); }); // 显示当前的 tab $title._active = true; $title.addClass('w-e-active'); $content.show(); }); }); // 绑定关闭事件 $container.on('click', function (e) { // 点击时阻止冒泡 e.stopPropagation(); }); $body.on('click', function (e) { _this.hide(); }); // 添加到 DOM $textContainerElem.append($container); // 绑定 opt 的事件,只有添加到 DOM 之后才能绑定成功 tabs.forEach(function (tab, index) { if (!tab) { return; } var events = tab.events || []; events.forEach(function (event) { var selector = event.selector; var type = event.type; var fn = event.fn || emptyFn; var $content = tabContentArr[index]; $content.find(selector).on(type, function (e) { e.stopPropagation(); var needToHide = fn(e); // 执行完事件之后,是否要关闭 panel if (needToHide) { _this.hide(); } }); }); }); // focus 第一个 elem var $inputs = $container.find('input[type=text],textarea'); if ($inputs.length) { $inputs.get(0).focus(); } // 添加到属性 this.$container = $container; // 隐藏其他 panel this._hideOtherPanels(); // 记录该 menu 已经创建了 panel _isCreatedPanelMenus.push(menu); }, // 隐藏(移除DOM) hide: function hide() { var menu = this.menu; var $container = this.$container; if ($container) { $container.remove(); } // 将该 menu 记录中移除 _isCreatedPanelMenus = _isCreatedPanelMenus.filter(function (item) { if (item === menu) { return false; } else { return true; } }); }, // 一个 panel 展示时,隐藏其他 panel _hideOtherPanels: function _hideOtherPanels() { if (!_isCreatedPanelMenus.length) { return; } _isCreatedPanelMenus.forEach(function (menu) { var panel = menu.panel || {}; if (panel.hide) { panel.hide(); } }); } }; /* menu - link */ // 构造函数 function Link(editor) { this.editor = editor; this.$elem = $('
      '); this.type = 'panel'; // 当前是否 active 状态 this._active = false; } // 原型 Link.prototype = { constructor: Link, // 点击事件 onClick: function onClick(e) { var editor = this.editor; var $linkelem = void 0; if (this._active) { // 当前选区在链接里面 $linkelem = editor.selection.getSelectionContainerElem(); if (!$linkelem) { return; } // 将该元素都包含在选取之内,以便后面整体替换 editor.selection.createRangeByElem($linkelem); editor.selection.restoreSelection(); // 显示 panel this._createPanel($linkelem.text(), $linkelem.attr('href')); } else { // 当前选区不在链接里面 if (editor.selection.isSelectionEmpty()) { // 选区是空的,未选中内容 this._createPanel('', ''); } else { // 选中内容了 this._createPanel(editor.selection.getSelectionText(), ''); } } }, // 创建 panel _createPanel: function _createPanel(text, link) { var _this = this; // panel 中需要用到的id var inputLinkId = getRandom('input-link'); var inputTextId = getRandom('input-text'); var btnOkId = getRandom('btn-ok'); var btnDelId = getRandom('btn-del'); // 是否显示“删除链接” var delBtnDisplay = this._active ? 'inline-block' : 'none'; // 初始化并显示 panel var panel = new Panel(this, { width: 300, // panel 中可包含多个 tab tabs: [{ // tab 的标题 title: '链接', // 模板 tpl: '
      \n \n \n
      \n \n \n
      \n
      ', // 事件绑定 events: [ // 插入链接 { selector: '#' + btnOkId, type: 'click', fn: function fn() { // 执行插入链接 var $link = $('#' + inputLinkId); var $text = $('#' + inputTextId); var link = $link.val(); var text = $text.val(); _this._insertLink(text, link); // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 return true; } }, // 删除链接 { selector: '#' + btnDelId, type: 'click', fn: function fn() { // 执行删除链接 _this._delLink(); // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 return true; } }] } // tab end ] // tabs end }); // 显示 panel panel.show(); // 记录属性 this.panel = panel; }, // 删除当前链接 _delLink: function _delLink() { if (!this._active) { return; } var editor = this.editor; var $selectionELem = editor.selection.getSelectionContainerElem(); if (!$selectionELem) { return; } var selectionText = editor.selection.getSelectionText(); editor.cmd.do('insertHTML', '' + selectionText + ''); }, // 插入链接 _insertLink: function _insertLink(text, link) { var editor = this.editor; var config = editor.config; var linkCheck = config.linkCheck; var checkResult = true; // 默认为 true if (linkCheck && typeof linkCheck === 'function') { checkResult = linkCheck(text, link); } if (checkResult === true) { editor.cmd.do('insertHTML', '' + text + ''); } else { alert(checkResult); } }, // 试图改变 active 状态 tryChangeActive: function tryChangeActive(e) { var editor = this.editor; var $elem = this.$elem; var $selectionELem = editor.selection.getSelectionContainerElem(); if (!$selectionELem) { return; } if ($selectionELem.getNodeName() === 'A') { this._active = true; $elem.addClass('w-e-active'); } else { this._active = false; $elem.removeClass('w-e-active'); } } }; /* italic-menu */ // 构造函数 function Italic(editor) { this.editor = editor; this.$elem = $('
      \n \n
      '); this.type = 'click'; // 当前是否 active 状态 this._active = false; } // 原型 Italic.prototype = { constructor: Italic, // 点击事件 onClick: function onClick(e) { // 点击菜单将触发这里 var editor = this.editor; var isSeleEmpty = editor.selection.isSelectionEmpty(); if (isSeleEmpty) { // 选区是空的,插入并选中一个“空白” editor.selection.createEmptyRange(); } // 执行 italic 命令 editor.cmd.do('italic'); if (isSeleEmpty) { // 需要将选取折叠起来 editor.selection.collapseRange(); editor.selection.restoreSelection(); } }, // 试图改变 active 状态 tryChangeActive: function tryChangeActive(e) { var editor = this.editor; var $elem = this.$elem; if (editor.cmd.queryCommandState('italic')) { this._active = true; $elem.addClass('w-e-active'); } else { this._active = false; $elem.removeClass('w-e-active'); } } }; /* redo-menu */ // 构造函数 function Redo(editor) { this.editor = editor; this.$elem = $('
      \n \n
      '); this.type = 'click'; // 当前是否 active 状态 this._active = false; } // 原型 Redo.prototype = { constructor: Redo, // 点击事件 onClick: function onClick(e) { // 点击菜单将触发这里 var editor = this.editor; // 执行 redo 命令 editor.cmd.do('redo'); } }; /* strikeThrough-menu */ // 构造函数 function StrikeThrough(editor) { this.editor = editor; this.$elem = $('
      \n \n
      '); this.type = 'click'; // 当前是否 active 状态 this._active = false; } // 原型 StrikeThrough.prototype = { constructor: StrikeThrough, // 点击事件 onClick: function onClick(e) { // 点击菜单将触发这里 var editor = this.editor; var isSeleEmpty = editor.selection.isSelectionEmpty(); if (isSeleEmpty) { // 选区是空的,插入并选中一个“空白” editor.selection.createEmptyRange(); } // 执行 strikeThrough 命令 editor.cmd.do('strikeThrough'); if (isSeleEmpty) { // 需要将选取折叠起来 editor.selection.collapseRange(); editor.selection.restoreSelection(); } }, // 试图改变 active 状态 tryChangeActive: function tryChangeActive(e) { var editor = this.editor; var $elem = this.$elem; if (editor.cmd.queryCommandState('strikeThrough')) { this._active = true; $elem.addClass('w-e-active'); } else { this._active = false; $elem.removeClass('w-e-active'); } } }; /* underline-menu */ // 构造函数 function Underline(editor) { this.editor = editor; this.$elem = $('
      \n \n
      '); this.type = 'click'; // 当前是否 active 状态 this._active = false; } // 原型 Underline.prototype = { constructor: Underline, // 点击事件 onClick: function onClick(e) { // 点击菜单将触发这里 var editor = this.editor; var isSeleEmpty = editor.selection.isSelectionEmpty(); if (isSeleEmpty) { // 选区是空的,插入并选中一个“空白” editor.selection.createEmptyRange(); } // 执行 underline 命令 editor.cmd.do('underline'); if (isSeleEmpty) { // 需要将选取折叠起来 editor.selection.collapseRange(); editor.selection.restoreSelection(); } }, // 试图改变 active 状态 tryChangeActive: function tryChangeActive(e) { var editor = this.editor; var $elem = this.$elem; if (editor.cmd.queryCommandState('underline')) { this._active = true; $elem.addClass('w-e-active'); } else { this._active = false; $elem.removeClass('w-e-active'); } } }; /* undo-menu */ // 构造函数 function Undo(editor) { this.editor = editor; this.$elem = $('
      \n \n
      '); this.type = 'click'; // 当前是否 active 状态 this._active = false; } // 原型 Undo.prototype = { constructor: Undo, // 点击事件 onClick: function onClick(e) { // 点击菜单将触发这里 var editor = this.editor; // 执行 undo 命令 editor.cmd.do('undo'); } }; /* menu - list */ // 构造函数 function List(editor) { var _this = this; this.editor = editor; this.$elem = $('
      '); this.type = 'droplist'; // 当前是否 active 状态 this._active = false; // 初始化 droplist this.droplist = new DropList(this, { width: 120, $title: $('

      设置列表

      '), type: 'list', // droplist 以列表形式展示 list: [{ $elem: $(' 有序列表'), value: 'insertOrderedList' }, { $elem: $(' 无序列表'), value: 'insertUnorderedList' }], onClick: function onClick(value) { // 注意 this 是指向当前的 List 对象 _this._command(value); } }); } // 原型 List.prototype = { constructor: List, // 执行命令 _command: function _command(value) { var editor = this.editor; var $textElem = editor.$textElem; editor.selection.restoreSelection(); if (editor.cmd.queryCommandState(value)) { return; } editor.cmd.do(value); // 验证列表是否被包裹在

      之内 var $selectionElem = editor.selection.getSelectionContainerElem(); if ($selectionElem.getNodeName() === 'LI') { $selectionElem = $selectionElem.parent(); } if (/^ol|ul$/i.test($selectionElem.getNodeName()) === false) { return; } if ($selectionElem.equal($textElem)) { // 证明是顶级标签,没有被

      包裹 return; } var $parent = $selectionElem.parent(); if ($parent.equal($textElem)) { // $parent 是顶级标签,不能删除 return; } $selectionElem.insertAfter($parent); $parent.remove(); }, // 试图改变 active 状态 tryChangeActive: function tryChangeActive(e) { var editor = this.editor; var $elem = this.$elem; if (editor.cmd.queryCommandState('insertUnOrderedList') || editor.cmd.queryCommandState('insertOrderedList')) { this._active = true; $elem.addClass('w-e-active'); } else { this._active = false; $elem.removeClass('w-e-active'); } } }; /* menu - justify */ // 构造函数 function Justify(editor) { var _this = this; this.editor = editor; this.$elem = $('

      '); this.type = 'droplist'; // 当前是否 active 状态 this._active = false; // 初始化 droplist this.droplist = new DropList(this, { width: 100, $title: $('

      对齐方式

      '), type: 'list', // droplist 以列表形式展示 list: [{ $elem: $(' 靠左'), value: 'justifyLeft' }, { $elem: $(' 居中'), value: 'justifyCenter' }, { $elem: $(' 靠右'), value: 'justifyRight' }], onClick: function onClick(value) { // 注意 this 是指向当前的 List 对象 _this._command(value); } }); } // 原型 Justify.prototype = { constructor: Justify, // 执行命令 _command: function _command(value) { var editor = this.editor; editor.cmd.do(value); } }; /* menu - Forecolor */ // 构造函数 function ForeColor(editor) { var _this = this; this.editor = editor; this.$elem = $('
      '); this.type = 'droplist'; // 获取配置的颜色 var config = editor.config; var colors = config.colors || []; // 当前是否 active 状态 this._active = false; // 初始化 droplist this.droplist = new DropList(this, { width: 120, $title: $('

      文字颜色

      '), type: 'inline-block', // droplist 内容以 block 形式展示 list: colors.map(function (color) { return { $elem: $(''), value: color }; }), onClick: function onClick(value) { // 注意 this 是指向当前的 ForeColor 对象 _this._command(value); } }); } // 原型 ForeColor.prototype = { constructor: ForeColor, // 执行命令 _command: function _command(value) { var editor = this.editor; editor.cmd.do('foreColor', value); } }; /* menu - BackColor */ // 构造函数 function BackColor(editor) { var _this = this; this.editor = editor; this.$elem = $('
      '); this.type = 'droplist'; // 获取配置的颜色 var config = editor.config; var colors = config.colors || []; // 当前是否 active 状态 this._active = false; // 初始化 droplist this.droplist = new DropList(this, { width: 120, $title: $('

      背景色

      '), type: 'inline-block', // droplist 内容以 block 形式展示 list: colors.map(function (color) { return { $elem: $(''), value: color }; }), onClick: function onClick(value) { // 注意 this 是指向当前的 BackColor 对象 _this._command(value); } }); } // 原型 BackColor.prototype = { constructor: BackColor, // 执行命令 _command: function _command(value) { var editor = this.editor; editor.cmd.do('backColor', value); } }; /* menu - quote */ // 构造函数 function Quote(editor) { this.editor = editor; this.$elem = $('
      \n \n
      '); this.type = 'click'; // 当前是否 active 状态 this._active = false; } // 原型 Quote.prototype = { constructor: Quote, onClick: function onClick(e) { var editor = this.editor; var $selectionElem = editor.selection.getSelectionContainerElem(); var nodeName = $selectionElem.getNodeName(); if (!UA.isIE()) { if (nodeName === 'BLOCKQUOTE') { // 撤销 quote editor.cmd.do('formatBlock', '

      '); } else { // 转换为 quote editor.cmd.do('formatBlock', '

      '); } return; } // IE 中不支持 formatBlock
      ,要用其他方式兼容 var content = void 0, $targetELem = void 0; if (nodeName === 'P') { // 将 P 转换为 quote content = $selectionElem.text(); $targetELem = $('
      ' + content + '
      '); $targetELem.insertAfter($selectionElem); $selectionElem.remove(); return; } if (nodeName === 'BLOCKQUOTE') { // 撤销 quote content = $selectionElem.text(); $targetELem = $('

      ' + content + '

      '); $targetELem.insertAfter($selectionElem); $selectionElem.remove(); } }, tryChangeActive: function tryChangeActive(e) { var editor = this.editor; var $elem = this.$elem; var reg = /^BLOCKQUOTE$/i; var cmdValue = editor.cmd.queryCommandValue('formatBlock'); if (reg.test(cmdValue)) { this._active = true; $elem.addClass('w-e-active'); } else { this._active = false; $elem.removeClass('w-e-active'); } } }; /* menu - code */ // 构造函数 function Code(editor) { this.editor = editor; this.$elem = $('
      \n \n
      '); this.type = 'panel'; // 当前是否 active 状态 this._active = false; } // 原型 Code.prototype = { constructor: Code, onClick: function onClick(e) { var editor = this.editor; var $startElem = editor.selection.getSelectionStartElem(); var $endElem = editor.selection.getSelectionEndElem(); var isSeleEmpty = editor.selection.isSelectionEmpty(); var selectionText = editor.selection.getSelectionText(); var $code = void 0; if (!$startElem.equal($endElem)) { // 跨元素选择,不做处理 editor.selection.restoreSelection(); return; } if (!isSeleEmpty) { // 选取不是空,用 包裹即可 $code = $('' + selectionText + ''); editor.cmd.do('insertElem', $code); editor.selection.createRangeByElem($code, false); editor.selection.restoreSelection(); return; } // 选取是空,且没有夸元素选择,则插入
      
              if (this._active) {
                  // 选中状态,将编辑内容
                  this._createPanel($startElem.html());
              } else {
                  // 未选中状态,将创建内容
                  this._createPanel();
              }
          },
      
          _createPanel: function _createPanel(value) {
              var _this = this;
      
              // value - 要编辑的内容
              value = value || '';
              var type = !value ? 'new' : 'edit';
              var textId = getRandom('texxt');
              var btnId = getRandom('btn');
      
              var panel = new Panel(this, {
                  width: 500,
                  // 一个 Panel 包含多个 tab
                  tabs: [{
                      // 标题
                      title: '插入代码',
                      // 模板
                      tpl: '
      \n \n
      \n \n
      \n
      ', // 事件绑定 events: [ // 插入代码 { selector: '#' + btnId, type: 'click', fn: function fn() { var $text = $('#' + textId); var text = $text.val() || $text.html(); text = replaceHtmlSymbol(text); if (type === 'new') { // 新插入 _this._insertCode(text); } else { // 编辑更新 _this._updateCode(text); } // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 return true; } }] } // first tab end ] // tabs end }); // new Panel end // 显示 panel panel.show(); // 记录属性 this.panel = panel; }, // 插入代码 _insertCode: function _insertCode(value) { var editor = this.editor; editor.cmd.do('insertHTML', '
      ' + value + '


      '); }, // 更新代码 _updateCode: function _updateCode(value) { var editor = this.editor; var $selectionELem = editor.selection.getSelectionContainerElem(); if (!$selectionELem) { return; } $selectionELem.html(value); editor.selection.restoreSelection(); }, // 试图改变 active 状态 tryChangeActive: function tryChangeActive(e) { var editor = this.editor; var $elem = this.$elem; var $selectionELem = editor.selection.getSelectionContainerElem(); if (!$selectionELem) { return; } var $parentElem = $selectionELem.parent(); if ($selectionELem.getNodeName() === 'CODE' && $parentElem.getNodeName() === 'PRE') { this._active = true; $elem.addClass('w-e-active'); } else { this._active = false; $elem.removeClass('w-e-active'); } } }; /* menu - emoticon */ // 构造函数 function Emoticon(editor) { this.editor = editor; this.$elem = $('
      \n \n
      '); this.type = 'panel'; // 当前是否 active 状态 this._active = false; } // 原型 Emoticon.prototype = { constructor: Emoticon, onClick: function onClick() { this._createPanel(); }, _createPanel: function _createPanel() { var _this = this; var editor = this.editor; var config = editor.config; // 获取表情配置 var emotions = config.emotions || []; // 创建表情 dropPanel 的配置 var tabConfig = []; emotions.forEach(function (emotData) { var emotType = emotData.type; var content = emotData.content || []; // 这一组表情最终拼接出来的 html var faceHtml = ''; // emoji 表情 if (emotType === 'emoji') { content.forEach(function (item) { if (item) { faceHtml += '' + item + ''; } }); } // 图片表情 if (emotType === 'image') { content.forEach(function (item) { var src = item.src; var alt = item.alt; if (src) { // 加一个 data-w-e 属性,点击图片的时候不再提示编辑图片 faceHtml += '' + alt + ''; } }); } tabConfig.push({ title: emotData.title, tpl: '
      ' + faceHtml + '
      ', events: [{ selector: 'span.w-e-item', type: 'click', fn: function fn(e) { var target = e.target; var $target = $(target); var nodeName = $target.getNodeName(); var insertHtml = void 0; if (nodeName === 'IMG') { // 插入图片 insertHtml = $target.parent().html(); } else { // 插入 emoji insertHtml = '' + $target.html() + ''; } _this._insert(insertHtml); // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 return true; } }] }); }); var panel = new Panel(this, { width: 300, height: 200, // 一个 Panel 包含多个 tab tabs: tabConfig }); // 显示 panel panel.show(); // 记录属性 this.panel = panel; }, // 插入表情 _insert: function _insert(emotHtml) { var editor = this.editor; editor.cmd.do('insertHTML', emotHtml); } }; /* menu - table */ // 构造函数 function Table(editor) { this.editor = editor; this.$elem = $('
      '); this.type = 'panel'; // 当前是否 active 状态 this._active = false; } // 原型 Table.prototype = { constructor: Table, onClick: function onClick() { if (this._active) { // 编辑现有表格 this._createEditPanel(); } else { // 插入新表格 this._createInsertPanel(); } }, // 创建插入新表格的 panel _createInsertPanel: function _createInsertPanel() { var _this = this; // 用到的 id var btnInsertId = getRandom('btn'); var textRowNum = getRandom('row'); var textColNum = getRandom('col'); var panel = new Panel(this, { width: 250, // panel 包含多个 tab tabs: [{ // 标题 title: '插入表格', // 模板 tpl: '
      \n

      \n \u521B\u5EFA\n \n \u884C\n \n \u5217\u7684\u8868\u683C\n

      \n
      \n \n
      \n
      ', // 事件绑定 events: [{ // 点击按钮,插入表格 selector: '#' + btnInsertId, type: 'click', fn: function fn() { var rowNum = parseInt($('#' + textRowNum).val()); var colNum = parseInt($('#' + textColNum).val()); if (rowNum && colNum && rowNum > 0 && colNum > 0) { // form 数据有效 _this._insert(rowNum, colNum); } // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 return true; } }] } // first tab end ] // tabs end }); // panel end // 展示 panel panel.show(); // 记录属性 this.panel = panel; }, // 插入表格 _insert: function _insert(rowNum, colNum) { // 拼接 table 模板 var r = void 0, c = void 0; var html = ''; for (r = 0; r < rowNum; r++) { html += ''; if (r === 0) { for (c = 0; c < colNum; c++) { html += ''; } } else { for (c = 0; c < colNum; c++) { html += ''; } } html += ''; } html += '
        


      '; // 执行命令 var editor = this.editor; editor.cmd.do('insertHTML', html); // 防止 firefox 下出现 resize 的控制点 editor.cmd.do('enableObjectResizing', false); editor.cmd.do('enableInlineTableEditing', false); }, // 创建编辑表格的 panel _createEditPanel: function _createEditPanel() { var _this2 = this; // 可用的 id var addRowBtnId = getRandom('add-row'); var addColBtnId = getRandom('add-col'); var delRowBtnId = getRandom('del-row'); var delColBtnId = getRandom('del-col'); var delTableBtnId = getRandom('del-table'); // 创建 panel 对象 var panel = new Panel(this, { width: 320, // panel 包含多个 tab tabs: [{ // 标题 title: '编辑表格', // 模板 tpl: '
      \n
      \n \n \n \n \n
      \n
      \n \n \n
      ', // 事件绑定 events: [{ // 增加行 selector: '#' + addRowBtnId, type: 'click', fn: function fn() { _this2._addRow(); // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 return true; } }, { // 增加列 selector: '#' + addColBtnId, type: 'click', fn: function fn() { _this2._addCol(); // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 return true; } }, { // 删除行 selector: '#' + delRowBtnId, type: 'click', fn: function fn() { _this2._delRow(); // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 return true; } }, { // 删除列 selector: '#' + delColBtnId, type: 'click', fn: function fn() { _this2._delCol(); // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 return true; } }, { // 删除表格 selector: '#' + delTableBtnId, type: 'click', fn: function fn() { _this2._delTable(); // 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭 return true; } }] }] }); // 显示 panel panel.show(); }, // 获取选中的单元格的位置信息 _getLocationData: function _getLocationData() { var result = {}; var editor = this.editor; var $selectionELem = editor.selection.getSelectionContainerElem(); if (!$selectionELem) { return; } var nodeName = $selectionELem.getNodeName(); if (nodeName !== 'TD' && nodeName !== 'TH') { return; } // 获取 td index var $tr = $selectionELem.parent(); var $tds = $tr.children(); var tdLength = $tds.length; $tds.forEach(function (td, index) { if (td === $selectionELem[0]) { // 记录并跳出循环 result.td = { index: index, elem: td, length: tdLength }; return false; } }); // 获取 tr index var $tbody = $tr.parent(); var $trs = $tbody.children(); var trLength = $trs.length; $trs.forEach(function (tr, index) { if (tr === $tr[0]) { // 记录并跳出循环 result.tr = { index: index, elem: tr, length: trLength }; return false; } }); // 返回结果 return result; }, // 增加行 _addRow: function _addRow() { // 获取当前单元格的位置信息 var locationData = this._getLocationData(); if (!locationData) { return; } var trData = locationData.tr; var $currentTr = $(trData.elem); var tdData = locationData.td; var tdLength = tdData.length; // 拼接即将插入的字符串 var newTr = document.createElement('tr'); var tpl = '', i = void 0; for (i = 0; i < tdLength; i++) { tpl += ' '; } newTr.innerHTML = tpl; // 插入 $(newTr).insertAfter($currentTr); }, // 增加列 _addCol: function _addCol() { // 获取当前单元格的位置信息 var locationData = this._getLocationData(); if (!locationData) { return; } var trData = locationData.tr; var tdData = locationData.td; var tdIndex = tdData.index; var $currentTr = $(trData.elem); var $trParent = $currentTr.parent(); var $trs = $trParent.children(); // 遍历所有行 $trs.forEach(function (tr) { var $tr = $(tr); var $tds = $tr.children(); var $currentTd = $tds.get(tdIndex); var name = $currentTd.getNodeName().toLowerCase(); // new 一个 td,并插入 var newTd = document.createElement(name); $(newTd).insertAfter($currentTd); }); }, // 删除行 _delRow: function _delRow() { // 获取当前单元格的位置信息 var locationData = this._getLocationData(); if (!locationData) { return; } var trData = locationData.tr; var $currentTr = $(trData.elem); $currentTr.remove(); }, // 删除列 _delCol: function _delCol() { // 获取当前单元格的位置信息 var locationData = this._getLocationData(); if (!locationData) { return; } var trData = locationData.tr; var tdData = locationData.td; var tdIndex = tdData.index; var $currentTr = $(trData.elem); var $trParent = $currentTr.parent(); var $trs = $trParent.children(); // 遍历所有行 $trs.forEach(function (tr) { var $tr = $(tr); var $tds = $tr.children(); var $currentTd = $tds.get(tdIndex); // 删除 $currentTd.remove(); }); }, // 删除表格 _delTable: function _delTable() { var editor = this.editor; var $selectionELem = editor.selection.getSelectionContainerElem(); if (!$selectionELem) { return; } var $table = $selectionELem.parentUntil('table'); if (!$table) { return; } $table.remove(); }, // 试图改变 active 状态 tryChangeActive: function tryChangeActive(e) { var editor = this.editor; var $elem = this.$elem; var $selectionELem = editor.selection.getSelectionContainerElem(); if (!$selectionELem) { return; } var nodeName = $selectionELem.getNodeName(); if (nodeName === 'TD' || nodeName === 'TH') { this._active = true; $elem.addClass('w-e-active'); } else { this._active = false; $elem.removeClass('w-e-active'); } } }; // /* menu - video */ // 构造函数 function Video(editor) { this.editor = editor; this.$elem = $('
      '); this.type = 'panel'; // 当前是否 active 状态 this._active = false; } // 原型 Video.prototype = { constructor: Video, onClick: function onClick() { this._createInsertPanel(); }, _createInsertPanel: function _createInsertPanel() { var editor = this.editor; var uploadVideo = editor.uploadVideo; var config = editor.config; // id var upTriggerId = getRandom('up-trigger'); var upFileId = getRandom('up-file'); // tabs 的配置 var tabsConfig = [{ title: '上传 video', tpl: '
      \n ' + '
      \n ' + '\n
      \n ' + '
      \n \n ' + '
      \n
      ', events: [{ // 触发选择视频 selector: '#' + upTriggerId, type: 'click', fn: function fn() { var $file = $('#' + upFileId); var fileElem = $file[0]; if (fileElem) { fileElem.click(); } else { // 返回 true 可关闭 panel return true; } } }, { // 选择视频完毕 selector: '#' + upFileId, type: 'change', fn: function fn() { var $file = $('#' + upFileId); var fileElem = $file[0]; if (!fileElem) { // 返回 true 可关闭 panel return true; } // 获取选中的 file 对象列表 var fileList = fileElem.files; if (fileList.length) { uploadVideo.uploadVideo(fileList); } // 返回 true 可关闭 panel return true; } }] } ]; // tabs end // 判断 tabs 的显示 var tabsConfigResult = []; tabsConfigResult.push(tabsConfig[0]); // 创建 panel 并显示 var panel = new Panel(this, { width: 300, tabs: tabsConfigResult }); panel.show(); // 记录属性 this.panel = panel; }, // 试图改变 active 状态 tryChangeActive: function tryChangeActive(e) { var editor = this.editor; var $elem = this.$elem; if (editor._selectedImg) { this._active = true; $elem.addClass('w-e-active'); } else { this._active = false; $elem.removeClass('w-e-active'); } } }; // 构造函数 function UploadVideo(editor) { this.editor = editor; } // 原型 UploadVideo.prototype = { constructor: UploadVideo, // 根据 debug 弹出不同的信息 _alert: function _alert(alertInfo, debugInfo) { var editor = this.editor; var debug = editor.config.debug; // var debug = true; var customAlert = editor.config.customAlert; if (debug) { throw new Error('wangEditor: ' + (debugInfo || alertInfo)); } else { if (customAlert && typeof customAlert === 'function') { customAlert(alertInfo); } else { alert(alertInfo); } } }, //插入视频的方法 需要单独定义 insertLinkVideo:function(link){ var _this3 = this; if (!link) { return; } var editor = this.editor; var config = editor.config; // 校验格式 var linkVideoCheck = config.linkVideoCheck; var checkResult = void 0; if (linkVideoCheck && linkVideoCheck === 'function') { checkResult = linkVideoCheck(link); if (typeof checkResult === 'string') { // 校验失败,提示信息 alert(checkResult); return; } } editor.cmd.do('insertHTML', '

      你可能感兴趣的:(富文本)