/*! * UEditor * version: ueditor * build: Wed Aug 10 2016 11:06:16 GMT+0800 (CST) */ var isOneFile = true; //发通知那边用,记录单次是否只上传(拖拽)一个文件 (function () { // editor.js UEDITOR_CONFIG = window.UEDITOR_CONFIG || {}; var baidu = window.baidu || {}; window.baidu = baidu; window.UE = baidu.editor = window.UE || {}; UE.plugins = {}; UE.commands = {}; UE.instants = {}; UE.I18N = {}; UE._customizeUI = {}; UE.XTSendData = []; UE.version = "1.4.3"; UE.account = {}; UE.addressList = []; UE.lastTime = { "time": 0 }; UE.isSendEnter = false; UE.isSendDelete = false; UE.isDeleteAll = false; //UE.deleteReturn = false; var dom = UE.dom = {}; //复制表格用到的变量 var tableCopyList, isFullCol, isFullRow; //特殊字符 var inputkeycodes = ['BracketLeft', 'BracketRight', 'Backquote', 'Minus', 'Equal', 'Backslash', 'Semicolon', 'Quote', 'Comma', 'Period', 'Slash']; var inputType = false;//判断输入法输入状态 //判断是否是在发通知页面 var isNotice = window.location.host == 'notice.chaoxing.com'; var myLoadingId = ''; //发通知那边用,当标题为空时记录第一个上传的附件 //视频附件后缀 var videoReg = new RegExp(/mp4|3gp|avi|rmvb|asf|divx|mpg|mpeg|mpe|mkv|vob|flv|m4v|mov|f4v|wmv/) function RMap() { this.elements = new Array(); //向MAP中增加元素(key, value) this.put = function (_key, _value) { this.removeByKey(_key); this.elements.push({ key: _key, value: _value }); }; //获取指定KEY的元素值VALUE,失败返回NULL this.get = function (_key) { try { for (i = 0; i < this.elements.length; i++) { if (this.elements[i].key == _key) { return this.elements[i].value; } } } catch (e) { return false; } return false; }; //删除指定KEY的元素,成功返回True,失败返回False this.removeByKey = function (_key) { var bln = false; try { for (i = 0; i < this.elements.length; i++) { if (this.elements[i].key == _key) { this.elements.splice(i, 1); return true; } } } catch (e) { bln = false; } return bln; }; } // core/browser.js /** * 浏览器判断模块 * @file * @module UE.browser * @since 1.2.6.1RichTextUitl.puid */ /** * 提供浏览器检测的模块 * @unfile * @module UE.browser */ var browser = UE.browser = function () { var agent = navigator.userAgent.toLowerCase(), opera = window.opera, browser = { /** * @property {boolean} ie 检测当前浏览器是否为IE * @example * ```javascript * if ( UE.browser.ie ) { * console.log( '当前浏览器是IE' ); * } * ``` */ ie: /(msie\s|trident.*rv:)([\w.]+)/.test(agent), /** * @property {boolean} opera 检测当前浏览器是否为Opera * @example * ```javascript * if ( UE.browser.opera ) { * console.log( '当前浏览器是Opera' ); * } * ``` */ opera: (!!opera && opera.version), /** * @property {boolean} firefox 检测当前浏览器是否为Firefox * @example * ```javascript * if ( UE.browser.firefox ) { * console.log( '当前浏览器是Firefox' ); * } * ``` */ firefox: (agent.indexOf("firefox") > -1), /** * @property {boolean} webkit 检测当前浏览器是否是webkit内核的浏览器 * @example * ```javascript * if ( UE.browser.webkit ) { * console.log( '当前浏览器是webkit内核浏览器' ); * } * ``` */ webkit: (agent.indexOf(' applewebkit/') > -1), /** * @property {boolean} mac 检测当前浏览器是否是运行在mac平台下 * @example * ```javascript * if ( UE.browser.mac ) { * console.log( '当前浏览器运行在mac平台下' ); * } * ``` */ mac: (agent.indexOf('macintosh') > -1), /** * @property {boolean} quirks 检测当前浏览器是否处于“怪异模式”下 * @example * ```javascript * if ( UE.browser.quirks ) { * console.log( '当前浏览器运行处于“怪异模式”' ); * } * ``` */ quirks: (document.compatMode == 'BackCompat') }; /** * @property {boolean} gecko 检测当前浏览器内核是否是gecko内核 * @example * ```javascript * if ( UE.browser.gecko ) { * console.log( '当前浏览器内核是gecko内核' ); * } * ``` */ browser.gecko = (navigator.product == 'Gecko' && !browser.webkit && !browser.opera && !browser.ie); var version = 0; // Internet Explorer 6.0+ if (browser.ie) { var v1 = agent.match(/(?:msie\s([\w.]+))/); var v2 = agent.match(/(?:trident.*rv:([\w.]+))/); if (v1 && v2 && v1[1] && v2[1]) { version = Math.max(v1[1] * 1, v2[1] * 1); } else if (v1 && v1[1]) { version = v1[1] * 1; } else if (v2 && v2[1]) { version = v2[1] * 1; } else { version = 0; } browser.ie11Compat = document.documentMode == 11; /** * @property { boolean } ie9Compat 检测浏览器模式是否为 IE9 兼容模式 * @warning 如果浏览器不是IE, 则该值为undefined * @example * ```javascript * if ( UE.browser.ie9Compat ) { * console.log( '当前浏览器运行在IE9兼容模式下' ); * } * ``` */ browser.ie9Compat = document.documentMode == 9; /** * @property { boolean } ie8 检测浏览器是否是IE8浏览器 * @warning 如果浏览器不是IE, 则该值为undefined * @example * ```javascript * if ( UE.browser.ie8 ) { * console.log( '当前浏览器是IE8浏览器' ); * } * ``` */ browser.ie8 = !!document.documentMode; /** * @property { boolean } ie8Compat 检测浏览器模式是否为 IE8 兼容模式 * @warning 如果浏览器不是IE, 则该值为undefined * @example * ```javascript * if ( UE.browser.ie8Compat ) { * console.log( '当前浏览器运行在IE8兼容模式下' ); * } * ``` */ browser.ie8Compat = document.documentMode == 8; /** * @property { boolean } ie7Compat 检测浏览器模式是否为 IE7 兼容模式 * @warning 如果浏览器不是IE, 则该值为undefined * @example * ```javascript * if ( UE.browser.ie7Compat ) { * console.log( '当前浏览器运行在IE7兼容模式下' ); * } * ``` */ browser.ie7Compat = ((version == 7 && !document.documentMode) || document.documentMode == 7); /** * @property { boolean } ie6Compat 检测浏览器模式是否为 IE6 模式 或者怪异模式 * @warning 如果浏览器不是IE, 则该值为undefined * @example * ```javascript * if ( UE.browser.ie6Compat ) { * console.log( '当前浏览器运行在IE6模式或者怪异模式下' ); * } * ``` */ browser.ie6Compat = (version < 7 || browser.quirks); browser.ie9above = version > 8; browser.ie9below = version < 9; browser.ie11above = version > 10; browser.ie11below = version < 11; } // Gecko. if (browser.gecko) { var geckoRelease = agent.match(/rv:([\d\.]+)/); if (geckoRelease) { geckoRelease = geckoRelease[1].split('.'); version = geckoRelease[0] * 10000 + (geckoRelease[1] || 0) * 100 + (geckoRelease[2] || 0) * 1; } } /** * @property { Number } chrome 检测当前浏览器是否为Chrome, 如果是,则返回Chrome的大版本号 * @warning 如果浏览器不是chrome, 则该值为undefined * @example * ```javascript * if ( UE.browser.chrome ) { * console.log( '当前浏览器是Chrome' ); * } * ``` */ if (/chrome\/(\d+\.\d)/i.test(agent)) { browser.chrome = +RegExp['\x241']; } /** * @property { Number } safari 检测当前浏览器是否为Safari, 如果是,则返回Safari的大版本号 * @warning 如果浏览器不是safari, 则该值为undefined * @example * ```javascript * if ( UE.browser.safari ) { * console.log( '当前浏览器是Safari' ); * } * ``` */ if (/(\d+\.\d)?(?:\.\d)?\s+safari\/?(\d+\.\d+)?/i.test(agent) && !/chrome/i.test(agent)) { browser.safari = +(RegExp['\x241'] || RegExp['\x242']); } // Opera 9.50+ if (browser.opera) version = parseFloat(opera.version()); // WebKit 522+ (Safari 3+) if (browser.webkit) version = parseFloat(agent.match(/ applewebkit\/(\d+)/)[1]); /** * @property { Number } version 检测当前浏览器版本号 * @remind *
* console.log( wrapNode.innerHTML ); * * * UE.dom.domUtils.breakParent( node, parent ); * //拆分后 * //output: * console.log( wrapNode.innerHTML ); * * ``` */ breakParent: function (node, parent) { var tmpNode, parentClone = node, clone = node, leftNodes, rightNodes; do { parentClone = parentClone.parentNode; if (leftNodes) { tmpNode = parentClone.cloneNode(false); tmpNode.appendChild(leftNodes); leftNodes = tmpNode; tmpNode = parentClone.cloneNode(false); tmpNode.appendChild(rightNodes); rightNodes = tmpNode; } else { leftNodes = parentClone.cloneNode(false); rightNodes = leftNodes.cloneNode(false); } while (tmpNode = clone.previousSibling) { leftNodes.insertBefore(tmpNode, leftNodes.firstChild); } while (tmpNode = clone.nextSibling) { rightNodes.appendChild(tmpNode); } clone = parentClone; } while (parent !== parentClone); tmpNode = parent.parentNode; tmpNode.insertBefore(leftNodes, parent); tmpNode.insertBefore(rightNodes, parent); tmpNode.insertBefore(node, rightNodes); var elementId = parent.getAttribute('element-id') domUtils.remove(parent); //20200603 协同编辑 加id if (leftNodes && domUtils.isBlockElm(leftNodes)) { leftNodes.setAttribute('element-id', elementId); } if (rightNodes && domUtils.isBlockElm(rightNodes)) { rightNodes.setAttribute('element-id', domUtils.getRandomId()); } return node; }, /** * 检查节点node是否是空inline节点 * @method isEmptyInlineElement * @param { Node } node 需要检测的节点对象 * @return { Number } 如果给定的节点是空的inline节点, 则返回1, 否则返回0。 * @example * ```html * => 1 * => 1 * => 1 * xx => 0 * ``` */ isEmptyInlineElement: function (node) { if (node.nodeType != 1 || !dtd.$removeEmpty[node.tagName]) { return 0; } node = node.firstChild; while (node) { //如果是创建的bookmark就跳过 if (domUtils.isBookmarkNode(node)) { return 0; } if (node.nodeType == 1 && !domUtils.isEmptyInlineElement(node) || node.nodeType == 3 && !domUtils.isWhitespace(node) ) { return 0; } node = node.nextSibling; } return 1; }, /** * 删除node节点下首尾两端的空白文本子节点 * @method trimWhiteTextNode * @param { Element } node 需要执行删除操作的元素对象 * @example * ```javascript * var node = document.createElement("div"); * * node.appendChild( document.createTextNode( "" ) ); * * node.appendChild( document.createElement("div") ); * * node.appendChild( document.createTextNode( "" ) ); * * //3 * console.log( node.childNodes.length ); * * UE.dom.domUtils.trimWhiteTextNode( node ); * * //1 * console.log( node.childNodes.length ); * ``` */ trimWhiteTextNode: function (node) { function remove(dir) { var child; while ((child = node[dir]) && child.nodeType == 3 && domUtils.isWhitespace(child)) { node.removeChild(child); } } remove('firstChild'); remove('lastChild'); }, /** * 合并node节点下相同的子节点 * @name mergeChild * @desc * UE.dom.domUtils.mergeChild(node,tagName) //tagName要合并的子节点的标签 * @example *
xxaaxx
* ==> UE.dom.domUtils.mergeChild(node,'span') *xxaaxx
*/ mergeChild: function (node, tagName, attrs) { var list = domUtils.getElementsByTagName(node, node.tagName.toLowerCase()); for (var i = 0, ci; ci = list[i++];) { if (!ci.parentNode || domUtils.isBookmarkNode(ci)) { continue; } //span单独处理 if (ci.tagName.toLowerCase() == 'span') { //20200513 classname带todo的不处理 解决多选框设置字体删除框 if (node === ci.parentNode && !(ci.className && ci.className.indexOf('todo') != -1)) { domUtils.trimWhiteTextNode(node); if (node.childNodes.length == 1) { // 遍历ci元素的所有属性 for (var t = 0, attr; attr = ci.attributes[t++];) { // 将每个属性设置到node元素上 if(attr.name == 'style'){ continue; } node.setAttribute(attr.name, attr.value); } node.style.cssText = ci.style.cssText + ";" + node.style.cssText; domUtils.remove(ci, true); continue; } } ci.style.cssText = node.style.cssText + ';' + ci.style.cssText; if (attrs) { var style = attrs.style; if (style) { style = style.split(';'); for (var j = 0, s; s = style[j++];) { ci.style[utils.cssStyleToDomStyle(s.split(':')[0])] = s.split(':')[1]; } } } //20200513 classname带todo的不处理 解决多选框设置字体删除框 if (domUtils.isSameStyle(ci, node) && !(ci.className && ci.className.indexOf('todo') != -1)) { domUtils.remove(ci, true); } continue; } if (domUtils.isSameElement(node, ci)) { domUtils.remove(ci, true); } } }, /** * 原生方法getElementsByTagName的封装 * @method getElementsByTagName * @param { Node } node 目标节点对象 * @param { String } tagName 需要查找的节点的tagName, 多个tagName以空格分割 * @return { Array } 符合条件的节点集合 */ getElementsByTagName: function (node, name, filter) { if (filter && utils.isString(filter)) { var className = filter; filter = function (node) { return domUtils.hasClass(node, className) } } name = utils.trim(name).replace(/[ ]{2,}/g, ' ').split(' '); var arr = []; for (var n = 0, ni; ni = name[n++];) { var list = node.getElementsByTagName(ni); for (var i = 0, ci; ci = list[i++];) { if (!filter || filter(ci)) arr.push(ci); } } return arr; }, /** * 将节点node提取到父节点上 * @method mergeToParent * @param { Element } node 需要提取的元素对象 * @example * ```html *xxxx[xxxx]x
==> range.applyInlineStyle("strong") ==>xxxx[xxxx]x
* ``` */ /** * 给range选区中的内容添加给定的inline标签, 并且为标签附加上一些初始化属性。 * @method applyInlineStyle * @param { String } tagName 需要添加的标签名 * @param { Object } attrs 跟随新添加的标签的属性 * @return { UE.dom.Range } 当前选区 * @example * ```html *xxxx[xxxx]x
* * ==> * * * range.applyInlineStyle("strong",{"style":"font-size:12px"}) * * ==> * *xxxx[xxxx]x
* ``` */ applyInlineStyle: function (tagName, attrs, list) { if (this.collapsed) return this; this.trimBoundary().enlarge(false, function (node) { return node.nodeType == 1 && domUtils.isBlockElm(node) }).adjustmentBoundary(); var bookmark = this.createBookmark(), end = bookmark.end, filterFn = function (node) { return node.nodeType == 1 ? node.tagName.toLowerCase() != 'br' : !domUtils.isWhitespace(node); }, current = domUtils.getNextDomNode(bookmark.start, false, filterFn), node, pre, range = this.cloneRange(); while (current && (domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING)) { // 20200526 多选框设置字体后多选框外层套span font-size,导致多选框上移 // if (current.nodeType == 3 || dtd[tagName][current.tagName]) { //解决a标签不能设置颜色和 if ((current.nodeType == 3 || (dtd[tagName][current.tagName] && current.tagName != 'A' && current.tagName != 'SPAN' && current.tagName != 'STRIKE')) && !(current.className && current.className.indexOf('todo') > -1)) { range.setStartBefore(current); node = current; while (node && (node.nodeType == 3 || dtd[tagName][node.tagName]) && node !== end) { pre = node; node = domUtils.getNextDomNode(node, node.nodeType == 1, null, function (parent) { return dtd[tagName][parent.tagName]; }); } var frag = range.setEndAfter(pre).extractContents(), elm; if (list && list.length > 0) { var level, top; top = level = list[0].cloneNode(false); for (var i = 1, ci; ci = list[i++];) { level.appendChild(ci.cloneNode(false)); level = level.firstChild; } elm = level; } else { elm = range.document.createElement(tagName); } if (attrs) { domUtils.setAttributes(elm, attrs); } elm.appendChild(frag); range.insertNode(list ? top : elm); if (tagName == 'em') { elm.className = 'sqp-emphasize-dot' } //处理下滑线在a上的情况 var aNode; if (tagName == 'span' && attrs.style && /text\-decoration/.test(attrs.style) && (aNode = domUtils.findParentByTagName(elm, 'a', true))) { domUtils.setAttributes(aNode, attrs); domUtils.remove(elm, true); elm = aNode; } else { domUtils.mergeSibling(elm); domUtils.clearEmptySibling(elm); } //去除子节点相同的 domUtils.mergeChild(elm, attrs); current = domUtils.getNextDomNode(elm, false, filterFn); domUtils.mergeToParent(elm); if (node === end) { break; } } else { current = domUtils.getNextDomNode(current, true, filterFn); } } return this.moveToBookmark(bookmark); }, /** * 移除当前选区内指定的inline标签,但保留其中的内容 * @method removeInlineStyle * @param { String } tagName 需要移除的标签名 * @return { UE.dom.Range } 当前的range对象 * @example * ```html * xx[xxxxyyyzz]z => range.removeInlineStyle(["em"]) => xx[xxxxyyyzz]z * ``` */ /** * 移除当前选区内指定的一组inline标签,但保留其中的内容 * @method removeInlineStyle * @param { Array } tagNameArr 需要移除的标签名的数组 * @return { UE.dom.Range } 当前的range对象 * @see UE.dom.Range:removeInlineStyle(String) */ removeInlineStyle: function (tagNames) { if (this.collapsed) return this; tagNames = utils.isArray(tagNames) ? tagNames : [tagNames]; this.shrinkBoundary().adjustmentBoundary(); var start = this.startContainer, end = this.endContainer; while (1) { if (start.nodeType == 1) { if (utils.indexOf(tagNames, start.tagName.toLowerCase()) > -1) { break; } if (start.tagName.toLowerCase() == 'body') { start = null; break; } } start = start.parentNode; } while (1) { if (end.nodeType == 1) { if (utils.indexOf(tagNames, end.tagName.toLowerCase()) > -1) { break; } if (end.tagName.toLowerCase() == 'body') { end = null; break; } } end = end.parentNode; } var bookmark = this.createBookmark(), frag, tmpRange; if (start) { tmpRange = this.cloneRange().setEndBefore(bookmark.start).setStartBefore(start); frag = tmpRange.extractContents(); tmpRange.insertNode(frag); domUtils.clearEmptySibling(start, true); start.parentNode.insertBefore(bookmark.start, start); } if (end) { tmpRange = this.cloneRange().setStartAfter(bookmark.end).setEndAfter(end); frag = tmpRange.extractContents(); tmpRange.insertNode(frag); domUtils.clearEmptySibling(end, false, true); end.parentNode.insertBefore(bookmark.end, end.nextSibling); } var current = domUtils.getNextDomNode(bookmark.start, false, function (node) { return node.nodeType == 1; }), next; while (current && current !== bookmark.end) { next = domUtils.getNextDomNode(current, true, function (node) { return node.nodeType == 1; }); if (utils.indexOf(tagNames, current.tagName.toLowerCase()) > -1) { domUtils.remove(current, true); } current = next; } //20200107去掉拆分后的空标签 if (next && next.nextSibling && next.nextSibling.nodeType == 1) { next = next.nextSibling; var nextvalue = next.innerText.replace(new RegExp(UE.dom.domUtils.fillChar, 'g'), '').replace(/^\s+|\s+$/g, ''); if (nextvalue == '' && next.nodeType == 1 && next.childNodes.length <= 1) { domUtils.remove(next); } } return this.moveToBookmark(bookmark); }, /** * 获取当前选中的自闭合的节点 * @method getClosedNode * @return { Node | NULL } 如果当前选中的是自闭合节点, 则返回该节点, 否则返回NULL */ getClosedNode: function () { var node; if (!this.collapsed) { var range = this.cloneRange().adjustmentBoundary().shrinkBoundary(); if (selectOneNode(range)) { var child = range.startContainer.childNodes[range.startOffset]; if (child && child.nodeType == 1 && (dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName])) { node = child; } } } return node; }, /** * 在页面上高亮range所表示的选区 * @method select * @return { UE.dom.Range } 返回当前Range对象 */ //这里不区分ie9以上,trace:3824 select: browser.ie ? function (noFillData, textRange) { var nativeRange; if (!this.collapsed) this.shrinkBoundary(); var node = this.getClosedNode(); if (node && !textRange) { try { nativeRange = this.document.body.createControlRange(); nativeRange.addElement(node); nativeRange.select(); } catch (e) { } return this; } var bookmark = this.createBookmark(), start = bookmark.start, end; nativeRange = this.document.body.createTextRange(); nativeRange.moveToElementText(start); nativeRange.moveStart('character', 1); if (!this.collapsed) { var nativeRangeEnd = this.document.body.createTextRange(); end = bookmark.end; nativeRangeEnd.moveToElementText(end); nativeRange.setEndPoint('EndToEnd', nativeRangeEnd); } else { if (!noFillData && this.startContainer.nodeType != 3) { //使用|x固定住光标 var tmpText = this.document.createTextNode(domUtils.fillChar), tmp = this.document.createElement('span'); tmp.appendChild(this.document.createTextNode(domUtils.fillChar)); start.parentNode.insertBefore(tmp, start); start.parentNode.insertBefore(tmpText, start); //当点b,i,u时,不能清除i上边的b removeFillData(this.document, tmpText); fillData = tmpText; mergeSibling(tmp, 'previousSibling'); mergeSibling(start, 'nextSibling'); nativeRange.moveStart('character', -1); nativeRange.collapse(true); } } this.moveToBookmark(bookmark); tmp && domUtils.remove(tmp); //IE在隐藏状态下不支持range操作,catch一下 try { nativeRange.select(); } catch (e) { } return this; } : function (notInsertFillData) { function checkOffset(rng) { function check(node, offset, dir) { if (node.nodeType == 3 && node.nodeValue.length < offset) { rng[dir + 'Offset'] = node.nodeValue.length } } check(rng.startContainer, rng.startOffset, 'start'); check(rng.endContainer, rng.endOffset, 'end'); } var win = domUtils.getWindow(this.document), sel = win.getSelection(), txtNode; //FF下关闭自动长高时滚动条在关闭dialog时会跳 //ff下如果不body.focus将不能定位闭合光标到编辑器内 browser.gecko ? this.document.body.focus() : win.focus(); if (sel) { sel.removeAllRanges(); // trace:870 chrome/safari后边是br对于闭合得range不能定位 所以去掉了判断 // this.startContainer.nodeType != 3 &&! ((child = this.startContainer.childNodes[this.startOffset]) && child.nodeType == 1 && child.tagName == 'BR' if (this.collapsed && !notInsertFillData) { // //opear如果没有节点接着,原生的不能够定位,不能在body的第一级插入空白节点 // if (notInsertFillData && browser.opera && !domUtils.isBody(this.startContainer) && this.startContainer.nodeType == 1) { // var tmp = this.document.createTextNode(''); // this.insertNode(tmp).setStart(tmp, 0).collapse(true); // } // //处理光标落在文本节点的情况 //处理以下的情况 //|xxxx //xxxx|xxxx //xxxx| var start = this.startContainer, child = start; if (start.nodeType == 1) { child = start.childNodes[this.startOffset]; } if (!(start.nodeType == 3 && this.startOffset) && (child ? (!child.previousSibling || child.previousSibling.nodeType != 3) : (!start.lastChild || start.lastChild.nodeType != 3) ) ) { txtNode = this.document.createTextNode(domUtils.fillChar); //跟着前边走 this.insertNode(txtNode); removeFillData(this.document, txtNode); mergeSibling(txtNode, 'previousSibling'); mergeSibling(txtNode, 'nextSibling'); fillData = txtNode; this.setStart(txtNode, browser.webkit ? 1 : 0).collapse(true); } } var nativeRange = this.document.createRange(); if (this.collapsed && browser.opera && this.startContainer.nodeType == 1) { var child = this.startContainer.childNodes[this.startOffset]; if (!child) { //往前靠拢 child = this.startContainer.lastChild; if (child && domUtils.isBr(child)) { this.setStartBefore(child).collapse(true); } } else { //向后靠拢 while (child && domUtils.isBlockElm(child)) { if (child.nodeType == 1 && child.childNodes[0]) { child = child.childNodes[0] } else { break; } } child && this.setStartBefore(child).collapse(true) } } //是createAddress最后一位算的不准,现在这里进行微调 checkOffset(this); nativeRange.setStart(this.startContainer, this.startOffset); nativeRange.setEnd(this.endContainer, this.endOffset); sel.addRange(nativeRange); } return this; }, /** * 滚动到当前range开始的位置 * @method scrollToView * @param { Window } win 当前range对象所属的window对象 * @return { UE.dom.Range } 当前Range对象 */ /** * 滚动到距离当前range开始位置 offset 的位置处 * @method scrollToView * @param { Window } win 当前range对象所属的window对象 * @param { Number } offset 距离range开始位置处的偏移量, 如果为正数, 则向下偏移, 反之, 则向上偏移 * @return { UE.dom.Range } 当前Range对象 */ scrollToView: function (win, offset) { win = win ? window : domUtils.getWindow(this.document); var me = this, span = me.document.createElement('span'); //trace:717 span.innerHTML = ' '; me.cloneRange().insertNode(span); domUtils.scrollToView(span, win, offset); domUtils.remove(span); return me; }, /** * 判断当前选区内容是否占位符 * @private * @method inFillChar * @return { Boolean } 如果是占位符返回true,否则返回false */ inFillChar: function () { var start = this.startContainer; if (this.collapsed && start.nodeType == 3 && start.nodeValue.replace(new RegExp('^' + domUtils.fillChar), '').length + 1 == start.nodeValue.length ) { return true; } return false; }, /** * 保存 * @method createAddress * @private * @return { Boolean } 返回开始和结束的位置 * @example * ```html * ** aaaa * * * bbbb * * *
* * * * ``` */ createAddress: function (ignoreEnd, ignoreTxt) { var addr = {}, me = this; function getAddress(isStart) { var node = isStart ? me.startContainer : me.endContainer; var hasFillChar = 0; var parents = domUtils.findParents(node, true, function (node) { return !domUtils.isBody(node) }), addrs = []; for (var i = 0, ci; ci = parents[i++];) { hasFillChar = 0; var index = domUtils.getNodeIndex(ci, ignoreTxt); if (domUtils.isFillChar(ci) && index == 0) { //20200702 8203不计 break; } else { //20200619 去除8203,还原不准 if (ci.parentNode && ci.parentNode.firstChild && domUtils.isFillChar(ci.parentNode.firstChild)) { hasFillChar = 1; } if (index > 0) { addrs.push(index - hasFillChar); } else { addrs.push(index); } } } var firstIndex = 0; hasFillChar = 0; if (ignoreTxt) { if (node.nodeType == 3) { var tmpNode = node.previousSibling; while (tmpNode && tmpNode.nodeType == 3) { firstIndex += tmpNode.nodeValue.replace(fillCharReg, '').length; tmpNode = tmpNode.previousSibling; } if (node.nodeValue.indexOf(domUtils.fillChar) > -1) { //8203和文字连在一起 hasFillChar = 1; } firstIndex += (isStart ? me.startOffset : me.endOffset) - hasFillChar; // firstIndex += (isStart ? me.startOffset : me.endOffset)// - (fillCharReg.test(node.nodeValue) ? 1 : 0 ) } else { if (node && node.firstChild && domUtils.isFillChar(node.firstChild)) { //"8203" "XXX"
hasFillChar = 1; } node = node.childNodes[isStart ? me.startOffset : me.endOffset]; if (node) { firstIndex = domUtils.getNodeIndex(node, ignoreTxt) - hasFillChar; } else { node = isStart ? me.startContainer : me.endContainer; var first = node.firstChild; while (first) { if (domUtils.isFillChar(first)) { first = first.nextSibling; continue; } firstIndex++; if (first.nodeType == 3) { while (first && first.nodeType == 3) { first = first.nextSibling; } } else { first = first.nextSibling; } } } } } else { if (node.nodeType == 3) { if (node.nodeValue.indexOf(domUtils.fillChar) > -1) { //8203和文字连在一起 hasFillChar = 1; } } else { if (node && node.firstChild && domUtils.isFillChar(node.firstChild)) { //"8203" "XXX"
hasFillChar = 1; } } firstIndex = (isStart ? me.startOffset : me.endOffset) - hasFillChar; // firstIndex = isStart ? domUtils.isFillChar(node) ? 0 : me.startOffset : me.endOffset; } if (firstIndex < 0) { firstIndex = 0; } addrs.push(firstIndex); return addrs; } addr.startAddress = getAddress(true); if (!ignoreEnd) { addr.endAddress = me.collapsed ? [].concat(addr.startAddress) : getAddress(); } // if(addr.startAddress.length == 1){ // addr.startAddress.push(0) // } // if(addr.endAddress.length == 1){ // addr.endAddress.push(0) // } return addr; }, /** * 保存 * @method createAddress * @private * @return { Boolean } 返回开始和结束的位置 * @example * ```html * ** aaaa * * * bbbb * * *
* * * * ``` */ moveToAddress: function (addr, ignoreEnd) { var me = this; function getNode(address, isStart) { var tmpNode = me.document.body, parentNode, offset; for (var i = 0, ci, l = address.length; i < l; i++) { ci = address[i]; parentNode = tmpNode; //20200619 去除8203,还原不准 if (tmpNode && tmpNode.firstChild && domUtils.isFillChar(tmpNode.firstChild) && tmpNode.childNodes.length > 1) { domUtils.remove(tmpNode.firstChild); } tmpNode = tmpNode.childNodes[ci]; if (!tmpNode) { offset = ci; break; } } if (isStart) { if (tmpNode) { me.setStartBefore(tmpNode) } else { me.setStart(parentNode, offset) } } else { if (tmpNode) { me.setEndBefore(tmpNode) } else { me.setEnd(parentNode, offset) } } } getNode(addr.startAddress, true); !ignoreEnd && addr.endAddress && getNode(addr.endAddress); return me; }, /** * 判断给定的Range对象是否和当前Range对象表示的是同一个选区 * @method equals * @param { UE.dom.Range } 需要判断的Range对象 * @return { Boolean } 如果给定的Range对象与当前Range对象表示的是同一个选区, 则返回true, 否则返回false */ equals: function (rng) { for (var p in this) { if (this.hasOwnProperty(p)) { if (this[p] !== rng[p]) return false } } return true; }, /** * 遍历range内的节点。每当遍历一个节点时, 都会执行参数项 doFn 指定的函数, 该函数的接受当前遍历的节点 * 作为其参数。 * @method traversal * @param { Function } doFn 对每个遍历的节点要执行的方法, 该方法接受当前遍历的节点作为其参数 * @return { UE.dom.Range } 当前range对象 * @example * ```html * * * * * * * * * * * ``` */ /** * 遍历range内的节点。 * 每当遍历一个节点时, 都会执行参数项 doFn 指定的函数, 该函数的接受当前遍历的节点 * 作为其参数。 * 可以通过参数项 filterFn 来指定一个过滤器, 只有符合该过滤器过滤规则的节点才会触 * 发doFn函数的执行 * @method traversal * @param { Function } doFn 对每个遍历的节点要执行的方法, 该方法接受当前遍历的节点作为其参数 * @param { Function } filterFn 过滤器, 该函数接受当前遍历的节点作为参数, 如果该节点满足过滤 * 规则, 请返回true, 该节点会触发doFn, 否则, 请返回false, 则该节点不 * 会触发doFn。 * @return { UE.dom.Range } 当前range对象 * @see UE.dom.Range:traversal(Function) * @example * ```html * * * * * * * * * * * ``` */ traversal: function (doFn, filterFn) { if (this.collapsed) return this; var bookmark = this.createBookmark(), end = bookmark.end, current = domUtils.getNextDomNode(bookmark.start, false, filterFn); while (current && current !== end && (domUtils.getPosition(current, end) & domUtils.POSITION_PRECEDING)) { var tmpNode = domUtils.getNextDomNode(current, false, filterFn); doFn(current); current = tmpNode; } return this.moveToBookmark(bookmark); } }; })(); // core/Selection.js /** * 选集 * @file * @module UE.dom * @class Selection * @since 1.2.6.1 */ /** * 选区集合 * @unfile * @module UE.dom * @class Selection */ (function () { function getBoundaryInformation(range, start) { var getIndex = domUtils.getNodeIndex; range = range.duplicate(); range.collapse(start); var parent = range.parentElement(); //如果节点里没有子节点,直接退出 if (!parent.hasChildNodes()) { return { container: parent, offset: 0 }; } var siblings = parent.children, child, testRange = range.duplicate(), startIndex = 0, endIndex = siblings.length - 1, index = -1, distance; while (startIndex <= endIndex) { index = Math.floor((startIndex + endIndex) / 2); child = siblings[index]; testRange.moveToElementText(child); var position = testRange.compareEndPoints('StartToStart', range); if (position > 0) { endIndex = index - 1; } else if (position < 0) { startIndex = index + 1; } else { //trace:1043 return { container: parent, offset: getIndex(child) }; } } if (index == -1) { testRange.moveToElementText(parent); testRange.setEndPoint('StartToStart', range); distance = testRange.text.replace(/(\r\n|\r)/g, '\n').length; siblings = parent.childNodes; if (!distance) { child = siblings[siblings.length - 1]; return { container: child, offset: child.nodeValue.length }; } var i = siblings.length; while (distance > 0) { distance -= siblings[--i].nodeValue.length; } return { container: siblings[i], offset: -distance }; } testRange.collapse(position > 0); testRange.setEndPoint(position > 0 ? 'StartToStart' : 'EndToStart', range); distance = testRange.text.replace(/(\r\n|\r)/g, '\n').length; if (!distance) { return dtd.$empty[child.tagName] || dtd.$nonChild[child.tagName] ? { container: parent, offset: getIndex(child) + (position > 0 ? 0 : 1) } : { container: child, offset: position > 0 ? 0 : child.childNodes.length } } while (distance > 0) { try { var pre = child; child = child[position > 0 ? 'previousSibling' : 'nextSibling']; distance -= child.nodeValue.length; } catch (e) { return { container: parent, offset: getIndex(pre) }; } } return { container: child, offset: position > 0 ? -distance : child.nodeValue.length + distance } } /** * 将ieRange转换为Range对象 * @param {Range} ieRange ieRange对象 * @param {Range} range Range对象 * @return {Range} range 返回转换后的Range对象 */ function transformIERangeToRange(ieRange, range) { if (ieRange.item) { range.selectNode(ieRange.item(0)); } else { var bi = getBoundaryInformation(ieRange, true); range.setStart(bi.container, bi.offset); if (ieRange.compareEndPoints('StartToEnd', ieRange) != 0) { bi = getBoundaryInformation(ieRange, false); range.setEnd(bi.container, bi.offset); } } return range; } /** * 获得ieRange * @param {Selection} sel Selection对象 * @return {ieRange} 得到ieRange */ function _getIERange(sel) { var ieRange; //ie下有可能报错 try { ieRange = sel.getNative().createRange(); } catch (e) { return null; } var el = ieRange.item ? ieRange.item(0) : ieRange.parentElement(); if ((el.ownerDocument || el) === sel.document) { return ieRange; } return null; } var Selection = dom.Selection = function (doc) { var me = this, iframe; me.document = doc; if (browser.ie9below) { iframe = domUtils.getWindow(doc).frameElement; domUtils.on(iframe, 'beforedeactivate', function () { me._bakIERange = me.getIERange(); }); domUtils.on(iframe, 'activate', function () { try { if (!_getIERange(me) && me._bakIERange) { me._bakIERange.select(); } } catch (ex) { } me._bakIERange = null; }); } iframe = doc = null; }; Selection.prototype = { rangeInBody: function (rng, txtRange) { var node = browser.ie9below || txtRange ? rng.item ? rng.item() : rng.parentElement() : rng.startContainer; return node === this.document.body || domUtils.inDoc(node, this.document); }, /** * 获取原生seleciton对象 * @method getNative * @return { Object } 获得selection对象 * @example * ```javascript * editor.selection.getNative(); * ``` */ getNative: function () { var doc = this.document; try { return !doc ? null : browser.ie9below ? doc.selection : domUtils.getWindow(doc).getSelection(); } catch (e) { return null; } }, /** * 获得ieRange * @method getIERange * @return { Object } 返回ie原生的Range * @example * ```javascript * editor.selection.getIERange(); * ``` */ getIERange: function () { var ieRange = _getIERange(this); if (!ieRange) { if (this._bakIERange) { return this._bakIERange; } } return ieRange; }, /** * 缓存当前选区的range和选区的开始节点 * @method cache */ cache: function () { this.clear(); this._cachedRange = this.getRange(); this._cachedStartElement = this.getStart(); this._cachedStartElementPath = this.getStartElementPath(); }, /** * 获取选区开始位置的父节点到body * @method getStartElementPath * @return { Array } 返回父节点集合 * @example * ```javascript * editor.selection.getStartElementPath(); * ``` */ getStartElementPath: function () { if (this._cachedStartElementPath) { return this._cachedStartElementPath; } var start = this.getStart(); if (start) { return domUtils.findParents(start, true, null, true) } return []; }, /** * 清空缓存 * @method clear */ clear: function () { this._cachedStartElementPath = this._cachedRange = this._cachedStartElement = null; }, /** * 编辑器是否得到了选区 * @method isFocus */ isFocus: function () { try { if (browser.ie9below) { var nativeRange = _getIERange(this); return !!(nativeRange && this.rangeInBody(nativeRange)); } else { return !!this.getNative().rangeCount; } } catch (e) { return false; } }, /** * 获取选区对应的Range * @method getRange * @return { Object } 得到Range对象 * @example * ```javascript * editor.selection.getRange(); * ``` */ getRange: function () { var me = this; function optimze(range) { var child = me.document.body.firstChild, collapsed = range.collapsed; while (child && child.firstChild) { range.setStart(child, 0); child = child.firstChild; } if (!range.startContainer) { range.setStart(me.document.body, 0) } if (collapsed) { range.collapse(true); } } if (me._cachedRange != null) { return this._cachedRange; } var range = new baidu.editor.dom.Range(me.document); if (browser.ie9below) { var nativeRange = me.getIERange(); if (nativeRange) { //备份的_bakIERange可能已经实效了,dom树发生了变化比如从源码模式切回来,所以try一下,实效就放到body开始位置 try { transformIERangeToRange(nativeRange, range); } catch (e) { optimze(range); } } else { optimze(range); } } else { var sel = me.getNative(); if (sel && sel.rangeCount) { var firstRange = sel.getRangeAt(0); var lastRange = sel.getRangeAt(sel.rangeCount - 1); range.setStart(firstRange.startContainer, firstRange.startOffset).setEnd(lastRange.endContainer, lastRange.endOffset); if (range.collapsed && domUtils.isBody(range.startContainer) && !range.startOffset) { optimze(range); } } else { //trace:1734 有可能已经不在dom树上了,标识的节点 if (this._bakRange && domUtils.inDoc(this._bakRange.startContainer, this.document)) { return this._bakRange; } optimze(range); } } return this._bakRange = range; }, /** * 获取开始元素,用于状态反射 * @method getStart * @return { Element } 获得开始元素 * @example * ```javascript * editor.selection.getStart(); * ``` */ getStart: function () { if (this._cachedStartElement) { return this._cachedStartElement; } var range = browser.ie9below ? this.getIERange() : this.getRange(), tmpRange, start, tmp, parent; if (browser.ie9below) { if (!range) { //todo 给第一个值可能会有问题 return this.document.body.firstChild; } //control元素 if (range.item) { return range.item(0); } tmpRange = range.duplicate(); //修正ie下x[xx] 闭合后 x|xx tmpRange.text.length > 0 && tmpRange.moveStart('character', 1); tmpRange.collapse(1); start = tmpRange.parentElement(); parent = tmp = range.parentElement(); while (tmp = tmp.parentNode) { if (tmp == start) { start = parent; break; } } } else { range.shrinkBoundary(); start = range.startContainer; if (start.nodeType == 1 && start.hasChildNodes()) { start = start.childNodes[Math.min(start.childNodes.length - 1, range.startOffset)]; } if (start.nodeType == 3) { return start.parentNode; } } return start; }, /** * 得到选区中的文本 * @method getText * @return { String } 选区中包含的文本 * @example * ```javascript * editor.selection.getText(); * ``` */ getText: function () { var nativeSel, nativeRange; if (this.isFocus() && (nativeSel = this.getNative())) { nativeRange = browser.ie9below ? nativeSel.createRange() : nativeSel.getRangeAt(0); return browser.ie9below ? nativeRange.text : nativeRange.toString(); } return ''; }, /** * 清除选区 * @method clearRange * @example * ```javascript * editor.selection.clearRange(); * ``` */ clearRange: function () { this.getNative()[browser.ie9below ? 'empty' : 'removeAllRanges'](); } }; })(); // core/Editor.js /** * 编辑器主类,包含编辑器提供的大部分公用接口 * @file * @module UE * @class Editor * @since 1.2.6.1 */ /** * UEditor公用空间,UEditor所有的功能都挂载在该空间下 * @unfile * @module UE */ /** * UEditor的核心类,为用户提供与编辑器交互的接口。 * @unfile * @module UE * @class Editor */ (function () { var uid = 0, _selectionChangeTimer; /** * 获取编辑器的html内容,赋值到编辑器所在表单的textarea文本域里面 * @private * @method setValue * @param { UE.Editor } editor 编辑器事例 */ function setValue(form, editor) { var textarea; if (editor.textarea) { if (utils.isString(editor.textarea)) { for (var i = 0, ti, tis = domUtils.getElementsByTagName(form, 'textarea'); ti = tis[i++];) { if (ti.id == 'ueditor_textarea_' + editor.options.textarea) { textarea = ti; break; } } } else { textarea = editor.textarea; } } if (!textarea) { form.appendChild(textarea = domUtils.createElement(document, 'textarea', { 'name': editor.options.textarea, 'id': 'ueditor_textarea_' + editor.options.textarea, 'style': "display:none" })); //不要产生多个textarea editor.textarea = textarea; } !textarea.getAttribute('name') && textarea.setAttribute('name', editor.options.textarea); textarea.value = editor.hasContents() ? (editor.options.allHtmlEnabled ? editor.getAllHtml() : editor.getContent(null, null, true)) : '' } function loadPlugins(me) { //初始化插件 for (var pi in UE.plugins) { UE.plugins[pi].call(me); } } function checkCurLang(I18N) { for (var lang in I18N) { return lang } } function langReadied(me) { me.langIsReady = true; me.fireEvent("langReady"); } /** * 编辑器准备就绪后会触发该事件 * @module UE * @class Editor * @event ready * @remind render方法执行完成之后,会触发该事件 * @remind * @example * ```javascript * editor.addListener( 'ready', function( editor ) { * editor.execCommand( 'focus' ); //编辑器家在完成后,让编辑器拿到焦点 * } ); * ``` */ /** * 执行destroy方法,会触发该事件 * @module UE * @class Editor * @event destroy * @see UE.Editor:destroy() */ /** * 执行reset方法,会触发该事件 * @module UE * @class Editor * @event reset * @see UE.Editor:reset() */ /** * 执行focus方法,会触发该事件 * @module UE * @class Editor * @event focus * @see UE.Editor:focus(Boolean) */ /** * 语言加载完成会触发该事件 * @module UE * @class Editor * @event langReady */ /** * 运行命令之后会触发该命令 * @module UE * @class Editor * @event beforeExecCommand */ /** * 运行命令之后会触发该命令 * @module UE * @class Editor * @event afterExecCommand */ /** * 运行命令之前会触发该命令 * @module UE * @class Editor * @event firstBeforeExecCommand */ /** * 在getContent方法执行之前会触发该事件 * @module UE * @class Editor * @event beforeGetContent * @see UE.Editor:getContent() */ /** * 在getContent方法执行之后会触发该事件 * @module UE * @class Editor * @event afterGetContent * @see UE.Editor:getContent() */ /** * 在getAllHtml方法执行时会触发该事件 * @module UE * @class Editor * @event getAllHtml * @see UE.Editor:getAllHtml() */ /** * 在setContent方法执行之前会触发该事件 * @module UE * @class Editor * @event beforeSetContent * @see UE.Editor:setContent(String) */ /** * 在setContent方法执行之后会触发该事件 * @module UE * @class Editor * @event afterSetContent * @see UE.Editor:setContent(String) */ /** * 每当编辑器内部选区发生改变时,将触发该事件 * @event selectionchange * @warning 该事件的触发非常频繁,不建议在该事件的处理过程中做重量级的处理 * @example * ```javascript * editor.addListener( 'selectionchange', function( editor ) { * console.log('选区发生改变'); * } */ /** * 在所有selectionchange的监听函数执行之前,会触发该事件 * @module UE * @class Editor * @event beforeSelectionChange * @see UE.Editor:selectionchange */ /** * 在所有selectionchange的监听函数执行完之后,会触发该事件 * @module UE * @class Editor * @event afterSelectionChange * @see UE.Editor:selectionchange */ /** * 编辑器内容发生改变时会触发该事件 * @module UE * @class Editor * @event contentChange */ /** * 以默认参数构建一个编辑器实例 * @constructor * @remind 通过 改构造方法实例化的编辑器,不带ui层.需要render到一个容器,编辑器实例才能正常渲染到页面 * @example * ```javascript * var editor = new UE.Editor(); * editor.execCommand('blod'); * ``` * @see UE.Config */ /** * 以给定的参数集合创建一个编辑器实例,对于未指定的参数,将应用默认参数。 * @constructor * @remind 通过 改构造方法实例化的编辑器,不带ui层.需要render到一个容器,编辑器实例才能正常渲染到页面 * @param { Object } setting 创建编辑器的参数 * @example * ```javascript * var editor = new UE.Editor(); * editor.execCommand('blod'); * ``` * @see UE.Config */ var Editor = UE.Editor = function (options) { var me = this; var FILE_MAX_SIZE = 15 * 1024 * 1024 * 1024 me.uid = uid++; EventBase.call(me); me.commands = {}; me.options = utils.extend(utils.clone(options || {}), UEDITOR_CONFIG, true); me.shortcutkeys = {}; me.inputRules = []; me.outputRules = []; //设置默认的常用属性 me.setOpt(Editor.defaultOptions(me)); /* 尝试异步加载后台配置 */ me.loadServerConfig(); // 分片上传最大支持 15G if(me.options.fileMaxSize > FILE_MAX_SIZE) { me.options.fileMaxSize = FILE_MAX_SIZE } if (!utils.isEmptyObject(UE.I18N)) { //修改默认的语言类型 me.options.lang = checkCurLang(UE.I18N); UE.plugin.load(me); langReadied(me); } else { utils.loadFile(document, { src: me.options.langPath + me.options.lang + "/" + me.options.lang + ".js", tag: "script", type: "text/javascript", defer: "defer" }, function () { try { UE.plugin.load(me); langReadied(me); }catch (e) { } }); } UE.instants['ueditorInstant' + me.uid] = me; }; Editor.prototype = { registerCommand: function (name, obj) { this.commands[name] = obj; }, /** * 编辑器对外提供的监听ready事件的接口, 通过调用该方法,达到的效果与监听ready事件是一致的 * @method ready * @param { Function } fn 编辑器ready之后所执行的回调, 如果在注册事件之前编辑器已经ready,将会 * 立即触发该回调。 * @remind 需要等待编辑器加载完成后才能执行的代码,可以使用该方法传入 * @example * ```javascript * editor.ready( function( editor ) { * editor.setContent('初始化完毕'); * } ); * ``` * @see UE.Editor.event:ready */ ready: function (fn) { var me = this; if (fn) { me.isReady ? fn.apply(me) : me.addListener('ready', fn); } }, /** * 该方法是提供给插件里面使用,设置配置项默认值 * @method setOpt * @warning 三处设置配置项的优先级: 实例化时传入参数 > setOpt()设置 > config文件里设置 * @warning 该方法仅供编辑器插件内部和编辑器初始化时调用,其他地方不能调用。 * @param { String } key 编辑器的可接受的选项名称 * @param { * } val 该选项可接受的值 * @example * ```javascript * editor.setOpt( 'initContent', '欢迎使用编辑器' ); * ``` */ /** * 该方法是提供给插件里面使用,以{key:value}集合的方式设置插件内用到的配置项默认值 * @method setOpt * @warning 三处设置配置项的优先级: 实例化时传入参数 > setOpt()设置 > config文件里设置 * @warning 该方法仅供编辑器插件内部和编辑器初始化时调用,其他地方不能调用。 * @param { Object } options 将要设置的选项的键值对对象 * @example * ```javascript * editor.setOpt( { * 'initContent': '欢迎使用编辑器' * } ); * ``` */ setOpt: function (key, val) { var obj = {}; if (utils.isString(key)) { obj[key] = val } else { obj = key; } utils.extend(this.options, obj, true); }, getOpt: function (key) { return this.options[key] }, /** * 销毁编辑器实例,使用textarea代替 * @method destroy * @example * ```javascript * editor.destroy(); * ``` */ destroy: function () { var me = this; me.fireEvent('destroy'); var container = me.container.parentNode; var textarea = me.textarea; if (!textarea) { // textarea = document.createElement('textarea'); // container.parentNode.insertBefore(textarea, container); } else { textarea.style.display = '' textarea.style.width = me.iframe.offsetWidth + 'px'; textarea.style.height = me.iframe.offsetHeight + 'px'; textarea.value = me.getContent(); textarea.id = me.key; } container.innerHTML = ''; domUtils.remove(container); var key = me.key; //trace:2004 for (var p in me) { if (me.hasOwnProperty(p)) { delete this[p]; } } UE.delEditor(key); }, /** * 渲染编辑器的DOM到指定容器 * @method render * @param { String } containerId 指定一个容器ID * @remind 执行该方法,会触发ready事件 * @warning 必须且只能调用一次 */ /** * 渲染编辑器的DOM到指定容器 * @method render * @param { Element } containerDom 直接指定容器对象 * @remind 执行该方法,会触发ready事件 * @warning 必须且只能调用一次 */ render: function (container) { var me = this, options = me.options, getStyleValue = function (attr) { return parseInt(domUtils.getComputedStyle(container, attr)); }; if (utils.isString(container)) { container = document.getElementById(container); } if (container) { if (options.initialFrameWidth) { options.minFrameWidth = options.initialFrameWidth } else { options.minFrameWidth = options.initialFrameWidth = container.offsetWidth; } if (options.initialFrameHeight) { options.minFrameHeight = options.initialFrameHeight } else { options.initialFrameHeight = options.minFrameHeight = container.offsetHeight; } container.style.width = /%$/.test(options.initialFrameWidth) ? '100%' : options.initialFrameWidth - getStyleValue("padding-left") - getStyleValue("padding-right") + 'px'; container.style.height = /%$/.test(options.initialFrameHeight) ? '100%' : options.initialFrameHeight - getStyleValue("padding-top") - getStyleValue("padding-bottom") + 'px'; container.style.zIndex = options.zIndex; //附件预览大窗口 var addclass = '',style = ''; if (options.largePreview) { addclass = 'largePreview'; } if (me.OSnow() == 'mac') { addclass += "mac" } style = ' style=\''; if(options.themeColor){ style += 'color:'+ options.themeColor + ';'; } // 默认字体 if(options.defaultFont){ style += options.defaultFont + ';'; } style += '\'' var html = (ie && browser.version < 9 ? '' : '') + '' + '' + (options.iframeCssUrl ? '' : '') + (options.viewerCssurl ? '' : '') + (options.increaseCssurl ? '' : '') + (options.initialStyle ? '' : '') + '' + ''; container.appendChild(domUtils.createElement(document, 'iframe', { id: 'ueditor_' + me.uid, width: "100%", height: "100%", frameborder: "0", //先注释掉了,加的原因忘记了,但开启会直接导致全屏模式下内容多时不会出现滚动条 // scrolling :'no', src: 'javascript:void(function(){document.open();' + (options.customDomain && document.domain != location.hostname ? 'document.domain="' + document.domain + '";' : '') + 'document.write("' + html + '");document.close();}())' })); container.style.overflow = 'hidden'; //解决如果是给定的百分比,会导致高度算不对的问题 setTimeout(function () { if (/%$/.test(options.initialFrameWidth)) { options.minFrameWidth = options.initialFrameWidth = container.offsetWidth; //如果这里给定宽度,会导致ie在拖动窗口大小时,编辑区域不随着变化 // container.style.width = options.initialFrameWidth + 'px'; } if (/%$/.test(options.initialFrameHeight)) { options.minFrameHeight = options.initialFrameHeight = container.offsetHeight; container.style.height = options.initialFrameHeight + 'px'; } }) } //添加删除弹窗 var imgPrefix = (RichTextUitl.prefix || RichTextUitl.noteDomain) + '/res/plugin/ueditor/'; if(RichTextUitl.intranetMode){ imgPrefix = RichTextUitl.prefix } if ($('.popUeditorDelShowHide').length == 0) { var div = document.createElement('div'); div.className = 'maskDiv popUeditorDelShowHide editorMaskDiv'; div.style.cssText = 'display: none;' div.innerHTML = '' + me.getLang('popModal.sureDelete') + '
' + '' + '' + '' + (browser.ie ? '' : '
') + '
123456
* var content = editor.getContent(); //返回值:123456
* ``` */ /** * 获取编辑器的内容。 可以通过参数定义编辑器内置的判空规则 * @method getContent * @param { Function } fn 自定的判空规则, 要求该方法返回一个boolean类型的值, * 代表当前编辑器的内容是否空, * 如果返回true, 则该方法将直接返回空字符串;如果返回false,则编辑器将返回 * 经过内置过滤规则处理后的内容。 * @remind 该方法在处理包含有初始化内容的时候能起到很好的作用。 * @warning 该方法获取到的是经过编辑器内置的过滤规则进行过滤后得到的内容 * @return { String } 编辑器的内容字符串 * @example * ```javascript * // editor 是一个编辑器的实例 * var content = editor.getContent( function ( editor ) { * return editor.body.innerHTML === '欢迎使用UEditor'; //返回空字符串 * } ); * ``` */ getContent: function (cmd, fn, notSetCursor, ignoreBlank, formatter) { var me = this; if (cmd && utils.isFunction(cmd)) { fn = cmd; cmd = ''; } if (fn ? !fn() : !this.hasContents()) { return ''; } //PC出去的表格没有套.table的全部套上.table var tables = me.body.querySelectorAll('table'); for (var i = 0; table = tables[i++];) { if (!(table.parentNode.className && table.parentNode.className == 'table')) { var tempdiv = document.createElement('div'); tempdiv.setAttribute('element-id', domUtils.getRandomId()) tempdiv.setAttribute("class", "table"); tempdiv.setAttribute('style', 'width:100%;max-width:100%;overflow-x:auto;'); table.parentNode.insertBefore(tempdiv, table); tempdiv.appendChild(table); } } //标题没有elementid的加上id,避免出现每次getContent()不一样的情况 $(me.body).find('h1:not([element-id]),h2:not([element-id]),h3:not([element-id]),h4:not([element-id]),h5:not([element-id]),h6:not([element-id])').each(function () { $(this).attr('element-id', domUtils.getRandomId()); }) var url = ''; try { url = top.location.href || ''; } catch (e) { url = document.referrer || ''; } if (url && url.indexOf('notice') == -1) { //最后一个元素是不可编辑,后面加一个空行 if (me.body.lastChild.nodeType == 1 && me.body.lastChild.getAttribute('contenteditable') && me.body.lastChild.getAttribute('contenteditable') == 'false' && !$(me.body.lastChild).is('#ue_tableDragLine')) { if (!me.body.lastChild.nextSibling) { var p = document.createElement('p'); p.setAttribute('element-id', domUtils.getRandomId()) p.appendChild(document.createElement('br')); me.body.appendChild(p); } } } me.fireEvent('beforegetcontent'); var html = me.body.innerHTML; //xss攻击 var xssReg = new RegExp("(\\baler(?=t\\s*\\())|(\\bhref(?=\\s*=\\s*['\"]?\\s*javascript:))|(\\bsrc(?=\\s*=\\s*['\"]?\\s*javascript:))|((data|src)\\s*=['\"]?\\s*data(?=:)(?!:\\s*image))|(^[^<]*<(?=/textarea\\s*>))|(<(?=(script)|(/script)))|(<(?=(details)|(/details)))|(\\b(onstart|onafterprint|onbeforeprint|onbeforeunload|onerror|onhaschange|onload|onmessage|onoffline|ononline|onpagehide|onpageshow|onpopstate|onredo|onresize|onstorage|onundo|onunload|onblur|onchange|oncontextmenu|onfocus|onformchange|onforminput|oninput|oninvalid|onreset|onreset|onsubmit|onkey\\w*|onclick|ondblclick|ondrag\\w*|ondrop|onmouse\\w*|onscroll|ontouch\\w*)(?=(\\s*)=))", 'gi'); html = html.replace(xssReg, function () { return arguments[0] + ' '; }) var root = UE.htmlparser(html, ignoreBlank); if(html.indexOf('1
2
* console.log(editor.getPlainTxt()); //输出:"1\n2\n * ``` */ getPlainTxt: function () { var $wrap = $(this.body).clone(true); $wrap.find("ol li").each(function () { $(this).prepend($(this).attr('serialnum') + ". "); }); $wrap.find("ul li").each(function () { var level = parseInt($(this).parent().attr('level')) || 1; switch (level % 3) { case 0: $(this).prepend(" ▪ "); break; case 1: $(this).prepend("• "); break; case 2: $(this).prepend(" ◦ "); break; default: break; } }); //避免生成的图片后多一个空行 $wrap.find(".drag-image-wrap .editor-image").each(function () { $(this).unwrap(); }); var html = $wrap.html(); var me = this; var root = UE.htmlparser($wrap.html(), true); me.filterOutputRule(root); html = root.toHtml(); var reg = new RegExp(domUtils.fillChar, 'g'); html = html.replace(/[\n\r]/g, ''); //ie要先去了\n在处理 html = html.replace(/<(ol|ul|li)[^>]*>/g, '').replace(/<(\/ol|\/ul|\/li)>/g, ''); html = html.replace(/<(p|div)[^>]*>(1
2
* console.log(editor.getPlainTxt()); //输出:"12 * ``` */ getContentTxt: function () { var reg = new RegExp(domUtils.fillChar, 'g'); //取出来的空格会有c2a0会变成乱码,处理这种情况\u00a0 return this.body[browser.ie ? 'innerText' : 'textContent'].replace(reg, '').replace(/\u00a0/g, ' '); }, /** * 根据图片地址后的宽高设置图片占位符 */ getImgurlParam: function (url, name) { if (url.indexOf("?") != -1) { var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i"); var r = url.split("?")[1].match(reg); if (r != null) return unescape(r[2]); return null; } else { return null; } }, loadImg: function () { var me = this; var imgList = me.body.querySelectorAll('img'); for (var i = 0; i < imgList.length; i++) { // 计算固定宽高图片排版的老数据操作 if($(imgList[i]).parents('.column-img-b').find('img').length > 1 ){ me.resetColumnImgWdith(imgList[i],2); continue; }else if(RichTextUitl.imageLayout == true){ if($(imgList[i]).parents('.drag-image-wrap').find('img').length > 1){ var width = parseInt($(imgList[i]).parents('.drag-image-wrap').width()/$(imgList[i]).parents('.drag-image-wrap').find('img').length) - 14; imgList[i].style.width = width + 'px'; imgList[i].style.height = parseInt(width / 1.5) + 'px'; } continue; } if ($(imgList[i]).parents('.drag-image-wrap').find('img').length > 1 && !$(imgList[i]).parents('.drag-image-wrap').attr('totalWidth')) { //计算并排图片的总宽度,记录原始图片宽度 var totalWidth = 0; $(imgList[i]).parents('.drag-image-wrap').find('img').each(function (index, item) { totalWidth += parseInt(item.getAttribute('width') || item.style.width.replace('px', '')); item.setAttribute('owidth', parseInt(item.getAttribute('width') || item.style.width.replace('px', '')) + 2); }) $(imgList[i]).parents('.drag-image-wrap').attr('totalWidth', totalWidth) } if(imgList[i].style.width && imgList[i].style.width == '100%') {imgList[i].style.width = ''} var attrwidth = parseInt(imgList[i].getAttribute("width")) || imgList[i].style.width; if(imgList[i].style.width && imgList[i].style.width.indexOf('px') > -1){ attrwidth = parseInt(imgList[i].style.width.replace('px', '')) } var attrheight = parseInt(imgList[i].getAttribute("height")) || parseInt(imgList[i].style.height.replace('px', '') || 0); var addr = imgList[i].getAttribute("src"); if (!addr) { continue; } addr = addr.replace(/&/g, '&'); var winWidth = $(me.body).width() || 800; //最大宽度 var imgW1 = parseInt(attrwidth || me.getImgurlParam(addr, 'rw') || imgList[i].clientWidth || imgList[i].naturalWidth || 0); //原始图片宽度 var imgH1 = parseInt(attrheight || me.getImgurlParam(addr, 'rh') || imgList[i].clientHeight || imgList[i].naturalHeight || 0); //原始图片高度 var imgW2, imgH2; if (imgW1 && typeof imgW1 == 'string' && imgW1.indexOf('%') > -1) { imgList[i].style.width = imgW1; imgList[i].style.height = 'auto'; }else if (imgW1 && imgH1) { imgList[i].parentNode.style.backgroundColor = "#F5F6F8"; if (attrwidth && attrwidth < winWidth) { imgW2 = attrwidth; } else if(imgW1 > winWidth){ imgW2 = winWidth; } else{ imgW2 = imgW1; } imgH2 = parseInt(imgW2 * imgH1 / imgW1); imgList[i].style.width = imgW2 + 'px'; imgList[i].style.height = imgH2 + 'px'; imgList[i].setAttribute('width', imgW2); imgList[i].onload = function () { this.style.opacity = 1; this.parentNode.style.backgroundColor = ""; this.style.height = ""; this.setAttribute('height', ''); if ($(this).parents('.drag-image-wrap').find('img').length > 1) { me.resetImgWidth($(this).parents('.drag-image-wrap').find('img')) } me.fireEvent("contentchange") } } else { imgList[i].parentNode.style.backgroundColor = "#F5F6F8"; if (!(imgList[i].style.width && imgList[i].style.width.replace('px', ''))) { imgList[i].style.height = "auto"; imgList[i].style.minHeight = "200px"; } else { imgList[i].style.height = "auto"; } imgList[i].onload = function () { this.style.minHeight = ""; this.parentNode.style.backgroundColor = ""; if (this.getAttribute("width")) { this.style.width = this.getAttribute("width"); // this.style.height = parseInt(this.getAttribute("width") * this.clientHeight / this.clientWidth) + 'px'; // this.setAttribute('height', parseInt(this.getAttribute("width") * this.clientHeight / this.clientWidth)); } else { this.style.height = ""; this.setAttribute('height', ''); } if ($(this).parents('.drag-image-wrap').find('img').length > 1) { me.resetImgWidth($(this).parents('.drag-image-wrap').find('img')) } me.fireEvent("contentchange") } } } }, //并排图片按比例设置图片宽度 resetImgWidth: function (imgList) { var me = this; if (!imgList.parents('.drag-image-wrap').attr('totalWidth')) { return } var totalWidth = parseInt(imgList.parents('.drag-image-wrap').attr('totalWidth')); if (totalWidth + imgList.length * 6 > $(me.body).width()) { //防止图片没加载完就开始计算宽度 for (var i = 0; i < imgList.length; i++) { if (!imgList[i].clientHeight) return } for (var i = 0; i < imgList.length; i++) { var scale = imgList[i].clientWidth / imgList[i].clientHeight; var width = parseInt(($(me.body).width() - imgList.length * 6) * imgList.eq(i).attr('owidth') / totalWidth); imgList[i].width = width; imgList[i].style.width = width + 'px'; imgList[i].style.height = parseInt(width / scale) + 'px'; imgList[i].height = ''; } imgList.parents('.drag-image-wrap').removeAttr('totalWidth'); imgList.removeAttr('owidth'); } me.fireEvent("contentchange") }, // 计算固定宽高图片排版 resetColumnImgWdith:function (img,columnNum){ var me = this; var scale = 589/415; var width = parseInt($(me.body).width()/columnNum) - 6; img.style.width = width + 'px'; img.style.height = parseInt(width / scale) + 'px'; }, /** * 设置编辑器的内容,可修改编辑器当前的html内容 * @method setContent * @warning 通过该方法插入的内容,是经过编辑器内置的过滤规则进行过滤后得到的内容 * @warning 该方法会触发selectionchange事件 * @param { String } html 要插入的html内容 * @example * ```javascript * editor.getContent('test
'); * ``` */ /** * 设置编辑器的内容,可修改编辑器当前的html内容 * @method setContent * @warning 通过该方法插入的内容,是经过编辑器内置的过滤规则进行过滤后得到的内容 * @warning 该方法会触发selectionchange事件 * @param { String } html 要插入的html内容 * @param { Boolean } isAppendTo 若传入true,不清空原来的内容,在最后插入内容,否则,清空内容再插入 * @example * ```javascript * //假设设置前的编辑器内容是old text
* editor.setContent('new text
', true); //插入的结果是old text
new text
* ``` */ setContent: function (html, isAppendTo, notFireSelectionchange) { var me = this; if (html && html.length > 1 && html.substr(0, 1) == ' ') { html = '' + html.substr(1, html.length); } //xss攻击 var xssReg = new RegExp("(\\baler(?=t\\s*\\())|(\\bhref(?=\\s*=\\s*['\"]?\\s*javascript:))|(\\bsrc(?=\\s*=\\s*['\"]?\\s*javascript:))|((data|src)\\s*=['\"]?\\s*data(?=:)(?!:\\s*image))|(^[^<]*<(?=/textarea\\s*>))|(<(?=(script)|(/script)))|(<(?=(details)|(/details)))|(\\b(onstart|onafterprint|onbeforeprint|onbeforeunload|onerror|onhaschange|onload|onmessage|onoffline|ononline|onpagehide|onpageshow|onpopstate|onredo|onresize|onstorage|onundo|onunload|onblur|onchange|oncontextmenu|onfocus|onformchange|onforminput|oninput|oninvalid|onreset|onreset|onsubmit|onkey\\w*|onclick|ondblclick|ondrag\\w*|ondrop|onmouse\\w*|onscroll|ontouch\\w*)(?=(\\s*)=))", 'gi'); html = html.replace(xssReg, function () { return arguments[0] + ' '; }) //把英文字母中间的 换成空格 20201104 html = html.replace(/\b( )+\b/gi, function () { html = arguments[0].replace(/ /gi, ' '); return html; }); me.fireEvent('beforesetcontent', html); var root = UE.htmlparser(html); if(html.indexOf('' + (browser.ie ? ' ' : '
') + '
' + (browser.ie ? ' ' : '
') + '
' + me.getLang('popModal.hint') + '
' + '' + me.getLang('popModal.reconnectTips') + '
' + '' + (browser.ie ? '' : '
') + '
');
// doSave = 1;
// }
// } else {
//chrome remove div
if (start.nodeType == 1) {
//折叠标题后换行的,换到折叠标题的最后一行
if (range.startContainer.previousElementSibling && domUtils.isBlockElm(range.startContainer.previousElementSibling) && range.startContainer.previousElementSibling.className.indexOf('tempShow') > -1) {
var p = range.startContainer;
p.previousElementSibling.style.display = 'none'
p.previousElementSibling.classList.remove('tempShow');
var h = document.createElement(hTag);
h.innerHTML = p.innerHTML;
h.setAttribute('element-id', p.getAttribute('element-id'));
p.parentNode.insertBefore(h, p);
range.setStart(h, 0).collapse(true).select(true);
p.parentNode.removeChild(p);
} else {
var tmp = me.document.createTextNode(''),
div;
range.insertNode(tmp);
div = domUtils.findParentByTagName(tmp, 'div', true);
if (div) {
var p = me.document.createElement('p');
p.setAttribute('element-id', domUtils.getRandomId())
while (div.firstChild) {
p.appendChild(div.firstChild);
}
div.parentNode.insertBefore(p, div);
domUtils.remove(div);
range.setStartBefore(tmp).setCursor();
doSave = 1;
}
domUtils.remove(tmp);
}
}
// }
$(me.body).find('.tempShow').removeClass('tempShow').removeAttr('style')
if (me.undoManger && doSave) {
me.undoManger.save();
}
},
//20200324 设置签名
setSign: function (html) {
var me = this;
me.fireEvent('beforesetcontent', html);
if (html == '无') {
if (me.body.querySelector('#signDiv') && me.body.querySelector('#signDiv').parentNode.tagName.toLowerCase() == 'body') {
domUtils.remove(me.body.querySelector('#signDiv'));
}
} else {
var div = document.createElement('div');
div.setAttribute('element-id', domUtils.getRandomId())
div.id = 'signDiv';
div.className = 'signDiv';
div.style.cssText = 'padding-top: 90px;'
div.innerHTML = html;
div.contentEditable = 'false';
if (me.body.querySelector('#notice_main')) {
me.body.insertBefore(div, me.body.querySelector('#notice_main'))
} else {
me.body.appendChild(div)
}
//点击签名,光标定到编辑器
$(me.body).find('#signDiv').off('click').on('click', function () {
var range = me.selection.getRange();
var node = this.previousSibling;
if (node && node.nodeType == 1 && !dtd.$empty[node.tagName]) {
while (node.lastChild && node.lastChild.nodeType == 1 && !dtd.$empty[node.lastChild.tagName]) {
node = node.lastChild;
}
if (domUtils.isEmptyBlock(node)) {
range.setStartAtFirst(node)
} else {
range.setStartAtLast(node)
}
range.collapse(true);
}
range.select(true);
})
}
me.fireEvent('aftersetcontent');
me.fireEvent('contentchange');
},
//20200527 选择模版
setNoticeTemplate: function (html) {
var me = this;
me.fireEvent('beforesetcontent', html);
if (html) {
var div = document.createElement('div');
div.setAttribute('element-id', domUtils.getRandomId())
div.innerHTML = html;
if (me.body.querySelector('#signDiv') && me.body.querySelector('#signDiv').parentNode.tagName.toLowerCase() == 'body') {
//有签名,在签名前插入
me.body.insertBefore(div, me.body.querySelector('#signDiv'));
} else if (me.body.querySelector('#notice_main')) {
//有原站内信函,在原站内信函前插入
me.body.insertBefore(div, me.body.querySelector('#notice_main'));
} else {
//没有签名,在编辑器最后插入
me.body.appendChild(div);
}
me.focus(true);
var rng = me.selection.getRange();
rng.setStartAfter(div).collapse(true).select();
me.fireEvent('aftersetcontent');
me.fireEvent('contentchange');
}
},
//将base64转换为file
dataURLtoFile: function (dataurl) {//将base64转换为文件
var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
while (n--) {
u8arr[n] = bstr.charCodeAt(n);
}
return new File([u8arr], domUtils.getRandomId() + '.' + mime.split('/')[1], {type: mime});
},
//base64图片替换为云盘地址
replaceBase64Img: function (img) {
if (!RichTextUitl.puid || !RichTextUitl.yunToken) {
RichTextUitl.getUploadConfig(true);
}
var me = this;
/* 创建Ajax并提交 */
var actionUrl = me.getActionUrl(me.getOpt('imageActionName'));
var xhr = new XMLHttpRequest(),
fd = new FormData();
var file = me.dataURLtoFile((img.getAttribute('src') || img.getAttribute('_src')));
fd.append('file', file, file.name);
fd.append('type', 'ajax');
fd.append("puid", RichTextUitl.puid);
fd.append("_token", RichTextUitl.yunToken);
xhr.open("post", actionUrl, true);
xhr.addEventListener('load', function (e) {
try {
var json = JSON.parse(e.target.response);
if (RichTextUitl.intranetMode && typeof RichTextUitl.customUploadDataAnalysis == 'function') {
// 镜像版本需要处理下接口返回值
json = RichTextUitl.customUploadDataAnalysis(json);
}
if (json.result) {
var suffix = json.data.suffix || 'jpg';
var imgUrl;
if (RichTextUitl.intranetMode) {
imgUrl = data.data.imgUrl;
} else {
imgUrl = (RichTextUitl.mirrorPhotoDomain || 'https://p.cldisk.com') + '/star3/origin/' + json.data.objectId + "." + suffix;
}
img.src = imgUrl;
img.onload = function(){
imgUrl = imgUrl + '?rw=' + img.clientWidth + '&rh=' + img.clientHeight + '&_fileSize=' + json.data.size + '&_orientation=1';
img.setAttribute('_src', imgUrl);
}
img.setAttribute('_src', imgUrl);
} else {
domUtils.setAttributes(img, {
"src": RichTextUitl.downloadFailedImg,
"_src": RichTextUitl.downloadFailedImg,
"objectid": RichTextUitl.randomUUID(),
});
img.removeAttribute('style','')
img.removeAttribute('width','')
img.removeAttribute('height','')
domUtils.addClass(img, 'image-package failImg');
RichTextUitl.showTips(json.msg, 0);
}
img.parentNode.classList.remove('remoteImage')
} catch (er) {
domUtils.setAttributes(img, {
"src": RichTextUitl.downloadFailedImg,
"_src": RichTextUitl.downloadFailedImg,
"objectid": RichTextUitl.randomUUID(),
});
img.removeAttribute('style','')
img.removeAttribute('width','')
img.removeAttribute('height','')
domUtils.addClass(img, 'image-package failImg');
RichTextUitl.showTips('上传图片失败', 0)
}
});
xhr.send(fd);
},
//打开删除弹窗
openDeleteModal: function (delType, delIndex, editorId) {
// if(delType == '1'){
// $('.popUeditorDelShowHide .typeText').text('图片')
// }else if(delType == '2'){
// $('.popUeditorDelShowHide .typeText').text('附件')
// }else if(delType == '3'){
// $('.popUeditorDelShowHide .typeText').text('表格')
// }
//新泛雅弹窗覆盖顶部和左侧
if (top) {
top.postMessage('{"cmd":1,"toggle":true}', "*");
}
$('.popUeditorDelShowHide').addClass('maskFadeOut').attr('deltype', delType).attr('delindex', delIndex).attr('editorId', editorId).show();
$('body').addClass('popOverflow');
$('.popUeditorDelShowHide .popDiv').css({
top: function () {
return ($(window).height() - $(this).height()) / 2;
},
left: function () {
return ($(window).width() - $(this).width()) / 2;
},
transform: 'none'
});
},
//删除元素:参数(元素在页面中的索引,元素名)
deleteElement: function (index, tagName, isrecovery, editorId) {
$('.edui-editor-resizer').removeClass('scale').removeClass('hover').removeClass('show');
var editor = UE.getEditor(editorId);
var me = editor;
var rng = me.selection.getRange();
if (!isrecovery && me.options.cooperation) {
var data = {};
data.name = 'deleteElement';
data.elementIndex = index;
data.tagName = tagName;
me.sendJoinData(data);
}
// var editor = UE.getEditor(editorId)
var ele = $(me.body).find(tagName).eq(index);
var isOneImg = false;
if (tagName == 'img' || tagName == 'iframe') {
if (ele.parents('.drag-image-wrap').length > 0 && ele.parents('.drag-image-wrap').find('.editor-image').length > 0) {
isOneImg = true;
//兼容图片并排后一行放多个图片
if (ele.parents('.drag-image-wrap')[0].previousSibling && ele.parents('.drag-image-wrap')[0].previousSibling.nodeType == 1 && ele.parents('.drag-image-wrap').find('.editor-image').length == 1
&& !ele.parents('.drag-image-wrap')[0].previousSibling.getAttribute('contenteditable') && ele.parents('.drag-image-wrap')[0].previousSibling.lastChild) {
//imagewrap有前一个元素时,光标定位到前一个元素
rng.setEndAfter(ele.parents('.drag-image-wrap')[0].previousSibling.lastChild).collapse();
} else if (ele.parents('.drag-image-wrap')[0].nextSibling && ele.parents('.drag-image-wrap')[0].nextSibling.nodeType == 1 && !ele.parents('.drag-image-wrap')[0].nextSibling.getAttribute('contenteditable') && ele.parents('.drag-image-wrap')[0].nextSibling.firstChild) {
rng.setStartBefore(ele[0].parentNode.parentNode.nextSibling.firstChild).collapse(true);//防止删除后没有光标
} else {
rng.setStartBefore(ele[0].parentNode.parentNode).collapse(true);//防止删除后没有光标
}
}else if (ele.parents('.drag-iframe-wrap').length > 0 && ele.parents('.drag-iframe-wrap').find('.editor-iframe').length > 0) {
isOneImg = true;
//兼容视频并排后一行放多个视频
if (ele.parents('.drag-iframe-wrap')[0].previousSibling && ele.parents('.drag-iframe-wrap')[0].previousSibling.nodeType == 1 && ele.parents('.drag-iframe-wrap').find('.editor-iframe').length == 1
&& !ele.parents('.drag-iframe-wrap')[0].previousSibling.getAttribute('contenteditable') && ele.parents('.drag-iframe-wrap')[0].previousSibling.lastChild) {
//iframewrap有前一个元素时,光标定位到前一个元素
rng.setEndAfter(ele.parents('.drag-iframe-wrap')[0].previousSibling.lastChild).collapse();
} else if (ele.parents('.drag-iframe-wrap')[0].nextSibling && ele.parents('.drag-iframe-wrap')[0].nextSibling.nodeType == 1 && !ele.parents('.drag-iframe-wrap')[0].nextSibling.getAttribute('contenteditable') && ele.parents('.drag-iframe-wrap')[0].nextSibling.firstChild) {
rng.setStartBefore(ele[0].parentNode.parentNode.nextSibling.firstChild).collapse(true);//防止删除后没有光标
} else {
rng.setStartBefore(ele[0].parentNode.parentNode).collapse(true);//防止删除后没有光标
}
} else if(ele.parent().parent().hasClass('record-iframe')) {
//打点附件
rng.setStart(ele.parents('.record-box').prev()[0],ele.parents('.record-box').prev().length).collapse(true);//防止删除后没有光标
}else {
rng.setStartBefore(ele[0].parentNode).collapse(true);//防止删除后没有光标
}
if (!ele.hasClass('loadingClass') && ele.siblings('.attachprogress').length == 0 && ele.siblings('.imgprogress').length == 0) {
if (me.options.statsAttach) {
//统计图片附件弹窗删除
var staAtt = [{
'type': tagName == 'img' ? 'img' : 'iframe',
'resource': tagName == 'img' ? ele.attr('src') : ele.attr('name')
}]
me.anasycStatsAttach(staAtt, 0);
}
}
} else {
rng.setStartBefore(ele[0]);
}
if (ele.length === 0) {
return;
}
var elePack = ele;
if(ele.parent().parent().hasClass('record-iframe')) {
//打点附件,删除附件
var start = ele[0].parentNode;
startParent = start.parentNode; //record-iframe
startParentParent = startParent.parentNode; //record-box
// nowstart = start;
while (startParent.firstChild) {
startParentParent.parentNode.insertBefore(startParent.firstChild, startParentParent);
}
domUtils.remove(startParent);
}else if (ele.parent().length > 0 && ele.parent().attr('contenteditable') == 'false') {
elePack = ele.parent();
//兼容图片并排后一行放多个图片
if (elePack.parent().length > 0 && elePack.parent().attr('contenteditable') == 'false' && elePack.parent().hasClass('drag-image-wrap') && elePack.parent().find('.editor-image').length == 1) {
elePack = elePack.parent();
}else if (elePack.parent().length > 0 && elePack.parent().attr('contenteditable') == 'false' && elePack.parent().hasClass('drag-iframe-wrap') && elePack.parent().find('.editor-iframe').length == 1) {
elePack = elePack.parent();
}
} else if (elePack.parent().length > 0 && elePack.parent().attr('class') == 'table') {
elePack = elePack.parent();
}
elePack.remove();
if (isOneImg) {
rng = rng.shrinkBoundary();
}
//删除后 顶部悬浮操作栏隐藏
$('.edui-editor-resizer').removeClass('hover');
if (!isrecovery) {
rng.select(true);
}
me.fireEvent('contentchange');
me.fireEvent('saveScene');
},
//删除元素
deleteEle: function (dom, nodeName) {
var me = this;
$('.edui-editor-resizer').removeClass('scale').removeClass('hover').removeClass('show');
var nodeName;
var index = $(dom).parents('.edui-editor-resizer').attr('index');
var delType;
if (dom.className.indexOf('img') > -1) {
delType = '1';
} else if (dom.className.indexOf('iframe') > -1) {
var type = $(dom).parents('.edui-editor-resizer').attr('iframetype');
if (type && type == 'text') {
delType = '4';
} else {
delType = '2';
}
} else if (dom.className.indexOf('table') > -1) {
delType = '3';
} else if (dom.className.indexOf('pre') > -1) {
//4是a标签
delType = '5';
}
if (delType) {
me.openDeleteModal(delType, index, me.key);
}
},
//剪切图片
cutEle: function (dom) {
var me = this;
var nodeName;
if (dom.className.indexOf('img') > -1) {
nodeName = 'img';
} else if (dom.className.indexOf('iframe') > -1) {
var type = $(dom).parents('.edui-editor-resizer').attr('iframetype');
if (type && type == 'text') {
nodeName = 'a';
} else {
nodeName = 'iframe';
}
} else if (dom.className.indexOf('table') > -1) {
nodeName = 'table';
}
$('.edui-editor-resizer').removeClass('scale').removeClass('hover').removeClass('show');
var index = $(dom).parents('.edui-editor-resizer').attr('index');
var ele;
if (nodeName == 'img') {
ele = $(me.document.body).find('img').eq(index)[0];
} else if (nodeName == 'iframe') {
ele = $(me.document.body).find('iframe').eq(index)[0];
} else if (nodeName == 'a') {
ele = $(me.document.body).find('a').eq(index)[0];
} else if (nodeName == 'table') {
ele = $(me.document.body).find('table').eq(index)[0];
}
if (!ele) {
return;
}
if (ele.parentNode && ele.parentNode.getAttribute('contenteditable') == 'false') {
ele = ele.parentNode;
}
if (!window.dt) {
var prefix = (RichTextUitl.prefix || RichTextUitl.noteDomain) + '/res/plugin/ueditor/';
if(RichTextUitl.intranetMode){
prefix = RichTextUitl.prefix
}
url = prefix + "third-party/clipboard-polyfill.promise.js";
utils.loadFile(document, {
src: url,
tag: "script",
type: "text/javascript",
defer: "defer"
}, function () {
window.dt = new clipboard.DT();
me.initclipboard('cut', ele, index, nodeName)
});
} else {
me.initclipboard('cut', ele, index, nodeName)
}
},
copyEle: function (dom) {
var me = this;
$('.edui-editor-resizer').removeClass('scale').removeClass('hover').removeClass('show');
var index = $(dom).parents('.edui-editor-resizer').attr('index');
var nodeName;
if (dom.className.indexOf('img') > -1) {
nodeName = 'img';
} else if (dom.className.indexOf('iframe') > -1) {
var type = $(dom).parents('.edui-editor-resizer').attr('iframetype');
if (type && type == 'text') {
nodeName = 'a';
} else {
nodeName = 'iframe';
}
} else if (dom.className.indexOf('table') > -1) {
nodeName = 'table';
} else if (dom.className.indexOf('link') > -1) {
nodeName = 'a';
}
var ele;
if (nodeName == 'img') {
ele = $(me.document.body).find('img').eq(index)[0];
} else if (nodeName == 'iframe') {
ele = $(me.document.body).find('iframe').eq(index)[0];
} else if (nodeName == 'a') {
ele = $(me.document.body).find('a').eq(index)[0];
} else if (nodeName == 'table') {
ele = $(me.document.body).find('table').eq(index)[0];
} else if (dom.className.indexOf('callout') > -1) {
ele = $(me.document.body).find('.callout-block').eq(index)[0];
}
if (!ele) {
return;
}
if (ele.parentNode && ele.parentNode.getAttribute('contenteditable') == 'false') {
ele.classList.remove('hover');
ele = ele.parentNode;
} else if (ele.parentNode && ele.parentNode.className && ele.parentNode.className == 'table') {
ele = ele.parentNode;
}
if (!window.dt) {
var prefix = (RichTextUitl.prefix || RichTextUitl.noteDomain) + '/res/plugin/ueditor/';
if(RichTextUitl.intranetMode){
prefix = RichTextUitl.prefix
}
url = prefix + "third-party/clipboard-polyfill.promise.js";
utils.loadFile(document, {
src: url,
tag: "script",
type: "text/javascript",
defer: "defer"
}, function () {
me.initclipboard('copy', ele, index, nodeName)
});
} else {
me.initclipboard('copy', ele, index, nodeName)
}
},
initclipboard: function (type, node, index, nodeName) {
var me = this;
if (!window.dt) {
window.dt = new clipboard.DT();
}
var html = '
' + node.outerHTML;
dt.setData("text/html", html);
clipboard.write(dt).then(function () {
if (nodeName == 'img') {
$(me.document.body).find('.editor-image').removeClass('scale');
}
$('.edui-editor-resizer').removeClass('scale').removeClass('hover').removeClass('show');
if ($('.toolTipBox').length > 0) {
$('.toolTipBox').remove()
}
var prefix = (RichTextUitl.prefix || RichTextUitl.noteDomain) + '/res/plugin/ueditor/';
if(RichTextUitl.intranetMode){
prefix = RichTextUitl.prefix
}
$(document.body).append('
'+signName +'
'+ ''+signTime +'
'+ ''+pointData[i].content+'
' + (ie ? '' : '
') + '
' + cont + '
'; me.addListener('firstBeforeExecCommand focus', clear); } }(), /** * 显示编辑器 * @method setShow * @example * ```javascript * editor.setShow() * ``` */ setShow: function () { var me = this, range = me.selection.getRange(); if (me.container.style.display == 'none') { //有可能内容丢失了 try { range.moveToBookmark(me.lastBk); delete me.lastBk } catch (e) { range.setStartAtFirst(me.body).collapse(true) } //ie下focus实效,所以做了个延迟 setTimeout(function () { range.select(true); }, 100); me.container.style.display = ''; } }, show: function () { return this.setShow(); }, /** * 隐藏编辑器 * @method setHide * @example * ```javascript * editor.setHide() * ``` */ setHide: function () { var me = this; if (!me.lastBk) { me.lastBk = me.selection.getRange().createBookmark(true); } me.container.style.display = 'none' }, hide: function () { return this.setHide(); }, /** * 根据指定的路径,获取对应的语言资源 * @method getLang * @param { String } path 路径根据的是lang目录下的语言文件的路径结构 * @return { Object | String } 根据路径返回语言资源的Json格式对象或者语言字符串 * @example * ```javascript * editor.getLang('contextMenu.delete'); //如果当前是中文,那返回是的是'删除' * ``` */ getLang: function (path) { var lang = UE.I18N[this.options.lang]; if (!lang) { throw Error("not import language file"); } path = (path || "").split("."); for (var i = 0, ci; ci = path[i++];) { lang = lang[ci]; if (!lang) break; } return lang; }, /** * 计算编辑器html内容字符串的长度 * @method getContentLength * @return { Number } 返回计算的长度 * @example * ```javascript * //编辑器html内容132
* editor.getContentLength() //返回27 * ``` */ /** * 计算编辑器当前纯文本内容的长度 * @method getContentLength * @param { Boolean } ingoneHtml 传入true时,只按照纯文本来计算 * @return { Number } 返回计算的长度,内容中有hr/img/iframe标签,长度加1 * @example * ```javascript * //编辑器html内容132
* editor.getContentLength() //返回3 * ``` */ getContentLength: function (ingoneHtml, tagNames) { var count = this.getContent(false, false, true).length; if (ingoneHtml) { tagNames = (tagNames || []).concat(['hr', 'img', 'iframe']); count = this.getContentTxt().replace(/[\t\r\n]+/g, '').length; for (var i = 0, ci; ci = tagNames[i++];) { count += this.document.getElementsByTagName(ci).length; } } return count; }, /** * PC端 优化计算编辑器当前纯文本内容的长度 不算图片和附件 * @method getWordCountLength * @return { Number } 返回计算的长度,内容中有hr/img/iframe标签 忽略 * @example */ getWordCountLength: function () { var tagNames = (tagNames || []).concat(['hr', 'img', 'iframe']); var count = this.getContentTxt().replace(/[\t\r\n]+/g, '').length; return count; }, /** * 注册输入过滤规则 * @method addInputRule * @param { Function } rule 要添加的过滤规则 * @example * ```javascript * editor.addInputRule(function(root){ * $.each(root.getNodesByTagName('div'),function(i,node){ * node.tagName="p"; * }); * }); * ``` */ addInputRule: function (rule) { this.inputRules.push(rule); }, /** * 执行注册的过滤规则 * @method filterInputRule * @param { UE.uNode } root 要过滤的uNode节点 * @remind 执行editor.setContent方法和执行'inserthtml'命令后,会运行该过滤函数 * @example * ```javascript * editor.filterInputRule(editor.body); * ``` * @see UE.Editor:addInputRule */ filterInputRule: function (root) { for (var i = 0, ci; ci = this.inputRules[i++];) { ci.call(this, root) } }, /** * 注册输出过滤规则 * @method addOutputRule * @param { Function } rule 要添加的过滤规则 * @example * ```javascript * editor.addOutputRule(function(root){ * $.each(root.getNodesByTagName('p'),function(i,node){ * node.tagName="div"; * }); * }); * ``` */ addOutputRule: function (rule) { this.outputRules.push(rule) }, /** * 根据输出过滤规则,过滤编辑器内容 * @method filterOutputRule * @remind 执行editor.getContent方法的时候,会先运行该过滤函数 * @param { UE.uNode } root 要过滤的uNode节点 * @example * ```javascript * editor.filterOutputRule(editor.body); * ``` * @see UE.Editor:addOutputRule */ filterOutputRule: function (root) { for (var i = 0, ci; ci = this.outputRules[i++];) { ci.call(this, root) } }, /** * 根据action名称获取请求的路径 * @method getActionUrl * @remind 假如没有设置serverUrl,会根据imageUrl设置默认的controller路径 * @param { String } action action名称 * @example * ```javascript * editor.getActionUrl('config'); //返回 "/ueditor/php/controller.php?action=config" * editor.getActionUrl('image'); //返回 "/ueditor/php/controller.php?action=uplaodimage" * editor.getActionUrl('scrawl'); //返回 "/ueditor/php/controller.php?action=uplaodscrawl" * editor.getActionUrl('imageManager'); //返回 "/ueditor/php/controller.php?action=listimage" * ``` */ getActionUrl: function (action) { // 上传图片和文件的地址单独配置 if (action == 'uploadimage' || action == 'uploadfile' || action == 'uploadvideo') { //return 'https://pan-yz.chaoxing.com/upload'; // 兼容镜像逻辑 if (window.location.host.indexOf('course.ustc.edu.cn') > -1 && !(RichTextUitl.prefix && RichTextUitl.prefix.indexOf('chaoxing.com') > -1)) { RichTextUitl.mirrorPhotoDomain = 'https://cs.course.ustc.edu.cn'; RichTextUitl.uploadUrl = 'https://pan.course.ustc.edu.cn/upload'; } if(window.obj && window.obj.mirrorDomain){ RichTextUitl.mirrorPhotoDomain = window.obj.mirrorDomain.photoDomain; if(!RichTextUitl.cloudUrl){ RichTextUitl.uploadUrl = window.location.protocol + window.obj.mirrorDomain.panDomain.replace('https:','').replace('http:','')+'/upload'; } } return RichTextUitl.uploadUrl || 'https://pan-yz.chaoxing.com/upload'; } else if (action == "catchimage") { // return 'https://noteyd.chaoxing.com/pc/files/uploadRemoteImage'; // 兼容镜像逻辑 return RichTextUitl.uploadRemoteImageUrl || RichTextUitl.convertUrl('https://noteyd.chaoxing.com/pc/files/uploadRemoteImage'); } else if (action == 'convertfile') { // return 'https://exportyd.chaoxing.com/convert/convertToHtml'; // 兼容镜像逻辑 return RichTextUitl.convertToHtmlUrl || RichTextUitl.convertUrl('https://exportyd.chaoxing.com/convert/convertToHtml'); } else { var actionName = this.getOpt(action) || action, imageUrl = this.getOpt('imageUrl'), serverUrl = this.getOpt('serverUrl'); if (!serverUrl && imageUrl) { serverUrl = imageUrl.replace(/^(.*[\/]).+([\.].+)$/, '$1controller$2'); } if (serverUrl) { serverUrl = serverUrl + (serverUrl.indexOf('?') == -1 ? '?' : '&') + 'action=' + (actionName || ''); return utils.formatUrl(serverUrl); } else { return ''; } } }, /** * 根据上传接口返回的内容向页面加入云盘附件 * @param cloudData */ insertCloudAttachment: function (data) { if (!data) { return; } var me = this; var cloudData = getCloudAttachmentStructure(data); cloudData.cid = RichTextUitl.randomUUID(); var attHtml = ']*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi, "
$1
" ) .replace(/]*class="?MsoHeading"?[^>]*>(.*?)<\/p>/gi, "
$1
") //去掉多余的属性 .replace(/\s+(lang|align)\s*=\s*(['"]?)([\w-]+)\2/ig, function (str, name, marks, val) { //保留list的标示 return name == 'class' && val == 'MsoListParagraph' ? str : '' }) //清除多余的font/span不能匹配 有可能是空格 .replace(/<(font|span)[^>]*>(\s*)<\/\1>/gi, function (a, b, c) { return c.replace(/[\t\r\n ]+/g, ' ') }) //处理style的问题 .replace(/(<[a-z][^>]*)\sstyle=(["'])([^\2]*?)\2/gi, function (str, tag, tmp, style) { var n = [], s = style.replace(/^\s+|\s+$/, '') .replace(/'/g, '\'') .replace(/"/gi, "'") .replace(/[\d.]+(cm|pt)/g, function (str) { return utils.transUnitToPx(str) }) .split(/;\s*/g); for (var i = 0, v; v = s[i]; i++) { var name, value, parts = v.split(":"); if (parts.length == 2) { name = parts[0].toLowerCase(); value = parts[1].toLowerCase(); if (/^(background)\w*/.test(name) && value.replace(/(initial|\s)/g, '').length == 0 || /^(margin)\w*/.test(name) && /^0\w+$/.test(value) ) { continue; } switch (name) { case "mso-padding-alt": case "mso-padding-top-alt": case "mso-padding-right-alt": case "mso-padding-bottom-alt": case "mso-padding-left-alt": case "mso-margin-alt": case "mso-margin-top-alt": case "mso-margin-right-alt": case "mso-margin-bottom-alt": case "mso-margin-left-alt": continue; //ie下会出现挤到一起的情况 //case "mso-table-layout-alt": case "mso-height": case "mso-width": case "mso-vertical-align-alt": //trace:1819 ff下会解析出padding在table上 if (!/| 这样的标签了
//先去掉了,加上的原因忘了,这里先记录
var re_tag = /<(?:(?:\/([^>]+)>)|(?:!--([\S|\s]*?)-->)|(?:([^\s\/<>]+)\s*((?:(?:"[^"]*")|(?:'[^']*')|[^"'<>])*)\/?>))/g,
re_attr = /([\w\-:.]+)(?:(?:\s*=\s*(?:(?:"([^"]*)")|(?:'([^']*)')|([^\s>]+)))|(?=\s|$))/g;
//ie下取得的html可能会有\n存在,要去掉,在处理replace(/[\t\r\n]*/g,'');代码高量的\n不能去除
var allowEmptyTags = {
b: 1,
code: 1,
i: 1,
u: 1,
strike: 1,
s: 1,
tt: 1,
strong: 1,
q: 1,
samp: 1,
em: 1,
span: 1,
sub: 1,
img: 1,
sup: 1,
font: 1,
big: 1,
small: 1,
iframe: 1,
a: 1,
br: 1,
pre: 1
};
// htmlstr = htmlstr.replace(new RegExp(domUtils.fillChar, 'g'), '');
if (!ignoreBlank) {
htmlstr = htmlstr.replace(new RegExp('[\\r\\t\\n' + (ignoreBlank ? '' : ' ') + ']*<\/?(\\w+)\\s*(?:[^>]*)>[\\r\\t\\n' + (ignoreBlank ? '' : ' ') + ']*', 'g'), function (a, b) {
//br暂时单独处理
if (b && allowEmptyTags[b.toLowerCase()]) {
return a.replace(/(^[\n\r]+)|([\n\r]+$)/g, '');
}
return a.replace(new RegExp('^[\\r\\n' + (ignoreBlank ? '' : ' ') + ']+'), '').replace(new RegExp('[\\r\\n' + (ignoreBlank ? '' : ' ') + ']+$'), '');
});
}
var notTransAttrs = {
'href': 1,
'src': 1
};
var uNode = UE.uNode,
needParentNode = {
'td': 'tr',
'tr': ['tbody', 'thead', 'tfoot'],
'tbody': 'table',
'th': 'tr',
'thead': 'table',
'tfoot': 'table',
'caption': 'table',
'li': ['ul', 'ol'],
'dt': 'dl',
'dd': 'dl',
'option': 'select'
},
needChild = {
'ol': 'li',
'ul': 'li'
};
function text(parent, data) {
if (needChild[parent.tagName]) {
var tmpNode = uNode.createElement(needChild[parent.tagName]);
parent.appendChild(tmpNode);
tmpNode.appendChild(uNode.createText(data));
parent = tmpNode;
} else {
parent.appendChild(uNode.createText(data));
}
}
function element(parent, tagName, htmlattr) {
var needParentTag;
if (needParentTag = needParentNode[tagName]) {
var tmpParent = parent,
hasParent;
while (tmpParent.type != 'root') {
if (utils.isArray(needParentTag) ? utils.indexOf(needParentTag, tmpParent.tagName) != -1 : needParentTag == tmpParent.tagName) {
parent = tmpParent;
hasParent = true;
break;
}
tmpParent = tmpParent.parentNode;
}
if (!hasParent) {
parent = element(parent, utils.isArray(needParentTag) ? needParentTag[0] : needParentTag)
}
}
//按dtd处理嵌套
// if(parent.type != 'root' && !dtd[parent.tagName][tagName])
// parent = parent.parentNode;
var elm = new uNode({
parentNode: parent,
type: 'element',
tagName: tagName.toLowerCase(),
//是自闭合的处理一下
children: dtd.$empty[tagName] ? null : []
});
//如果属性存在,处理属性
if (htmlattr) {
var attrs = {},
match;
while (match = re_attr.exec(htmlattr)) {
attrs[match[1].toLowerCase()] = notTransAttrs[match[1].toLowerCase()] ? (match[2] || match[3] || match[4]) : utils.unhtml(match[2] || match[3] || match[4])
}
elm.attrs = attrs;
}
//trace:3970
// //如果parent下不能放elm
// if(dtd.$inline[parent.tagName] && dtd.$block[elm.tagName] && !dtd[parent.tagName][elm.tagName]){
// parent = parent.parentNode;
// elm.parentNode = parent;
// }
parent.children.push(elm);
//如果是自闭合节点返回父亲节点
return dtd.$empty[tagName] ? parent : elm
}
function comment(parent, data) {
parent.children.push(new uNode({
type: 'comment',
data: data,
parentNode: parent
}));
}
var match, currentIndex = 0,
nextIndex = 0;
//设置根节点
var root = new uNode({
type: 'root',
children: []
});
var currentParent = root;
while (match = re_tag.exec(htmlstr)) {
currentIndex = match.index;
try {
if (currentIndex > nextIndex) {
//text node
text(currentParent, htmlstr.slice(nextIndex, currentIndex));
}
if (match[3]) {
if (dtd.$cdata[currentParent.tagName]) {
text(currentParent, match[0]);
} else {
//start tag
currentParent = element(currentParent, match[3].toLowerCase(), match[4]);
}
} else if (match[1]) {
if (currentParent.type != 'root') {
if (dtd.$cdata[currentParent.tagName] && !dtd.$cdata[match[1]]) {
text(currentParent, match[0]);
} else {
var tmpParent = currentParent;
while (currentParent.type == 'element' && currentParent.tagName != match[1].toLowerCase()) {
currentParent = currentParent.parentNode;
if (currentParent.type == 'root') {
currentParent = tmpParent;
throw 'break'
}
}
//end tag
currentParent = currentParent.parentNode;
}
}
} else if (match[2]) {
//comment
comment(currentParent, match[2])
}
} catch (e) {
}
nextIndex = re_tag.lastIndex;
}
//如果结束是文本,就有可能丢掉,所以这里手动判断一下
//例如 换成') } else { node.parentNode.removeChild(node); } } node.setStyle('float', ''); if (node.getAttr('contenteditable')) { node.tagName = 'div'; } // node.setStyle('font-size', ''); // break; case 'div': if (node.getAttr('cdata_tag')) { break; } if (!node.getAttr('element-id') || node.getAttr('element-id') == 'init') node.setAttr('element-id', domUtils.getRandomId()); node.setStyle('font-size', ''); //针对代码这里不处理插入代码的div val = node.getAttr('class'); if(val && (val.indexOf('noteDetail_main') > -1 || val.indexOf('noteContent') > -1 || val.indexOf('richtext') > -1)){ node.setAttr('class','') } //录音标注后要加文本节点占位 if (val && val.indexOf('record-list-tit') > -1) { if (node.lastChild() && (node.lastChild().type == 'text' || (node.lastChild().type == 'element' && node.lastChild().tagName == 'br'))) { } else { var newTextNode = UE.uNode.createElement('br'); node.appendChild(newTextNode); } } // 2022-6-8 如果div里只有文字,标签改为p if (node.tagName == 'div' && node.firstChild() && node.firstChild() == node.lastChild() && node.firstChild().type == 'text') { node.tagName = 'p'; break; } //20200703 去除图片div添加的背景 if (node.getAttr('class') && node.getAttr('class').indexOf('editor-image') > -1) { node.setStyle('background', ''); node.setStyle('background-color', ''); //解决浮动图片悬浮事件没有触发的问题 if (node.getStyle('float') == 'left' || node.getStyle('float') == 'right') { node.setStyle('z-index', '1'); } else { node.setStyle('z-index', ''); } } else { node.setStyle('float', ''); } if (node.getAttr('class') && node.getAttr('class').indexOf('editor-image') > -1) { //2022-3-24 拖动图片到一排-给图片外层加拖拽容器div if (node.parentNode && !(node.parentNode.getAttr('class') && node.parentNode.getAttr('class').indexOf('drag-image-wrap') > -1)) { var div = UE.uNode.createElement('div'); div.setAttr('element-id', domUtils.getRandomId()); div.setAttr('class', 'drag-image-wrap' + node.getAttr('class').replace('editor-image', '').replace('remoteImage', '')); div.setAttr('contenteditable', 'false'); node.parentNode.insertBefore(div, node); div.appendChild(node); node.setAttr('draggable', 'true'); } } else if (node.getAttr('class') && node.getAttr('class').indexOf('editor-iframe') > -1) { node.setAttr('draggable', 'true'); } if (node.getAttr('class') && node.getAttr('class').indexOf('drag-image-wrap') > -1) { node.setAttr('contenteditable', 'false'); node.setAttr('class', 'drag-image-wrap'); } if (node.getAttr('class') && ((node.getAttr('class').indexOf('editor-iframe') > -1 && node.getNodeByClass('editor-iframe')) || (node.getAttr('class').indexOf('drag-image-wrap') > -1 && node.getNodeByClass('drag-image-wrap')) || (node.getAttr('class').indexOf('editor-image') > -1 && node.getNodeByClass('editor-image')) || (node.getAttr('class').indexOf('table') > -1 && node.getNodeByClass('table')))) { while (node.firstChild()) { node.parentNode.insertBefore(node.firstChild(), node); } node.parentNode.removeChild(node); break; } //将image-wrap里面粘贴的其他元素移出来 2022-6-17 if (node.getAttr('class') && node.getAttr('class').indexOf('drag-image-wrap') > -1) { var firstChild = node.firstChild(), next; var hasImg = false; while (firstChild) { next = firstChild.nextSibling(); if (firstChild.getAttr('contenteditable') && firstChild.getAttr('class').indexOf('editor-image') > -1) { hasImg = true; } else if (firstChild.type == 'text' || !UE.dom.dtd.$block[firstChild.tagName]) { var p = UE.uNode.createElement('p'); p.setAttr('element-id', domUtils.getRandomId()); p.appendChild(firstChild); if (hasImg) { node.parentNode.insertAfter(p, node); } else { node.parentNode.insertBefore(p, node); } } else { if (hasImg) { node.parentNode.insertAfter(firstChild, node); } else { node.parentNode.insertBefore(firstChild, node); } } firstChild = next; } } //20210331 处理文本附件外层的div if (node.tagName == 'div' && node.getAttr('class') == 'editor-textiframe') { node.tagName = 'p'; node.setAttr('contenteditable', ''); node.setAttr('element-id', domUtils.getRandomId()); node.setAttr('class', ''); } if (node.getAttr('class') && node.getAttr('class').indexOf('table') > -1 && node.firstChild()) { node.setStyle('overflow', ''); node.setStyle('margin-left', ''); if (node.firstChild().data == domUtils.fillChar) { node.removeChild(node.firstChild()); } if (node.lastChild().data == domUtils.fillChar) { node.removeChild(node.lastChild()); } } if (val && /^line number\d+/.test(val)) { break; } //如果div没有class和style或者是飞书的图片class,移除外层的div if (node.tagName == 'div' && ((!node.getAttr('style') && !node.getAttr('class') && !(node.parentNode && node.parentNode.getAttr('class') && node.parentNode.getAttr('class').indexOf('classul') > -1)) || (node.getAttr('class') && node.getAttr('class').indexOf('image-uploaded') > -1 && node.getAttr('class').indexOf('gallery') > -1))) { var p = UE.uNode.createElement('p'); p.setAttr('element-id', domUtils.getRandomId()); node.parentNode.insertBefore(p, node); while (node.firstChild()) { if (node.firstChild().type == 'text' || !UE.dom.dtd.$block[node.firstChild().tagName]) { p.appendChild(node.firstChild()); } else if (node.firstChild.tagName == 'br') { p.appendChild(node.firstChild()); p = UE.uNode.createElement('p'); p.setAttr('element-id', domUtils.getRandomId()); } else { node.parentNode.insertBefore(node.firstChild(), node); } } if (!p.firstChild()) { p.parentNode.removeChild(p); } node.parentNode.removeChild(node); break; } //如果不允许div转p,跳出,下面是处理div转p的 if (!allowDivTransToP) { break; } var tmpNode, p = UE.uNode.createElement('p'); p.setAttr('element-id', domUtils.getRandomId()) while (tmpNode = node.firstChild()) { if (tmpNode.type == 'text' || !UE.dom.dtd.$block[tmpNode.tagName]) { p.appendChild(tmpNode); } else { if (p.firstChild()) { node.parentNode.insertBefore(p, node); p = UE.uNode.createElement('p'); p.setAttr('element-id', domUtils.getRandomId()) } else { node.parentNode.insertBefore(tmpNode, node); } } } if (p.firstChild()) { node.parentNode.insertBefore(p, node); } node.parentNode.removeChild(node); break; case 'dl': node.tagName = 'ul'; break; case 'dt': case 'dd': node.tagName = 'li'; break; case 'ul': case 'ol': node.setAttr('style', 'list-style-type: decimal;'); //去除font-size 14 if (node.getStyle('font-size') == '14px') { node.setStyle('font-size', '') } case 'li': var color = node.getStyle('color'); if (color) { node.setStyle('color', color); } if (node.getStyle('caret-color')) { node.setStyle('caret-color', ''); } //去除粘贴列表带出来的display:inline!important if (node.getStyle('display')) { node.setStyle('display', ''); } node.traversal(function (node) { if (node.tagName != 'li' && node.getStyle('line-height') && node.getStyle('line-height') != '') { node.setStyle('line-height', '') } }) break; case 'th': case 'td': var tmpNodes = node.getNodesByTagName('iframe'); if (tmpNodes.length > 0) { node.setAttr('width', '440'); } else if (node.getAttr('width') && node.getAttr('width').indexOf('%') > -1) { var width = parseInt(node.getAttr('width')) * $(me.body).width() / 100; node.setAttr('width', '' + width + ''); } else if (node.getAttr('width') && node.getAttr('width') < 40) { node.setAttr('width', '') } //去除font-size 14 if (node.setStyle('font-size') == '14px' && node.parentNode.tagName != 'LI') { node.setStyle('font-size', '') } node.setStyle('width', ''); // node.setAttr('vAlign', 'middle'); //如果只有一个br或纯文字,给br套一个p标签 if (node.children.length == 1 && (node.firstChild().tagName == 'br' || node.firstChild().type == 'text')) { var p = UE.uNode.createElement('p'); p.appendChild(node.firstChild()); node.appendChild(p); } break; case 'caption': if (!node.children || !node.children.length) { node.appendChild(browser.ie11below ? UE.uNode.createText(' ') : UE.uNode.createElement('br')) } break; case 'table': if (me.options.disabledTableInTable && tdParent(node)) { node.parentNode.insertBefore(UE.uNode.createText(node.innerText()), node); node.parentNode.removeChild(node) } node.setStyle('width', ''); if (node.getAttr('width') && (node.getAttr('width') < 500 || node.getAttr('width') == 'NaN' || node.getAttr('width') == '')) { node.setAttr('width','') } case 'col': if (node.getAttr('width') && (node.getAttr('width') == 'NaN' || node.getAttr('width') == '')) { node.setAttr('width','') } } //标题处理 if (/h\d/i.test(node.tagName)) { //20210317 更新目录--旧笔记没有element-id的加上id if (!node.getAttr('element-id') || node.getAttr('element-id') == 'init') node.setAttr('element-id', domUtils.getRandomId()); //去除font-size 14 if (node.getStyle('font-size') == '14px' && node.parentNode.tagName != 'LI') { node.setStyle('font-size', '') } } //标题折叠:去掉标题折叠的三角 if (node.getAttr('class') && node.getAttr('class').indexOf('foldtitle-tri-wrap') > -1) { node.parentNode.removeChild(node); } //不是表格的外面套了.table,去掉class if (node.tagName != 'table' && node.parentNode && node.parentNode.getAttr('class') && node.parentNode.getAttr('class') == 'table') { node.parentNode.setAttr('class', '') } //去除onclick方法 if (node.getAttr('onclick')) { node.setAttr('onclick', ''); } //white-space 属性改为空 if (node.getStyle('white-space')) { node.setStyle('white-space', ''); } if (node.getStyle('caret-color')) { node.setStyle('caret-color', ''); } //20200422去除translate,防止文字右移超出版心 if (node.getStyle('transform') && node.getStyle('transform').indexOf('translate') > -1) { node.setStyle('transform', ''); } //20201010 浮动后文字不跟过去 if (node.getStyle('clear')) { node.setStyle('clear', ''); } if (node.getStyle('visibility')) { node.setStyle('visibility', ''); } //去除其他地方粘贴过来的contenteditable属性 if (node.getAttr('contenteditable') == 'true') { node.setAttr('contenteditable', ''); } if (node.getStyle('background') && node.getStyle('background').indexOf('url') > -1) { node.setStyle('background', ''); } if (node.getStyle('background-image') && node.getStyle('background-image') == 'url( default/images/callout-icon.png )') { node.setStyle('background-image', ''); } //有 div存在background-image属性 的情况 // node.setStyle('background-image', ''); if (node.getStyle('line-height').trim() == '2em') { node.setStyle('line-height', ''); } //去除img以外标签的宽度 if (node.getStyle('width') && node.tagName.toLocaleLowerCase() != 'img' && node.tagName.toLocaleLowerCase() != 'col' && node.tagName.toLocaleLowerCase() != 'table') { if (node.getStyle('width').indexOf('px') == -1 && node.getStyle('width').indexOf('%') == -1) { if (node.getStyle('width').indexOf('em') != -1) { //em 转换为px var w = node.getStyle('width').slice(0, node.getStyle('width').length - 2) * 16 node.setStyle('width', w + 'px'); } else { node.setStyle('width', 'auto'); } } } if (node.getStyle('position') && node.getStyle('position') == 'fixed') { node.setStyle('position','') } //去除定位相关样式 // if (!me.options.showXiumi && node.tagName && node.tagName.toLowerCase() != 'section') { // node.setStyle('position', ''); // node.setStyle('left', ''); // node.setStyle('top', ''); // node.setStyle('bottom', ''); // node.setStyle('right', ''); // node.setStyle('overflow', ''); // node.setStyle('height', ''); // } if (node.tagName && node.tagName.toLowerCase() != 'table' && node.tagName.toLowerCase() != 'section') { node.setStyle('margin', ''); } // node.setStyle('padding', ''); // node.setStyle('margin-top', ''); // node.setStyle('padding-top', ''); // node.setStyle('margin-bottom', ''); // node.setStyle('padding-bottom', ''); /*if(node.getStyle('margin-left').indexOf('-')){ node.setStyle('margin-left',''); }*/ // node.setStyle('margin-right',''); // if (node.getStyle('display') && (node.getStyle('display').indexOf('box') > -1 || node.getStyle('display').indexOf('flex') > -1)) { // node.setStyle('display', ''); // } node.setStyle('touch-action', ''); node.setStyle('flex', ''); if(node.getStyle('display') && node.getStyle('display').indexOf('flex')){ node.setStyle('display', ''); } node.setStyle('max-width', ''); if (node.getStyle('font-size') && node.getStyle('font-size').indexOf('em') > -1) { node.setStyle('font-size', ''); } else if (node.getStyle('font-size') && node.getStyle('font-size').indexOf('medium') > -1) { node.setStyle('font-size', '16px'); } else if (node.getStyle('font-size') && node.getStyle('font-size').indexOf('large') > -1) { node.setStyle('font-size', '18px'); } else if (node.getStyle('font-size') && node.getStyle('font-size').indexOf('small') > -1) { node.setStyle('font-size', '14px'); } //删除线加下划线 if (dtd.$inline[node.tagName] && node.tagName != 'img' && (node.getStyle('text-decoration-line').indexOf("line-through") > -1 || node.getStyle('text-decoration').indexOf("line-through") > -1) && (node.getStyle('text-decoration-line').indexOf("underline") > -1 || node.getStyle('text-decoration').indexOf("underline") > -1)) { node.setStyle('text-decoration', ''); node.setStyle('text-decoration-line', ''); var strike = UE.uNode.createElement('strike'); strike.appendChild(node.children[0]); node.appendChild(strike); if (node.children.length > 0 && node.attrs.style != '') { var u = UE.uNode.createElement('u'); u.appendChild(strike.children[0]); strike.appendChild(u); } else { node.tagName = 'u'; } } else if (dtd.$inline[node.tagName] && node.tagName != 'img' && node.getStyle('text-decoration-line').indexOf("line-through") > -1 || node.getStyle('text-decoration').indexOf("line-through") > -1) { node.setStyle('text-decoration', ''); node.setStyle('text-decoration-line', ''); if (node.children.length > 0 && node.attrs.style != '') { var span = UE.uNode.createElement('strike'); span.appendChild(node.children[0]); node.appendChild(span); } else { node.tagName = 'strike'; } } else if (dtd.$inline[node.tagName] && node.tagName != 'img' && node.getStyle('text-decoration-line').indexOf("underline") > -1 || node.getStyle('text-decoration').indexOf("underline") > -1) { node.setStyle('text-decoration', ''); node.setStyle('text-decoration-line', ''); if (node.children.length > 0 && node.attrs.style != '') { var span = UE.uNode.createElement('u'); span.appendChild(node.children[0]); node.appendChild(span); } else { node.tagName = 'u'; } } //斜体 if (dtd.$inline[node.tagName] && node.tagName != 'img' && node.getStyle('font-style').indexOf('italic') > -1) { node.setStyle('font-style', ''); if (node.children.length > 0 && node.attrs.style != '') { var span = UE.uNode.createElement('i'); span.appendChild(node.children[0]); node.appendChild(span); } else { node.tagName = 'i'; } } //粗体 if (dtd.$inline[node.tagName] && node.tagName != 'img' && (node.getStyle('font-weight').indexOf('bold') > -1 || node.getStyle('font-weight') >= 600)) { node.setStyle('font-weight', ''); if (node.children.length > 0 && node.attrs.style != '') { var span = UE.uNode.createElement('b'); while (node.children[0]) { span.appendChild(node.children[0]); } node.appendChild(span); } else { node.tagName = 'b'; } } } }) }); //从编辑器出去的内容处理 me.addOutputRule(function (root) { var val; root.traversal(function (node) { if (node.type == 'element') { if (me.options.autoClearEmptyNode && dtd.$inline[node.tagName] && !dtd.$empty[node.tagName] && (!node.attrs || utils.isEmptyObject(node.attrs))) { if (!node.firstChild()) node.parentNode.removeChild(node); else if (node.tagName == 'span' && (!node.attrs || utils.isEmptyObject(node.attrs))) { node.parentNode.removeChild(node, true) } return; } //勾选框不删除2019.10.25 if (node.getAttr('class') == 'todo-inner' || node.getAttr('class') == 'todo-mark' || node.getAttr('class') == 'callout-icon' || node.getAttr('class') == 'callout-inner') { return; } else if (node.children && node.children.length == 0 && node.tagName != 'iframe' && node.tagName != 'img' && node.tagName != 'tr' && node.tagName != 'br' && node.tagName != 'canvas' && !(node.getAttr('module') && node.getAttr('module') == "chart")) { //去除空标签 node.parentNode.removeChild(node, true); return; } switch (node.tagName) { case 'section': node.tagName = 'div'; case 'div': if (val = node.getAttr('cdata_tag')) { node.tagName = val; node.appendChild(UE.uNode.createText(node.getAttr('cdata_data'))); node.setAttr({ cdata_tag: '', cdata_data: '', '_ue_custom_node_': '' }); } // 20200324 完成笔记时去除原站内信函的签名id if (node.getAttr('id') && node.getAttr('id') == 'signDiv' && node.parentNode.type != 'root') { node.setAttr('id', ''); } node.setAttr('draggable', ''); //20200603 完成时去除编辑图片给div添加的class:scale或hover if (node.getAttr('class') && node.getAttr('class').indexOf('editor-image') > -1 && node.getAttr('class').indexOf('scale') > -1) { node.setAttr('class', node.getAttr('class').replace('scale', '')); } if (node.getAttr('class') && node.getAttr('class').indexOf('drag-image-wrap') > -1) { node.setAttr('contenteditable', 'false'); } //20200731 去除附件拖动把手,去除拖动辅助线 if (node.getAttr('class') && (node.getAttr('class') == 'draghandle' || node.getAttr('class').indexOf('dragGuideLine') > -1)) { node.parentNode.removeChild(node); } //20210323 去除套的多余的 div editor-iframe、editor-image、table if (node.children.length == 1 && node.firstChild().tagName == 'div' && node.getAttr('class') && node.firstChild().getAttr('class') && ((node.getAttr('class').indexOf('editor-iframe') > -1 && node.firstChild().getAttr('class').indexOf('editor-iframe') > -1) || (node.firstChild().getAttr('class').indexOf('editor-image') > -1 && node.getAttr('class').indexOf('editor-image') > -1) || (node.firstChild().getAttr('class').indexOf('table') > -1 && node.getAttr('class').indexOf('table') > -1))) { var firstChild = node.firstChild(); while (firstChild.firstChild()) { node.insertBefore(firstChild.firstChild(), firstChild); } node.removeChild(firstChild); } if (node.getAttr('class') && node.getAttr('class') == 'editor-iframe' && node.getAttr('class') == 'editor-image') { node.setStyle('width', ''); } break; case 'ul': node.setStyle('width', ''); break; case 'ol': node.setStyle('width', ''); break; case 'li': node.setAttr('class', ''); node.traversal(function (node) { if (node.tagName != 'li' && node.getStyle('line-height') && node.getStyle('line-height') != '') { node.setStyle('line-height', '') } }) break; case 'a': if (val = node.getAttr('_href')) { node.setAttr({ 'href': utils.html(val), '_href': '' }) } break; case 'span': val = node.getAttr('id'); if (val && /^_baidu_bookmark_/i.test(val)) { node.parentNode.removeChild(node) } // 20200529 去除图片编辑框的蓝色色块 if (node.getAttr('class') && node.getAttr('class').indexOf('edui-editor-imagescale-hand') > -1) { node.parentNode.removeChild(node); } // 20200609 去除todo-inner里的内容 if (node.getAttr('class') && node.getAttr('class').indexOf('todo-inner') > -1) { node.nodeValue = ''; } break; case 'img': if (val = node.getAttr('_src') && node.parentNode.getAttr('class') && node.parentNode.getAttr('class').indexOf('remoteImage') == -1) { node.setAttr({ 'src': node.getAttr('_src'), '_src': '' }) } if(node.getAttr('src')) node.parentNode.setAttr('class','editor-image') node.setAttr('role', 'img') node.setAttr('tabindex', '0') // 处理固定宽高图片排版的老数据图片结构 if(node.getAttr('class') && node.getAttr('class').indexOf('width-column-img') > -1){ node.setAttr('class', 'width-column-img') }else{ node.setAttr('class', ''); } //20200520 保留图片宽高 // node.setAttr('width','auto'); // node.setAttr('height','auto'); node.setAttr('fileid', ''); //img外层没有div包裹 if (browser.firefox || browser.ie) { if (node.parentNode.tagName == 'div' && !node.parentNode.attrs.class && node.parentNode.children.length == 1) { node.parentNode.setAttr('class', 'editor-image'); node.parentNode.setAttr('contenteditable', 'false'); } else if (node.parentNode.tagName == 'p' && !node.parentNode.attrs.class && node.parentNode.children.length == 1) { node.parentNode.tagName = 'div'; node.parentNode.setAttr('class', 'editor-image'); node.parentNode.setAttr('contenteditable', 'false'); } else { var div = UE.uNode.createElement('div'); div.setAttr('element-id', domUtils.getRandomId()) node.parentNode.insertBefore(div, node); div.appendChild(node); div.setAttr("class", "editor-image"); div.setAttr('contenteditable', 'false'); } } break; case 'iframe': if (browser.firefox || browser.ie) { //iframe外层没有div包裹 if (domUtils.isBlockElm(node.parentNode) && !node.parentNode.attrs.class && node.parentNode.children.length == 1) { node.parentNode.setAttr('class', 'editor-iframe'); node.parentNode.setAttr('contenteditable', 'false'); } else if (node.parentNode.tagName == 'p' && !node.parentNode.attrs.class && node.parentNode.children.length == 1) { node.parentNode.tagName = 'div'; node.parentNode.setAttr('class', 'editor-iframe'); node.parentNode.setAttr('contenteditable', 'false'); } else { var div = UE.uNode.createElement('div'); div.setAttr('element-id', domUtils.getRandomId()) node.parentNode.insertBefore(div, node); div.appendChild(node); div.setAttr("class", "editor-iframe"); div.setAttr('contenteditable', 'false') } } break; case 'table': node.setStyle('width', ''); if (node.getAttr('width') && (node.getAttr('width') == 'NaN' || node.getAttr('width') == '')) { node.setAttr('width','') } break; case 'col': if (node.getAttr('width') && (node.getAttr('width') == 'NaN' || node.getAttr('width') == '')) { node.setAttr('width','') } break; case 'h1': //20210317 更新目录--旧笔记没有element-id的加上id if (!node.getAttr('element-id') || node.getAttr('element-id') == 'init') node.setAttr('element-id', domUtils.getRandomId()); break; case 'h2': if (!node.getAttr('element-id') || node.getAttr('element-id') == 'init') node.setAttr('element-id', domUtils.getRandomId()); break; case 'h3': if (!node.getAttr('element-id') || node.getAttr('element-id') == 'init') node.setAttr('element-id', domUtils.getRandomId()); break; case 'h4': if (!node.getAttr('element-id') || node.getAttr('element-id') == 'init') node.setAttr('element-id', domUtils.getRandomId()); break; case 'h5': if (!node.getAttr('element-id') || node.getAttr('element-id') == 'init') node.setAttr('element-id', domUtils.getRandomId()); break; case 'h6': if (!node.getAttr('element-id') || node.getAttr('element-id') == 'init') node.setAttr('element-id', domUtils.getRandomId()); break; } if (node.getStyle('position') && node.getStyle('position').indexOf('absolute') > 0) { if (!(node.getAttr('id') && node.getAttr('id') == 'ue_tableDragLine')) { node.parentNode.removeChild(node, true) } } if (node.getStyle('position') && node.getStyle('position') == 'fixed') { node.setStyle('position','') } if (node.getStyle('text-align') && node.getStyle('text-align') == 'start') { node.setStyle('text-align', ''); } if (node.getStyle('display') && node.getStyle('display') == 'none') { //标题折叠:完成时需要展开折叠标题 node.setStyle('display', ''); } if (node.getAttr('class') && node.getAttr('class').indexOf('tempShow') > -1) { node.setAttr('class', '') } node.setStyle('touch-action', ''); } }) }); }; // plugins/inserthtml.js /** * 插入html字符串插件 * @file * @since 1.2.6.1 */ /** * 插入html代码 * @command inserthtml * @method execCommand * @param { String } cmd 命令字符串 * @param { String } html 插入的html字符串 * @remaind 插入的标签内容是在当前的选区位置上插入,如果当前是闭合状态,那直接插入内容, 如果当前是选中状态,将先清除当前选中内容后,再做插入 * @warning 注意:该命令会对当前选区的位置,对插入的内容进行过滤转换处理。 过滤的规则遵循html语意化的原则。 * @example * ```javascript * //xxx[BB]xxx 当前选区为非闭合选区,选中BB这两个文本 * //执行命令,插入CC * //插入后的效果 xxxCCxxx * // xx|xxx 当前选区为闭合状态 * //插入CC * //结果xx CC xxx * //xxxx |xxx 当前选区在两个p标签之间 * //插入 xxxx * //结果xxxx xxxx xxx * ``` */ UE.commands['inserthtml'] = { execCommand: function (command, html, notNeedFilter, tmpRange) { var me = this, range, div; if (!html) { return; } if (me.fireEvent('beforeinserthtml', html) === true) { return; } range = me.selection.getRange(); //20200619 tmpRange是协同恢复的时候用的range if (tmpRange) { range = tmpRange } else { // 20211022 如果光标在contenteditable=false 里面,移出 if (range.startContainer.nodeType == 1 && range.startContainer.getAttribute('contenteditable') && range.startContainer.nodeName != 'BODY') { if (range.startOffset == 0 && domUtils.getPreDomNode(range.startContainer, false)) { range.setStart(domUtils.getPreDomNode(range.startContainer, false), domUtils.getPreDomNode(range.startContainer, false).childNodes.length - 1); } else if (range.startOffset == 0) { range.setStartBefore(range.startContainer) } else if (domUtils.getNextDomNode(range.startContainer, false)) { range.setStart(domUtils.getNextDomNode(range.startContainer, false), 0); } else { range.setStartAfter(range.startContainer) } } if (range.endContainer.nodeType == 1 && range.endContainer.getAttribute('contenteditable') && range.endContainer.nodeName != 'BODY') { if (range.endOffset == 0 && domUtils.getPreDomNode(range.endContainer, false)) { range.setEnd(domUtils.getPreDomNode(range.endContainer, false), domUtils.getPreDomNode(range.endContainer, false).childNodes.length - 1); } else if (range.endOffset == 0) { range.setEndBefore(range.endContainer) } else if (domUtils.getNextDomNode(range.endContainer, false)) { range.setEnd(domUtils.getNextDomNode(range.endContainer, false), 0); } else { range.setEndAfter(range.endContainer) } } range.select(true) } if (range.collapsed && range.startContainer.nodeType == 1 && (range.startContainer.className.indexOf('editor-image') > -1 || range.startContainer.className.indexOf('editor-iframe') > -1 || range.startContainer.tagName == 'A')) { range.setStartAfter(range.startContainer); range.setEndAfter(range.startContainer); range.collapse(true); } else if (range.collapsed && $(range.startContainer).parents('a').length > 0 && html.indexOf('<') > -1) { //光标在a标签里,移出//如果插入的内容没有标签,可以直接插入到a标签里 range.setStartAfter($(range.startContainer).parents('a')[0]).collapse(true); } if (html.indexOf(' |