(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]; } } // 创建构造函数 function DomElement(selector) { if (!selector) { return; } // selector 本来就是 DomElement 对象,直接返回 if (selector instanceof DomElement) { return selector; } this.selector = selector; // 根据 selector 得出的结果(如 DOM,DOM List) var selectorResult = []; if (selector.nodeType === 1) { // 单个 DOM 节点 selectorResult = [selector]; } else if (isDOMList(selector)) { // DOM List selectorResult = selector; } else if (typeof selector === 'string') { // 字符串 selector = selector.replace('/\n/mg', '').trim(); if (selector.indexOf('<') === 0) { // 如
设置标题
'), type: 'list', // droplist 以列表形式展示 list: [{ $elem: $('正文
'), value: '' }], onClick: function onClick(value) { // 注意 this 是指向当前的 Head 对象 _this._command(value); } }); } // 原型 Head.prototype = { constructor: Head, // 执行命令 _command: function _command(value) { var editor = this.editor; 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'); } } }; /* 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 = $('设置列表
'), 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 - backcolor */ // 构造函数 function BackColor(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: 'inline-block', // droplist 内容以 block 形式展示 list: [{ $elem: $(''), value: '#000000' }, { $elem: $(''), value: '#eeece0' }, { $elem: $(''), value: '#1c487f' }, { $elem: $(''), value: '#4d80bf' }, { $elem: $(''), value: '#c24f4a' }, { $elem: $(''), value: '#8baa4a' }, { $elem: $(''), value: '#7b5ba1' }, { $elem: $(''), value: '#46acc8' }, { $elem: $(''), value: '#f9963b' }, { $elem: $(''), value: '#ffffff' }], onClick: function onClick(value) { // 注意 this 是指向当前的 BackColor 对象 _this._command(value); } }); } // 原型 BackColor.prototype = { constructor: BackColor, // 执行命令 _command: function _command(value) { var editor = this.editor; editor.cmd.do('foreColor', value); } }; /* menu - forecolor */ // 构造函数 function ForeColor$1(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: 'inline-block', // droplist 内容以 block 形式展示 list: [{ $elem: $(''), value: '#000000' }, { $elem: $(''), value: '#eeece0' }, { $elem: $(''), value: '#1c487f' }, { $elem: $(''), value: '#4d80bf' }, { $elem: $(''), value: '#c24f4a' }, { $elem: $(''), value: '#8baa4a' }, { $elem: $(''), value: '#7b5ba1' }, { $elem: $(''), value: '#46acc8' }, { $elem: $(''), value: '#f9963b' }, { $elem: $(''), value: '#ffffff' }], onClick: function onClick(value) { // 注意 this 是指向当前的 ForeColor 对象 _this._command(value); } }); } // 原型 ForeColor$1.prototype = { constructor: ForeColor$1, // 执行命令 _command: function _command(value) { var editor = this.editor; editor.cmd.do('backColor', value); } }; /* menu - quote */ // 构造函数 function Quote(editor) { this.editor = editor; this.$elem = $(' '); this.type = 'click'; // 当前是否 active 状态 this._active = false; } // 原型 Quote.prototype = { constructor: Quote, onClick: function onClick(e) { var editor = this.editor; editor.cmd.do('formatBlock', '');
},
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 = $(' 包裹即可
$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 ',
// 事件绑定
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 = $(' ');
this.type = 'panel';
// 当前是否 active 状态
this._active = false;
}
// 原型
Emoticon.prototype = {
constructor: Emoticon,
onClick: function onClick() {
this._createPanel();
},
_createPanel: function _createPanel() {
var _this = this;
// 拼接表情字符串
var faceHtml = '';
var faceStr = '😀 😃 😄 😁 😆 😅 😂 😊 😇 🙂 🙃 😉 😌 😍 😘 😗 😙 😚 😋 😜 😝 😛 🤑 🤗 🤓 😎 😏 😒 😞 😔 😟 😕 🙁 😣 😖 😫 😩 😤 😠 😡 😶 😐 😑 😯 😦 😧 😮 😲 😵 😳 😱 😨 😰 😢 😥 😭 😓 😪 😴 🙄 🤔 😬 🤐';
faceStr.split(/\s/).forEach(function (item) {
if (item) {
faceHtml += '' + item + '';
}
});
var handHtml = '';
var handStr = '🙌 👏 👋 👍 👎 👊 ✊ ️👌 ✋ 👐 💪 🙏 ️👆 👇 👈 👉 🖕 🖐 🤘 🖖';
handStr.split(/\s/).forEach(function (item) {
if (item) {
handHtml += '' + item + '';
}
});
var panel = new Panel(this, {
width: 300,
height: 200,
// 一个 Panel 包含多个 tab
tabs: [{
// 标题
title: '表情',
// 模板
tpl: '' + faceHtml + '',
// 事件绑定
events: [{
selector: 'span.w-e-item',
type: 'click',
fn: function fn(e) {
var target = e.target;
_this._insert(target.innerHTML);
// 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭
return true;
}
}]
}, // first tab end
{
// 标题
title: '手势',
// 模板
tpl: '' + handHtml + '',
// 事件绑定
events: [{
selector: 'span.w-e-item',
type: 'click',
fn: function fn(e) {
var target = e.target;
_this._insert(target.innerHTML);
// 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭
return true;
}
}]
} // second tab end
] // tabs end
});
// 显示 panel
panel.show();
// 记录属性
this.panel = panel;
},
// 插入表情
_insert: function _insert(emoji) {
var editor = this.editor;
editor.cmd.do('insertHTML', '' + emoji + '');
}
};
/*
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 ',
// 事件绑定
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 ';
}
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._createPanel();
},
_createPanel: function _createPanel() {
var _this = this;
// 创建 id
var textValId = getRandom('text-val');
var btnId = getRandom('btn');
// 创建 panel
var panel = new Panel(this, {
width: 350,
// 一个 panel 多个 tab
tabs: [{
// 标题
title: '插入视频',
// 模板
tpl: '\n \n ',
// 事件绑定
events: [{
selector: '#' + btnId,
type: 'click',
fn: function fn() {
var $text = $('#' + textValId);
var val = $text.val().trim();
// 测试用视频地址
//
if (val) {
// 插入视频
_this._insert(val);
}
// 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭
return true;
}
}]
} // first tab end
] // tabs end
}); // panel end
// 显示 panel
panel.show();
// 记录属性
this.panel = panel;
},
// 插入视频
_insert: function _insert(val) {
var editor = this.editor;
editor.cmd.do('insertHTML', val + ' \n
');
}
};
/*
menu - img
*/
// 构造函数
function Image(editor) {
this.editor = editor;
this.$elem = $(' ');
this.type = 'panel';
// 当前是否 active 状态
this._active = false;
}
// 原型
Image.prototype = {
constructor: Image,
onClick: function onClick() {
if (this._active) {
this._createEditPanel();
} else {
this._createInsertPanel();
}
},
_createEditPanel: function _createEditPanel() {
var editor = this.editor;
// id
var width30 = getRandom('width-30');
var width50 = getRandom('width-50');
var width100 = getRandom('width-100');
var delBtn = getRandom('del-btn');
// tab 配置
var tabsConfig = [{
title: '编辑图片',
tpl: '\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) {
uploadImg.uploadImg(fileList);
}
// 返回 true 可关闭 panel
return true;
}
}]
}, // first tab end
{
title: '网络图片',
tpl: '\n \n ',
events: [{
selector: '#' + linkBtnId,
type: 'click',
fn: function fn() {
var $linkUrl = $('#' + linkUrlId);
var url = $linkUrl.val().trim();
if (url) {
uploadImg.insertLinkImg(url);
}
// 返回 true 表示函数执行结束之后关闭 panel
return true;
}
}]
} // second tab end
]; // tabs end
// 判断 tabs 的显示
var tabsConfigResult = [];
if ((config.uploadImgShowBase64 || config.uploadImgServer) && window.FileReader) {
// 显示“上传图片”
tabsConfigResult.push(tabsConfig[0]);
}
if (config.showLinkImg) {
// 显示“网络图片”
tabsConfigResult.push(tabsConfig[1]);
}
// 创建 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');
}
}
};
/*
所有菜单的汇总
*/
// 存储菜单的构造函数
var MenuConstructors = {};
MenuConstructors.bold = Bold;
MenuConstructors.head = Head;
MenuConstructors.link = Link;
MenuConstructors.italic = Italic;
MenuConstructors.redo = Redo;
MenuConstructors.strikeThrough = StrikeThrough;
MenuConstructors.underline = Underline;
MenuConstructors.undo = Undo;
MenuConstructors.list = List;
MenuConstructors.justify = Justify;
MenuConstructors.foreColor = BackColor;
MenuConstructors.backColor = ForeColor$1;
MenuConstructors.quote = Quote;
MenuConstructors.code = Code;
MenuConstructors.emoticon = Emoticon;
MenuConstructors.table = Table;
MenuConstructors.video = Video;
MenuConstructors.image = Image;
/*
菜单集合
*/
// 构造函数
function Menus(editor) {
this.editor = editor;
this.menus = {};
}
// 修改原型
Menus.prototype = {
constructor: Menus,
// 初始化菜单
init: function init() {
var _this = this;
var editor = this.editor;
var config = editor.config || {};
var configMenus = config.menus || []; // 获取配置中的菜单
// 根据配置信息,创建菜单
configMenus.forEach(function (menuKey) {
var MenuConstructor = MenuConstructors[menuKey];
if (MenuConstructor && typeof MenuConstructor === 'function') {
// 创建单个菜单
_this.menus[menuKey] = new MenuConstructor(editor);
}
});
// 添加到菜单栏
this._addToToolbar();
// 绑定事件
this._bindEvent();
},
// 添加到菜单栏
_addToToolbar: function _addToToolbar() {
var editor = this.editor;
var $toolbarElem = editor.$toolbarElem;
var menus = this.menus;
objForEach(menus, function (key, menu) {
var $elem = menu.$elem;
if ($elem) {
$toolbarElem.append($elem);
}
});
},
// 绑定菜单 click mouseenter 事件
_bindEvent: function _bindEvent() {
var menus = this.menus;
var editor = this.editor;
objForEach(menus, function (key, menu) {
var type = menu.type;
if (!type) {
return;
}
var $elem = menu.$elem;
var droplist = menu.droplist;
var panel = menu.panel;
// 点击类型,例如 bold
if (type === 'click' && menu.onClick) {
$elem.on('click', function (e) {
if (editor.selection.getRange() == null) {
return;
}
menu.onClick(e);
});
}
// 下拉框,例如 head
if (type === 'droplist' && droplist) {
$elem.on('mouseenter', function (e) {
if (editor.selection.getRange() == null) {
return;
}
// 显示
droplist.showTimeoutId = setTimeout(function () {
droplist.show();
}, 200);
}).on('mouseleave', function (e) {
// 隐藏
droplist.hideTimeoutId = setTimeout(function () {
droplist.hide();
}, 0);
});
}
// 弹框类型,例如 link
if (type === 'panel' && menu.onClick) {
$elem.on('click', function (e) {
e.stopPropagation();
if (editor.selection.getRange() == null) {
return;
}
// 在自定义事件中显示 panel
menu.onClick(e);
});
}
});
},
// 尝试修改菜单状态
changeActive: function changeActive() {
var menus = this.menus;
objForEach(menus, function (key, menu) {
if (menu.tryChangeActive) {
setTimeout(function () {
menu.tryChangeActive();
}, 100);
}
});
}
};
/*
粘贴信息的处理
*/
// 获取粘贴的纯文本
function getPasteText(e) {
var clipboardData = e.clipboardData || e.originalEvent && e.originalEvent.clipboardData;
var pasteText = void 0;
if (clipboardData == null) {
pasteText = window.clipboardData && window.clipboardData.getData('text');
} else {
pasteText = clipboardData.getData('text/plain');
}
return replaceHtmlSymbol(pasteText);
}
// 获取粘贴的html
function getPasteHtml(e) {
var clipboardData = e.clipboardData || e.originalEvent && e.originalEvent.clipboardData;
var pasteText = void 0,
pasteHtml = void 0;
if (clipboardData == null) {
pasteText = window.clipboardData && window.clipboardData.getData('text');
} else {
pasteText = clipboardData.getData('text/plain');
pasteHtml = clipboardData.getData('text/html');
}
if (!pasteHtml && pasteText) {
pasteHtml = ' \n ' + replaceHtmlSymbol(pasteText) + '
';
}
if (!pasteHtml) {
return;
}
// 过滤word中状态过来的无用字符
var docSplitHtml = pasteHtml.split(' \n ',
events: [{
selector: '#' + width30,
type: 'click',
fn: function fn() {
var $img = editor._selectedImg;
if ($img) {
$img.css('max-width', '30%');
}
// 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭
return true;
}
}, {
selector: '#' + width50,
type: 'click',
fn: function fn() {
var $img = editor._selectedImg;
if ($img) {
$img.css('max-width', '50%');
}
// 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭
return true;
}
}, {
selector: '#' + width100,
type: 'click',
fn: function fn() {
var $img = editor._selectedImg;
if ($img) {
$img.css('max-width', '100%');
}
// 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭
return true;
}
}, {
selector: '#' + delBtn,
type: 'click',
fn: function fn() {
var $img = editor._selectedImg;
if ($img) {
$img.remove();
}
// 返回 true,表示该事件执行完之后,panel 要关闭。否则 panel 不会关闭
return true;
}
}]
}];
// 创建 panel 并显示
var panel = new Panel(this, {
width: 300,
tabs: tabsConfig
});
panel.show();
// 记录属性
this.panel = panel;
},
_createInsertPanel: function _createInsertPanel() {
var editor = this.editor;
var uploadImg = editor.uploadImg;
var config = editor.config;
// id
var upTriggerId = getRandom('up-trigger');
var upFileId = getRandom('up-file');
var linkUrlId = getRandom('link-url');
var linkBtnId = getRandom('link-btn');
// tabs 的配置
var tabsConfig = [{
title: '上传图片',
tpl: ' \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 += ' \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) {
// 选取不是空,用