From c47d1c46c1b7f2f4c5ef3c332a26bb164f0a05b3 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Sun, 19 Jan 2020 23:13:14 +0900 Subject: [PATCH 01/99] fix: detachRangeFormatElement - br split --- src/lib/core.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/core.js b/src/lib/core.js index 0a00ff702..509947888 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -1035,7 +1035,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { while (children[0]) { c = children[0]; - if (util.isIgnoreNodeChange(c) && !util.isListCell(format)) { + if (util.isIgnoreNodeChange(c) && !util.isBreak(c) && !util.isListCell(format)) { if (format.childNodes.length > 0) { if (!first) first = format; parent.insertBefore(format, sibling); From 5c1b56eae17a3e28533c084cad699c6fba9ed886 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Tue, 21 Jan 2020 18:53:43 +0900 Subject: [PATCH 02/99] fix: __se__format__ className replace --- src/lib/util.js | 2 +- test/dev/suneditor_build_test.js | 18 ++++++++++++++++-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/src/lib/util.js b/src/lib/util.js index 9d85cfd57..4d2ea741d 100755 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -401,7 +401,7 @@ const util = { */ copyFormatAttributes: function (originEl, copyEl) { copyEl = copyEl.cloneNode(false); - copyEl.className = copyEl.className.replace(/(\s|^)__se__format__(\s|$)/g, ''); + copyEl.className = copyEl.className.replace(/(\s|^)__se__format__[^\s]+/g, ''); this.copyTagAttributes(originEl, copyEl); }, diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index f704ece34..68f4cfcab 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -20,8 +20,22 @@ const align = require('../../src/plugins/submenu/align') let s1 = suneditor.create('editor', { plugins: plugins, - buttonList: [['align', 'link', 'bold', 'underline', 'italic', 'strike', 'fontColor', 'hiliteColor', 'removeFormat', 'codeView', 'preview']], - width: '100%' + buttonList: [['align', 'link', 'bold', 'underline', 'italic', 'strike', 'fontColor', 'hiliteColor', 'removeFormat', 'formatBlock', 'codeView', 'preview']], + width: '100%', + formats: [ + { + tag: 'p', // Tag name + name: 'NORMAL', // default: tag name + command: 'replace', // default: "replace" + class: '__se__format__NORMAL', // Class names must always begin with "__se__format__" + }, + { + tag: 'div', // Tag name + name: 'CODE', // default: tag name + command: 'replace', // default: "replace" + class: '__se__format__CODE', // Class names must always begin with "__se__format__" + } + ] }) window.cm = CodeMirror From 2809603d674e4ee24e95a8a613797039640a716f Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Tue, 21 Jan 2020 19:35:49 +0900 Subject: [PATCH 03/99] fix: formatBlock - custom class __se__format__ --- src/lib/core.js | 5 ++-- src/plugins/submenu/formatBlock.js | 44 +++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/lib/core.js b/src/lib/core.js index 509947888..e3586a783 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -3468,8 +3468,9 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { /* Format block */ if (findFormat && commandMap.FORMAT) { commandMapNodes.push('FORMAT'); - util.changeTxt(commandMap.FORMAT, nodeName); - commandMap.FORMAT.setAttribute('data-focus', nodeName); + core.callPlugin('formatBlock', function () { + core.plugins.formatBlock.active.call(core, selectionParent); + }); findFormat = false; } diff --git a/src/plugins/submenu/formatBlock.js b/src/plugins/submenu/formatBlock.js index 98f66771d..f0f0ccf83 100644 --- a/src/plugins/submenu/formatBlock.js +++ b/src/plugins/submenu/formatBlock.js @@ -41,7 +41,7 @@ export default { const formatList = !option.formats || option.formats.length === 0 ? defaultFormats : option.formats; let list = '
diff --git a/src/lib/core.js b/src/lib/core.js index f4269e92d..3c9f9d297 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -1040,7 +1040,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { while (children[0]) { c = children[0]; - if (util.isIgnoreNodeChange(c) && !util.isBreak(c) && !util.isListCell(format)) { + if (util._isIgnoreNodeChange(c) && !util.isBreak(c) && !util.isListCell(format)) { if (format.childNodes.length > 0) { if (!first) first = format; parent.insertBefore(format, sibling); @@ -1423,19 +1423,19 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { // node Changes newNode = appendNode.cloneNode(false); - const isRemoveAnchor = isRemoveFormat || (isRemoveNode && (function (arr, isAnchor) { + const isRemoveAnchor = isRemoveFormat || (isRemoveNode && (function (arr, _isMaintainedNode) { for (let n = 0, len = arr.length; n < len; n++) { - if (isAnchor(arr[n])) return true; + if (_isMaintainedNode(arr[n])) return true; } return false; - })(removeNodeArray, util.isAnchor)); + })(removeNodeArray, util._isMaintainedNode)); - const _getAnchor = this._util_getAnchor.bind(util, isRemoveAnchor); - const _isAnchor = this._util_isAnchor.bind(util, isRemoveAnchor); + const _getMaintainedNode = this._util_getMaintainedNode.bind(util, isRemoveAnchor); + const _isMaintainedNode = this._util_isMaintainedNode.bind(util, isRemoveAnchor); // one line if (oneLine) { - const newRange = this._nodeChange_oneLine(lineNodes[0], newNode, validation, startCon, startOff, endCon, endOff, isRemoveFormat, isRemoveNode, range.collapsed, _removeCheck, _getAnchor, _isAnchor); + const newRange = this._nodeChange_oneLine(lineNodes[0], newNode, validation, startCon, startOff, endCon, endOff, isRemoveFormat, isRemoveNode, range.collapsed, _removeCheck, _getMaintainedNode, _isMaintainedNode); start.container = newRange.startContainer; start.offset = newRange.startOffset; end.container = newRange.endContainer; @@ -1444,7 +1444,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { // multi line else { // start - start = this._nodeChange_startLine(lineNodes[0], newNode, validation, startCon, startOff, isRemoveFormat, isRemoveNode, _removeCheck, _getAnchor, _isAnchor); + start = this._nodeChange_startLine(lineNodes[0], newNode, validation, startCon, startOff, isRemoveFormat, isRemoveNode, _removeCheck, _getMaintainedNode, _isMaintainedNode); // mid for (let i = 1; i < endLength; i++) { newNode = appendNode.cloneNode(false); @@ -1453,7 +1453,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { // end if (endLength > 0) { newNode = appendNode.cloneNode(false); - end = this._nodeChange_endLine(lineNodes[endLength], newNode, validation, endCon, endOff, isRemoveFormat, isRemoveNode, _removeCheck, _getAnchor, _isAnchor); + end = this._nodeChange_endLine(lineNodes[endLength], newNode, validation, endCon, endOff, isRemoveFormat, isRemoveNode, _removeCheck, _getMaintainedNode, _isMaintainedNode); } else { end = start; } @@ -1605,25 +1605,25 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { }, /** - * @description Return the parent anchor tag. (bind and use a util object) - * @param {Boolean} isRemove Delete anchor tag + * @description Return the parent maintained tag. (bind and use a util object) + * @param {Boolean} isRemove Delete maintained tag * @param {Element} element Element * @returns {Element} * @private */ - _util_getAnchor: function (isRemove, element) { - return element && !isRemove ? this.getParentElement(element, function (current) {return this.isAnchor(current);}.bind(this)) : null; + _util_getMaintainedNode: function (isRemove, element) { + return element && !isRemove ? this.getParentElement(element, function (current) {return this._isMaintainedNode(current);}.bind(this)) : null; }, /** - * @description Checks if the element is an anchor tag. (bind and use a util object) - * @param {Boolean} isRemove Delete anchor tag + * @description Check if element is a tag that should be persisted. (bind and use a util object) + * @param {Boolean} isRemove Delete maintained tag * @param {Element} element Element * @returns {Element} * @private */ - _util_isAnchor: function (isRemove, element) { - return element && !isRemove && element.nodeType !== 3 && this.isAnchor(element); + _util_isMaintainedNode: function (isRemove, element) { + return element && !isRemove && element.nodeType !== 3 && this._isMaintainedNode(element); }, /** @@ -1641,7 +1641,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { * @returns {{startContainer: *, startOffset: *, endContainer: *, endOffset: *}} * @private */ - _nodeChange_oneLine: function (element, newInnerNode, validation, startCon, startOff, endCon, endOff, isRemoveFormat, isRemoveNode, collapsed, _removeCheck, _getAnchor, _isAnchor) { + _nodeChange_oneLine: function (element, newInnerNode, validation, startCon, startOff, endCon, endOff, isRemoveFormat, isRemoveNode, collapsed, _removeCheck, _getMaintainedNode, _isMaintainedNode) { // not add tag let parentCon = startCon.parentNode; while (!parentCon.nextSibling && !parentCon.previousSibling && !util.isFormatElement(parentCon.parentNode) && !util.isWysiwygDiv(parentCon.parentNode)) { @@ -1721,7 +1721,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { // startContainer if (!startPass && child === startContainer) { let line = pNode; - anchorNode = _getAnchor(child); + anchorNode = _getMaintainedNode(child); const prevNode = util.createTextNode(startContainer.nodeType === 1 ? '' : startContainer.substringData(0, startOffset)); const textNode = util.createTextNode(startContainer.nodeType === 1 ? '' : startContainer.substringData(startOffset, isSameNode ? @@ -1730,7 +1730,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { ); if (anchorNode) { - const a = _getAnchor(ancestor); + const a = _getMaintainedNode(ancestor); if (a && a.parentNode !== line) { let m = a; let p = null; @@ -1751,7 +1751,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { ancestor.appendChild(prevNode); } - const prevAnchorNode = _getAnchor(ancestor); + const prevAnchorNode = _getMaintainedNode(ancestor); if (!!prevAnchorNode) anchorNode = prevAnchorNode; if (anchorNode) line = anchorNode; @@ -1759,7 +1759,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { pCurrent = []; cssText = ''; while (newNode !== line && newNode !== el && newNode !== null) { - vNode = _isAnchor(newNode) ? null : validation(newNode); + vNode = _isMaintainedNode(newNode) ? null : validation(newNode); if (vNode && newNode.nodeType === 1 && checkCss(newNode)) { pCurrent.push(vNode); cssText += newNode.style.cssText.substr(0, newNode.style.cssText.indexOf(':')) + '|'; @@ -1778,7 +1778,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { newInnerNode.appendChild(childNode); line.appendChild(newInnerNode); - if (anchorNode && !_getAnchor(endContainer)) { + if (anchorNode && !_getMaintainedNode(endContainer)) { newInnerNode = newInnerNode.cloneNode(false); pNode.appendChild(newInnerNode); nNodeArray.push(newInnerNode); @@ -1794,13 +1794,13 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { // endContainer if (!endPass && child === endContainer) { - anchorNode = _getAnchor(child); + anchorNode = _getMaintainedNode(child); const afterNode = util.createTextNode(endContainer.nodeType === 1 ? '' : endContainer.substringData(endOffset, (endContainer.length - endOffset))); const textNode = util.createTextNode(isSameNode || endContainer.nodeType === 1 ? '' : endContainer.substringData(0, endOffset)); if (anchorNode) { anchorNode = anchorNode.cloneNode(false); - } else if (_isAnchor(newInnerNode.parentNode) && !anchorNode) { + } else if (_isMaintainedNode(newInnerNode.parentNode) && !anchorNode) { newInnerNode = newInnerNode.cloneNode(false); pNode.appendChild(newInnerNode); nNodeArray.push(newInnerNode); @@ -1813,7 +1813,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { const anchors = []; while (newNode !== pNode && newNode !== el && newNode !== null) { if (newNode.nodeType === 1 && checkCss(newNode)) { - if (_isAnchor(newNode)) anchors.push(newNode.cloneNode(false)); + if (_isMaintainedNode(newNode)) anchors.push(newNode.cloneNode(false)); else pCurrent.push(newNode.cloneNode(false)); cssText += newNode.style.cssText.substr(0, newNode.style.cssText.indexOf(':')) + '|'; } @@ -1833,7 +1833,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { } if (anchorNode && cloneNode) { - const afterAnchorNode = _getAnchor(cloneNode); + const afterAnchorNode = _getMaintainedNode(cloneNode); if (afterAnchorNode) { anchorNode = afterAnchorNode; } @@ -1843,7 +1843,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { pCurrent = []; cssText = ''; while (newNode !== pNode && newNode !== el && newNode !== null) { - vNode = _isAnchor(newNode) ? null : validation(newNode); + vNode = _isMaintainedNode(newNode) ? null : validation(newNode); if (vNode && newNode.nodeType === 1 && checkCss(newNode)) { pCurrent.push(vNode); cssText += newNode.style.cssText.substr(0, newNode.style.cssText.indexOf(':')) + '|'; @@ -1886,7 +1886,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { // other if (startPass) { if (child.nodeType === 1 && !util.isBreak(child)) { - if (!collapsed && util.isIgnoreNodeChange(child)) { + if (!collapsed && util._isIgnoreNodeChange(child)) { newInnerNode = newInnerNode.cloneNode(false); pNode.appendChild(child); pNode.appendChild(newInnerNode); @@ -1906,7 +1906,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { vNode = endPass ? newNode.cloneNode(false) : validation(newNode); if (newNode.nodeType === 1 && !util.isBreak(child) && vNode && checkCss(newNode)) { if (vNode) { - if (_isAnchor(vNode)) { + if (_isMaintainedNode(vNode)) { if (!anchorNode) anchors.push(vNode); } else { pCurrent.push(vNode); @@ -1926,13 +1926,13 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { appendNode = newNode; } - if (_isAnchor(newInnerNode.parentNode) && !_isAnchor(childNode)) { + if (_isMaintainedNode(newInnerNode.parentNode) && !_isMaintainedNode(childNode)) { newInnerNode = newInnerNode.cloneNode(false); pNode.appendChild(newInnerNode); nNodeArray.push(newInnerNode); } - if (!endPass && !anchorNode && _isAnchor(childNode)) { + if (!endPass && !anchorNode && _isMaintainedNode(childNode)) { newInnerNode = newInnerNode.cloneNode(false); const aChildren = childNode.childNodes; for (let a = 0, aLen = aChildren.length; a < aLen; a++) { @@ -1955,8 +1955,8 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { } if (anchorNode && child.nodeType === 3) { - if (_getAnchor(child)) { - const ancestorAnchorNode = util.getParentElement(ancestor, function (current) {return this.isAnchor(current.parentNode) || current.parentNode === pNode;}.bind(util)); + if (_getMaintainedNode(child)) { + const ancestorAnchorNode = util.getParentElement(ancestor, function (current) {return this._isMaintainedNode(current.parentNode) || current.parentNode === pNode;}.bind(util)); anchorNode.appendChild(ancestorAnchorNode); newInnerNode = ancestorAnchorNode.cloneNode(false); nNodeArray.push(newInnerNode); @@ -2064,7 +2064,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { * @returns {{container: *, offset: *}} * @private */ - _nodeChange_startLine: function (element, newInnerNode, validation, startCon, startOff, isRemoveFormat, isRemoveNode, _removeCheck, _getAnchor, _isAnchor) { + _nodeChange_startLine: function (element, newInnerNode, validation, startCon, startOff, isRemoveFormat, isRemoveNode, _removeCheck, _getMaintainedNode, _isMaintainedNode) { // not add tag let parentCon = startCon.parentNode; while (!parentCon.nextSibling && !parentCon.previousSibling && !util.isFormatElement(parentCon.parentNode) && !util.isWysiwygDiv(parentCon.parentNode)) { @@ -2114,7 +2114,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (passNode && !util.isBreak(child)) { if (child.nodeType === 1) { - if (util.isIgnoreNodeChange(child)) { + if (util._isIgnoreNodeChange(child)) { newInnerNode = newInnerNode.cloneNode(false); pNode.appendChild(child); pNode.appendChild(newInnerNode); @@ -2132,7 +2132,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { while (newNode.parentNode !== null && newNode !== el && newNode !== newInnerNode) { vNode = validation(newNode); if (newNode.nodeType === 1 && vNode) { - if (_isAnchor(vNode)) { + if (_isMaintainedNode(vNode)) { if (!anchorNode) anchors.push(vNode); } else { pCurrent.push(vNode); @@ -2151,13 +2151,13 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { appendNode = newNode; } - if (_isAnchor(newInnerNode.parentNode) && !_isAnchor(childNode)) { + if (_isMaintainedNode(newInnerNode.parentNode) && !_isMaintainedNode(childNode)) { newInnerNode = newInnerNode.cloneNode(false); pNode.appendChild(newInnerNode); nNodeArray.push(newInnerNode); } - if (!anchorNode && _isAnchor(childNode)) { + if (!anchorNode && _isMaintainedNode(childNode)) { newInnerNode = newInnerNode.cloneNode(false); const aChildren = childNode.childNodes; for (let a = 0, aLen = aChildren.length; a < aLen; a++) { @@ -2165,7 +2165,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { } childNode.appendChild(newInnerNode); pNode.appendChild(childNode); - ancestor = !_isAnchor(newNode) ? newNode : newInnerNode; + ancestor = !_isMaintainedNode(newNode) ? newNode : newInnerNode; nNodeArray.push(newInnerNode); } else if (isTopNode) { newInnerNode.appendChild(childNode); @@ -2175,8 +2175,8 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { } if (anchorNode && child.nodeType === 3) { - if (_getAnchor(child)) { - const ancestorAnchorNode = util.getParentElement(ancestor, function (current) {return this.isAnchor(current.parentNode) || current.parentNode === pNode;}.bind(util)); + if (_getMaintainedNode(child)) { + const ancestorAnchorNode = util.getParentElement(ancestor, function (current) {return this._isMaintainedNode(current.parentNode) || current.parentNode === pNode;}.bind(util)); anchorNode.appendChild(ancestorAnchorNode); newInnerNode = ancestorAnchorNode.cloneNode(false); nNodeArray.push(newInnerNode); @@ -2190,12 +2190,12 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { // startContainer if (!passNode && child === container) { let line = pNode; - anchorNode = _getAnchor(child); + anchorNode = _getMaintainedNode(child); const prevNode = util.createTextNode(container.nodeType === 1 ? '' : container.substringData(0, offset)); const textNode = util.createTextNode(container.nodeType === 1 ? '' : container.substringData(offset, (container.length - offset))); if (anchorNode) { - const a = _getAnchor(ancestor); + const a = _getMaintainedNode(ancestor); if (a && a.parentNode !== line) { let m = a; let p = null; @@ -2216,7 +2216,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { ancestor.appendChild(prevNode); } - const prevAnchorNode = _getAnchor(ancestor); + const prevAnchorNode = _getMaintainedNode(ancestor); if (!!prevAnchorNode) anchorNode = prevAnchorNode; if (anchorNode) line = anchorNode; @@ -2381,7 +2381,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (!child) continue; let coverNode = ancestor; - if (util.isIgnoreNodeChange(child)) { + if (util._isIgnoreNodeChange(child)) { pNode.appendChild(newInnerNode); newInnerNode = newInnerNode.cloneNode(false); pNode.appendChild(child); @@ -2440,7 +2440,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { * @returns {{container: *, offset: *}} * @private */ - _nodeChange_endLine: function (element, newInnerNode, validation, endCon, endOff, isRemoveFormat, isRemoveNode, _removeCheck, _getAnchor, _isAnchor) { + _nodeChange_endLine: function (element, newInnerNode, validation, endCon, endOff, isRemoveFormat, isRemoveNode, _removeCheck, _getMaintainedNode, _isMaintainedNode) { // not add tag let parentCon = endCon.parentNode; while (!parentCon.nextSibling && !parentCon.previousSibling && !util.isFormatElement(parentCon.parentNode) && !util.isWysiwygDiv(parentCon.parentNode)) { @@ -2490,7 +2490,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (passNode && !util.isBreak(child)) { if (child.nodeType === 1) { - if (util.isIgnoreNodeChange(child)) { + if (util._isIgnoreNodeChange(child)) { newInnerNode = newInnerNode.cloneNode(false); pNode.insertBefore(child, ancestor); pNode.insertBefore(newInnerNode, child); @@ -2508,7 +2508,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { while (newNode.parentNode !== null && newNode !== el && newNode !== newInnerNode) { vNode = validation(newNode); if (vNode && newNode.nodeType === 1) { - if (_isAnchor(vNode)) { + if (_isMaintainedNode(vNode)) { if (!anchorNode) anchors.push(vNode); } else { pCurrent.push(vNode); @@ -2527,13 +2527,13 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { appendNode = newNode; } - if (_isAnchor(newInnerNode.parentNode) && !_isAnchor(childNode)) { + if (_isMaintainedNode(newInnerNode.parentNode) && !_isMaintainedNode(childNode)) { newInnerNode = newInnerNode.cloneNode(false); pNode.insertBefore(newInnerNode, pNode.firstChild); nNodeArray.push(newInnerNode); } - if (!anchorNode && _isAnchor(childNode)) { + if (!anchorNode && _isMaintainedNode(childNode)) { newInnerNode = newInnerNode.cloneNode(false); const aChildren = childNode.childNodes; for (let a = 0, aLen = aChildren.length; a < aLen; a++) { @@ -2552,8 +2552,8 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { } if (anchorNode && child.nodeType === 3) { - if (_getAnchor(child)) { - const ancestorAnchorNode = util.getParentElement(ancestor, function (current) {return this.isAnchor(current.parentNode) || current.parentNode === pNode;}.bind(util)); + if (_getMaintainedNode(child)) { + const ancestorAnchorNode = util.getParentElement(ancestor, function (current) {return this._isMaintainedNode(current.parentNode) || current.parentNode === pNode;}.bind(util)); anchorNode.appendChild(ancestorAnchorNode); newInnerNode = ancestorAnchorNode.cloneNode(false); nNodeArray.push(newInnerNode); @@ -2566,13 +2566,13 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { // endContainer if (!passNode && child === container) { - anchorNode = _getAnchor(child); + anchorNode = _getMaintainedNode(child); const afterNode = util.createTextNode(container.nodeType === 1 ? '' : container.substringData(offset, (container.length - offset))); const textNode = util.createTextNode(container.nodeType === 1 ? '' : container.substringData(0, offset)); if (anchorNode) { anchorNode = anchorNode.cloneNode(false); - const a = _getAnchor(ancestor); + const a = _getMaintainedNode(ancestor); if (a && a.parentNode !== pNode) { let m = a; let p = null; @@ -2587,7 +2587,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { m.parentNode.insertBefore(a, m.parentNode.firstChild); } anchorNode = anchorNode.cloneNode(false); - } else if (_isAnchor(newInnerNode.parentNode) && !anchorNode) { + } else if (_isMaintainedNode(newInnerNode.parentNode) && !anchorNode) { newInnerNode = newInnerNode.cloneNode(false); pNode.appendChild(newInnerNode); nNodeArray.push(newInnerNode); @@ -2600,7 +2600,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { newNode = ancestor; pCurrent = []; while (newNode !== pNode && newNode !== null) { - vNode = _isAnchor(newNode) ? null : validation(newNode); + vNode = _isMaintainedNode(newNode) ? null : validation(newNode); if (vNode && newNode.nodeType === 1) { pCurrent.push(vNode); } diff --git a/src/lib/util.js b/src/lib/util.js index 758276f2e..60f9247b7 100755 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -1008,7 +1008,7 @@ const util = { const inst = this; (function recursionFunc(current) { - if (current !== element && inst.onlyZeroWidthSpace(current.textContent) && !/^BR$/i.test(current.nodeName) && + if (current !== element && inst.onlyZeroWidthSpace(current.textContent) && !inst._notTextNode(current) && (!current.firstChild || !/^BR$/i.test(current.firstChild.nodeName)) && !inst.isComponent(current)) { if (current.parentNode) { current.parentNode.removeChild(current); @@ -1028,15 +1028,6 @@ const util = { if (element.childNodes.length === 0) element.innerHTML = '
'; }, - /** - * @description Nodes that need to be added without modification when changing text nodes !(span|font|b|strong|var|i|em|u|ins|s|strike|del|sub|sup|a) - * @param {Element} element Element to check - * @returns {Boolean} - */ - isIgnoreNodeChange: function (element) { - return element.nodeType !== 3 && !/^(span|font|b|strong|var|i|em|u|ins|s|strike|del|sub|sup|mark|a)$/i.test(element.nodeName); - }, - /** * @description Gets the clean HTML code for editor * @param {String} html HTML string @@ -1071,6 +1062,36 @@ const util = { return this._tagConvertor(cleanHTML || html); }, + /** + * @description Nodes that need to be added without modification when changing text nodes + * @param {Element} element Element to check + * @returns {Boolean} + * @private + */ + _isIgnoreNodeChange: function (element) { + return element.nodeType !== 3 && !(/^(span|font|b|strong|var|i|em|u|ins|s|strike|del|sub|sup|mark|a|label)$/i.test(element.nodeName)); + }, + + /** + * @description Nodes that must remain undetached when changing text nodes + * @param {Element} element Element to check + * @returns {Boolean} + * @private + */ + _isMaintainedNode: function (element) { + return element.nodeType !== 3 && /^(a|label)$/i.test(element.nodeName); + }, + + /** + * @description Nodes without text + * @param {Element} element Element to check + * @returns {Boolean} + * @private + */ + _notTextNode: function (element) { + return element.nodeType !== 3 && /^(br|input|canvas|img|iframe|audio|video)$/i.test(element.nodeName); + }, + /** * @description Delete Exclusion tags regexp object * @returns {Object} diff --git a/src/plugins/submenu/list.js b/src/plugins/submenu/list.js index 2cbbc017c..91252598d 100644 --- a/src/plugins/submenu/list.js +++ b/src/plugins/submenu/list.js @@ -163,7 +163,7 @@ export default { for (let i = 0, len = selectedFormsts.length, newCell, fTag, isCell, next, originParent, nextParent, parentTag, siblingTag, rangeTag; i < len; i++) { fTag = selectedFormsts[i]; - if (fTag.childNodes.length === 0 && !this.util.isIgnoreNodeChange(fTag)) { + if (fTag.childNodes.length === 0 && !this.util._isIgnoreNodeChange(fTag)) { this.util.removeItem(fTag); continue; } From 672fd5728127287ac6d480f1a807afb7f72293ba Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Tue, 11 Feb 2020 16:37:36 +0900 Subject: [PATCH 13/99] modify: PRE tag enter key, custom formats #190 --- README.md | 2 +- sample/html/getting-started.html | 2 +- src/lib/core.js | 8 +++++--- src/lib/util.js | 4 ++-- test/dev/suneditor_build_test.html | 5 ++++- test/dev/suneditor_build_test.js | 28 ++++++++++++++-------------- 6 files changed, 27 insertions(+), 22 deletions(-) diff --git a/README.md b/README.md index 6d488844c..1d4c23b0c 100644 --- a/README.md +++ b/README.md @@ -360,7 +360,7 @@ formats : Change default formatBlock array. default: [.. tag: 'div', // Tag name name: 'Custom div' || null, // default: tag name command: 'replace' || 'range', // default: "replace" - class: '__se__format__replace__xxx' || '__se__format__range__xxx', // Class names must always begin with "__se__format__(replace or range)__" + class: '__se__format__replace_xxx' || '__se__format__range_xxx', // Class names must always begin with "__se__format__(replace or range)_" }] colorList : Change default color array of color picker. default: [..[..]..] {Array} Default value: [ diff --git a/sample/html/getting-started.html b/sample/html/getting-started.html index 962ba0910..4196a3710 100644 --- a/sample/html/getting-started.html +++ b/sample/html/getting-started.html @@ -317,7 +317,7 @@ tag: 'div', // Tag name name: 'Custom div' || null, // default: tag name command: 'replace' || 'range', // default: "replace" - class: '__se__format__replace__xxx' || '__se__format__range__xxx', // Class names must always begin with "__se__format__(replace or range)__" + class: '__se__format__replace_xxx' || '__se__format__range_xxx', // Class names must always begin with "__se__format__(replace or range)_" }] colorList : Change default color array of color picker. default: [..[..]..] {Array} Default value: [ diff --git a/src/lib/core.js b/src/lib/core.js index 3c9f9d297..13ca76361 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -4055,8 +4055,10 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { e.preventDefault(); const selectionFormat = selectionNode === formatEl; - if ((selectionFormat && range.collapsed && selectionNode.children.length === range.endOffset) || (!selectionFormat && util.onlyZeroWidthSpace(selectionNode.textContent) && util.isBreak(selectionNode.previousSibling) && !selectionNode.nextSibling)) { - if (!selectionFormat) util.removeItem(selectionNode); + if ((selectionFormat && range.collapsed && selectionNode.childNodes.length - 2 === range.endOffset && util.isBreak(selectionNode.childNodes[range.endOffset]) && util.isBreak(selectionNode.childNodes[range.endOffset - 1]) && util.isBreak(selectionNode.childNodes[range.endOffset - 2])) || + (!selectionFormat && util.onlyZeroWidthSpace(selectionNode.textContent) && util.isBreak(selectionNode.previousElementSibling) && util.isBreak(selectionNode.previousElementSibling.previousElementSibling) && (!selectionNode.nextSibling || (!util.isBreak(selectionNode.nextSibling) && util.onlyZeroWidthSpace(selectionNode.nextSibling.textContent))))) { + if (selectionFormat) util.removeItem(selectionNode.childNodes[range.endOffset - 1]); + else util.removeItem(selectionNode); const newEl = core.appendFormatTag(formatEl, formatEl.nextElementSibling ? formatEl.nextElementSibling.nodeName : 'P'); util.copyFormatAttributes(newEl, formatEl); core.setRange(newEl, 1, newEl, 1); @@ -4070,7 +4072,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { let con = wSelection.focusNode; let offset = 1; if (/^PRE$/i.test(wSelection.focusNode.nodeName)) { - con = con.childNodes[wSelection.focusOffset > 1 ? wSelection.focusOffset - 1 : wSelection.focusOffset]; + con = con.childNodes[util.isBreak(con.childNodes[wSelection.focusOffset - 1]) ? wSelection.focusOffset - 1 : wSelection.focusOffset]; } else { con = con.previousSibling; } diff --git a/src/lib/util.js b/src/lib/util.js index 60f9247b7..5a84f264f 100755 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -306,7 +306,7 @@ const util = { * @returns {Boolean} */ isFormatElement: function (element) { - if (element && element.nodeType === 1 && (/^(P|DIV|H[1-6]|PRE|LI|TH|TD)$/i.test(element.nodeName) || this.hasClass(element, '(\\s|^)__se__format__replace__.+(\\s|$)')) && !this.isComponent(element) && !this.isWysiwygDiv(element)) return true; + if (element && element.nodeType === 1 && (/^(P|DIV|H[1-6]|PRE|LI|TH|TD)$/i.test(element.nodeName) || this.hasClass(element, '(\\s|^)__se__format__replace_.+(\\s|$)')) && !this.isComponent(element) && !this.isWysiwygDiv(element)) return true; return false; }, @@ -317,7 +317,7 @@ const util = { * @returns {Boolean} */ isRangeFormatElement: function (element) { - if (element && element.nodeType === 1 && (/^(BLOCKQUOTE|OL|UL|FIGCAPTION|TABLE|THEAD|TBODY|TR|TH|TD)$/i.test(element.nodeName) || this.hasClass(element, '(\\s|^)__se__format__range__.+(\\s|$)'))) return true; + if (element && element.nodeType === 1 && (/^(BLOCKQUOTE|OL|UL|FIGCAPTION|TABLE|THEAD|TBODY|TR|TH|TD)$/i.test(element.nodeName) || this.hasClass(element, '(\\s|^)__se__format__range_.+(\\s|$)'))) return true; return false; }, diff --git a/test/dev/suneditor_build_test.html b/test/dev/suneditor_build_test.html index 759d98f9f..353bf62d6 100644 --- a/test/dev/suneditor_build_test.html +++ b/test/dev/suneditor_build_test.html @@ -108,9 +108,12 @@ margin: 0; padding: 0; } - .sun-editor .__se__format__aaa, .sun-editor-editable .__se__format__aaa { + .sun-editor .__se__format__replace_NORMAL, .sun-editor-editable .__se__format__replace_NORMAL { background-color: aquamarine; } + .sun-editor .__se__format__replace_CODE, .sun-editor-editable .__se__format__replace_CODE { + border: 1px solid #333; + } diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index b2d61b7c7..70db95c25 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -23,20 +23,20 @@ let s1 = suneditor.create('editor', { // mode: 'balloon', buttonList: [['table', 'align', 'link', 'bold', 'underline', 'italic', 'strike', 'fontColor', 'hiliteColor', 'removeFormat', 'formatBlock', 'codeView', 'preview']], width: '100%', -// formats: [ -// { -// tag: 'p', // Tag name -// name: 'NORMAL', // default: tag name -// command: 'replace', // default: "replace" -// class: '__se__format__replace__NORMAL', // Class names must always begin with "__se__format__" -// }, -// { -// tag: 'div', // Tag name -// name: 'CODE', // default: tag name -// command: 'replace', // default: "replace" -// class: '__se__format__CODE', // Class names must always begin with "__se__format__" -// } -// ] + formats: [ + { + tag: 'div', // Tag name + name: 'NORMAL', // default: tag name + command: 'replace', // default: "replace" + class: '__se__format__replace_NORMAL', // Class names must always begin with "__se__format__" + }, + { + tag: 'div', // Tag name + name: 'CODE', // default: tag name + command: 'replace', // default: "replace" + class: '__se__format__replace_CODE', // Class names must always begin with "__se__format__" + } + ] }) window.cm = CodeMirror From a2ab114c998763fb90a61a84b681866eccc9bd74 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Tue, 11 Feb 2020 19:59:34 +0900 Subject: [PATCH 14/99] modify: pre - enter #190 --- src/lib/core.js | 24 ++++++++++++++---------- src/lib/util.js | 2 +- test/dev/suneditor_build_test.js | 3 ++- 3 files changed, 17 insertions(+), 12 deletions(-) diff --git a/src/lib/core.js b/src/lib/core.js index 13ca76361..1b80973b5 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -4054,10 +4054,12 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (!shift && /^PRE$/i.test(formatEl.nodeName)) { e.preventDefault(); const selectionFormat = selectionNode === formatEl; + const wSelection = core.getSelection(); + const children = selectionNode.childNodes, offset = wSelection.focusOffset, prev = selectionNode.previousElementSibling, next = selectionNode.nextSibling; - if ((selectionFormat && range.collapsed && selectionNode.childNodes.length - 2 === range.endOffset && util.isBreak(selectionNode.childNodes[range.endOffset]) && util.isBreak(selectionNode.childNodes[range.endOffset - 1]) && util.isBreak(selectionNode.childNodes[range.endOffset - 2])) || - (!selectionFormat && util.onlyZeroWidthSpace(selectionNode.textContent) && util.isBreak(selectionNode.previousElementSibling) && util.isBreak(selectionNode.previousElementSibling.previousElementSibling) && (!selectionNode.nextSibling || (!util.isBreak(selectionNode.nextSibling) && util.onlyZeroWidthSpace(selectionNode.nextSibling.textContent))))) { - if (selectionFormat) util.removeItem(selectionNode.childNodes[range.endOffset - 1]); + if ((selectionFormat && range.collapsed && children.length - 1 <= offset + 1 && util.isBreak(children[offset]) && (!children[offset + 1] || (!children[offset + 2] && children[offset + 1].nodeType === 3 && util.onlyZeroWidthSpace(children[offset + 1].textContent))) && offset > 0 && util.isBreak(children[offset - 1])) || + (!selectionFormat && util.onlyZeroWidthSpace(selectionNode.textContent) && util.isBreak(prev) && (!prev.previousElementSibling || util.isBreak(prev.previousElementSibling)) && (!next || (!util.isBreak(next) && util.onlyZeroWidthSpace(next.textContent))))) { + if (selectionFormat) util.removeItem(children[offset - 1]); else util.removeItem(selectionNode); const newEl = core.appendFormatTag(formatEl, formatEl.nextElementSibling ? formatEl.nextElementSibling.nodeName : 'P'); util.copyFormatAttributes(newEl, formatEl); @@ -4068,23 +4070,25 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (selectionFormat) { core.execCommand('insertHTML', false, '

'); - const wSelection = _w.getSelection(); let con = wSelection.focusNode; - let offset = 1; - if (/^PRE$/i.test(wSelection.focusNode.nodeName)) { - con = con.childNodes[util.isBreak(con.childNodes[wSelection.focusOffset - 1]) ? wSelection.focusOffset - 1 : wSelection.focusOffset]; + const wOffset = wSelection.focusOffset; + if (formatEl === con) { + con = con.childNodes[wOffset - offset > 1 ? wOffset - 1 : wOffset]; } else { con = con.previousSibling; } - core.setRange(con, offset, con, offset); + + core.setRange(con, 1, con, 1); } else { const br = util.createElement('BR'); core.insertNode(br); - if (!util.isBreak(br.previousSibling) && (!br.nextSibling || util.onlyZeroWidthSpace(br.nextSibling))) { + + const brPrev = br.previousSibling, brNext = br.nextSibling; + if (!util.isBreak(brPrev) && (!brNext || util.onlyZeroWidthSpace(brNext))) { br.parentNode.insertBefore(br.cloneNode(false), br); core.setRange(br, 1, br, 1); } else { - core.setRange(br.nextSibling, 0, br.nextSibling, 0); + core.setRange(brNext, 0, brNext, 0); } } diff --git a/src/lib/util.js b/src/lib/util.js index 5a84f264f..3afef8d5a 100755 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -1069,7 +1069,7 @@ const util = { * @private */ _isIgnoreNodeChange: function (element) { - return element.nodeType !== 3 && !(/^(span|font|b|strong|var|i|em|u|ins|s|strike|del|sub|sup|mark|a|label)$/i.test(element.nodeName)); + return element.nodeType !== 3 && !/^(span|font|b|strong|var|i|em|u|ins|s|strike|del|sub|sup|mark|a|label)$/i.test(element.nodeName); }, /** diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index 70db95c25..644389b51 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -35,7 +35,8 @@ let s1 = suneditor.create('editor', { name: 'CODE', // default: tag name command: 'replace', // default: "replace" class: '__se__format__replace_CODE', // Class names must always begin with "__se__format__" - } + }, + 'pre' ] }) From 688f45d4370c7d4323dc0ed31e3018348c076d74 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Wed, 12 Feb 2020 17:56:10 +0900 Subject: [PATCH 15/99] add: format - freeFormat(pre), add: util-isFreeFormatElement, getFreeFormatElement #190 --- README.md | 6 ++- sample/html/getting-started.html | 4 +- sample/html/out/document-util.html | 68 +++++++++++++++++++++++++++++- src/lib/core.js | 29 +++++++------ src/lib/util.js | 43 ++++++++++++++++--- test/dev/suneditor_build_test.html | 2 +- test/dev/suneditor_build_test.js | 4 +- 7 files changed, 130 insertions(+), 26 deletions(-) diff --git a/README.md b/README.md index 1d4c23b0c..8d94a3e28 100644 --- a/README.md +++ b/README.md @@ -355,12 +355,14 @@ fontSizeUnit : The font size unit. default: 'px formats : Change default formatBlock array. default: [...] {Array} Default value: [ 'p', 'div', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' + // "blockquote": range format, "pre": free format, "Other tags": replace format ], Custom: [{ tag: 'div', // Tag name name: 'Custom div' || null, // default: tag name - command: 'replace' || 'range', // default: "replace" - class: '__se__format__replace_xxx' || '__se__format__range_xxx', // Class names must always begin with "__se__format__(replace or range)_" + command: 'replace' || 'range' || 'free', // default: "replace" + class: '__se__format__replace_xxx' || '__se__format__range_xxx' || '__se__format__free_xxx' + // Class names must always begin with "__se__format__(replace, range, free)_" }] colorList : Change default color array of color picker. default: [..[..]..] {Array} Default value: [ diff --git a/sample/html/getting-started.html b/sample/html/getting-started.html index 4196a3710..60c890343 100644 --- a/sample/html/getting-started.html +++ b/sample/html/getting-started.html @@ -312,12 +312,14 @@ formats : Change default formatBlock array. default: [...] {Array} Default value: [ 'p', 'div', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6' + // "blockquote": range format, "pre": free format, "Other tags": replace format ], Custom: [{ tag: 'div', // Tag name name: 'Custom div' || null, // default: tag name command: 'replace' || 'range', // default: "replace" - class: '__se__format__replace_xxx' || '__se__format__range_xxx', // Class names must always begin with "__se__format__(replace or range)_" + class: '__se__format__replace_xxx' || '__se__format__range_xxx' || '__se__format__free_xxx' + // Class names must always begin with "__se__format__(replace, range, free)_" }] colorList : Change default color array of color picker. default: [..[..]..] {Array} Default value: [ diff --git a/sample/html/out/document-util.html b/sample/html/out/document-util.html index f0ac27d08..1b424fc4b 100644 --- a/sample/html/out/document-util.html +++ b/sample/html/out/document-util.html @@ -354,7 +354,7 @@
Parameters:

isFormatElement(element) → {Boolean}

- It is judged whether it is the format element. (P, DIV, H1-6, PRE, LI, TH, TD) + It is judged whether it is the format element. (P, DIV, H1-6, PRE, LI)
Parameters:
@@ -382,7 +382,35 @@

i class="type-signature"> → {Boolean}

It is judged whether it is the range format element. (BLOCKQUOTE, OL, UL, FIGCAPTION, TABLE, THEAD, TBODY, TR, TH, TD)
- Range format element is wrap the format element (P, DIV, H1-6, LI) + Range format element is wrap the format element (P, DIV, H1-6, PRE, LI) +
+
Parameters:
+
+ + + + + + + + + + + + + + +
NameTypeDescription
element + Element + The element to check
+
+ + +

isFreeFormatElement(element) → {Boolean}

+
+ It is judged whether it is the free format element. (PRE)
+ Free format elements's line break is "BR" tag.
Parameters:
@@ -501,6 +529,40 @@
Parameters:
+

getFreeFormatElement(element, validation) → {Element|null}

+
+ If a parent node that contains an argument node finds a free format node (PRE), it returns that node. +
+
Parameters:
+
+ + + + + + + + + + + + + + + + + + + +
NameTypeDescription
element + Element + Reference element if null or no value, it is relative to the current focus node.
validation + Function|null + Additional validation function.
+
+ +

copyTagAttributes(originEl, copyEl)

@@ -1701,9 +1763,11 @@

util

  • isWysiwygDiv
  • isFormatElement
  • isRangeFormatElement
  • +
  • isFreeFormatElement
  • isComponent
  • getFormatElement
  • getRangeFormatElement
  • +
  • getFreeFormatElement
  • copyTagAttributes
  • copyFormatAttributes
  • getArrayIndex
  • diff --git a/src/lib/core.js b/src/lib/core.js index 1b80973b5..97733ad9c 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -738,7 +738,8 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { /** No Select range node */ if (range.collapsed) { if (commonCon.nodeType === 3) { - afterNode = commonCon.splitText(endOff); + if (commonCon.textContent.length > endOff) afterNode = commonCon.splitText(endOff); + else afterNode = commonCon.nextSibling; } else { if (!util.isBreak(parentNode)) { @@ -4051,18 +4052,19 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { break; case 13: /** enter key */ - if (!shift && /^PRE$/i.test(formatEl.nodeName)) { + const freeFormatEl = util.getFreeFormatElement(selectionNode); + if (!shift && freeFormatEl) { e.preventDefault(); - const selectionFormat = selectionNode === formatEl; + const selectionFormat = selectionNode === freeFormatEl; const wSelection = core.getSelection(); const children = selectionNode.childNodes, offset = wSelection.focusOffset, prev = selectionNode.previousElementSibling, next = selectionNode.nextSibling; - if ((selectionFormat && range.collapsed && children.length - 1 <= offset + 1 && util.isBreak(children[offset]) && (!children[offset + 1] || (!children[offset + 2] && children[offset + 1].nodeType === 3 && util.onlyZeroWidthSpace(children[offset + 1].textContent))) && offset > 0 && util.isBreak(children[offset - 1])) || - (!selectionFormat && util.onlyZeroWidthSpace(selectionNode.textContent) && util.isBreak(prev) && (!prev.previousElementSibling || util.isBreak(prev.previousElementSibling)) && (!next || (!util.isBreak(next) && util.onlyZeroWidthSpace(next.textContent))))) { + if ((selectionFormat && range.collapsed && children.length - 1 <= offset + 1 && util.isBreak(children[offset]) && (!children[offset + 1] || ((!children[offset + 2] || util.onlyZeroWidthSpace(children[offset + 2].textContent)) && children[offset + 1].nodeType === 3 && util.onlyZeroWidthSpace(children[offset + 1].textContent))) && offset > 0 && util.isBreak(children[offset - 1])) || + (!selectionFormat && util.onlyZeroWidthSpace(selectionNode.textContent) && util.isBreak(prev) && (util.isBreak(prev.previousSibling) || !util.onlyZeroWidthSpace(prev.previousSibling.textContent)) && (!next || (!util.isBreak(next) && util.onlyZeroWidthSpace(next.textContent))))) { if (selectionFormat) util.removeItem(children[offset - 1]); else util.removeItem(selectionNode); - const newEl = core.appendFormatTag(formatEl, formatEl.nextElementSibling ? formatEl.nextElementSibling.nodeName : 'P'); - util.copyFormatAttributes(newEl, formatEl); + const newEl = core.appendFormatTag(freeFormatEl, freeFormatEl.nextElementSibling ? freeFormatEl.nextElementSibling.nodeName : 'P'); + util.copyFormatAttributes(newEl, freeFormatEl); core.setRange(newEl, 1, newEl, 1); break; } @@ -4070,21 +4072,22 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (selectionFormat) { core.execCommand('insertHTML', false, '

    '); - let con = wSelection.focusNode; + let focusNode = wSelection.focusNode; const wOffset = wSelection.focusOffset; - if (formatEl === con) { - con = con.childNodes[wOffset - offset > 1 ? wOffset - 1 : wOffset]; + if (freeFormatEl === focusNode) { + focusNode = focusNode.childNodes[wOffset - offset > 1 ? wOffset - 1 : wOffset]; } else { - con = con.previousSibling; + focusNode = focusNode.previousSibling; } - core.setRange(con, 1, con, 1); + core.setRange(focusNode, 1, focusNode, 1); } else { + const focusNext = wSelection.focusNode.nextSibling; const br = util.createElement('BR'); core.insertNode(br); const brPrev = br.previousSibling, brNext = br.nextSibling; - if (!util.isBreak(brPrev) && (!brNext || util.onlyZeroWidthSpace(brNext))) { + if (!util.isBreak(focusNext) && !util.isBreak(brPrev) && (!brNext || util.onlyZeroWidthSpace(brNext))) { br.parentNode.insertBefore(br.cloneNode(false), br); core.setRange(br, 1, br, 1); } else { diff --git a/src/lib/util.js b/src/lib/util.js index 3afef8d5a..663c23ede 100755 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -301,18 +301,18 @@ const util = { }, /** - * @description It is judged whether it is the format element (P, DIV, H1-6, PRE, LI, TH, TD) + * @description It is judged whether it is the format element (P, DIV, H1-6, PRE, LI) * @param {Element} element The element to check * @returns {Boolean} */ isFormatElement: function (element) { - if (element && element.nodeType === 1 && (/^(P|DIV|H[1-6]|PRE|LI|TH|TD)$/i.test(element.nodeName) || this.hasClass(element, '(\\s|^)__se__format__replace_.+(\\s|$)')) && !this.isComponent(element) && !this.isWysiwygDiv(element)) return true; + if (element && element.nodeType === 1 && (/^(P|DIV|H[1-6]|PRE|LI)$/i.test(element.nodeName) || this.hasClass(element, '(\\s|^)__se__format__replace_.+(\\s|$)')) && !this.isComponent(element) && !this.isWysiwygDiv(element)) return true; return false; }, /** * @description It is judged whether it is the range format element. (BLOCKQUOTE, OL, UL, FIGCAPTION, TABLE, THEAD, TBODY, TR, TH, TD) - * * Range format element is wrap the format element (P, DIV, H1-6, LI) + * * Range format element is wrap the format element (P, DIV, H1-6, PRE, LI) * @param {Element} element The element to check * @returns {Boolean} */ @@ -321,6 +321,17 @@ const util = { return false; }, + /** + * @description It is judged whether it is the free format element. (PRE) + * Free format elements's line break is "BR" tag. + * @param {Element} element + * @returns {Boolean} + */ + isFreeFormatElement: function (element) { + if (element && element.nodeType === 1 && (/^PRE$/i.test(element.nodeName) || this.hasClass(element, '(\\s|^)__se__format__free_.+(\\s|$)')) && !this.isComponent(element) && !this.isWysiwygDiv(element)) return true; + return false; + }, + /** * @description It is judged whether it is the component(img, iframe cover, table, hr) element - ".se-component" * @param {Element} element The element to check @@ -331,7 +342,7 @@ const util = { }, /** - * @description If a parent node that contains an argument node finds a format node (P, DIV, H[1-6], LI), it returns that node. + * @description If a parent node that contains an argument node finds a format node (P, DIV, H[1-6], PRE, LI), it returns that node. * @param {Element} element Reference element if null or no value, it is relative to the current focus node. * @param {Function|null} validation Additional validation function. * @returns {Element} @@ -354,7 +365,7 @@ const util = { }, /** - * @description If a parent node that contains an argument node finds a format node (BLOCKQUOTE, TABLE, TH, TD, OL, UL, PRE), it returns that node. + * @description If a parent node that contains an argument node finds a format node (BLOCKQUOTE, TABLE, TH, TD, OL, UL, TH, TD), it returns that node. * @param {Element} element Reference element if null or no value, it is relative to the current focus node. * @param {Function|null} validation Additional validation function. * @returns {Element|null} @@ -374,6 +385,28 @@ const util = { return null; }, + /** + * @description If a parent node that contains an argument node finds a free format node (PRE), it returns that node. + * @param {Element} element Reference element if null or no value, it is relative to the current focus node. + * @param {Function|null} validation Additional validation function. + * @returns {Element} + */ + getFreeFormatElement: function (element, validation) { + if (!element) return null; + if (!validation) { + validation = function () { return true; }; + } + + while (element) { + if (this.isWysiwygDiv(element)) return null; + if (this.isFreeFormatElement(element) && validation(element)) return element; + + element = element.parentNode; + } + + return null; + }, + /** * @description Add style and className of copyEl to originEl * @param {Element} originEl Origin element diff --git a/test/dev/suneditor_build_test.html b/test/dev/suneditor_build_test.html index 353bf62d6..9bb176fa4 100644 --- a/test/dev/suneditor_build_test.html +++ b/test/dev/suneditor_build_test.html @@ -108,7 +108,7 @@ margin: 0; padding: 0; } - .sun-editor .__se__format__replace_NORMAL, .sun-editor-editable .__se__format__replace_NORMAL { + .sun-editor .__se__format__free_NORMAL, .sun-editor-editable .__se__format__free_NORMAL { background-color: aquamarine; } .sun-editor .__se__format__replace_CODE, .sun-editor-editable .__se__format__replace_CODE { diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index 644389b51..7f12f7328 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -27,8 +27,8 @@ let s1 = suneditor.create('editor', { { tag: 'div', // Tag name name: 'NORMAL', // default: tag name - command: 'replace', // default: "replace" - class: '__se__format__replace_NORMAL', // Class names must always begin with "__se__format__" + command: 'free', // default: "replace" + class: '__se__format__free_NORMAL', // Class names must always begin with "__se__format__" }, { tag: 'div', // Tag name From 4dbcf35242c2e401f90c3e945125a098c73b9545 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Wed, 12 Feb 2020 20:26:37 +0900 Subject: [PATCH 16/99] add: formatBlock-free command --- src/plugins/submenu/formatBlock.js | 42 ++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) diff --git a/src/plugins/submenu/formatBlock.js b/src/plugins/submenu/formatBlock.js index 7319f3785..cf9b9e8b5 100644 --- a/src/plugins/submenu/formatBlock.js +++ b/src/plugins/submenu/formatBlock.js @@ -46,7 +46,7 @@ export default { if (typeof format === 'string' && defaultFormats.indexOf(format) > -1) { tagName = format.toLowerCase(); - command = tagName === 'blockquote' ? 'range' : 'replace'; + command = tagName === 'blockquote' ? 'range' : tagName === 'pre' ? 'free' : 'replace'; h = /^h/.test(tagName) ? tagName.match(/\d+/)[0] : ''; name = lang_toolbar['tag_' + (h ? 'h' : tagName)] + h; className = ''; @@ -130,11 +130,49 @@ export default { if (!command) return; - // blockquote, pre + // blockquote if (command === 'range') { const rangeElement = tag.cloneNode(false); this.applyRangeFormatElement(rangeElement); } + // pre + else if (command === 'free') { + const selectedFormsts = this.getSelectedElementsAndComponents(); + const getParentFunc = function (current) { + return !this.isFormatElement(current); + }.bind(this.util); + const getBeforeFunc = function (current) { + return !this.isFormatElement(current.parentNode); + }.bind(this.util); + + let parentNode = this.util.getParentElement(selectedFormsts[0].parentNode, getParentFunc); + let freeElement = tag.cloneNode(false); + const focusElement = freeElement; + + for (let i = 0, len = selectedFormsts.length, f, before, html, isComp; i < len; i++) { + f = selectedFormsts[i]; + if (!this.util.getParentElement(f, '.se-wrapper-inner')) continue; + + before = this.util.getParentElement(f, getBeforeFunc); + isComp = this.util.isComponent(f); + html = (isComp ? '' : f.innerHTML).replace(/\n/g, '') + '
    '; + + if (parentNode !== f.parentNode || isComp) { + parentNode = before.parentNode; + parentNode.insertBefore(freeElement, before); + freeElement = tag.cloneNode(false); + } + + freeElement.innerHTML += html; + if (len - 1 === i) before.parentNode.insertBefore(freeElement, before); + + if (!isComp) this.util.removeItem(before); + } + + // history stack + this.history.push(false); + this.setRange(focusElement, 0, focusElement, 0); + } // others else { const range = this.getRange(); From 549d8295cc781ab2dc194b5eadeda9f11e8bcbb5 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Thu, 13 Feb 2020 19:32:30 +0900 Subject: [PATCH 17/99] modify: formatblock --- sample/html/out/document-util.html | 6 +- src/lib/context.js | 1 + src/lib/core.js | 10 ++- src/lib/util.js | 4 +- src/plugins/submenu/formatBlock.js | 127 +++++++++++++++-------------- 5 files changed, 80 insertions(+), 68 deletions(-) diff --git a/sample/html/out/document-util.html b/sample/html/out/document-util.html index 1b424fc4b..f8ec4ca3b 100644 --- a/sample/html/out/document-util.html +++ b/sample/html/out/document-util.html @@ -354,7 +354,8 @@
    Parameters:

    isFormatElement(element) → {Boolean}

    - It is judged whether it is the format element. (P, DIV, H1-6, PRE, LI) + It is judged whether it is the format element. (P, DIV, H1-6, PRE, LI)
    + Format element also contain "free format Element"
    Parameters:
    @@ -410,7 +411,8 @@

    is class="type-signature"> → {Boolean}

    It is judged whether it is the free format element. (PRE)
    - Free format elements's line break is "BR" tag. + Free format elements's line break is "BR" tag.
    + Free format elements is included in the format element.
    Parameters:
    diff --git a/src/lib/context.js b/src/lib/context.js index be5fbdfed..0a7f9670c 100755 --- a/src/lib/context.js +++ b/src/lib/context.js @@ -46,6 +46,7 @@ const _Context = function (element, cons, options) { font: cons._toolBar.querySelector('._se_command_font_family .txt'), fontTooltip: cons._toolBar.querySelector('._se_command_font_family .se-tooltip-text'), format: cons._toolBar.querySelector('._se_command_format'), + formatTooltip: cons._toolBar.querySelector('._se_command_format .se-tooltip-text'), fontSize: cons._toolBar.querySelector('._se_command_font_size'), align: cons._toolBar.querySelector('._se_command_align'), list: cons._toolBar.querySelector('._se_command_list'), diff --git a/src/lib/core.js b/src/lib/core.js index 97733ad9c..2b4537c04 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -3336,6 +3336,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { this.commandMap = { FORMAT: context.tool.format, + FORMAT_TOOLTIP: context.tool.formatTooltip, FONT: context.tool.font, FONT_TOOLTIP: context.tool.fontTooltip, SIZE: context.tool.fontSize, @@ -3485,9 +3486,8 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (util.isFormatElement(selectionParent)) { /* Format block */ if (findFormat && commandMap.FORMAT) { - commandMapNodes.push('FORMAT'); core.callPlugin('formatBlock', function () { - core.plugins.formatBlock.active.call(core, selectionParent); + if (core.plugins.formatBlock.active.call(core, selectionParent)) commandMapNodes.push('FORMAT'); }); findFormat = false; } @@ -3571,7 +3571,11 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { for (let key in commandMap) { if (commandMapNodes.indexOf(key) > -1) continue; - if (commandMap.FONT && /^FONT$/i.test(key)) { + if (commandMap.FORMAT && /^FORMAT$/i.test(key)) { + util.changeTxt(commandMap.FORMAT, lang.toolbar.formats); + util.changeTxt(commandMap.FORMAT_TOOLTIP, lang.toolbar.formats); + } + else if (commandMap.FONT && /^FONT$/i.test(key)) { util.changeTxt(commandMap.FONT, lang.toolbar.font); util.changeTxt(commandMap.FONT_TOOLTIP, lang.toolbar.font); } diff --git a/src/lib/util.js b/src/lib/util.js index 663c23ede..484a45462 100755 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -302,11 +302,12 @@ const util = { /** * @description It is judged whether it is the format element (P, DIV, H1-6, PRE, LI) + * Format element also contain "free format Element" * @param {Element} element The element to check * @returns {Boolean} */ isFormatElement: function (element) { - if (element && element.nodeType === 1 && (/^(P|DIV|H[1-6]|PRE|LI)$/i.test(element.nodeName) || this.hasClass(element, '(\\s|^)__se__format__replace_.+(\\s|$)')) && !this.isComponent(element) && !this.isWysiwygDiv(element)) return true; + if (element && element.nodeType === 1 && (/^(P|DIV|H[1-6]|PRE|LI)$/i.test(element.nodeName) || this.hasClass(element, '(\\s|^)__se__format__replace_.+(\\s|$)|(\\s|^)__se__format__free_.+(\\s|$)')) && !this.isComponent(element) && !this.isWysiwygDiv(element)) return true; return false; }, @@ -324,6 +325,7 @@ const util = { /** * @description It is judged whether it is the free format element. (PRE) * Free format elements's line break is "BR" tag. + * Free format elements is included in the format element. * @param {Element} element * @returns {Boolean} */ diff --git a/src/plugins/submenu/formatBlock.js b/src/plugins/submenu/formatBlock.js index cf9b9e8b5..45f63bc39 100644 --- a/src/plugins/submenu/formatBlock.js +++ b/src/plugins/submenu/formatBlock.js @@ -87,8 +87,11 @@ export default { } this.util.changeTxt(this.commandMap.FORMAT, formatTitle); + this.util.changeTxt(this.commandMap.FORMAT_TOOLTIP, formatTitle); this.commandMap.FORMAT.setAttribute('data-value', nodeName); this.commandMap.FORMAT.setAttribute('data-class', className); + + return formatTitle !== this.lang.formats; }, on: function () { @@ -135,51 +138,13 @@ export default { const rangeElement = tag.cloneNode(false); this.applyRangeFormatElement(rangeElement); } - // pre - else if (command === 'free') { - const selectedFormsts = this.getSelectedElementsAndComponents(); - const getParentFunc = function (current) { - return !this.isFormatElement(current); - }.bind(this.util); - const getBeforeFunc = function (current) { - return !this.isFormatElement(current.parentNode); - }.bind(this.util); - - let parentNode = this.util.getParentElement(selectedFormsts[0].parentNode, getParentFunc); - let freeElement = tag.cloneNode(false); - const focusElement = freeElement; - - for (let i = 0, len = selectedFormsts.length, f, before, html, isComp; i < len; i++) { - f = selectedFormsts[i]; - if (!this.util.getParentElement(f, '.se-wrapper-inner')) continue; - - before = this.util.getParentElement(f, getBeforeFunc); - isComp = this.util.isComponent(f); - html = (isComp ? '' : f.innerHTML).replace(/\n/g, '') + '
    '; - - if (parentNode !== f.parentNode || isComp) { - parentNode = before.parentNode; - parentNode.insertBefore(freeElement, before); - freeElement = tag.cloneNode(false); - } - - freeElement.innerHTML += html; - if (len - 1 === i) before.parentNode.insertBefore(freeElement, before); - - if (!isComp) this.util.removeItem(before); - } - - // history stack - this.history.push(false); - this.setRange(focusElement, 0, focusElement, 0); - } - // others + // free, others else { const range = this.getRange(); const startOffset = range.startOffset; const endOffset = range.endOffset; - let selectedFormsts = this.getSelectedElementsAndComponents(); + const selectedFormsts = this.getSelectedElementsAndComponents(); if (selectedFormsts.length === 0) return; let first = selectedFormsts[0]; @@ -187,7 +152,7 @@ export default { const firstPath = this.util.getNodePath(range.startContainer, first, null); const lastPath = this.util.getNodePath(range.endContainer, last, null); - // remove list + // remove selected list let rangeArr = {}; let listFirst = false; let listLast = false; @@ -225,35 +190,73 @@ export default { if (lastIndex && this.util.isList(r)) { const edge = this.detachRangeFormatElement(rangeArr.r, rangeArr.f, null, false, true); - if (listLast || len === 1) { - last = edge.ec; - if (listFirst) first = edge.sc || last; - } + if (listLast || len === 1) last = edge.ec; + if (listFirst) first = edge.sc || last; } } // change format tag this.setRange(this.util.getNodeFromPath(firstPath, first), startOffset, this.util.getNodeFromPath(lastPath, last), endOffset); - selectedFormsts = this.getSelectedElementsAndComponents(); - for (let i = 0, len = selectedFormsts.length, node, newFormat; i < len; i++) { - node = selectedFormsts[i]; - - if ((node.nodeName.toLowerCase() !== value.toLowerCase() || (node.className.match(/(\s|^)__se__format__[^\s]+/) || [''])[0].trim() !== className) && !this.util.isComponent(node)) { - newFormat = tag.cloneNode(false); - this.util.copyFormatAttributes(newFormat, node); - newFormat.innerHTML = node.innerHTML; - - node.parentNode.insertBefore(newFormat, node); - this.util.removeItem(node); - } + const modifiedFormsts = this.getSelectedElementsAndComponents(); + + // free format + if (command === 'free') { + const getParentFunc = function (current) { + return !this.isFormatElement(current); + }.bind(this.util); + const getBeforeFunc = function (current) { + return !this.isFormatElement(current.parentNode); + }.bind(this.util); + + let parentNode = this.util.getParentElement(modifiedFormsts[0].parentNode, getParentFunc); + let freeElement = tag.cloneNode(false); + const focusElement = freeElement; + + for (let i = 0, len = modifiedFormsts.length, f, before, html, isComp, first = true; i < len; i++) { + f = modifiedFormsts[i]; + if (f === (!modifiedFormsts[i + 1] ? null : modifiedFormsts[i + 1].parentNode)) continue; + + isComp = this.util.isComponent(f); + html = isComp ? '' : f.innerHTML.replace(/(?!>)\s+(?=<)|\n/g, ' '); + before = this.util.getParentElement(f, getBeforeFunc); + + if (parentNode !== f.parentNode || isComp) { + parentNode.insertBefore(freeElement, before); + parentNode = before.parentNode; + freeElement = tag.cloneNode(false); + } + + freeElement.innerHTML += (first || !html || /
    $/i.test(html)) ? html : '
    ' + html; + first = false; - if (i === 0) first = newFormat || node; - if (i === len - 1) last = newFormat || node; - newFormat = null; + if (len - 1 === i) before.parentNode.insertBefore(freeElement, before); + if (!isComp) this.util.removeItem(before); + } + + this.setRange(focusElement, 0, focusElement, 0); + } + // others format + else { + for (let i = 0, len = modifiedFormsts.length, node, newFormat; i < len; i++) { + node = modifiedFormsts[i]; + + if ((node.nodeName.toLowerCase() !== value.toLowerCase() || (node.className.match(/(\s|^)__se__format__[^\s]+/) || [''])[0].trim() !== className) && !this.util.isComponent(node)) { + newFormat = tag.cloneNode(false); + this.util.copyFormatAttributes(newFormat, node); + newFormat.innerHTML = node.innerHTML; + + node.parentNode.insertBefore(newFormat, node); + this.util.removeItem(node); + } + + if (i === 0) first = newFormat || node; + if (i === len - 1) last = newFormat || node; + newFormat = null; + } + + this.setRange(this.util.getNodeFromPath(firstPath, first), startOffset, this.util.getNodeFromPath(lastPath, last), endOffset); } - this.setRange(this.util.getNodeFromPath(firstPath, first), startOffset, this.util.getNodeFromPath(lastPath, last), endOffset); - // history stack this.history.push(false); } From 444f251c0d26f778a93501a7df8e01b63962b5dc Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Fri, 14 Feb 2020 17:54:39 +0900 Subject: [PATCH 18/99] modify: free format --- src/plugins/submenu/formatBlock.js | 49 ++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/src/plugins/submenu/formatBlock.js b/src/plugins/submenu/formatBlock.js index 45f63bc39..619fcfb8a 100644 --- a/src/plugins/submenu/formatBlock.js +++ b/src/plugins/submenu/formatBlock.js @@ -201,36 +201,53 @@ export default { // free format if (command === 'free') { - const getParentFunc = function (current) { - return !this.isFormatElement(current); - }.bind(this.util); - const getBeforeFunc = function (current) { - return !this.isFormatElement(current.parentNode); - }.bind(this.util); - - let parentNode = this.util.getParentElement(modifiedFormsts[0].parentNode, getParentFunc); + let parentNode = modifiedFormsts[0].parentNode; let freeElement = tag.cloneNode(false); const focusElement = freeElement; - for (let i = 0, len = modifiedFormsts.length, f, before, html, isComp, first = true; i < len; i++) { + for (let i = modifiedFormsts.length - 1, f, html, before, next, inner, isComp, first = true; i >= 0; i--) { f = modifiedFormsts[i]; if (f === (!modifiedFormsts[i + 1] ? null : modifiedFormsts[i + 1].parentNode)) continue; isComp = this.util.isComponent(f); html = isComp ? '' : f.innerHTML.replace(/(?!>)\s+(?=<)|\n/g, ' '); - before = this.util.getParentElement(f, getBeforeFunc); + before = this.util.getParentElement(f, function (current) { + return current.parentNode === parentNode; + }); if (parentNode !== f.parentNode || isComp) { - parentNode.insertBefore(freeElement, before); - parentNode = before.parentNode; + if (this.util.isFormatElement(parentNode)) { + parentNode.parentNode.insertBefore(freeElement, parentNode.nextSibling); + parentNode = parentNode.parentNode; + } else { + parentNode.insertBefore(freeElement, before ? before.nextSibling : null); + parentNode = f.parentNode; + } + + next = freeElement.nextSibling; + if (next && freeElement.nodeName === next.nodeName && this.util.isSameAttributes(freeElement, next)) { + freeElement.innerHTML += '
    ' + next.innerHTML; + this.util.removeItem(next); + } + freeElement = tag.cloneNode(false); + first = true; } - freeElement.innerHTML += (first || !html || /
    $/i.test(html)) ? html : '
    ' + html; - first = false; + inner = freeElement.innerHTML; + freeElement.innerHTML = ((first || !html || !inner || /
    $/i.test(html)) ? html : html + '
    ') + inner; + + if (i === 0) { + parentNode.insertBefore(freeElement, f); + next = f.nextSibling; + if (next && freeElement.nodeName === next.nodeName && this.util.isSameAttributes(freeElement, next)) { + freeElement.innerHTML += '
    ' + next.innerHTML; + this.util.removeItem(next); + } + } - if (len - 1 === i) before.parentNode.insertBefore(freeElement, before); - if (!isComp) this.util.removeItem(before); + if (!isComp) this.util.removeItem(f); + if (!!html) first = false; } this.setRange(focusElement, 0, focusElement, 0); From e9556e24fedf75d519ba98a1a05ee493480da367 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Fri, 14 Feb 2020 18:26:04 +0900 Subject: [PATCH 19/99] modify: free format --- src/lib/core.js | 1 + src/plugins/submenu/formatBlock.js | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/lib/core.js b/src/lib/core.js index 2b4537c04..3458a8008 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -431,6 +431,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { const commandMap = this.commandMap; util.changeTxt(commandMap.FORMAT, lang.toolbar.formats); + util.changeTxt(commandMap.FORMAT_TOOLTIP, lang.toolbar.formats); util.changeTxt(commandMap.FONT, lang.toolbar.font); util.changeTxt(commandMap.FONT_TOOLTIP, lang.toolbar.font); util.changeTxt(commandMap.SIZE, lang.toolbar.fontSize); diff --git a/src/plugins/submenu/formatBlock.js b/src/plugins/submenu/formatBlock.js index 619fcfb8a..2451fc066 100644 --- a/src/plugins/submenu/formatBlock.js +++ b/src/plugins/submenu/formatBlock.js @@ -201,11 +201,12 @@ export default { // free format if (command === 'free') { - let parentNode = modifiedFormsts[0].parentNode; + const len = modifiedFormsts.length - 1; + let parentNode = modifiedFormsts[len].parentNode; let freeElement = tag.cloneNode(false); const focusElement = freeElement; - for (let i = modifiedFormsts.length - 1, f, html, before, next, inner, isComp, first = true; i >= 0; i--) { + for (let i = len, f, html, before, next, inner, isComp, first = true; i >= 0; i--) { f = modifiedFormsts[i]; if (f === (!modifiedFormsts[i + 1] ? null : modifiedFormsts[i + 1].parentNode)) continue; @@ -244,6 +245,12 @@ export default { freeElement.innerHTML += '
    ' + next.innerHTML; this.util.removeItem(next); } + + const prev = freeElement.previousSibling; + if (prev && freeElement.nodeName === prev.nodeName && this.util.isSameAttributes(freeElement, prev)) { + prev.innerHTML += '
    ' + freeElement.innerHTML; + this.util.removeItem(freeElement); + } } if (!isComp) this.util.removeItem(f); From 3e18b3994e411f491de341c153941a0ae70c6637 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Fri, 14 Feb 2020 19:09:37 +0900 Subject: [PATCH 20/99] add: #198 onBlur event, add: event argument - core --- README.md | 24 +++++++++++----------- sample/html/examples.html | 22 +++++++++++---------- sample/html/getting-started.html | 22 +++++++++++---------- src/lib/core.js | 34 +++++++++++++++++--------------- test/dev/suneditor_build_test.js | 3 +++ 5 files changed, 58 insertions(+), 47 deletions(-) diff --git a/README.md b/README.md index 8d94a3e28..7905840b3 100644 --- a/README.md +++ b/README.md @@ -623,23 +623,25 @@ editor.toolbar.show(); // Event functions ------------------------------------------------------------------------------------- // It can be redefined by receiving event object as parameter. // It is not called in exceptional cases and is called after the default event function has finished. -editor.onScroll = function (e) { console.log('onScroll', e) } +editor.onScroll = function (e, core) { console.log('onScroll', e) } -editor.onClick = function (e) { console.log('onClick', e) } +editor.onClick = function (e, core) { console.log('onClick', e) } -editor.onKeyDown = function (e) { console.log('onKeyDown', e) } +editor.onKeyDown = function (e, core) { console.log('onKeyDown', e) } -editor.onKeyUp = function (e) { console.log('onKeyUp', e) } +editor.onKeyUp = function (e, core) { console.log('onKeyUp', e) } -editor.onDrop = function (e) { console.log('onDrop', e) } +editor.onDrop = function (e, core) { console.log('onDrop', e) } -editor.onChange = function (contents) { console.log('onChange', contents) } +editor.onChange = function (contents, core) { console.log('onChange', contents) } + +editor.onBlur = function (e, core) { console.log('onBlur', e) } // onload event // When reloaded with the "setOptions" method, the value of the "reload" argument is true. editor.onload = function (core, reload) { console.log('onload-core', core) - console.log('onload-reload', reload) + console.log('onload-reload', reload) } // Paste event. @@ -649,7 +651,7 @@ editor.onload = function (core, reload) { * cleanData : HTML string modified for editor format * maxCharCount : maxChartCount option (true if max character is exceeded) */ -editor.onPaste = function (e, cleanData, maxCharCount) { console.log('onPaste', e, cleanData, maxCharCount) } +editor.onPaste = function (e, cleanData, maxCharCount, core) { console.log('onPaste', e) } // Called when the image is uploaded or the uploaded image is deleted. /** @@ -665,7 +667,7 @@ editor.onPaste = function (e, cleanData, maxCharCount) { console.log('onPaste', * } * remainingFilesCount: Count of remaining image files */ -editor.onImageUpload = function (targetImgElement, index, state, imageInfo, remainingFilesCount) { +editor.onImageUpload = function (targetImgElement, index, state, imageInfo, remainingFilesCount, core) { console.log(`targetImgElement:${targetImgElement}, index:${index}, state('create', 'update', 'delete'):${state}`) console.log(`imageInfo:${imageInfo}, remainingFilesCount:${remainingFilesCount}`) } @@ -676,7 +678,7 @@ editor.onImageUpload = function (targetImgElement, index, state, imageInfo, rema * errorMessage: Error message to show * result: Result object */ -editor.onImageUploadError = function (errorMessage, result) { +editor.onImageUploadError = function (errorMessage, result, core) { alert(errorMessage) } @@ -684,7 +686,7 @@ editor.onImageUploadError = function (errorMessage, result) { * toolbar: Toolbar Element * context: The editor's context object (editor.getContext()) */ -editor.showInline = function (toolbar, context) { +editor.showInline = function (toolbar, context, core) { console.log('toolbar', toolbar); console.log('context', context); } diff --git a/sample/html/examples.html b/sample/html/examples.html index 55143ec02..d0c7ff967 100644 --- a/sample/html/examples.html +++ b/sample/html/examples.html @@ -478,17 +478,19 @@ // Event functions -------------------------------------------------------------------------------------// It can be redefined by receiving event object as parameter.// It is not called in exceptional cases and is called after the default event function has finished. -editor.onScroll=function (e) { console.log('onScroll', e) } +editor.onScroll=function (e, core) { console.log('onScroll', e) } -editor.onClick=function (e) { console.log('onClick', e) } +editor.onClick=function (e, core) { console.log('onClick', e) } -editor.onKeyDown=function (e) { console.log('onKeyDown', e) } +editor.onKeyDown=function (e, core) { console.log('onKeyDown', e) } -editor.onKeyUp=function (e) { console.log('onKeyUp', e) } +editor.onKeyUp=function (e, core) { console.log('onKeyUp', e) } -editor.onDrop=function (e) { console.log('onDrop', e) } +editor.onDrop=function (e, core) { console.log('onDrop', e) } -editor.onChange=function (contents) { console.log('onChange', contents) } +editor.onChange=function (contents, core) { console.log('onChange', contents) } + +editor.onBlur=function (e, core) { console.log('onBlur', e) } // onload event// When reloaded with the "setOptions" method, the value of the "reload" argument is true. @@ -504,7 +506,7 @@ * cleanData : HTML string modified for editor format * maxCharCount : maxChartCount option (true if max character is exceeded)*/ -editor.onPaste=function (e, cleanData, maxCharCount) { console.log('onPaste', e, cleanData, maxCharCount) } +editor.onPaste=function (e, cleanData, maxCharCount, core) { console.log('onPaste', e, cleanData, maxCharCount) } // Called when the image is uploaded or the uploaded image is deleted./** @@ -520,7 +522,7 @@ * } * remainingFilesCount: Count of remaining image files*/ -editor.onImageUpload=function (targetImgElement, index, state, imageInfo, remainingFilesCount) { +editor.onImageUpload=function (targetImgElement, index, state, imageInfo, remainingFilesCount, core) { console.log(`targetImgElement:${targetImgElement}, index:${index}, state('create', 'update', 'delete'):${state}`) console.log(`imageInfo:${imageInfo}, remainingFilesCount:${remainingFilesCount}`) } @@ -531,7 +533,7 @@ * errorMessage: Error message to show * result: Result object */ -editor.onImageUploadError=function (errorMessage, result) { +editor.onImageUploadError=function (errorMessage, result, core) { alert(errorMessage) } @@ -539,7 +541,7 @@ * toolbar: Toolbar Element * context: The editor's context object (editor.getContext())*/ -editor.showInline=function (toolbar, context) { +editor.showInline=function (toolbar, context, core) { console.log('toolbar', toolbar); console.log('context', context); } diff --git a/sample/html/getting-started.html b/sample/html/getting-started.html index 60c890343..22ff65080 100644 --- a/sample/html/getting-started.html +++ b/sample/html/getting-started.html @@ -578,17 +578,19 @@ // Event functions -------------------------------------------------------------------------------------// It can be redefined by receiving event object as parameter.// It is not called in exceptional cases and is called after the default event function has finished. -editor.onScroll=function (e) { console.log('onScroll', e) } +editor.onScroll=function (e, core) { console.log('onScroll', e) } -editor.onClick=function (e) { console.log('onClick', e) } +editor.onClick=function (e, core) { console.log('onClick', e) } -editor.onKeyDown=function (e) { console.log('onKeyDown', e) } +editor.onKeyDown=function (e, core) { console.log('onKeyDown', e) } -editor.onKeyUp=function (e) { console.log('onKeyUp', e) } +editor.onKeyUp=function (e, core) { console.log('onKeyUp', e) } -editor.onDrop=function (e) { console.log('onDrop', e) } +editor.onDrop=function (e, core) { console.log('onDrop', e) } -editor.onChange=function (contents) { console.log('onChange', contents) } +editor.onChange=function (contents, core) { console.log('onChange', contents) } + +editor.onBlur=function (e, core) { console.log('onBlur', e) } // onload event// When reloaded with the "setOptions" method, the value of the "reload" argument is true. @@ -604,7 +606,7 @@ * cleanData : HTML string modified for editor format * maxCharCount : maxChartCount option (true if max character is exceeded)*/ -editor.onPaste=function (e, cleanData, maxCharCount) { console.log('onPaste', e, cleanData, maxCharCount) } +editor.onPaste=function (e, cleanData, maxCharCount, core) { console.log('onPaste', e, cleanData, maxCharCount) } // Called when the image is uploaded or the uploaded image is deleted./** @@ -620,7 +622,7 @@ * } * remainingFilesCount: Count of remaining image files*/ -editor.onImageUpload=function (targetImgElement, index, state, imageInfo, remainingFilesCount) { +editor.onImageUpload=function (targetImgElement, index, state, imageInfo, remainingFilesCount, core) { console.log(`targetImgElement:${targetImgElement}, index:${index}, state('create', 'update', 'delete'):${state}`) console.log(`imageInfo:${imageInfo}, remainingFilesCount:${remainingFilesCount}`) } @@ -631,7 +633,7 @@ * errorMessage: Error message to show * result: Result object */ -editor.onImageUploadError=function (errorMessage, result) { +editor.onImageUploadError=function (errorMessage, result, core) { alert(errorMessage) } @@ -639,7 +641,7 @@ * toolbar: Toolbar Element * context: The editor's context object (editor.getContext())*/ -editor.showInline=function (toolbar, context) { +editor.showInline=function (toolbar, context, core) { console.log('toolbar', toolbar); console.log('context', context); } diff --git a/src/lib/core.js b/src/lib/core.js index 3458a8008..2aa1e5ef5 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -157,7 +157,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { * @private */ _imageUpload: function (targetImgElement, index, state, imageInfo, remainingFilesCount) { - if (typeof userFunction.onImageUpload === 'function') userFunction.onImageUpload(targetImgElement, index * 1, state, imageInfo, remainingFilesCount); + if (typeof userFunction.onImageUpload === 'function') userFunction.onImageUpload(targetImgElement, index * 1, state, imageInfo, remainingFilesCount, core); }, /** @@ -165,7 +165,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { * @private */ _imageUploadError: function (errorMessage, result) { - if (typeof userFunction.onImageUploadError === 'function') return userFunction.onImageUploadError(errorMessage, result); + if (typeof userFunction.onImageUploadError === 'function') return userFunction.onImageUploadError(errorMessage, result, core); return true; }, @@ -3766,7 +3766,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { else event._showToolbarBalloon(range); } - if (userFunction.onClick) userFunction.onClick(e); + if (userFunction.onClick) userFunction.onClick(e, core); }, _showToolbarBalloon: function (rangeObj) { @@ -3860,7 +3860,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { core._inlineToolbarAttr.width = toolbar.style.width = context.option.toolbarWidth; core._inlineToolbarAttr.top = toolbar.style.top = (-1 - toolbar.offsetHeight) + 'px'; - if (typeof userFunction.showInline === 'function') userFunction.showInline(toolbar, context); + if (typeof userFunction.showInline === 'function') userFunction.showInline(toolbar, context, core); event.onScroll_window(); core._inlineToolbarAttr.isShow = true; @@ -4173,7 +4173,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { } } - if (userFunction.onKeyDown) userFunction.onKeyDown(e); + if (userFunction.onKeyDown) userFunction.onKeyDown(e, core); }, onKeyUp_wysiwyg: function (e) { @@ -4247,13 +4247,18 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { core.history.push(true); } - if (userFunction.onKeyUp) userFunction.onKeyUp(e); + if (userFunction.onKeyUp) userFunction.onKeyUp(e, core); }, onScroll_wysiwyg: function (e) { core.controllersOff(); if (core._isBalloon) event._hideToolbar(); - if (userFunction.onScroll) userFunction.onScroll(e); + if (userFunction.onScroll) userFunction.onScroll(e, core); + }, + + onBlur_wysiwyg: function (e) { + if (core._isInline || core._isBalloon) event._hideToolbar(); + if (userFunction.onBlur) userFunction.onBlur(e, core); }, onMouseDown_resizingBar: function (e) { @@ -4370,7 +4375,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { const maxCharCount = core._charCount(clipboardData.getData('text/plain').length, true); const cleanData = util.cleanHTML(clipboardData.getData('text/html')); - if (typeof userFunction.onPaste === 'function' && !userFunction.onPaste(e, cleanData, maxCharCount)) { + if (typeof userFunction.onPaste === 'function' && !userFunction.onPaste(e, cleanData, maxCharCount, core)) { e.preventDefault(); e.stopPropagation(); return false; @@ -4432,7 +4437,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { } } - if (userFunction.onDrop) userFunction.onDrop(e); + if (userFunction.onDrop) userFunction.onDrop(e, core); }, _setDropLocationSelection: function (e) { @@ -4445,7 +4450,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { _onChange_historyStack: function () { if (context.tool.save) context.tool.save.removeAttribute('disabled'); - if (userFunction.onChange) userFunction.onChange(core.getContents(true)); + if (userFunction.onChange) userFunction.onChange(core.getContents(true), core); }, _addEvent: function () { @@ -4463,6 +4468,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { eventWysiwyg.addEventListener('dragover', event.onDragOver_wysiwyg, false); eventWysiwyg.addEventListener('drop', event.onDrop_wysiwyg, false); eventWysiwyg.addEventListener('scroll', event.onScroll_wysiwyg, false); + eventWysiwyg.addEventListener('blur', event.onBlur_wysiwyg, false); /** Events are registered only a balloon mode or when there is a table plugin. */ if (core._isBalloon || core.plugins.table) { @@ -4494,11 +4500,6 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (core._isInline) { eventWysiwyg.addEventListener('focus', event._showToolbarInline, false); } - - /** inline, balloon editor */ - if (core._isInline || core._isBalloon) { - eventWysiwyg.addEventListener('blur', event._hideToolbar, false); - } /** window event */ _w.removeEventListener('resize', event.onResize_window); @@ -4529,7 +4530,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { eventWysiwyg.removeEventListener('touchstart', event.onMouseDown_wysiwyg, {passive: true, useCapture: false}); eventWysiwyg.removeEventListener('focus', event._showToolbarInline); - eventWysiwyg.removeEventListener('blur', event._hideToolbar); + eventWysiwyg.removeEventListener('blur', event.onBlur_wysiwyg); context.element.code.removeEventListener('keydown', event._codeViewAutoHeight); context.element.code.removeEventListener('keyup', event._codeViewAutoHeight); @@ -4564,6 +4565,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { onDrop: null, onChange: null, onPaste: null, + onBlur: null, showInline: null, /** diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index 7f12f7328..32e2aec2d 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -112,6 +112,9 @@ ss.onScroll = function (e) { ss.onClick = function (e) { console.log('onClick', e); }; +ss.onBlur = function (e, core) { + console.log('onBlur', e); +}; ss.onKeyDown = function (e) { console.log('onKeyDown', e); }; From 1d8f49c7bd352404a41bce144d8eb710762a8169 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Fri, 14 Feb 2020 20:02:30 +0900 Subject: [PATCH 21/99] modify: #209, #213 hide cell controller, fix: #210 disabled status- it's can table edited fix: #214 disabled button cursor pointer --- src/assets/css/suneditor.css | 2 +- src/lib/core.js | 2 ++ src/plugins/submenu/table.js | 6 ++++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/assets/css/suneditor.css b/src/assets/css/suneditor.css index cdee4d69c..4feafb81f 100755 --- a/src/assets/css/suneditor.css +++ b/src/assets/css/suneditor.css @@ -154,7 +154,7 @@ .sun-editor .se-btn:enabled.on:hover, .sun-editor .se-btn:enabled.on:focus {background-color:#d1d1d1; border-color:#c1c1c1; outline:0 none;} .sun-editor .se-btn:enabled.on:active {background-color:#c1c1c1; border-color:#b1b1b1; -webkit-box-shadow:inset 0 3px 5px #b1b1b1; box-shadow:inset 0 3px 5px #b1b1b1;} /* disabled buttons, icon blur */ -.sun-editor .se-btn:disabled, .sun-editor .se-btn-list:disabled, .sun-editor :disabled [class*='se-icon-']::before {cursor:not-allowed; background-color:inherit; color:#bdbdbd;} +.sun-editor .se-btn:disabled, .sun-editor .se-btn-list:disabled, .sun-editor button:disabled {cursor:not-allowed; background-color:inherit; color:#bdbdbd;} /** --- loading box */ .sun-editor .se-loading-box {position:absolute; display:none; width:100%; height:100%; top:0; left:0; background-color:#fff; opacity:.7; filter:alpha(opacity=70); z-index:2147483647;} diff --git a/src/lib/core.js b/src/lib/core.js index 2aa1e5ef5..3af9abd71 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -3686,6 +3686,8 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { * @warning Events are registered only when there is a table plugin. */ onMouseDown_wysiwyg: function (e) { + if (context.element.wysiwyg.getAttribute('contenteditable') === 'false') return; + const tableCell = util.getParentElement(e.target, util.isCell); if (tableCell) { const tablePlugin = core.plugins.table; diff --git a/src/plugins/submenu/table.js b/src/plugins/submenu/table.js index 1bdf013dd..f1a13300d 100644 --- a/src/plugins/submenu/table.js +++ b/src/plugins/submenu/table.js @@ -290,6 +290,12 @@ export default { /** table edit controller */ call_controller_tableEdit: function (tdElement) { + if (!this.getSelection().isCollapsed) { + this.controllersOff(); + this.util.removeClass(tdElement, 'se-table-selected-cell'); + return; + } + const contextTable = this.context.table; const tablePlugin = this.plugins.table; const tableController = contextTable.tableController; From d9a168d10852e958877274e21be8ebbc50a1ebc7 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Mon, 17 Feb 2020 01:49:01 +0900 Subject: [PATCH 22/99] #200, #203 add: options-addTagsWhitelist, pasteTagsWhitelist, add: util-createTagsWhitelist, modify: util-convertContentsForEditor, cleanHTML add whitelist argument --- README.md | 8 +++++ sample/html/options.html | 10 ++++++ sample/html/out/document-editor.html | 20 +++++++++++ sample/html/out/document-util.html | 53 ++++++++++++++++++++++++++-- src/lib/constructor.js | 5 ++- src/lib/context.js | 1 + src/lib/core.js | 36 +++++++++++++++---- src/lib/util.js | 27 ++++++++------ src/suneditor.js | 2 +- test/dev/suneditor_build_test.js | 7 ++-- 10 files changed, 145 insertions(+), 24 deletions(-) diff --git a/README.md b/README.md index 7905840b3..ac2af38a0 100644 --- a/README.md +++ b/README.md @@ -284,6 +284,14 @@ plugins: [ video ] : Plugins array. default: null {Array} +// Tags whitelist--------------------------------------å--------------------------------------------------------- +// _defaultTagsWhitelist : 'br|p|div|pre|blockquote|h[1-6]|ol|ul|dl|li|hr|figure|figcaption|img|iframe|audio|video|table|thead|tbody|tr|th|td|a|b|strong|var|i|em|u|ins|s|span|strike|del|sub|sup' +addTagsWhitelist : Add tags to the default tags whitelist of editor. default: '' {String} + ex) 'mark|canvas|label|select|option|input' +// _editorTagsWhitelist : _defaultTagsWhitelist + addTagsWhitelist +pasteTagsWhitelist : Whitelist of tags when pasting. default: _editorTagsWhitelist {String} + ex) 'p|h[1-6]' + // Layout------------------------------------------------------------------------------------------------------- lang : language object. default : en {Object} mode : The mode of the editor ('classic', 'inline', 'balloon'). default: 'classic' {String} diff --git a/sample/html/options.html b/sample/html/options.html index 1baf3d104..d931e2a87 100644 --- a/sample/html/options.html +++ b/sample/html/options.html @@ -50,6 +50,14 @@
    +

    --Tags whitelist

    + + +

    + + +
    +

    --Layout

    + + + + +
    Contents
    whitelist + String|RegExp + + Regular expression of allowed tags.
    + RegExp object is create by util.createTagsWhitelist method. (core.editorTagsWhitelistRegExp, core.pasteTagsWhitelistRegExp) +
    @@ -1712,7 +1722,7 @@
    Parameters:
    -

    cleanHTML(html)cleanHTML(html, whitelist) → {String}

    Gets the clean HTML code for editor @@ -1734,6 +1744,44 @@
    Parameters:
    HTML string + + whitelist + + String|RegExp + + + Regular expression of allowed tags.
    + RegExp object is create by util.createTagsWhitelist method. (core.editorTagsWhitelistRegExp, core.pasteTagsWhitelistRegExp) + + + + +
    + + +

    createTagsWhitelist(list) → {RegExp}

    +
    + Create whitelist RegExp object.
    + Return RegExp format: new RegExp("<\\/?(Loop(?!\\blist[i]\\b))[^>^>])+>", "g") +
    +
    Parameters:
    + + + + + + + + + + + + + +
    NameTypeDescription
    list + String + Tags list ("br|p|div|pre...")
    @@ -1805,6 +1853,7 @@

    util

  • removeItemAllParents
  • removeEmptyNode
  • cleanHTML
  • +
  • createTagsWhitelist
  • diff --git a/src/lib/constructor.js b/src/lib/constructor.js index 835e34ce4..a709b02ad 100755 --- a/src/lib/constructor.js +++ b/src/lib/constructor.js @@ -49,7 +49,7 @@ export default { editor_div.className = 'se-wrapper'; /** --- init elements and create bottom bar --- */ - const initHTML = util.convertContentsForEditor(element.value); + const initHTML = util.convertContentsForEditor(element.value, options._editorTagsWhitelist); const initElements = this._initElements(options, top_div, tool_bar.element, arrow, initHTML); const bottomBar = initElements.bottomBar; @@ -365,6 +365,9 @@ export default { _initOptions: function (element, options) { /** user options */ options.lang = options.lang || _defaultLang; + options._defaultTagsWhitelist = typeof options._defaultTagsWhitelist === 'string' ? options._defaultTagsWhitelist : 'br|p|div|pre|blockquote|h[1-6]|ol|ul|dl|li|hr|figure|figcaption|img|iframe|audio|video|table|thead|tbody|tr|th|td|a|b|strong|var|i|em|u|ins|s|span|strike|del|sub|sup'; + options._editorTagsWhitelist = options._defaultTagsWhitelist + (typeof options.addTagsWhitelist === 'string' && options.addTagsWhitelist.length > 0 ? '|' + options.addTagsWhitelist : ''); + options.pasteTagsWhitelist = typeof options.pasteTagsWhitelist === 'string' ? options.pasteTagsWhitelist : options._editorTagsWhitelist; /** Layout */ options.mode = options.mode || 'classic'; // classic, inline, balloon options.toolbarWidth = options.toolbarWidth ? (util.isNumber(options.toolbarWidth) ? options.toolbarWidth + 'px' : options.toolbarWidth) : 'auto'; diff --git a/src/lib/context.js b/src/lib/context.js index 0a7f9670c..2fed97c18 100755 --- a/src/lib/context.js +++ b/src/lib/context.js @@ -55,6 +55,7 @@ const _Context = function (element, cons, options) { save: cons._toolBar.querySelector('._se_command_save'), outdent: cons._toolBar.querySelector('._se_command_outdent') }, + options: options, option: options }; }; diff --git a/src/lib/core.js b/src/lib/core.js index 3af9abd71..185a95480 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -109,6 +109,18 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { */ history: null, + /** + * @description Editor tags whitelist (RegExp object) + * util.createTagsWhitelist(options._editorTagsWhitelist) + */ + editorTagsWhitelistRegExp: null, + + /** + * @description Tag whitelist when pasting (RegExp object) + * util.createTagsWhitelist(options.pasteTagsWhitelist) + */ + pasteTagsWhitelistRegExp: null, + /** * @description binded controllersOff method * @private @@ -2920,7 +2932,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { } this._wd.head.innerHTML = parseDocument.head.innerHTML; - this._wd.body.innerHTML = util.convertContentsForEditor(parseDocument.body.innerHTML); + this._wd.body.innerHTML = util.convertContentsForEditor(parseDocument.body.innerHTML, this.editorTagsWhitelistRegExp); const attrs = parseDocument.body.attributes; for (let i = 0, len = attrs.length; i < len; i++) { @@ -2928,7 +2940,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { this._wd.body.setAttribute(attrs[i].name, attrs[i].value); } } else { - context.element.wysiwyg.innerHTML = code_html.length > 0 ? util.convertContentsForEditor(code_html) : '


    '; + context.element.wysiwyg.innerHTML = code_html.length > 0 ? util.convertContentsForEditor(code_html, this.editorTagsWhitelistRegExp) : '


    '; } }, @@ -3142,7 +3154,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { * @param {String} html HTML string */ setContents: function (html) { - const convertValue = util.convertContentsForEditor(html); + const convertValue = util.convertContentsForEditor(html, this.editorTagsWhitelistRegExp); this._resetComponents(); if (!core._variable.isCodeView) { @@ -3331,6 +3343,9 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (typeof userFunction.onload === 'function') return userFunction.onload(core, reload); }.bind(this)); + this.editorTagsWhitelistRegExp = util.createTagsWhitelist(context.option._editorTagsWhitelist); + this.pasteTagsWhitelistRegExp = util.createTagsWhitelist(context.option.pasteTagsWhitelist); + this.codeViewDisabledButtons = context.element.toolbar.querySelectorAll('.se-toolbar button:not([class~="code-view-enabled"])'); this._isInline = /inline/i.test(context.option.mode); this._isBalloon = /balloon/i.test(context.option.mode); @@ -4375,7 +4390,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (!clipboardData) return true; const maxCharCount = core._charCount(clipboardData.getData('text/plain').length, true); - const cleanData = util.cleanHTML(clipboardData.getData('text/html')); + const cleanData = util.cleanHTML(clipboardData.getData('text/html'), core.pasteTagsWhitelistRegExp); if (typeof userFunction.onPaste === 'function' && !userFunction.onPaste(e, cleanData, maxCharCount, core)) { e.preventDefault(); @@ -4432,7 +4447,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { return false; // html paste } else { - const cleanData = util.cleanHTML(dataTransfer.getData('text/html')); + const cleanData = util.cleanHTML(dataTransfer.getData('text/html'), core.pasteTagsWhitelistRegExp); if (cleanData) { event._setDropLocationSelection(e); core.execCommand('insertHTML', false, cleanData); @@ -4745,10 +4760,17 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { * @param {String} contents Contents to Input */ appendContents: function (contents) { - const convertValue = util.convertContentsForEditor(contents); + const convertValue = util.convertContentsForEditor(contents, this.editorTagsWhitelistRegExp); if (!core._variable.isCodeView) { - context.element.wysiwyg.innerHTML += convertValue; + const temp = util.createElement('DIV'); + temp.innerHTML = convertValue; + + const wysiwyg = context.element.wysiwyg; + const children = temp.children; + for (let i = 0, len = children.length; i < len; i++) { + wysiwyg.appendChild(children[i]); + } } else { core._setCodeView(core._getCodeView() + '\n' + util.convertHTMLForCodeView(convertValue, core._variable.codeIndent)); } diff --git a/src/lib/util.js b/src/lib/util.js index 484a45462..2d2c83524 100755 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -212,9 +212,11 @@ const util = { /** * @description Converts contents into a format that can be placed in an editor * @param {String} contents contents + * @param {String|RegExp} whitelist Regular expression of allowed tags. + * RegExp object is create by util.createTagsWhitelist method. (core.editorTagsWhitelistRegExp, core.pasteTagsWhitelistRegExp) * @returns {String} */ - convertContentsForEditor: function (contents) { + convertContentsForEditor: function (contents, whitelist) { let returnHTML = ''; let tag = this._d.createRange().createContextualFragment(contents).childNodes; @@ -238,7 +240,7 @@ const util = { returnHTML = '

    ' + (contents.length > 0 ? contents : '
    ') + '

    '; } - return this._tagConvertor(returnHTML.replace(this._deleteExclusionTags, '')); + return this._tagConvertor(!whitelist ? returnHTML : returnHTML.replace(typeof whitelist === 'string' ? this.createTagsWhitelist(whitelist) : whitelist, '')); }, /** @@ -1066,9 +1068,11 @@ const util = { /** * @description Gets the clean HTML code for editor * @param {String} html HTML string + * @param {String|RegExp} whitelist Regular expression of allowed tags. + * RegExp object is create by util.createTagsWhitelist method. (core.editorTagsWhitelistRegExp, core.pasteTagsWhitelistRegExp) * @returns {String} */ - cleanHTML: function (html) { + cleanHTML: function (html, whitelist) { const tagsAllowed = new this._w.RegExp('^(meta|script|link|style|[a-z]+\:[a-z]+)$', 'i'); const domTree = this._d.createRange().createContextualFragment(html).childNodes; let cleanHTML = ''; @@ -1091,10 +1095,9 @@ const util = { } return t; }) - .replace(/<\/?(span[^>^<]*)>/g, '') - .replace(this._deleteExclusionTags, ''); + .replace(/<\/?(span[^>^<]*)>/g, ''); - return this._tagConvertor(cleanHTML || html); + return this._tagConvertor(!cleanHTML ? html : !whitelist ? cleanHTML : cleanHTML.replace(typeof whitelist === 'string' ? this.createTagsWhitelist(whitelist) : whitelist, '')); }, /** @@ -1128,12 +1131,14 @@ const util = { }, /** - * @description Delete Exclusion tags regexp object - * @returns {Object} + * @description Create whitelist RegExp object. + * Return RegExp format: new RegExp("<\\/?(" + (?!\\b list[i] \\b) + ")[^>^<])+>", "g") + * @param {String} list Tags list ("br|p|div|pre...") + * @returns {RegExp} * @private */ - _deleteExclusionTags: (function () { - const exclusionTags = 'br|p|div|pre|blockquote|h[1-6]|ol|ul|dl|li|hr|figure|figcaption|img|iframe|audio|video|table|thead|tbody|tr|th|td|a|b|strong|var|i|em|u|ins|s|span|strike|del|sub|sup|mark|canvas|label|select|option|input'.split('|'); + createTagsWhitelist: function (list) { + const exclusionTags = list.split('|'); let regStr = '<\\/?('; for (let i = 0, len = exclusionTags.length; i < len; i++) { @@ -1143,7 +1148,7 @@ const util = { regStr += '[^>^<])+>'; return new RegExp(regStr, 'g'); - })() + } }; export default util; \ No newline at end of file diff --git a/src/suneditor.js b/src/suneditor.js index 0b964b5b6..1e3fd5e8c 100644 --- a/src/suneditor.js +++ b/src/suneditor.js @@ -31,7 +31,7 @@ export default { * @description Create the suneditor * @param {String|Element} idOrElement textarea Id or textarea element * @param {Json} options user options - * @returns {{save: save, getContext: getContext, getContent: getContent, setContent: setContent, appendContent: appendContent, disabled: disabled, enabled: enabled, show: show, hide: hide, destroy: destroy}} + * @returns {Object} */ create: function (idOrElement, options, _init_options) { if (typeof options !== 'object') options = {}; diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index 32e2aec2d..f0633cce8 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -23,6 +23,7 @@ let s1 = suneditor.create('editor', { // mode: 'balloon', buttonList: [['table', 'align', 'link', 'bold', 'underline', 'italic', 'strike', 'fontColor', 'hiliteColor', 'removeFormat', 'formatBlock', 'codeView', 'preview']], width: '100%', + pasteTagsWhitelist: 'p|h[1-6]', formats: [ { tag: 'div', // Tag name @@ -92,6 +93,8 @@ let ss = window.ss = suneditor.create(document.getElementById('editor1'), { width: '100%', youtubeQuery :'autoplay=1&mute=1&enablejsapi=1', placeholder: 'SSSFdjskfdsff.f.fdsa.f...', + fullPage: true, + addTagsWhitelist: 'mark|canvas|label|select|option|input' // mode: 'inline' // videoHeightShow: false, // videoRatioShow: false, @@ -168,7 +171,7 @@ window.sun_getContents = function () { } window.sun_setContents = function (content) { - ss.setContents('

    '); + ss.setContents(''); ss.core.history.reset(true); // ss.core.context.tool.save.disabled = true; } @@ -306,7 +309,7 @@ const newOption = { placeholder: 'Placeholder...' } const newOption2 = { - plugins: plugins, + plugins: [plugins.align], mode: 'classic', maxHeight: '400px', height: 150, From e1e55b827685e98437d18fc7e1bed994cb25acc9 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Mon, 17 Feb 2020 01:53:39 +0900 Subject: [PATCH 23/99] fix: #202 setOptions bug-removes existing plugins --- src/lib/core.js | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/lib/core.js b/src/lib/core.js index 185a95480..4750728fa 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -4611,7 +4611,14 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { core.plugins = options.plugins || core.plugins; const mergeOptions = [context.option, options].reduce(function (init, option) { Object.keys(option).forEach(function (key) { - init[key] = option[key]; + if (key === 'plugins' && option[key] && init[key]) { + let i = init[key], o = option[key]; + i = i.length ? i : Object.keys(i).map(function(name) { return i[name]; }); + o = o.length ? o : Object.keys(o).map(function(name) { return o[name]; }); + init[key] = (o.filter(function(val) { return i.indexOf(val) === -1; })).concat(i); + } else { + init[key] = option[key]; + } }); return init; }, {}); From cec1d7403dda85d154c9b4da5877a66fe91feca3 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Mon, 17 Feb 2020 19:26:05 +0900 Subject: [PATCH 24/99] add: #207 blockquote command plugin --- src/lib/constructor.js | 7 +++++- src/lib/core.js | 28 ++++++++++++++++++++-- src/plugins/command/blockquote.js | 40 +++++++++++++++++++++++++++++++ src/plugins/index.js | 9 +++++-- test/dev/suneditor_build_test.js | 8 ++++--- 5 files changed, 84 insertions(+), 8 deletions(-) create mode 100644 src/plugins/command/blockquote.js diff --git a/src/lib/constructor.js b/src/lib/constructor.js index a709b02ad..c1b69f2af 100755 --- a/src/lib/constructor.js +++ b/src/lib/constructor.js @@ -448,7 +448,7 @@ export default { */ _defaultButtons: function (lang) { return { - /** command */ + /** default command */ bold: ['_se_command_bold', lang.toolbar.bold + ' (CTRL+B)', 'STRONG', '', '' ], @@ -517,6 +517,11 @@ export default { '', true ], + /** plugins - command */ + blockquote: ['', lang.toolbar.tag_blockquote, 'blockquote', 'command', + '' + ], + /** plugins - submenu */ font: ['se-btn-select se-btn-tool-font _se_command_font_family', lang.toolbar.font, 'font', 'submenu', '' + lang.toolbar.font + '' diff --git a/src/lib/core.js b/src/lib/core.js index 4750728fa..8ff4bec84 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -3350,7 +3350,14 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { this._isInline = /inline/i.test(context.option.mode); this._isBalloon = /balloon/i.test(context.option.mode); + Object.keys(plugins).forEach(function (key) { + if (plugins[key].command === 'command') { + core.callPlugin(key, null); + } + }); + this.commandMap = { + BLOCKQUOTE: this.plugins.blockquote, FORMAT: context.tool.format, FORMAT_TOOLTIP: context.tool.formatTooltip, FONT: context.tool.font, @@ -3489,7 +3496,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { const commandMapNodes = []; const currentNodes = []; - let findFormat = true, findAlign = true, findList = true, findFont = true, findSize = true, findOutdent = true, findA = true; + let findBlockquote = true, findFormat = true, findAlign = true, findList = true, findFont = true, findSize = true, findOutdent = true, findA = true; let nodeName = ''; for (let selectionParent = core.getSelectionNode(); !util.isWysiwygDiv(selectionParent); selectionParent = selectionParent.parentNode) { @@ -3498,6 +3505,14 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { nodeName = selectionParent.nodeName.toUpperCase(); currentNodes.push(nodeName); + /** Range format */ + /* Blockquote */ + if (findBlockquote && /blockquote/i.test(selectionParent.nodeName) && commandMap.BLOCKQUOTE) { + commandMap.BLOCKQUOTE.active.call(core, true); + commandMapNodes.push('BLOCKQUOTE'); + findBlockquote = false; + } + /** Format */ if (util.isFormatElement(selectionParent)) { /* Format block */ @@ -3587,7 +3602,10 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { for (let key in commandMap) { if (commandMapNodes.indexOf(key) > -1) continue; - if (commandMap.FORMAT && /^FORMAT$/i.test(key)) { + if (commandMap.BLOCKQUOTE && /^BLOCKQUOTE$/i.test(key)) { + commandMap.BLOCKQUOTE.active.call(core, false); + } + else if (commandMap.FORMAT && /^FORMAT$/i.test(key)) { util.changeTxt(commandMap.FORMAT, lang.toolbar.formats); util.changeTxt(commandMap.FORMAT_TOOLTIP, lang.toolbar.formats); } @@ -3686,6 +3704,11 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { }); return; } + else if (/command/.test(display)) { + core.callPlugin(command, function () { + core.plugins[command].action.call(core); + }); + } core.submenuOff(); return; @@ -4466,6 +4489,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { }, _onChange_historyStack: function () { + event._applyTagEffects(); if (context.tool.save) context.tool.save.removeAttribute('disabled'); if (userFunction.onChange) userFunction.onChange(core.getContents(true), core); }, diff --git a/src/plugins/command/blockquote.js b/src/plugins/command/blockquote.js new file mode 100644 index 000000000..88286785c --- /dev/null +++ b/src/plugins/command/blockquote.js @@ -0,0 +1,40 @@ +/* + * wysiwyg web editor + * + * suneditor.js + * Copyright 2017 JiHong Lee. + * MIT license. + */ +'use strict'; + +export default { + name: 'blockquote', + command: 'command', + add: function (core, targetElement) { + const context = core.context; + context.blockquote = { + commandButton: targetElement, + tag: core.util.createElement('BLOCKQUOTE') + }; + }, + + action: function () { + const currentBlockquote = this.util.getParentElement(this.getSelectionNode(), 'blockquote'); + + if (currentBlockquote) { + this.detachRangeFormatElement(currentBlockquote, this.getSelectedElements(), null, false, false); + } else { + this.applyRangeFormatElement(this.context.blockquote.tag.cloneNode(false)); + } + }, + + active: function (element) { + if (!!element && /blockquote/i.test(element.nodeName)) { + this.util.addClass(this.context.blockquote.commandButton, 'active'); + return true; + } else { + this.util.removeClass(this.context.blockquote.commandButton, 'active'); + return false; + } + } +}; \ No newline at end of file diff --git a/src/plugins/index.js b/src/plugins/index.js index 23ee98c3c..4b8acf0a0 100644 --- a/src/plugins/index.js +++ b/src/plugins/index.js @@ -1,5 +1,9 @@ 'use strict'; +// command +import blockquote from './command/blockquote'; + +// submenu import align from './submenu/align'; import font from './submenu/font'; import fontSize from './submenu/fontSize'; @@ -14,9 +18,10 @@ import template from './submenu/template'; import paragraphStyle from './submenu/paragraphStyle'; import textStyle from './submenu/textStyle'; +// dialog import link from './dialog/link'; import image from './dialog/image'; import video from './dialog/video'; -export { align, font, fontSize, fontColor, hiliteColor, horizontalRule, list, table, formatBlock, lineHeight, template, paragraphStyle, textStyle, link, image, video }; -export default { align, font, fontSize, fontColor, hiliteColor, horizontalRule, list, table, formatBlock, lineHeight, template, paragraphStyle, textStyle, link, image, video }; \ No newline at end of file +export { blockquote, align, font, fontSize, fontColor, hiliteColor, horizontalRule, list, table, formatBlock, lineHeight, template, paragraphStyle, textStyle, link, image, video }; +export default { blockquote, align, font, fontSize, fontColor, hiliteColor, horizontalRule, list, table, formatBlock, lineHeight, template, paragraphStyle, textStyle, link, image, video }; \ No newline at end of file diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index f0633cce8..d14342bb0 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -21,7 +21,7 @@ const align = require('../../src/plugins/submenu/align') let s1 = suneditor.create('editor', { plugins: plugins, // mode: 'balloon', - buttonList: [['table', 'align', 'link', 'bold', 'underline', 'italic', 'strike', 'fontColor', 'hiliteColor', 'removeFormat', 'formatBlock', 'codeView', 'preview']], + buttonList: [['blockquote'],['table', 'align', 'link', 'bold', 'underline', 'italic', 'strike', 'fontColor', 'hiliteColor', 'removeFormat', 'formatBlock', 'codeView', 'preview']], width: '100%', pasteTagsWhitelist: 'p|h[1-6]', formats: [ @@ -37,7 +37,8 @@ let s1 = suneditor.create('editor', { command: 'replace', // default: "replace" class: '__se__format__replace_CODE', // Class names must always begin with "__se__format__" }, - 'pre' + 'pre', + 'blockquote' ] }) @@ -62,7 +63,7 @@ window.cm = CodeMirror // }); window.sun_destroy1 = function () { - s1.destroy(); + s1.core.focus(); } window.sun_create1 = function () { @@ -108,6 +109,7 @@ let ss = window.ss = suneditor.create(document.getElementById('editor1'), { ss.onload = function (core) { console.log('onload', core); + core.focus(); }; ss.onScroll = function (e) { console.log('onScroll', e); From 3028d884e2cacc766b4f1a7248584028231a623c Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Tue, 18 Feb 2020 18:13:46 +0900 Subject: [PATCH 25/99] add: core-commandPlugins --- sample/html/out/document-editor.html | 54 ++++------------ src/lib/constructor.js | 4 +- src/lib/context.js | 12 ++-- src/lib/core.js | 92 +++++++++++----------------- src/plugins/command/blockquote.js | 23 +++---- src/plugins/submenu/font.js | 22 ++++++- src/plugins/submenu/formatBlock.js | 49 +++++++++------ test/dev/suneditor_build_test.js | 2 +- 8 files changed, 117 insertions(+), 141 deletions(-) diff --git a/sample/html/out/document-editor.html b/sample/html/out/document-editor.html index b78aa3a31..c984e47e6 100644 --- a/sample/html/out/document-editor.html +++ b/sample/html/out/document-editor.html @@ -757,10 +757,19 @@

    +

    commandPlugins

    +
    + Plugins array with active method. +
    +
    + +

    commandMap

    - Elements that need to change text or className for each selection change + Elements that need to change text or className for each selection change.
    + After creating the editor, commandPlugins are added.
    Properties:
    @@ -772,48 +781,6 @@
    Properties:
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - +
    FORMAT - Element - format button > span.txt
    FONT - Element - font family button > span.txt
    FONT_TOOLTIP - Element - font family tooltip element
    SIZE - Element - font size button > span.txt
    ALIGN - Element - align button > div.icon
    LI - Element - list button
    STRONG @@ -1908,6 +1875,7 @@

    core

  • controllerArray
  • controllerFunction
  • codeViewDisabledButtons
  • +
  • commandPlugins
  • commandMap
  • _variable
  • Methods
  • diff --git a/src/lib/constructor.js b/src/lib/constructor.js index c1b69f2af..c7ce96e7c 100755 --- a/src/lib/constructor.js +++ b/src/lib/constructor.js @@ -523,12 +523,12 @@ export default { ], /** plugins - submenu */ - font: ['se-btn-select se-btn-tool-font _se_command_font_family', lang.toolbar.font, 'font', 'submenu', + font: ['se-btn-select se-btn-tool-font', lang.toolbar.font, 'font', 'submenu', '' + lang.toolbar.font + '' ], formatBlock: ['se-btn-select se-btn-tool-format', lang.toolbar.formats, 'formatBlock', 'submenu', - '' + lang.toolbar.formats + '' + '' + lang.toolbar.formats + '' ], fontSize: ['se-btn-select se-btn-tool-size', lang.toolbar.fontSize, 'fontSize', 'submenu', diff --git a/src/lib/context.js b/src/lib/context.js index 2fed97c18..7374ab26f 100755 --- a/src/lib/context.js +++ b/src/lib/context.js @@ -43,17 +43,13 @@ const _Context = function (element, cons, options) { strike: cons._toolBar.querySelector('._se_command_strike'), subscript: cons._toolBar.querySelector('._se_command_subscript'), superscript: cons._toolBar.querySelector('._se_command_superscript'), - font: cons._toolBar.querySelector('._se_command_font_family .txt'), - fontTooltip: cons._toolBar.querySelector('._se_command_font_family .se-tooltip-text'), - format: cons._toolBar.querySelector('._se_command_format'), - formatTooltip: cons._toolBar.querySelector('._se_command_format .se-tooltip-text'), - fontSize: cons._toolBar.querySelector('._se_command_font_size'), - align: cons._toolBar.querySelector('._se_command_align'), - list: cons._toolBar.querySelector('._se_command_list'), undo: cons._toolBar.querySelector('._se_command_undo'), redo: cons._toolBar.querySelector('._se_command_redo'), save: cons._toolBar.querySelector('._se_command_save'), - outdent: cons._toolBar.querySelector('._se_command_outdent') + outdent: cons._toolBar.querySelector('._se_command_outdent'), + fontSize: cons._toolBar.querySelector('._se_command_font_size'), //delete + align: cons._toolBar.querySelector('._se_command_align'), + list: cons._toolBar.querySelector('._se_command_list') }, options: options, option: options diff --git a/src/lib/core.js b/src/lib/core.js index 8ff4bec84..e9d069ebf 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -181,14 +181,14 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { return true; }, + /** + * @description Plugins array with active method + */ + commandPlugins: null, + /** * @description Elements that need to change text or className for each selection change - * @property {Element} FORMAT format button > span.txt - * @property {Element} FONT font family button > span.txt - * @property {Element} FONT_TOOLTIP font family tooltip element - * @property {Element} SIZE font size button > span.txt - * @property {Element} ALIGN align button > div.icon - * @property {Element} LI list button + * After creating the editor, "commandPlugins" are added. * @property {Element} STRONG bold button * @property {Element} INS underline button * @property {Element} EM italic button @@ -442,14 +442,6 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { this.getSelection().removeAllRanges(); const commandMap = this.commandMap; - util.changeTxt(commandMap.FORMAT, lang.toolbar.formats); - util.changeTxt(commandMap.FORMAT_TOOLTIP, lang.toolbar.formats); - util.changeTxt(commandMap.FONT, lang.toolbar.font); - util.changeTxt(commandMap.FONT_TOOLTIP, lang.toolbar.font); - util.changeTxt(commandMap.SIZE, lang.toolbar.fontSize); - util.removeClass(commandMap.LI_ICON, 'se-icon-list-bullets'); - util.addClass(commandMap.LI_ICON, 'se-icon-list-number'); - util.removeClass(commandMap.LI, 'active'); util.removeClass(commandMap.STRONG, 'active'); util.removeClass(commandMap.INS, 'active'); util.removeClass(commandMap.EM, 'active'); @@ -458,11 +450,6 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { util.removeClass(commandMap.SUP, 'active'); if (commandMap.OUTDENT) commandMap.OUTDENT.setAttribute('disabled', true); - if (commandMap.LI) commandMap.LI.removeAttribute('data-focus'); - if (commandMap.ALIGN) { - commandMap.ALIGN.className = 'se-icon-align-left'; - commandMap.ALIGN.removeAttribute('data-focus'); - } }, /** @@ -3350,22 +3337,12 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { this._isInline = /inline/i.test(context.option.mode); this._isBalloon = /balloon/i.test(context.option.mode); - Object.keys(plugins).forEach(function (key) { - if (plugins[key].command === 'command') { - core.callPlugin(key, null); - } - }); - this.commandMap = { - BLOCKQUOTE: this.plugins.blockquote, - FORMAT: context.tool.format, - FORMAT_TOOLTIP: context.tool.formatTooltip, - FONT: context.tool.font, - FONT_TOOLTIP: context.tool.fontTooltip, - SIZE: context.tool.fontSize, - ALIGN: context.tool.align, LI: context.tool.list, LI_ICON: context.tool.list && context.tool.list.querySelector('i'), + SIZE: context.tool.fontSize, + ALIGN: context.tool.align, + STRONG: context.tool.bold, INS: context.tool.underline, EM: context.tool.italic, @@ -3375,6 +3352,21 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { OUTDENT: context.tool.outdent }; + // Command plugins registration + const commandPlugins = []; + Object.keys(plugins).forEach(function (key) { + const c = plugins[key]; + const button = pluginCallButtons[key]; + if (button) { + core.callPlugin(key, button); + if (c.active) { + core.commandMap[c.name] = button; + commandPlugins.push(c.name); + } + } + }); + this.commandPlugins = commandPlugins; + this._variable._originCssText = context.element.topArea.style.cssText; this._placeholder = context.element.placeholder; @@ -3496,6 +3488,9 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { const commandMapNodes = []; const currentNodes = []; + const commandPlugins = core.commandPlugins; + const cLen = commandPlugins.length; + let findBlockquote = true, findFormat = true, findAlign = true, findList = true, findFont = true, findSize = true, findOutdent = true, findA = true; let nodeName = ''; @@ -3505,24 +3500,15 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { nodeName = selectionParent.nodeName.toUpperCase(); currentNodes.push(nodeName); - /** Range format */ - /* Blockquote */ - if (findBlockquote && /blockquote/i.test(selectionParent.nodeName) && commandMap.BLOCKQUOTE) { - commandMap.BLOCKQUOTE.active.call(core, true); - commandMapNodes.push('BLOCKQUOTE'); - findBlockquote = false; + /* Command plugins */ + for (let c = 0, name; c < cLen; c++) { + name = commandPlugins[c]; + if (commandMapNodes.indexOf(name) < 0 && plugins[name].active.call(core, selectionParent)) { + commandMapNodes.push(name); + } } - /** Format */ if (util.isFormatElement(selectionParent)) { - /* Format block */ - if (findFormat && commandMap.FORMAT) { - core.callPlugin('formatBlock', function () { - if (core.plugins.formatBlock.active.call(core, selectionParent)) commandMapNodes.push('FORMAT'); - }); - findFormat = false; - } - /* Align */ const textAlign = selectionParent.style.textAlign; if (findAlign && textAlign && commandMap.ALIGN) { @@ -3602,16 +3588,8 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { for (let key in commandMap) { if (commandMapNodes.indexOf(key) > -1) continue; - if (commandMap.BLOCKQUOTE && /^BLOCKQUOTE$/i.test(key)) { - commandMap.BLOCKQUOTE.active.call(core, false); - } - else if (commandMap.FORMAT && /^FORMAT$/i.test(key)) { - util.changeTxt(commandMap.FORMAT, lang.toolbar.formats); - util.changeTxt(commandMap.FORMAT_TOOLTIP, lang.toolbar.formats); - } - else if (commandMap.FONT && /^FONT$/i.test(key)) { - util.changeTxt(commandMap.FONT, lang.toolbar.font); - util.changeTxt(commandMap.FONT_TOOLTIP, lang.toolbar.font); + if (commandPlugins.indexOf(key) > -1) { + plugins[key].active.call(core, null); } else if (commandMap.SIZE && /^SIZE$/i.test(key)) { util.changeTxt(commandMap.SIZE, lang.toolbar.fontSize); diff --git a/src/plugins/command/blockquote.js b/src/plugins/command/blockquote.js index 88286785c..808873823 100644 --- a/src/plugins/command/blockquote.js +++ b/src/plugins/command/blockquote.js @@ -13,11 +13,22 @@ export default { add: function (core, targetElement) { const context = core.context; context.blockquote = { - commandButton: targetElement, + targetButton: targetElement, tag: core.util.createElement('BLOCKQUOTE') }; }, + active: function (element) { + if (!element) { + this.util.removeClass(this.context.blockquote.targetButton, 'active'); + } else if (/blockquote/i.test(element.nodeName)) { + this.util.addClass(this.context.blockquote.targetButton, 'active'); + return true; + } + + return false; + }, + action: function () { const currentBlockquote = this.util.getParentElement(this.getSelectionNode(), 'blockquote'); @@ -26,15 +37,5 @@ export default { } else { this.applyRangeFormatElement(this.context.blockquote.tag.cloneNode(false)); } - }, - - active: function (element) { - if (!!element && /blockquote/i.test(element.nodeName)) { - this.util.addClass(this.context.blockquote.commandButton, 'active'); - return true; - } else { - this.util.removeClass(this.context.blockquote.commandButton, 'active'); - return false; - } } }; \ No newline at end of file diff --git a/src/plugins/submenu/font.js b/src/plugins/submenu/font.js index 7658b2b97..cbef8ece5 100644 --- a/src/plugins/submenu/font.js +++ b/src/plugins/submenu/font.js @@ -12,6 +12,8 @@ export default { add: function (core, targetElement) { const context = core.context; context.font = { + targetText: targetElement.querySelector('.txt'), + targetTooltip: targetElement.parentNode.querySelector('.se-tooltip-text'), _fontList: null, currentFont: '' }; @@ -65,10 +67,28 @@ export default { return listDiv; }, + active: function (element) { + const target = this.context.font.targetText; + const tooltip = this.context.font.targetTooltip; + + if (!element) { + const font = this.lang.toolbar.font; + this.util.changeTxt(target, font); + this.util.changeTxt(tooltip, font); + } else if (element.style.fontFamily.length > 0) { + const selectFont = element.style.fontFamily.replace(/["']/g,''); + this.util.changeTxt(target, selectFont); + this.util.changeTxt(tooltip, selectFont); + return true; + } + + return false; + }, + on: function () { const fontContext = this.context.font; const fontList = fontContext._fontList; - const currentFont = this.commandMap.FONT.textContent; + const currentFont = fontContext.targetText.textContent; if (currentFont !== fontContext.currentFont) { for (let i = 0, len = fontList.length; i < len; i++) { diff --git a/src/plugins/submenu/formatBlock.js b/src/plugins/submenu/formatBlock.js index 2451fc066..06f35d9a4 100644 --- a/src/plugins/submenu/formatBlock.js +++ b/src/plugins/submenu/formatBlock.js @@ -12,6 +12,8 @@ export default { add: function (core, targetElement) { const context = core.context; context.formatBlock = { + targetText: targetElement.querySelector('.txt'), + targetTooltip: targetElement.parentNode.querySelector('.se-tooltip-text'), _formatList: null, currentFormat: '' }; @@ -72,32 +74,43 @@ export default { }, active: function (element) { - const formatContext = this.context.formatBlock; - const formatList = formatContext._formatList; - const nodeName = element.nodeName.toLowerCase(); - const className = (element.className.match(/(\s|^)__se__format__[^\s]+/) || [''])[0].trim(); - let formatTitle = this.lang.formats; - - for (let i = 0, len = formatList.length, f; i < len; i++) { - f = formatList[i]; - if (nodeName === f.getAttribute('data-value') && className === f.getAttribute('data-class')) { - formatTitle = f.title; - break; + let formatTitle = this.lang.toolbar.formats; + const target = this.context.formatBlock.targetText; + const tooltip = this.context.formatBlock.targetTooltip; + + if (!element) { + this.util.changeTxt(target, formatTitle); + this.util.changeTxt(tooltip, formatTitle); + } else if (this.util.isFormatElement(element)) { + const formatContext = this.context.formatBlock; + const formatList = formatContext._formatList; + const nodeName = element.nodeName.toLowerCase(); + const className = (element.className.match(/(\s|^)__se__format__[^\s]+/) || [''])[0].trim(); + + for (let i = 0, len = formatList.length, f; i < len; i++) { + f = formatList[i]; + if (nodeName === f.getAttribute('data-value') && className === f.getAttribute('data-class')) { + formatTitle = f.title; + break; + } } - } - this.util.changeTxt(this.commandMap.FORMAT, formatTitle); - this.util.changeTxt(this.commandMap.FORMAT_TOOLTIP, formatTitle); - this.commandMap.FORMAT.setAttribute('data-value', nodeName); - this.commandMap.FORMAT.setAttribute('data-class', className); + this.util.changeTxt(target, formatTitle); + this.util.changeTxt(tooltip, formatTitle); + target.setAttribute('data-value', nodeName); + target.setAttribute('data-class', className); + + return true; + } - return formatTitle !== this.lang.formats; + return false; }, on: function () { const formatContext = this.context.formatBlock; const formatList = formatContext._formatList; - const currentFormat = (this.commandMap.FORMAT.getAttribute('data-value') || '') + (this.commandMap.FORMAT.getAttribute('data-class') || ''); + const target = formatContext.targetText; + const currentFormat = (target.getAttribute('data-value') || '') + (target.getAttribute('data-class') || ''); if (currentFormat !== formatContext.currentFormat) { for (let i = 0, len = formatList.length, f; i < len; i++) { diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index d14342bb0..49250bbd4 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -21,7 +21,7 @@ const align = require('../../src/plugins/submenu/align') let s1 = suneditor.create('editor', { plugins: plugins, // mode: 'balloon', - buttonList: [['blockquote'],['table', 'align', 'link', 'bold', 'underline', 'italic', 'strike', 'fontColor', 'hiliteColor', 'removeFormat', 'formatBlock', 'codeView', 'preview']], + buttonList: [['blockquote', 'font'],['table', 'align', 'link', 'bold', 'underline', 'italic', 'strike', 'fontColor', 'hiliteColor', 'removeFormat', 'formatBlock', 'codeView', 'preview']], width: '100%', pasteTagsWhitelist: 'p|h[1-6]', formats: [ From 5c131988ce5be5a828e02f272f43166369755bee Mon Sep 17 00:00:00 2001 From: Himalay Date: Tue, 18 Feb 2020 16:31:11 +0545 Subject: [PATCH 26/99] Add Math support using KaTeX --- src/lang/en.js | 7 + src/lang/ko.js | 7 + src/lib/constructor.js | 3 + src/lib/core.js | 14 +- src/plugins/dialog/math.js | 280 +++++++++++++++++++++++++++++++++++++ src/plugins/index.js | 5 +- 6 files changed, 313 insertions(+), 3 deletions(-) create mode 100644 src/plugins/dialog/math.js diff --git a/src/lang/en.js b/src/lang/en.js index d3594eb24..c267c6831 100644 --- a/src/lang/en.js +++ b/src/lang/en.js @@ -53,6 +53,7 @@ hr_dashed: 'Dashed', table: 'Table', link: 'Link', + math: 'math', image: 'Image', video: 'Video', fullScreen: 'Full screen', @@ -79,6 +80,12 @@ text: 'Text to display', newWindowCheck: 'Open in new window' }, + mathBox: { + title: 'Math', + inputLabel: 'Mathematical Notation', + fontSizeLabel: 'Font Size', + previewLabel: 'Preview' + }, imageBox: { title: 'Insert image', file: 'Select from files', diff --git a/src/lang/ko.js b/src/lang/ko.js index c45fcf5ba..587f60edb 100644 --- a/src/lang/ko.js +++ b/src/lang/ko.js @@ -53,6 +53,7 @@ hr_dashed: '대시', table: '테이블', link: '링크', + math: '수학', image: '이미지', video: '동영상', fullScreen: '전체 화면', @@ -79,6 +80,12 @@ text: '화면 텍스트', newWindowCheck: '새창으로 열기' }, + mathBox: { + title: '수학', + inputLabel: '수학적 표기법', + fontSizeLabel: '폰트 크기', + previewLabel: '시사' + }, imageBox: { title: '이미지 삽입', file: '파일 선택', diff --git a/src/lib/constructor.js b/src/lib/constructor.js index 835e34ce4..645e4e053 100755 --- a/src/lib/constructor.js +++ b/src/lib/constructor.js @@ -576,6 +576,9 @@ export default { video: ['', lang.toolbar.video, 'video', 'dialog', '' + ], + math: ['', lang.toolbar.math, 'math', 'dialog', + '' ] }; }, diff --git a/src/lib/core.js b/src/lib/core.js index be50f4540..dbe66ce43 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -3466,7 +3466,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { const commandMapNodes = []; const currentNodes = []; - let findFormat = true, findAlign = true, findList = true, findFont = true, findSize = true, findOutdent = true, findA = true; + let findFormat = true, findAlign = true, findList = true, findFont = true, findSize = true, findOutdent = true, findA = true, findMath = true; let nodeName = ''; for (let selectionParent = core.getSelectionNode(); !util.isWysiwygDiv(selectionParent); selectionParent = selectionParent.parentNode) { @@ -3547,6 +3547,18 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { core.controllersOff(); } + /** Math */ + if (findMath && core.plugins.math && selectionParent.getAttribute('data-exp')) { + if (!context.math || core.controllerArray[0] !== context.math.mathBtn) { + core.callPlugin('math', function () { + core.plugins.math.call_controller_mathButton.call(core, selectionParent); + }); + } + findMath = false; + } else if (findMath && context.math && core.controllerArray[0] === context.math.mathBtn) { + core.controllersOff(); + } + /** strong, ins, em, del, sub, sup */ if (classOnCheck.test(nodeName)) { commandMapNodes.push(nodeName); diff --git a/src/plugins/dialog/math.js b/src/plugins/dialog/math.js new file mode 100644 index 000000000..cb0940522 --- /dev/null +++ b/src/plugins/dialog/math.js @@ -0,0 +1,280 @@ +'use strict'; + +import dialog from '../modules/dialog'; + +const katexJsSrc = 'https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.js'; +const katexCssSrc = 'https://cdn.jsdelivr.net/npm/katex@0.11.1/dist/katex.min.css'; + +const script = document.createElement('script'); +script.type = 'text/javascript'; +script.src = katexJsSrc; + +const link = document.createElement('link'); +link.rel = 'stylesheet'; +link.href = katexCssSrc; + +document.head.appendChild(link); +document.head.appendChild(script); + +const htmlMathString = function (exp) { + return window.katex.renderToString(exp, { + throwOnError: false, + }); +} + +export default { + name: 'math', + add: function (core) { + core.addModule([dialog]); + + const context = core.context; + context.math = { + focusElement: null, + previewElement: null, + fontSizeElement: null, + _mathExp: null + }; + + /** math dialog */ + let math_dialog = this.setDialog.call(core); + context.math.modal = math_dialog; + context.math.focusElement = math_dialog.querySelector('._se_math_exp'); + context.math.previewElement = math_dialog.querySelector('._se_math_preview'); + context.math.fontSizeElement = math_dialog.querySelector('._se_math_size'); + + const renderMathExp = function () { + context.math.previewElement.innerHTML = htmlMathString(this.value); + }; + + context.math.focusElement.onkeyup = renderMathExp; + context.math.focusElement.onchange = renderMathExp; + + context.math.fontSizeElement.onchange = function () { + context.math.previewElement.style.fontSize = this.value; + }; + + /** math button */ + let math_button = this.setController_MathButton.call(core); + context.math.mathBtn = math_button; + context.math._mathExp = null; + math_button.addEventListener('mousedown', function (e) { e.stopPropagation(); }, false); + + /** add event listeners */ + math_dialog.querySelector('.se-btn-primary').addEventListener('click', this.submit.bind(core)); + math_button.addEventListener('click', this.onClick_mathBtn.bind(core)); + + /** append html */ + context.dialog.modal.appendChild(math_dialog); + context.element.relative.appendChild(math_button); + + /** empty memory */ + math_dialog = null, math_button = null; + }, + + /** dialog */ + setDialog: function () { + const lang = this.lang; + const dialog = this.util.createElement('DIV'); + + dialog.className = 'se-dialog-content'; + dialog.style.display = 'none'; + dialog.innerHTML = ` +
    +
    + + ${lang.dialogBox.mathBox.title} +
    +
    +
    + + +
    +
    + + +
    +
    + +

    +
    +
    + +
    + `; + + return dialog; + }, + + /** modify controller button */ + setController_MathButton: function () { + const lang = this.lang; + const math_btn = this.util.createElement('DIV'); + + math_btn.className = 'se-controller se-controller-link'; + math_btn.innerHTML = ` +
    + + `; + + return math_btn; + }, + + submit: function (e) { + this.showLoading(); + + e.preventDefault(); + e.stopPropagation(); + + const submitAction = function () { + if (this.context.math.focusElement.value.trim().length === 0) return false; + + const contextMath = this.context.math; + const mathExp = contextMath.focusElement.value; + const katexEl = new this._w.DOMParser() + .parseFromString(contextMath.previewElement.innerHTML, 'text/html') + .querySelector('.katex'); + katexEl.setAttribute('data-exp', mathExp); + katexEl.setAttribute('data-font-size', contextMath.fontSizeElement.value); + katexEl.style.fontSize = contextMath.fontSizeElement.value; + + if (!this.context.dialog.updateModal) { + const selectedFormats = this.getSelectedElements(); + + if (selectedFormats.length > 1) { + const oFormat = this.util.createElement(selectedFormats[0].nodeName); + oFormat.appendChild(katexEl); + this.insertNode(oFormat); + } else { + this.insertNode(katexEl); + } + + const empty = this.util.createTextNode(this.util.zeroWidthSpace); + katexEl.parentNode.insertBefore(empty, katexEl.nextSibling); + } else { + const findParent = (child, className) => { + if (child.classList.contains(className)) return child; + + const parent = child.parentNode; + + if (parent === document.body) return; + + if (parent.classList.contains(className)) { + return parent; + } else { + findParent(parent, className); + } + }; + const containerEl = findParent(contextMath._mathExp, 'katex'); + containerEl.parentNode.replaceChild(katexEl, containerEl); + } + + // history stack + this.history.push(false); + + contextMath.focusElement.value = ''; + contextMath.fontSizeElement.value = '1em'; + contextMath.previewElement.style.fontSize = '1em'; + contextMath.previewElement.innerHTML = ''; + }.bind(this); + + try { + submitAction(); + } finally { + this.plugins.dialog.close.call(this); + this.closeLoading(); + this.focus(); + } + + return false; + }, + + on: function (update) { + if (this.context.math._mathExp && update) { + const exp = this.context.math._mathExp.getAttribute('data-exp'); + const fontSize = this.context.math._mathExp.getAttribute('data-font-size') || '1em'; + + this.context.dialog.updateModal = true; + this.context.math.focusElement.value = exp; + this.context.math.fontSizeElement.value = fontSize; + this.context.math.previewElement.innerHTML = htmlMathString(exp); + this.context.math.previewElement.style.fontSize = fontSize; + } + }, + + call_controller_mathButton: function (selectionATag) { + this.editMath = this.context.math._mathExp = selectionATag; + const mathBtn = this.context.math.mathBtn; + + const offset = this.util.getOffset(selectionATag, this.context.element.wysiwygFrame); + mathBtn.style.top = (offset.top + selectionATag.offsetHeight + 10) + 'px'; + mathBtn.style.left = (offset.left - this.context.element.wysiwygFrame.scrollLeft) + 'px'; + + mathBtn.style.display = 'block'; + + const overLeft = this.context.element.wysiwygFrame.offsetWidth - (mathBtn.offsetLeft + mathBtn.offsetWidth); + if (overLeft < 0) { + mathBtn.style.left = (mathBtn.offsetLeft + overLeft) + 'px'; + mathBtn.firstElementChild.style.left = (20 - overLeft) + 'px'; + } else { + mathBtn.firstElementChild.style.left = '20px'; + } + + this.controllersOn(mathBtn, this.plugins.math.init.bind(this)); + }, + + onClick_mathBtn: function (e) { + e.stopPropagation(); + + const command = e.target.getAttribute('data-command') || e.target.parentNode.getAttribute('data-command'); + if (!command) return; + + e.preventDefault(); + + if (/update/.test(command)) { + this.context.math.focusElement.value = this.context.math._mathExp.getAttribute('data-exp'); + this.plugins.dialog.open.call(this, 'math', true); + } else if (/unlink/.test(command)) { + // do nothing + } else { + /** delete */ + this.util.removeItem(this.context.math._mathExp); + this.context.math._mathExp = null; + this.focus(); + + // history stack + this.history.push(false); + } + + this.controllersOff(); + }, + + init: function () { + if (!/math/i.test(this.context.dialog.kind)) { + const contextMath = this.context.math; + contextMath.mathBtn.style.display = 'none'; + contextMath._mathExp = null; + contextMath.focusElement.value = ''; + contextMath.previewElement.innerHTML = ''; + } + } +}; diff --git a/src/plugins/index.js b/src/plugins/index.js index 23ee98c3c..ad46a73eb 100644 --- a/src/plugins/index.js +++ b/src/plugins/index.js @@ -17,6 +17,7 @@ import textStyle from './submenu/textStyle'; import link from './dialog/link'; import image from './dialog/image'; import video from './dialog/video'; +import math from './dialog/math'; -export { align, font, fontSize, fontColor, hiliteColor, horizontalRule, list, table, formatBlock, lineHeight, template, paragraphStyle, textStyle, link, image, video }; -export default { align, font, fontSize, fontColor, hiliteColor, horizontalRule, list, table, formatBlock, lineHeight, template, paragraphStyle, textStyle, link, image, video }; \ No newline at end of file +export { align, font, fontSize, fontColor, hiliteColor, horizontalRule, list, table, formatBlock, lineHeight, template, paragraphStyle, textStyle, link, image, video, math }; +export default { align, font, fontSize, fontColor, hiliteColor, horizontalRule, list, table, formatBlock, lineHeight, template, paragraphStyle, textStyle, link, image, video, math }; \ No newline at end of file From 3ce4ce265b766341e90bd14ba2a5007729d87dc7 Mon Sep 17 00:00:00 2001 From: Himalay Date: Tue, 18 Feb 2020 16:31:25 +0545 Subject: [PATCH 27/99] Add math example --- test/dev/suneditor_build_test.html | 22 ++++++++++++++++++++++ test/dev/suneditor_build_test.js | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/test/dev/suneditor_build_test.html b/test/dev/suneditor_build_test.html index 759d98f9f..8d7e0e144 100644 --- a/test/dev/suneditor_build_test.html +++ b/test/dev/suneditor_build_test.html @@ -138,6 +138,28 @@
    - -
    - - -
    -
    - -

    -
    - - - - `; + dialog.innerHTML = '' + + '
    ' + + '
    ' + + '' + + '' + lang.dialogBox.mathBox.title + '' + + '
    ' + + '
    ' + + '
    ' + + '' + + '' + + '
    ' + + '
    ' + + '' + + '' + + '
    ' + + '
    ' + + '' + + '

    ' + + '
    ' + + '
    ' + + '' + + '
    ' + + ''; return dialog; }, @@ -120,21 +120,21 @@ export default { const math_btn = this.util.createElement('DIV'); math_btn.className = 'se-controller se-controller-link'; - math_btn.innerHTML = ` -
    - - `; + math_btn.innerHTML = '' + + '
    ' + + '' + + ''; return math_btn; }, @@ -150,9 +150,7 @@ export default { const contextMath = this.context.math; const mathExp = contextMath.focusElement.value; - const katexEl = new this._w.DOMParser() - .parseFromString(contextMath.previewElement.innerHTML, 'text/html') - .querySelector('.katex'); + const katexEl = contextMath.previewElement.querySelector('.katex'); katexEl.setAttribute('data-exp', mathExp); katexEl.setAttribute('data-font-size', contextMath.fontSizeElement.value); katexEl.style.fontSize = contextMath.fontSizeElement.value; @@ -171,7 +169,7 @@ export default { const empty = this.util.createTextNode(this.util.zeroWidthSpace); katexEl.parentNode.insertBefore(empty, katexEl.nextSibling); } else { - const findParent = (child, className) => { + const findParent = function (child, className) { if (child.classList.contains(className)) return child; const parent = child.parentNode; From 5d89975606bc4ad1f47e947b1692164b6f23ec57 Mon Sep 17 00:00:00 2001 From: Himalay Date: Wed, 19 Feb 2020 14:31:37 +0545 Subject: [PATCH 31/99] Add smaller math example --- test/dev/suneditor_build_test.html | 24 +----------------------- 1 file changed, 1 insertion(+), 23 deletions(-) diff --git a/test/dev/suneditor_build_test.html b/test/dev/suneditor_build_test.html index 8d7e0e144..ac51bbfd1 100644 --- a/test/dev/suneditor_build_test.html +++ b/test/dev/suneditor_build_test.html @@ -138,29 +138,7 @@
    ' + + '' + '' + '
    ' + '' + - '' + + '' + + '' + + '' + + '' + '' + '
    ' + '
    ' + '' + - '

    ' + + '

    ' + '
    ' + '' + '' + '
    ' + '
    ' + - '' + + '' + '' + '
    ' + '
    ' + - '' + + '' + '' + '
    ' + '
    ' + - '' + + '' + '

    ' + '
    ' + '
    ' + @@ -133,6 +133,8 @@ export default { const contextMath = this.context.math; const mathExp = contextMath.focusElement.value; const katexEl = contextMath.previewElement.querySelector('.katex'); + + if (!katexEl) return; katexEl.setAttribute('data-exp', mathExp); katexEl.setAttribute('data-font-size', contextMath.fontSizeElement.value); katexEl.style.fontSize = contextMath.fontSizeElement.value; @@ -150,6 +152,7 @@ export default { const empty = this.util.createTextNode(this.util.zeroWidthSpace); katexEl.parentNode.insertBefore(empty, katexEl.nextSibling); + this.setRange(katexEl, 0, katexEl, 1); } else { const findParent = function (child, className) { if (child.classList.contains(className)) return child; @@ -166,7 +169,7 @@ export default { }; const containerEl = findParent(contextMath._mathExp, 'katex'); containerEl.parentNode.replaceChild(katexEl, containerEl); - this.setRange(katexEl.childNodes[0], 0, katexEl.childNodes[0], 1); + this.setRange(katexEl, 0, katexEl, 1); } // history stack From 7b470134453c4ce6f5b3681f12986212c2a67a01 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Thu, 20 Feb 2020 02:29:10 +0900 Subject: [PATCH 35/99] modify: math plugin --- src/lib/core.js | 4 +++- src/lib/util.js | 2 +- src/plugins/dialog/math.js | 21 ++++++++++++++------- src/plugins/submenu/font.js | 2 +- src/plugins/submenu/fontSize.js | 2 +- test/dev/suneditor_build_test.html | 2 +- 6 files changed, 21 insertions(+), 12 deletions(-) diff --git a/src/lib/core.js b/src/lib/core.js index 79c5f4787..5f55e83f3 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -1188,7 +1188,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { let endOff = range.endOffset; let tempCon, tempOffset, tempChild; - if (isRemoveFormat && range.collapsed && util.isFormatElement(startCon.parentNode) && util.isFormatElement(endCon.parentNode)) { + if ((isRemoveFormat && range.collapsed && util.isFormatElement(startCon.parentNode) && util.isFormatElement(endCon.parentNode)) || util._isIgnoreNodeChange(range.commonAncestorContainer)) { return; } @@ -1283,6 +1283,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (!onlyBreak) { while (tempCon && !util.isBreak(tempCon) && tempCon.nodeType === 1) { tempChild = tempCon.childNodes; + if (tempChild.length === 0) break; tempCon = tempChild[tempOffset > 0 ? tempOffset - 1 : tempOffset] || !/FIGURE/i.test(tempChild[0].nodeName) ? tempChild[0] : (tempCon.previousElementSibling || tempCon.previousSibling || startCon); tempOffset = tempOffset > 0 ? tempCon.textContent.length : tempOffset; } @@ -1527,6 +1528,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { child = children[i]; next = children[i + 1]; if (!child) break; + if(inst.util._isIgnoreNodeChange(child)) continue; if (len === 1 && current.nodeName === child.nodeName) { inst.util.copyTagAttributes(child, current); current.parentNode.replaceChild(child, current); diff --git a/src/lib/util.js b/src/lib/util.js index 2d2c83524..01981e500 100755 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -1107,7 +1107,7 @@ const util = { * @private */ _isIgnoreNodeChange: function (element) { - return element.nodeType !== 3 && !/^(span|font|b|strong|var|i|em|u|ins|s|strike|del|sub|sup|mark|a|label)$/i.test(element.nodeName); + return element.nodeType !== 3 && (!!element.getAttribute('data-ignore-node') || !/^(span|font|b|strong|var|i|em|u|ins|s|strike|del|sub|sup|mark|a|label)$/i.test(element.nodeName)); }, /** diff --git a/src/plugins/dialog/math.js b/src/plugins/dialog/math.js index 3ce0f7f77..0d9a6d0c4 100644 --- a/src/plugins/dialog/math.js +++ b/src/plugins/dialog/math.js @@ -38,7 +38,7 @@ export default { math_button.addEventListener('mousedown', function (e) { e.stopPropagation(); }, false); /** add event listeners */ - math_dialog.querySelector('.se-btn-primary').addEventListener('click', this.submit.bind(core)); + math_dialog.querySelector('.se-btn-primary').addEventListener('click', this.submit.bind(core), false); math_button.addEventListener('click', this.onClick_mathBtn.bind(core)); /** append html */ @@ -86,8 +86,7 @@ export default { '' + - '' + - ''; + ''; return dialog; }, @@ -134,7 +133,8 @@ export default { const mathExp = contextMath.focusElement.value; const katexEl = contextMath.previewElement.querySelector('.katex'); - if (!katexEl) return; + if (!katexEl) return false; + katexEl.setAttribute('data-ignore-node', true); katexEl.setAttribute('data-exp', mathExp); katexEl.setAttribute('data-font-size', contextMath.fontSizeElement.value); katexEl.style.fontSize = contextMath.fontSizeElement.value; @@ -179,14 +179,20 @@ export default { contextMath.fontSizeElement.value = '1em'; contextMath.previewElement.style.fontSize = '1em'; contextMath.previewElement.innerHTML = ''; + + return true; }.bind(this); try { - submitAction(); - } finally { + if (submitAction()) { + this.plugins.dialog.close.call(this); + this.focus(); + } + } catch (e) { this.plugins.dialog.close.call(this); - this.closeLoading(); this.focus(); + } finally { + this.closeLoading(); } return false; @@ -197,6 +203,7 @@ export default { if (this.controllerArray[0] === this.context.math.mathBtn) this.controllersOff(); } else if (element.getAttribute('data-exp')) { if (this.controllerArray[0] !== this.context.math.mathBtn) { + this.setRange(element, 0, element, 1); this.plugins.math.call_controller_mathButton.call(this, element); return true; } diff --git a/src/plugins/submenu/font.js b/src/plugins/submenu/font.js index 83609ebff..ada1e80c3 100644 --- a/src/plugins/submenu/font.js +++ b/src/plugins/submenu/font.js @@ -76,7 +76,7 @@ export default { const font = this.lang.toolbar.font; this.util.changeTxt(target, font); this.util.changeTxt(tooltip, font); - } else if (element.style.fontFamily.length > 0) { + } else if (element.style && element.style.fontFamily.length > 0) { const selectFont = element.style.fontFamily.replace(/["']/g,''); this.util.changeTxt(target, selectFont); this.util.changeTxt(tooltip, selectFont); diff --git a/src/plugins/submenu/fontSize.js b/src/plugins/submenu/fontSize.js index 78867e4fe..bb8528781 100644 --- a/src/plugins/submenu/fontSize.js +++ b/src/plugins/submenu/fontSize.js @@ -60,7 +60,7 @@ export default { active: function (element) { if (!element) { this.util.changeTxt(this.context.fontSize.targetText, this.lang.toolbar.fontSize); - } else if (element.style.fontSize.length > 0) { + } else if (element.style && element.style.fontSize.length > 0) { this.util.changeTxt(this.context.fontSize.targetText, element.style.fontSize); return true; } diff --git a/test/dev/suneditor_build_test.html b/test/dev/suneditor_build_test.html index 9da6e3ce1..ad92386c4 100644 --- a/test/dev/suneditor_build_test.html +++ b/test/dev/suneditor_build_test.html @@ -141,7 +141,7 @@
    + +
    + +
    diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index 0262c1620..7e1724d18 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -21,6 +21,18 @@ import Katex from 'katex'; const align = require('../../src/plugins/submenu/align') + +suneditor.create("sample1", { + plugins: plugins, + mode: "balloon", + buttonList: [ + ["undo", "redo"], + ["font", "fontSize", "formatBlock"], + ["paragraphStyle", "table"] + ] +}); + + let s1 = suneditor.create('editor', { plugins: plugins, mode: 'balloon', @@ -82,6 +94,7 @@ window.sun_create1 = function () { let ss = window.ss = suneditor.create(document.getElementById('editor1'), { // lang: lang.ko, plugins: plugins, + mode: 'balloon', buttonList: [ ['undo', 'redo', 'font', 'fontSize', 'formatBlock', @@ -190,7 +203,7 @@ window.sun_getContents = function () { } window.sun_setContents = function (content) { - ss.setContents(''); + ss.setContents('



    '); ss.core.history.reset(true); // ss.core.context.tool.save.disabled = true; } From 2579674e3f1c15138e2624b758a8b0be2e039ea2 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Mon, 24 Feb 2020 02:10:05 +0900 Subject: [PATCH 45/99] update: #217 nested lists --- src/assets/css/suneditor.css | 30 ++++++------- src/lib/core.js | 17 +++++--- src/plugins/submenu/list.js | 74 +++++++++++++++++++++++++------- test/dev/suneditor_build_test.js | 26 ++++++++--- 4 files changed, 106 insertions(+), 41 deletions(-) diff --git a/src/assets/css/suneditor.css b/src/assets/css/suneditor.css index da7cf8e53..7225673ef 100755 --- a/src/assets/css/suneditor.css +++ b/src/assets/css/suneditor.css @@ -137,11 +137,11 @@ .sun-editor button {color:#000;} /** --- se-btn button */ -.sun-editor .se-btn {float:left; width:35px; height:35px; border:0; border-radius:4px; margin:1px !important; padding:0; font-size:12px; line-height:27px;} +.sun-editor .se-btn {float:left; width:35px; height:35px; border:0; border-radius:3px; margin:1px !important; padding:0; font-size:12px; line-height:27px;} .sun-editor .se-btn:enabled:hover, .sun-editor .se-btn:enabled:focus {background-color:#e1e1e1; border-color:#d1d1d1; outline:0 none;} .sun-editor .se-btn:enabled:active {background-color:#d1d1d1; border-color:#c1c1c1; -webkit-box-shadow:inset 0 3px 5px #c1c1c1; box-shadow:inset 0 3px 5px #c1c1c1;} /** --- primary button */ -.sun-editor .se-btn-primary {color:#000; background-color:#c7deff; border:1px solid #80bdff; border-radius:4px;} +.sun-editor .se-btn-primary {color:#000; background-color:#c7deff; border:1px solid #80bdff; border-radius:3px;} .sun-editor .se-btn-primary:hover, .sun-editor .se-btn-primary:focus {color:#000; background-color:#80bdff; border-color:#3f9dff; outline:0 none;} .sun-editor .se-btn-primary:active {color:#fff; background-color:#3f9dff; border-color:#4592ff; -webkit-box-shadow:inset 0 3px 5px #4592ff; box-shadow:inset 0 3px 5px #4592ff;} @@ -174,7 +174,7 @@ /** --- tool bar module group ---------------------------------------------------------- */ .sun-editor .se-btn-module {display:inline-block;} -.sun-editor .se-btn-module-border {border:1px solid #dadada; border-radius:4px;} +.sun-editor .se-btn-module-border {border:1px solid #dadada; border-radius:3px;} .sun-editor .se-btn-module-enter {display:block; width:100%; height:1px; margin-bottom:5px; background-color:transparent;} /* module innser ul */ .sun-editor .se-menu-list {float:left; padding:0; margin:0;} @@ -188,7 +188,7 @@ .sun-editor .se-btn-select.se-btn-tool-size {width:80px;} /** --- submenu layer ---------------------------------------------------------- */ -.sun-editor .se-list-layer {display:none; position:absolute; top:37px; z-index:4; left:1px; border:1px solid #bababa; border-radius:4px; padding:5px 0; background-color:#fff; -webkit-box-shadow:0 3px 9px rgba(0, 0, 0, .5); box-shadow:0 3px 9px rgba(0, 0, 0, .5); outline:0 none;} +.sun-editor .se-list-layer {display:none; position:absolute; top:37px; z-index:4; left:1px; border:1px solid #bababa; border-radius:3px; padding:5px 0; background-color:#fff; -webkit-box-shadow:0 3px 9px rgba(0, 0, 0, .5); box-shadow:0 3px 9px rgba(0, 0, 0, .5); outline:0 none;} .sun-editor .se-list-layer .se-list-inner {padding:0; margin:0; overflow-x:initial; overflow-y:initial; overflow:visible;} .sun-editor .se-list-layer button {margin:0; width:100%;} /* submenu layer - common list form */ @@ -222,7 +222,7 @@ .sun-editor .se-list-layer .se-list-format h5 {font-size:0.83em; font-weight:bold; color:#333;} .sun-editor .se-list-layer .se-list-format h6 {font-size:0.67em; font-weight:bold; color:#333;} .sun-editor .se-list-layer .se-list-format blockquote {font-size:13px; color:#999; height:22px; margin:0; background-color:transparent; line-height:1.5; border-style:solid; border-color:#b1b1b1; padding:0 0 0 7px; border-left-width:5px;} -.sun-editor .se-list-layer .se-list-format pre {font-size:13px; color:#666; padding:4px 11px; margin:0; background-color:#f9f9f9; border:1px solid #e1e1e1; border-radius:4px;} +.sun-editor .se-list-layer .se-list-format pre {font-size:13px; color:#666; padding:4px 11px; margin:0; background-color:#f9f9f9; border:1px solid #e1e1e1; border-radius:3px;} /* submenu layer - font size */ .sun-editor .se-list-layer .se-list-font-size {min-width:140px; max-height:300px; overflow-x:hidden; overflow-y:auto;} /* submenu layer - hr */ @@ -233,7 +233,7 @@ /* submenu layer - paragraph style, text style */ .sun-editor .se-list-layer .se-list-format div {padding:4px 2px;} /* submenu layer --- table selector */ -.sun-editor .se-selector-table {display:none; position:absolute; top:34px; left:1px; z-index:4; padding:5px 0; float:left; margin:2px 0 0; font-size:14px; text-align:left; list-style:none; background-color:#fff; -webkit-background-clip:padding-box; background-clip:padding-box; border:1px solid #ccc; border-radius:4px; -webkit-box-shadow:0 6px 12px rgba(0, 0, 0, .175); box-shadow:0 6px 12px rgba(0, 0, 0, .175);} +.sun-editor .se-selector-table {display:none; position:absolute; top:34px; left:1px; z-index:4; padding:5px 0; float:left; margin:2px 0 0; font-size:14px; text-align:left; list-style:none; background-color:#fff; -webkit-background-clip:padding-box; background-clip:padding-box; border:1px solid #ccc; border-radius:3px; -webkit-box-shadow:0 6px 12px rgba(0, 0, 0, .175); box-shadow:0 6px 12px rgba(0, 0, 0, .175);} .sun-editor .se-selector-table .se-table-size {font-size:18px; padding:0 5px;} .sun-editor .se-selector-table .se-table-size-picker {position:absolute !important; z-index:3; font-size:18px; width:10em; height:10em; cursor:pointer;} .sun-editor .se-selector-table .se-table-size-highlighted {position:absolute !important; z-index:2; font-size:18px; width:1em; height:1em; background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo4QTZCNzMzN0I3RUYxMUU4ODcwQ0QwMjM1NTgzRTJDNyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo4QTZCNzMzNkI3RUYxMUU4ODcwQ0QwMjM1NTgzRTJDNyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0MzYyNEUxRUI3RUUxMUU4ODZGQzgwRjNBODgyNTdFOSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0MzYyNEUxRkI3RUUxMUU4ODZGQzgwRjNBODgyNTdFOSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pl0yAuwAAABBSURBVDhPY/wPBAxUAGCDGvdBeWSAeicIDTfIXREiQArYeR9hEBOEohyMGkQYjBpEGAxjg6ib+yFMygCVvMbAAABj0hwMTNeKJwAAAABJRU5ErkJggg==') repeat;} @@ -281,7 +281,7 @@ .sun-editor .se-dialog .se-dialog-back {position:absolute; width:100%; height:100%; top:0; left:0; background-color:#222; opacity:0.5;} /* dialog - modal */ .sun-editor .se-dialog .se-dialog-inner {position:absolute; width:100%; height:100%; top:0; left:0;} -.sun-editor .se-dialog .se-dialog-inner .se-dialog-content {position:relative; width:auto; max-width:500px; margin:20px auto; background-color:#fff; -webkit-background-clip:padding-box; background-clip:padding-box; border:1px solid rgba(0, 0, 0, .2); border-radius:4px; outline:0; -webkit-box-shadow:0 3px 9px rgba(0, 0, 0, .5); box-shadow:0 3px 9px rgba(0, 0, 0, .5);} +.sun-editor .se-dialog .se-dialog-inner .se-dialog-content {position:relative; width:auto; max-width:500px; margin:20px auto; background-color:#fff; -webkit-background-clip:padding-box; background-clip:padding-box; border:1px solid rgba(0, 0, 0, .2); border-radius:3px; outline:0; -webkit-box-shadow:0 3px 9px rgba(0, 0, 0, .5); box-shadow:0 3px 9px rgba(0, 0, 0, .5);} @media screen and (max-width:509px) { .sun-editor .se-dialog .se-dialog-inner .se-dialog-content {width:100%;} } .sun-editor .se-dialog .se-dialog-inner .se-dialog-header {height:50px; padding:6px 15px 6px 15px; border-bottom:1px solid #e5e5e5;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-header .se-dialog-close {float:right; font-weight:bold; text-shadow:0 1px 0 #fff; -webkit-appearance:none; filter:alpha(opacity=100); opacity:1;} @@ -295,7 +295,7 @@ .sun-editor .se-dialog .se-dialog-inner .se-dialog-size-text .size-h {width:70px; text-align:center;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-size-x {margin:0 8px 0 8px; width:25px; text-align:center;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-content label {display:inline-block; max-width:100%; margin-bottom:5px; font-weight:bold;} -.sun-editor .se-dialog .se-dialog-inner .se-dialog-content .se-btn-primary {display:inline-block; padding:6px 12px; margin:0 0 10px 0 !important; font-size:14px; font-weight:normal; line-height:1.42857143; text-align:center; white-space:nowrap; vertical-align:middle; -ms-touch-action:manipulation; touch-action:manipulation; border-radius:4px;} +.sun-editor .se-dialog .se-dialog-inner .se-dialog-content .se-btn-primary {display:inline-block; padding:6px 12px; margin:0 0 10px 0 !important; font-size:14px; font-weight:normal; line-height:1.42857143; text-align:center; white-space:nowrap; vertical-align:middle; -ms-touch-action:manipulation; touch-action:manipulation; border-radius:3px;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-footer {padding:10px 15px 0px 15px; text-align:right; border-top:1px solid #e5e5e5;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-footer > div {float:left;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-footer > div > label {margin-top:5px;} @@ -303,9 +303,9 @@ .sun-editor .se-dialog .se-dialog-inner .se-dialog-btn-check {margin-left:12px; margin-right:4px;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-form-footer .se-dialog-btn-check {margin-left:0; margin-right:4px;} /* dialog - modal - input */ -.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-select {display:inline-block; width:70px; height:34px; font-size:14px; text-align:center; line-height:1.42857143; color:#000; border:1px solid #ccc; border-radius:4px; transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;} -.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-control {display:inline-block; width:70px; height:34px; font-size:14px; text-align:center; line-height:1.42857143; color:#000; border:1px solid #ccc; border-radius:4px; transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;} -.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-form {display:block; width:100%; height:34px; font-size:14px; line-height:1.42857143; padding:0 4px; color:#000; border:1px solid #ccc; border-radius:4px; transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;} +.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-select {display:inline-block; width:70px; height:34px; font-size:14px; text-align:center; line-height:1.42857143; color:#000; border:1px solid #ccc; border-radius:3px; transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;} +.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-control {display:inline-block; width:70px; height:34px; font-size:14px; text-align:center; line-height:1.42857143; color:#000; border:1px solid #ccc; border-radius:3px; transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;} +.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-form {display:block; width:100%; height:34px; font-size:14px; line-height:1.42857143; padding:0 4px; color:#000; border:1px solid #ccc; border-radius:3px; transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-form input:focus, .sun-editor .se-dialog .se-dialog-inner .se-dialog-form select:focus, .sun-editor .se-dialog .se-dialog-inner .se-dialog-form textarea:focus {border-color:#80bdff; outline:0; -webkit-box-shadow:0 0 0 0.2rem #c7deff; box-shadow:0 0 0 0.2rem #c7deff;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-video-ratio {margin-left:4px;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-form a {color:#004cff;} @@ -326,13 +326,13 @@ /** --- controller ---------------------------------------------------------- */ .sun-editor .se-controller .se-arrow.se-arrow-up {border-bottom-color:rgba(0, 0, 0, .25);} -.sun-editor .se-controller {position:absolute; display:none; overflow:visible; z-index:4; border:1px solid rgba(0, 0, 0, .25); border-radius:4px; text-align:start; text-decoration:none; text-shadow:none; text-transform:none; letter-spacing:normal; word-break:normal; word-spacing:normal; word-wrap:normal; white-space:normal; background-color:#fff; -webkit-background-clip:padding-box; background-clip:padding-box; -webkit-box-shadow:0 5px 10px rgba(0, 0, 0, .2); box-shadow:0 5px 10px rgba(0, 0, 0, .2); line-break:auto;} +.sun-editor .se-controller {position:absolute; display:none; overflow:visible; z-index:4; border:1px solid rgba(0, 0, 0, .25); border-radius:3px; text-align:start; text-decoration:none; text-shadow:none; text-transform:none; letter-spacing:normal; word-break:normal; word-spacing:normal; word-wrap:normal; white-space:normal; background-color:#fff; -webkit-background-clip:padding-box; background-clip:padding-box; -webkit-box-shadow:0 5px 10px rgba(0, 0, 0, .2); box-shadow:0 5px 10px rgba(0, 0, 0, .2); line-break:auto;} /* controller - button group */ .sun-editor .se-controller .se-btn-group {position:relative; display:flex; vertical-align:middle; padding:2px 2px 2px 0; top:0; left:0;} .sun-editor .se-controller .se-btn-group .se-btn-group-sub {left:50%; min-width:auto; width:max-content; display:none;/* display: inline-table; */} .sun-editor .se-controller .se-btn-group .se-btn-group-sub button {margin:0; min-width:72px;} -.sun-editor .se-controller .se-btn-group button {position:relative; min-height:35px; height:auto; border:none; border-radius:4px; border-top-right-radius:0; border-bottom-right-radius:0; margin:0 0 0 2px; padding:5px 10px; font-size:12px; line-height:1.5; display:inline-block; font-weight:normal; text-align:center; white-space:nowrap; vertical-align:middle; -ms-touch-action:manipulation; touch-action:manipulation;} +.sun-editor .se-controller .se-btn-group button {position:relative; min-height:35px; height:auto; border:none; border-radius:3px; border-top-right-radius:0; border-bottom-right-radius:0; margin:0 0 0 2px; padding:5px 10px; font-size:12px; line-height:1.5; display:inline-block; font-weight:normal; text-align:center; white-space:nowrap; vertical-align:middle; -ms-touch-action:manipulation; touch-action:manipulation;} .sun-editor .se-controller .se-btn-group button:hover:enabled, .sun-editor .se-controller .se-btn-group button:focus:enabled {background-color:#e1e1e1; border-color:#d1d1d1; outline:0 none;} .sun-editor .se-controller .se-btn-group button:active:enabled {background-color:#d1d1d1; border-color:#c1c1c1; -webkit-box-shadow:inset 0 3px 5px #c1c1c1; box-shadow:inset 0 3px 5px #c1c1c1;} .sun-editor .se-controller .se-btn-group button span {display:block; padding:0; margin:0;} @@ -360,7 +360,7 @@ .sun-editor .se-resizing-container .se-resize-dot > span.th {left:50%; top:-7px; cursor:n-resize;} .sun-editor .se-resizing-container .se-resize-dot > span.rw {right:-7px; bottom:50%; cursor:e-resize;} .sun-editor .se-resizing-container .se-resize-dot > span.bh {right:50%; bottom:-7px; cursor:s-resize;} -.sun-editor .se-resizing-container .se-resize-display {position:absolute; right:0; bottom:0; padding:5px; margin:5px; font-size:12px; color:#fff; background-color:#333; border-radius:4px;} +.sun-editor .se-resizing-container .se-resize-display {position:absolute; right:0; bottom:0; padding:5px; margin:5px; font-size:12px; color:#fff; background-color:#333; border-radius:3px;} /* controller - table */ .sun-editor .se-controller-table {width:auto; padding:0; font-size:14px; font-style:normal; font-weight:normal; line-height:1.42857143;} .sun-editor .se-controller-table-cell {width:auto; padding:0; font-size:14px; font-style:normal; font-weight:normal; line-height:1.42857143;} @@ -377,7 +377,7 @@ /** --- tooltip */ .sun-editor .se-tooltip {position:relative; overflow:visible;} .sun-editor .se-tooltip .se-tooltip-inner {visibility:hidden; position:absolute; display:block; width:auto; top:120%; left:50%; background:transparent; opacity:0; z-index:1; line-height:1.5; transition:opacity 0.5s; margin:0; padding:0; bottom:auto; float:none; pointer-events:none; backface-visibility:hidden; -webkit-backface-visibility:hidden; -moz-backface-visibility:hidden;} -.sun-editor .se-tooltip .se-tooltip-inner .se-tooltip-text {position:relative; display:inline-block; width:auto; left:-50%; font-size:0.9em; margin:0; padding:4px 6px; border-radius:4px; background-color:#333; color:#fff; text-align:center; line-height:unset; white-space:nowrap; cursor:auto;} +.sun-editor .se-tooltip .se-tooltip-inner .se-tooltip-text {position:relative; display:inline-block; width:auto; left:-50%; font-size:0.9em; margin:0; padding:4px 6px; border-radius:2px; background-color:#333; color:#fff; text-align:center; line-height:unset; white-space:nowrap; cursor:auto;} .sun-editor .se-tooltip .se-tooltip-inner .se-tooltip-text::after {content:""; position:absolute; bottom:100%; left:50%; margin-left:-5px; border-width:5px; border-style:solid; border-color:transparent transparent #333 transparent;} .sun-editor .se-tooltip:hover .se-tooltip-inner {visibility:visible; opacity:1;} diff --git a/src/lib/core.js b/src/lib/core.js index 3d1de76b6..7a7d52c3d 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -678,7 +678,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { * @returns {Boolean} */ isEdgePoint: function (container, offset) { - return (offset === 0) || (offset === container.nodeValue.length); + return (offset === 0) || (!container.nodeValue && offset === 1) || (offset === container.nodeValue.length); }, /** @@ -1158,7 +1158,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (!newList && util.isListCell(insNode)) { const inner = insNode; - insNode = util.isCell(rangeElement.parentNode) ? util.createElement('DIV') : util.createElement('P'); + insNode = util.createElement(util.isList(rangeElement.parentNode) ? 'LI' : util.isCell(rangeElement.parentNode) ? 'DIV' : 'P'); insNode.innerHTML = inner.innerHTML; util.copyFormatAttributes(insNode, inner); } else { @@ -3796,7 +3796,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { let scrollLeft = 0; let scrollTop = 0; - let el = context.element.topArea.parentElement; + let el = context.element.topArea; while (!!el) { scrollLeft += el.scrollLeft; scrollTop += el.scrollTop; @@ -4006,6 +4006,13 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (ctrl || alt || util.isWysiwygDiv(selectionNode)) break; core.controllersOff(); + + if (util.isListCell(formatEl) && (!range.collapsed || core.isEdgePoint(range.startContainer, range.startOffset)) && core.plugins.list) { + core.callPlugin('list', function () { + core.plugins.list.editInsideList.call(core, shift); + }); + break; + } let currentNode = selectionNode; while (!util.isCell(currentNode) && !util.isWysiwygDiv(currentNode)) { @@ -4125,7 +4132,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { const range = core.getRange(); if (!range.commonAncestorContainer.nextElementSibling && util.onlyZeroWidthSpace(formatEl.innerText.trim())) { e.preventDefault(); - const newEl = core.appendFormatTag(rangeEl, util.isCell(rangeEl.parentNode) ? 'DIV' : util.isListCell(formatEl) ? 'P' : null); + const newEl = core.appendFormatTag(rangeEl, util.isList(rangeEl.parentNode) ? 'LI' : util.isCell(rangeEl.parentNode) ? 'DIV' : util.isListCell(formatEl) ? 'P' : null); util.copyFormatAttributes(newEl, formatEl); util.removeItemAllParents(formatEl); core.setRange(newEl, 1, newEl, 1); @@ -4225,7 +4232,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { const formatEl = util.getFormatElement(selectionNode); const rangeEl = util.getRangeFormatElement(selectionNode); - if (!formatEl || formatEl === rangeEl) { + if ((!formatEl && range.collapsed) || formatEl === rangeEl) { core.execCommand('formatBlock', false, util.isRangeFormatElement(rangeEl) ? 'DIV' : 'P'); core.focus(); selectionNode = core.getSelectionNode(); diff --git a/src/plugins/submenu/list.js b/src/plugins/submenu/list.js index 6eec7039d..b9827bbbd 100644 --- a/src/plugins/submenu/list.js +++ b/src/plugins/submenu/list.js @@ -103,20 +103,7 @@ export default { } }, - pickup: function (e) { - e.preventDefault(); - e.stopPropagation(); - - let target = e.target; - let command = ''; - - while (!command && !/^UL$/i.test(target.tagName)) { - command = target.getAttribute('data-command'); - target = target.parentNode; - } - - if (!command) return; - + editList: function (command) { const selectedFormsts = this.getSelectedElementsAndComponents(); if (!selectedFormsts || selectedFormsts.length === 0) return; @@ -139,7 +126,7 @@ export default { } } - if (isRemove && (!topEl || command !== topEl.tagName) && (!bottomEl || command !== bottomEl.tagName)) { + if (isRemove && (!topEl || command !== topEl.tagName.toUpperCase()) && (!bottomEl || command !== bottomEl.tagName.toUpperCase())) { const currentFormat = this.util.getRangeFormatElement(this.getSelectionNode()); const cancel = currentFormat && currentFormat.tagName === command; let rangeArr, tempList; @@ -259,5 +246,62 @@ export default { // history stack this.history.push(false); + }, + + editInsideList: function (remove) { + const selectedCells = this.getSelectedElements().filter(function (el) { return this.isListCell(el); }.bind(this.util)); + const cellsLen = selectedCells.length; + if ((!remove && !selectedCells[0].previousElementSibling) || cellsLen === 0) return; + + let originList = selectedCells[0].parentNode; + let sc, so, ec, eo; + + if (remove) { + this.plugins.list.editList.call(this, originList.nodeName.toUpperCase()); + } else { + sc = selectedCells[0], eo = 1; + let innerList = this.util.createElement(originList.nodeName); + let next = sc.nextElementSibling; + + for (let i = 0, len = cellsLen, c; i < len; i++) { + c = selectedCells[i]; + if (c.parentNode !== originList) { + originList.insertBefore(innerList, next); + originList = c.parentNode; + innerList = this.util.createElement(originList.nodeName); + } + + next = c.nextElementSibling; + innerList.appendChild(c); + if (i === len - 1) { + originList.insertBefore(innerList, next); + } + } + + if (cellsLen > 1) { + so = 0, ec = selectedCells[cellsLen - 1]; + } else { + so = 1, ec = sc; + } + } + + this.setRange(sc, so, ec, eo); + }, + + pickup: function (e) { + e.preventDefault(); + e.stopPropagation(); + + let target = e.target; + let command = ''; + + while (!command && !/^UL$/i.test(target.tagName)) { + command = target.getAttribute('data-command'); + target = target.parentNode; + } + + if (!command) return; + + this.plugins.list.editList.call(this, command); } }; diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index 7e1724d18..86582638e 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -25,6 +25,7 @@ const align = require('../../src/plugins/submenu/align') suneditor.create("sample1", { plugins: plugins, mode: "balloon", + // iframe: true, buttonList: [ ["undo", "redo"], ["font", "fontSize", "formatBlock"], @@ -34,12 +35,25 @@ suneditor.create("sample1", { let s1 = suneditor.create('editor', { - plugins: plugins, - mode: 'balloon', - buttonList: [['blockquote', 'font'],['table', 'align', 'link', 'bold', 'underline', 'italic', 'strike', 'fontColor', 'hiliteColor', 'removeFormat', 'formatBlock', 'codeView', 'preview']], - width: '100%', - pasteTagsWhitelist: 'p|h[1-6]', - formats: [ + plugins: plugins, + // mode: 'balloon', + katex: Katex, + buttonList: [ + ['undo', 'redo', + 'font', 'fontSize', 'formatBlock', + 'blockquote', 'paragraphStyle', + 'bold', 'underline', 'italic', 'strike', 'subscript', 'superscript', + 'fontColor', 'hiliteColor', 'textStyle', + 'removeFormat', + 'outdent', 'indent', + 'align', 'horizontalRule', 'list', 'lineHeight', + 'table', 'link', 'image', 'video', 'math', + 'fullScreen', 'showBlocks', 'codeView', + 'preview', 'print', 'save', 'template'] + ], + width: '100%', + pasteTagsWhitelist: 'p|h[1-6]', + formats: [ { tag: 'div', // Tag name name: 'NORMAL', // default: tag name From cfab3a2604f91e85bde27fa3dfaa44615fd0984e Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Mon, 24 Feb 2020 21:18:50 +0900 Subject: [PATCH 46/99] update: #217 nested list --- src/lib/core.js | 2 +- src/plugins/submenu/list.js | 61 ++++++++++++++++++++++---------- test/dev/suneditor_build_test.js | 6 ++-- 3 files changed, 48 insertions(+), 21 deletions(-) diff --git a/src/lib/core.js b/src/lib/core.js index 7a7d52c3d..6f05d823b 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -1147,8 +1147,8 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (selectedFormats && selectedFormats.indexOf(insNode) === -1) { if (!rangeEl) rangeEl = rangeElement.cloneNode(false); - insNode = insNode.cloneNode(true); rangeEl.appendChild(insNode); + i--, len--; } else { if (rangeEl && rangeEl.children.length > 0) { diff --git a/src/plugins/submenu/list.js b/src/plugins/submenu/list.js index b9827bbbd..1693a9f57 100644 --- a/src/plugins/submenu/list.js +++ b/src/plugins/submenu/list.js @@ -103,8 +103,8 @@ export default { } }, - editList: function (command) { - const selectedFormsts = this.getSelectedElementsAndComponents(); + editList: function (command, selectedCells) { + const selectedFormsts = !selectedCells ? this.getSelectedElementsAndComponents() : selectedCells; if (!selectedFormsts || selectedFormsts.length === 0) return; let isRemove = true; @@ -126,7 +126,7 @@ export default { } } - if (isRemove && (!topEl || command !== topEl.tagName.toUpperCase()) && (!bottomEl || command !== bottomEl.tagName.toUpperCase())) { + if (isRemove && (!topEl || (firstSel.tagName !== topEl.tagName || command !== topEl.tagName.toUpperCase())) && (!bottomEl || (lastSel.tagName !== bottomEl.tagName || command !== bottomEl.tagName.toUpperCase()))) { const currentFormat = this.util.getRangeFormatElement(this.getSelectionNode()); const cancel = currentFormat && currentFormat.tagName === command; let rangeArr, tempList; @@ -251,41 +251,66 @@ export default { editInsideList: function (remove) { const selectedCells = this.getSelectedElements().filter(function (el) { return this.isListCell(el); }.bind(this.util)); const cellsLen = selectedCells.length; - if ((!remove && !selectedCells[0].previousElementSibling) || cellsLen === 0) return; + if (cellsLen === 0 || (!remove && (!selectedCells[0].previousElementSibling || !selectedCells[cellsLen - 1].nextElementSibling))) return; let originList = selectedCells[0].parentNode; - let sc, so, ec, eo; if (remove) { - this.plugins.list.editList.call(this, originList.nodeName.toUpperCase()); + this.plugins.list.editList.call(this, originList.nodeName.toUpperCase(), selectedCells); } else { - sc = selectedCells[0], eo = 1; + const sc = selectedCells[0], so = cellsLen > 1 ? 0 : 1, ec = selectedCells[cellsLen - 1], eo = 1; let innerList = this.util.createElement(originList.nodeName); + let prev = sc.previousElementSibling; let next = sc.nextElementSibling; for (let i = 0, len = cellsLen, c; i < len; i++) { c = selectedCells[i]; if (c.parentNode !== originList) { - originList.insertBefore(innerList, next); + this.plugins.list._insiedList(originList, innerList, prev, next); originList = c.parentNode; innerList = this.util.createElement(originList.nodeName); } + prev = c.previousElementSibling; next = c.nextElementSibling; innerList.appendChild(c); - if (i === len - 1) { - originList.insertBefore(innerList, next); - } } + + innerList = this.plugins.list._insiedList(originList, innerList, prev, next); + this.setRange(sc, so, ec, eo); - if (cellsLen > 1) { - so = 0, ec = selectedCells[cellsLen - 1]; - } else { - so = 1, ec = sc; + // history stack + this.history.push(false); + } + }, + + _insiedList: function (originList, innerList, prev, next) { + let insertPrev = false; + + if (prev && innerList.tagName === prev.tagName) { + const children = innerList.children; + while (children[0]) { + prev.appendChild(children[0]); } + + innerList = prev; + insertPrev = true; } - - this.setRange(sc, so, ec, eo); + + if (next && innerList.tagName === next.tagName) { + const children = next.children; + while (children[0]) { + innerList.appendChild(children[0]); + } + + const temp = next.nextElementSibling; + next.parentNode.removeChild(next); + next = temp; + } + + if (!insertPrev) originList.insertBefore(innerList, next); + + return innerList; }, pickup: function (e) { @@ -302,6 +327,6 @@ export default { if (!command) return; - this.plugins.list.editList.call(this, command); + this.plugins.list.editList.call(this, command, null); } }; diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index 86582638e..1063edd8e 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -52,7 +52,8 @@ let s1 = suneditor.create('editor', { 'preview', 'print', 'save', 'template'] ], width: '100%', - pasteTagsWhitelist: 'p|h[1-6]', + height: 'auto', + // pasteTagsWhitelist: 'p|h[1-6]', formats: [ { tag: 'div', // Tag name @@ -100,7 +101,8 @@ window.sun_create1 = function () { s1 = suneditor.create('editor', { plugins: [align, plugins.link], buttonList: [['align', 'link', 'bold', 'underline', 'italic', 'strike', 'removeFormat', 'codeView']], - width: '100%' + width: '100%', + height: 'auto' }) } From 62f54adcc8f0fea3b0d90548740b8a680fc53771 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Mon, 24 Feb 2020 21:51:05 +0900 Subject: [PATCH 47/99] update: #217 nested list --- src/lib/core.js | 1 - src/plugins/submenu/list.js | 15 ++++++++++++--- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/lib/core.js b/src/lib/core.js index 6f05d823b..34f189386 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -1185,7 +1185,6 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { firstNode = lastNode = insNode; } } - } } diff --git a/src/plugins/submenu/list.js b/src/plugins/submenu/list.js index 1693a9f57..1963928c1 100644 --- a/src/plugins/submenu/list.js +++ b/src/plugins/submenu/list.js @@ -254,11 +254,20 @@ export default { if (cellsLen === 0 || (!remove && (!selectedCells[0].previousElementSibling || !selectedCells[cellsLen - 1].nextElementSibling))) return; let originList = selectedCells[0].parentNode; - + let lastCell = selectedCells[cellsLen - 1]; + if (remove) { + if (originList !== lastCell.parentNode && lastCell.nextElementSibling) { + lastCell = lastCell.nextElementSibling; + while (lastCell) { + selectedCells.push(lastCell); + lastCell = lastCell.nextElementSibling; + } + } + this.plugins.list.editList.call(this, originList.nodeName.toUpperCase(), selectedCells); } else { - const sc = selectedCells[0], so = cellsLen > 1 ? 0 : 1, ec = selectedCells[cellsLen - 1], eo = 1; + const sc = selectedCells[0], so = cellsLen > 1 ? 0 : 1, ec = lastCell, eo = 1; let innerList = this.util.createElement(originList.nodeName); let prev = sc.previousElementSibling; let next = sc.nextElementSibling; @@ -327,6 +336,6 @@ export default { if (!command) return; - this.plugins.list.editList.call(this, command, null); + this.plugins.list.editList.call(this, command, null, null); } }; From c5459e1b6facc021e5b39d4dffbbb5ad0d0ededa Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Mon, 24 Feb 2020 21:56:14 +0900 Subject: [PATCH 48/99] fix: nested list --- src/plugins/submenu/list.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/submenu/list.js b/src/plugins/submenu/list.js index 1963928c1..ad4ac6255 100644 --- a/src/plugins/submenu/list.js +++ b/src/plugins/submenu/list.js @@ -251,7 +251,7 @@ export default { editInsideList: function (remove) { const selectedCells = this.getSelectedElements().filter(function (el) { return this.isListCell(el); }.bind(this.util)); const cellsLen = selectedCells.length; - if (cellsLen === 0 || (!remove && (!selectedCells[0].previousElementSibling || !selectedCells[cellsLen - 1].nextElementSibling))) return; + if (cellsLen === 0 || (!remove && (!this.util.isListCell(selectedCells[0].previousElementSibling) && !this.util.isListCell(selectedCells[cellsLen - 1].nextElementSibling)))) return; let originList = selectedCells[0].parentNode; let lastCell = selectedCells[cellsLen - 1]; From f48549e9fd0383f3f09367f77638e1e5a781fae9 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Tue, 25 Feb 2020 01:27:11 +0900 Subject: [PATCH 49/99] fix: util-getChildElement, nested list --- src/lib/core.js | 114 ++++++++++++++++++++--------- src/lib/util.js | 2 +- src/plugins/submenu/list.js | 53 ++++++++------ test/dev/suneditor_build_test.html | 18 ++++- 4 files changed, 127 insertions(+), 60 deletions(-) diff --git a/src/lib/core.js b/src/lib/core.js index 34f189386..e3249b176 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -4006,13 +4006,6 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { core.controllersOff(); - if (util.isListCell(formatEl) && (!range.collapsed || core.isEdgePoint(range.startContainer, range.startOffset)) && core.plugins.list) { - core.callPlugin('list', function () { - core.plugins.list.editInsideList.call(core, shift); - }); - break; - } - let currentNode = selectionNode; while (!util.isCell(currentNode) && !util.isWysiwygDiv(currentNode)) { currentNode = currentNode.parentNode; @@ -4033,47 +4026,98 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { break; } - const lines = core.getSelectedElements(); + const selectedFormats = core.getSelectedElements(); + const lines = [], cells = []; + const fc = util.isListCell(selectedFormats[0]), lc = util.isListCell(selectedFormats[selectedFormats.length - 1]); + let r = {sc: null, so: null, ec: null, eo: null}; + for (let i = 0, len = selectedFormats.length, f; i < len; i++) { + f = selectedFormats[i]; + if (util.isListCell(f)) cells.push(f); + else lines.push(f); + } + + // Nested list + if (cells.length > 0 && (!range.collapsed || core.isEdgePoint(range.startContainer, range.startOffset)) && core.plugins.list) { + core.callPlugin('list', function () { + const listRange = core.plugins.list.editInsideList.call(core, shift, cells); + if (fc) { + r.sc = listRange.sc; + r.so = listRange.so; + } + if (lc) { + r.ec = listRange.ec; + r.eo = listRange.eo; + } + }); + } - if (!shift) { - const tabText = util.createTextNode(new _w.Array(core._variable.tabSize + 1).join('\u00A0')); - if (lines.length === 1) { - const r = core.insertNode(tabText); - core.setRange(tabText, r.endOffset, tabText, r.endOffset); + // Lines tab(4) + if (lines.length > 0) { + if (!shift) { + const tabText = util.createTextNode(new _w.Array(core._variable.tabSize + 1).join('\u00A0')); + if (lines.length === 1) { + const textRange = core.insertNode(tabText); + if (!fc) { + r.sc = tabText; + r.so = textRange.endOffset; + } + if (!lc) { + r.ec = tabText; + r.eo = textRange.endOffset; + } + } else { + const len = lines.length - 1; + for (let i = 0, child; i <= len; i++) { + child = lines[i].firstChild; + if (!child) continue; + + if (util.isBreak(child)) { + lines[i].insertBefore(tabText.cloneNode(false), child); + } else { + child.textContent = tabText.textContent + child.textContent; + } + } + + const firstChild = util.getChildElement(lines[0], 'text', false); + const endChild = util.getChildElement(lines[len], 'text', true); + if (!fc && firstChild) { + r.sc = firstChild; + r.so = 0; + } + if (!lc && endChild) { + r.ec = endChild; + r.eo = endChild.textContent.length; + } + } } else { const len = lines.length - 1; for (let i = 0, child; i <= len; i++) { child = lines[i].firstChild; if (!child) continue; - - if (util.isBreak(child)) { - lines[i].insertBefore(tabText.cloneNode(false), child); - } else { - child.textContent = tabText.textContent + child.textContent; + + if (/^\s{1,4}$/.test(child.textContent)) { + util.removeItem(child); + } else if (/^\s{1,4}/.test(child.textContent)) { + child.textContent = child.textContent.replace(/^\s{1,4}/, ''); } } - + const firstChild = util.getChildElement(lines[0], 'text', false); const endChild = util.getChildElement(lines[len], 'text', true); - if (firstChild && endChild) core.setRange(firstChild, 0, endChild, endChild.textContent.length); - } - } else { - const len = lines.length - 1; - for (let i = 0, child; i <= len; i++) { - child = lines[i].firstChild; - if (!child) continue; - - if (/^\s{1,4}$/.test(child.textContent)) { - util.removeItem(child); - } else if (/^\s{1,4}/.test(child.textContent)) { - child.textContent = child.textContent.replace(/^\s{1,4}/, ''); + if (!fc && firstChild) { + r.sc = firstChild; + r.so = 0; + } + if (!lc && endChild) { + r.ec = endChild; + r.eo = endChild.textContent.length; } } - - const firstChild = util.getChildElement(lines[0], 'text', false); - const endChild = util.getChildElement(lines[len], 'text', true); - if (firstChild && endChild) core.setRange(firstChild, 0, endChild, endChild.textContent.length); } + + core.setRange(r.sc, r.so, r.ec, r.eo); + // history stack + core.history.push(false); break; case 13: /** enter key */ diff --git a/src/lib/util.js b/src/lib/util.js index b820fdd64..cbbcdf8b0 100755 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -827,7 +827,7 @@ const util = { query = '^' + query.split(':')[1] + '$'; } else { attr = 'nodeName'; - query = '^' + query + '$'; + query = '^' + (query === 'text' ? '#' + query : query) + '$'; } const regExp = new this._w.RegExp(query, 'i'); diff --git a/src/plugins/submenu/list.js b/src/plugins/submenu/list.js index ad4ac6255..90a0abf4f 100644 --- a/src/plugins/submenu/list.js +++ b/src/plugins/submenu/list.js @@ -127,7 +127,7 @@ export default { } if (isRemove && (!topEl || (firstSel.tagName !== topEl.tagName || command !== topEl.tagName.toUpperCase())) && (!bottomEl || (lastSel.tagName !== bottomEl.tagName || command !== bottomEl.tagName.toUpperCase()))) { - const currentFormat = this.util.getRangeFormatElement(this.getSelectionNode()); + const currentFormat = this.util.getRangeFormatElement(firstSel); const cancel = currentFormat && currentFormat.tagName === command; let rangeArr, tempList; const passComponent = function (current) { @@ -235,26 +235,32 @@ export default { edgeFirst = edgeLast = this.util.getEdgeChildNodes(firstList.firstChild, lastList.lastChild); } - - if (selectedFormsts.length > 1) { - this.setRange(edgeFirst.sc, 0, edgeLast.ec, edgeLast.ec.textContent.length); - } else { - this.setRange(edgeFirst.ec, edgeFirst.ec.textContent.length, edgeLast.ec, edgeLast.ec.textContent.length); - } - + this.submenuOff(); - // history stack - this.history.push(false); + return { + sc: selectedFormsts.length > 1 ? edgeFirst.sc : edgeFirst.ec, + so: selectedFormsts.length > 1 ? 0 : edgeFirst.ec.textContent.length, + ec: edgeLast.ec, + eo: edgeLast.ec.textContent.length + }; }, - editInsideList: function (remove) { - const selectedCells = this.getSelectedElements().filter(function (el) { return this.isListCell(el); }.bind(this.util)); + editInsideList: function (remove, selectedCells) { + selectedCells = !selectedCells ? this.getSelectedElements().filter(function (el) { return this.isListCell(el); }.bind(this.util)) : selectedCells; const cellsLen = selectedCells.length; - if (cellsLen === 0 || (!remove && (!this.util.isListCell(selectedCells[0].previousElementSibling) && !this.util.isListCell(selectedCells[cellsLen - 1].nextElementSibling)))) return; + if (cellsLen === 0 || (!remove && (!this.util.isListCell(selectedCells[0].previousElementSibling) && !this.util.isListCell(selectedCells[cellsLen - 1].nextElementSibling)))) { + return { + sc: selectedCells[0], + so: 0, + ec: selectedCells[cellsLen - 1], + eo: 1 + }; + } let originList = selectedCells[0].parentNode; let lastCell = selectedCells[cellsLen - 1]; + let range = null; if (remove) { if (originList !== lastCell.parentNode && lastCell.nextElementSibling) { @@ -264,13 +270,12 @@ export default { lastCell = lastCell.nextElementSibling; } } - - this.plugins.list.editList.call(this, originList.nodeName.toUpperCase(), selectedCells); + range = this.plugins.list.editList.call(this, originList.nodeName.toUpperCase(), selectedCells); } else { - const sc = selectedCells[0], so = cellsLen > 1 ? 0 : 1, ec = lastCell, eo = 1; + range = { sc: selectedCells[0], so: cellsLen > 1 ? 0 : 1, ec: lastCell, eo: 1 }; let innerList = this.util.createElement(originList.nodeName); - let prev = sc.previousElementSibling; - let next = sc.nextElementSibling; + let prev = range.sc.previousElementSibling; + let next = range.sc.nextElementSibling; for (let i = 0, len = cellsLen, c; i < len; i++) { c = selectedCells[i]; @@ -286,11 +291,9 @@ export default { } innerList = this.plugins.list._insiedList(originList, innerList, prev, next); - this.setRange(sc, so, ec, eo); - - // history stack - this.history.push(false); } + + return range; }, _insiedList: function (originList, innerList, prev, next) { @@ -336,6 +339,10 @@ export default { if (!command) return; - this.plugins.list.editList.call(this, command, null, null); + const range = this.plugins.list.editList.call(this, command, null, null); + this.setRange(range.sc, range.so, range.ec, range.eo); + + // history stack + this.history.push(false); } }; diff --git a/test/dev/suneditor_build_test.html b/test/dev/suneditor_build_test.html index af543ec41..75ca7beaa 100644 --- a/test/dev/suneditor_build_test.html +++ b/test/dev/suneditor_build_test.html @@ -154,7 +154,23 @@
    - +
    From e62b4acb8e67211246660be86e549d177e8ab4c3 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Tue, 25 Feb 2020 20:08:31 +0900 Subject: [PATCH 50/99] add: util-removeNestedTags --- sample/html/out/document-util.html | 35 ++++++++++++++++++++++++ src/lib/core.js | 43 +++++++++++++++++++----------- src/lib/util.js | 31 ++++++++++++++++++++- src/plugins/submenu/list.js | 2 +- test/dev/suneditor_build_test.js | 9 ++++--- 5 files changed, 99 insertions(+), 21 deletions(-) diff --git a/sample/html/out/document-util.html b/sample/html/out/document-util.html index 0ae26d0b2..6d3dfeb95 100644 --- a/sample/html/out/document-util.html +++ b/sample/html/out/document-util.html @@ -1695,6 +1695,40 @@
    Parameters:
    +

    removeNestedTags(element, validation)

    +
    + Remove nested tags without other child nodes. +
    +
    Parameters:
    + + + + + + + + + + + + + + + + + + + + +
    NameTypeDescription
    element + Element + Element object
    validation + Function|String|null + Validation function / String("tag1|tag2..") / If null, all tags are applicable.
    +
    + +

    removeEmptyNode(element, notRemoveNode)

    @@ -1858,6 +1892,7 @@

    util

  • toggleClass
  • removeItem
  • removeItemAllParents
  • +
  • removeNestedTags
  • removeEmptyNode
  • cleanHTML
  • createTagsWhitelist
  • diff --git a/src/lib/core.js b/src/lib/core.js index e3249b176..541cb4325 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -1007,7 +1007,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { const removeItems = function (parent, origin, before) { let cc = null; if (parent !== origin && !util.isTable(origin)) { - cc = util.removeItemAllParents(origin); + cc = util.removeItemAllParents(origin, null); } return cc ? cc.ec : before; @@ -1024,7 +1024,15 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { listParent.innerHTML += line.outerHTML; lineArr.push(line); - if (i === len - 1 || !util.getParentElement(rangeLines[i + 1], function (current) { return current === originParent; })) { + if (i === len - 1 || rangeLines[i + 1].parentNode !== originParent) { + let list = originParent.parentNode, p; + while (util.isList(list)) { + p = util.createElement(list.nodeName); + p.appendChild(listParent); + listParent = p; + list = list.parentNode; + } + const edge = this.detachRangeFormatElement(originParent, lineArr, null, true, true); if (parentDepth >= depth) { @@ -1061,6 +1069,8 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { } } + this._mergeSameTags(rangeElement, null, null, false); + util.removeNestedTags(rangeElement, function (current) { return this.isList(current); }.bind(util)); pElement.insertBefore(rangeElement, beforeTag); removeItems(rangeElement, beforeTag); @@ -1562,12 +1572,13 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { * @description Use with "npdePath (util.getNodePath)" to merge the same attributes and tags if they are present and modify the nodepath. * If "offset" has been changed, it will return as much "offset" as it has been modified. * "a", "b" You can send a maximum of two nodepaths. - * @param {Object} nodePath_s Start NodePath object (util.getNodePath) + * @param {Object|null} nodePath_s Start NodePath object (util.getNodePath) * @param {Object|null} nodePath_e End NodePath object (util.getNodePath) + * @param {Boolean} onlyText If true, the node with util._isIgnoreNodeChange() is true is ignored. * @returns {Object} {a: 0, b: 0} * @private */ - _mergeSameTags: function (element, nodePath_s, nodePath_e) { + _mergeSameTags: function (element, nodePath_s, nodePath_e, onlyText) { const inst = this; const offsets = {a: 0, b: 0}; @@ -1578,7 +1589,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { child = children[i]; next = children[i + 1]; if (!child) break; - if(inst.util._isIgnoreNodeChange(child)) continue; + if((onlyText && inst.util._isIgnoreNodeChange(child)) || (!onlyText && inst.util.isFormatElement(child) && !inst.util.isFreeFormatElement(child))) continue; if (len === 1 && current.nodeName === child.nodeName) { inst.util.copyTagAttributes(child, current); current.parentNode.replaceChild(child, current); @@ -2100,7 +2111,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { endOffset = (collapsed ? startOffset : mergeEndCon ? startContainer.textContent.length : endConReset ? endOffset + newStartOffset.s : endOffset + newEndOffset.s); // tag merge - const newOffsets = this._mergeSameTags(pNode, startPath, endPath); + const newOffsets = this._mergeSameTags(pNode, startPath, endPath, true); element.innerHTML = pNode.innerHTML; @@ -2372,7 +2383,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { offset += offsets.s; // tag merge - const newOffsets = this._mergeSameTags(pNode, path, null); + const newOffsets = this._mergeSameTags(pNode, path, null, true); element.innerHTML = pNode.innerHTML; @@ -2482,7 +2493,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { } util.removeEmptyNode(pNode, newInnerNode); - this._mergeSameTags(pNode, null, null); + this._mergeSameTags(pNode, null, null, true); // node change element.innerHTML = pNode.innerHTML; @@ -2761,7 +2772,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { offset += offsets.s; // tag merge - const newOffsets = this._mergeSameTags(pNode, path, null); + const newOffsets = this._mergeSameTags(pNode, path, null, true); element.innerHTML = pNode.innerHTML; @@ -2973,6 +2984,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { for (let i = 0, len = headChildren.length; i < len; i++) { if (/script/i.test(headChildren[i].tagName)) { parseDocument.head.removeChild(headChildren[i]); + i--, len--; } } @@ -2984,6 +2996,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (attrs[i].name === 'contenteditable') continue; this._wd.body.setAttribute(attrs[i].name, attrs[i].value); } + if (!util.hasClass(this._wd.body, 'sun-editor-editable')) util.addClass(this._wd.body, 'sun-editor-editable'); } else { context.element.wysiwyg.innerHTML = code_html.length > 0 ? util.convertContentsForEditor(code_html, this.editorTagsWhitelistRegExp) : '


    '; } @@ -3562,14 +3575,14 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { /* Active plugins */ for (let c = 0, name; c < cLen; c++) { name = activePlugins[c]; - if (commandMapNodes.indexOf(name) < 0 && plugins[name].active.call(core, element)) { + if (commandMapNodes.indexOf(name) === -1 && plugins[name].active.call(core, element)) { commandMapNodes.push(name); } } if (util.isFormatElement(element)) { /* Outdent */ - if (commandMapNodes.indexOf('OUTDENT') < 0 && element.style.marginLeft && util.getNumber(element.style.marginLeft, 0) > 0 && commandMap.OUTDENT) { + if (commandMapNodes.indexOf('OUTDENT') === -1 && element.style.marginLeft && util.getNumber(element.style.marginLeft, 0) > 0 && commandMap.OUTDENT) { commandMapNodes.push('OUTDENT'); commandMap.OUTDENT.removeAttribute('disabled'); } @@ -3758,12 +3771,12 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { } else { core.execCommand('formatBlock', false, util.isRangeFormatElement(rangeEl) ? 'DIV' : 'P'); } - + e.preventDefault(); core.focus(); + } else { + event._applyTagEffects(); } - event._applyTagEffects(); - if (core._isBalloon) _w.setTimeout(event._toggleToolbarBalloon); if (userFunction.onClick) userFunction.onClick(e, core); }, @@ -4177,7 +4190,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { e.preventDefault(); const newEl = core.appendFormatTag(rangeEl, util.isList(rangeEl.parentNode) ? 'LI' : util.isCell(rangeEl.parentNode) ? 'DIV' : util.isListCell(formatEl) ? 'P' : null); util.copyFormatAttributes(newEl, formatEl); - util.removeItemAllParents(formatEl); + util.removeItemAllParents(formatEl, null); core.setRange(newEl, 1, newEl, 1); break; } diff --git a/src/lib/util.js b/src/lib/util.js index cbbcdf8b0..913d87497 100755 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -609,7 +609,7 @@ const util = { * @returns {Boolean} */ isList: function (node) { - return node && /^(OL|UL)$/i.test(typeof node === 'string' ? node : node.nodeName); + return node && /^(OL|UL|DL)$/i.test(typeof node === 'string' ? node : node.nodeName); }, /** @@ -1038,6 +1038,35 @@ const util = { return cc; }, + /** + * @description Remove nested tags without other child nodes. + * @param {Element} element Element object + * @param {Function|String|null} validation Validation function / String("tag1|tag2..") / If null, all tags are applicable. + */ + removeNestedTags: function (element, validation) { + if (typeof validation === 'string') { + validation = function (current) { return this.test(current.tagName); }.bind(new this._w.RegExp('^(' + (validation ? validation : '.+') + ')$', 'i')); + } else if (typeof validation !== 'function') { + validation = function () { return true; }; + } + + (function recursionFunc(current) { + let children = current.children; + if (element !== current && children.length === 1 && children[0].nodeName === current.nodeName && validation(current)) { + const temp = children[0]; + children = temp.children; + while (children[0]) { + current.appendChild(children[0]); + } + current.removeChild(temp); + } + + for (let i = 0, len = current.children.length; i < len; i++) { + recursionFunc(current.children[i]); + } + })(element); + }, + /** * @description Delete a empty child node of argument element * @param {Element} element Element node diff --git a/src/plugins/submenu/list.js b/src/plugins/submenu/list.js index 90a0abf4f..740fd2bdf 100644 --- a/src/plugins/submenu/list.js +++ b/src/plugins/submenu/list.js @@ -272,7 +272,7 @@ export default { } range = this.plugins.list.editList.call(this, originList.nodeName.toUpperCase(), selectedCells); } else { - range = { sc: selectedCells[0], so: cellsLen > 1 ? 0 : 1, ec: lastCell, eo: 1 }; + range = { sc: selectedCells[0], so: cellsLen > 1 || !this.getRange().collapsed ? 0 : 1, ec: lastCell, eo: 1 }; let innerList = this.util.createElement(originList.nodeName); let prev = range.sc.previousElementSibling; let next = range.sc.nextElementSibling; diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index 1063edd8e..e0672d1e7 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -53,6 +53,7 @@ let s1 = suneditor.create('editor', { ], width: '100%', height: 'auto', + // fullPage: true, // pasteTagsWhitelist: 'p|h[1-6]', formats: [ { @@ -110,7 +111,7 @@ window.sun_create1 = function () { let ss = window.ss = suneditor.create(document.getElementById('editor1'), { // lang: lang.ko, plugins: plugins, - mode: 'balloon', + // mode: 'balloon', buttonList: [ ['undo', 'redo', 'font', 'fontSize', 'formatBlock', @@ -125,12 +126,12 @@ let ss = window.ss = suneditor.create(document.getElementById('editor1'), { 'preview', 'print', 'save', 'template'] ], katex: Katex, - height: 'auto', + height: '400', width: '100%', youtubeQuery :'autoplay=1&mute=1&enablejsapi=1', placeholder: 'SSSFdjskfdsff.f.fdsa.f...', fullPage: true, - addTagsWhitelist: 'mark|canvas|label|select|option|input', + addTagsWhitelist: 'mark|canvas|label|select|option|input|style|nav|button', imageUploadUrl: 'http://localhost:3000/files/upload', // mode: 'inline' // videoHeightShow: false, @@ -219,7 +220,7 @@ window.sun_getContents = function () { } window.sun_setContents = function (content) { - ss.setContents('



    '); + ss.setContents('



    '); ss.core.history.reset(true); // ss.core.context.tool.save.disabled = true; } From 762b06caf2621d914d6d8104b82d25f9341a0568 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Wed, 26 Feb 2020 16:17:48 +0900 Subject: [PATCH 51/99] fix:#226 history remove when call destory function --- src/lib/core.js | 3 +++ src/lib/history.js | 5 +++++ test/dev/suneditor_build_test.js | 13 ++++++++++++- 3 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/lib/core.js b/src/lib/core.js index 541cb4325..fbd86712a 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -4928,6 +4928,9 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { * @description Destroy the suneditor */ destroy: function () { + /** remove history */ + core.history._destroy(); + /** remove event listeners */ event._removeEvent(); diff --git a/src/lib/history.js b/src/lib/history.js index 9cdfc4789..bc28eb81f 100644 --- a/src/lib/history.js +++ b/src/lib/history.js @@ -160,6 +160,11 @@ export default function (core, change) { }; if (!ignoreChangeEvent) change(); + }, + + _destroy: function () { + if (pushDelay) _w.clearTimeout(pushDelay); + stack = null; } }; } \ No newline at end of file diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index e0672d1e7..28e59fbe9 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -216,7 +216,18 @@ window.sun_insertHTML = function (html) { window.sun_getContents = function () { // alert(ss.getContents()); - console.log(ss.getContents()); + + // console.log(ss.getContents()); + + // ss.core.commandHandler(null, 'selectAll') + // let t = ''; + // const lines = ss.core.getSelectedElements(); + // for (let i = 0, len = lines.length; i < len; i++) { + // t += lines[i].textContent + '\n'; + // } + // console.log(t); + + console.log(ss.core.context.element.wysiwyg.textContent) } window.sun_setContents = function (content) { From 4bfd6037c6b32e4ea822207348bd132482809f09 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Wed, 26 Feb 2020 17:41:56 +0900 Subject: [PATCH 52/99] modify: core-appendFormatTag --- sample/html/out/document-editor.html | 10 +++++----- src/lib/core.js | 18 +++++++++++------- src/lib/history.js | 4 ++++ 3 files changed, 20 insertions(+), 12 deletions(-) diff --git a/sample/html/out/document-editor.html b/sample/html/out/document-editor.html index 0fb4c7619..b4f8f3cb7 100644 --- a/sample/html/out/document-editor.html +++ b/sample/html/out/document-editor.html @@ -988,10 +988,10 @@

    closeLoad

    appendFormatTag(element, formatNodeName) → {Element}

    + class="signature">(element, formatNode) → {Element}
    Append format element to sibling node of argument element.
    - If the "formatNodeName" argument value is present, the tag of that argument value is inserted,
    + If the "formatNode" argument value is present, the tag of that argument value is inserted,
    If not, the currently selected format tag is inserted.
    Returns the inserted element.
    @@ -1013,11 +1013,11 @@
    Parameters:
    Insert as siblings of that element
    formatNodeNameformatNode - String | null + String|Element|null Node name to be insertedNode name or node obejct to be inserted
    diff --git a/src/lib/core.js b/src/lib/core.js index fbd86712a..2de3c9a4b 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -700,16 +700,20 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { * If the "formatNodeName" argument value is present, the tag of that argument value is inserted, * If not, the currently selected format tag is inserted. * @param {Element} element Insert as siblings of that element - * @param {String|null} formatNodeName Node name to be inserted + * @param {String|Element|null} formatNode Node name or node obejct to be inserted * @returns {Element} */ - appendFormatTag: function (element, formatNodeName) { + appendFormatTag: function (element, formatNode) { const formatEl = element; const currentFormatEl = util.getFormatElement(this.getSelectionNode()); - const oFormatName = formatNodeName ? formatNodeName : util.isFormatElement(currentFormatEl) ? currentFormatEl.nodeName : 'P'; + const oFormatName = formatNode ? (typeof formatNode === 'string' ? formatNode : formatNode.nodeName) : util.isFormatElement(currentFormatEl) ? currentFormatEl.nodeName : 'P'; const oFormat = util.createElement(oFormatName); oFormat.innerHTML = '
    '; + if ((formatNode && typeof formatNode !== 'string') || (!formatNode && util.isFormatElement(currentFormatEl))) { + util.copyTagAttributes(oFormat, formatNode || currentFormatEl); + } + if (util.isCell(formatEl)) formatEl.insertBefore(oFormat, element.nextElementSibling); else formatEl.parentNode.insertBefore(oFormat, formatEl.nextElementSibling); @@ -745,7 +749,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { } } else { this.insertNode(element, formatEl); - oNode = this.appendFormatTag(element); + oNode = this.appendFormatTag(element, null); } // history stack @@ -1038,7 +1042,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (parentDepth >= depth) { parentDepth = depth; pElement = edge.cc; - beforeTag = removeItems(pElement, originParent, edge.ec); + beforeTag = removeItems(pElement, originParent, depth > 1 ? edge.sc : edge.ec); if (beforeTag) pElement = beforeTag.parentNode; } else if (pElement === edge.cc) { beforeTag = edge.ec; @@ -4145,7 +4149,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { (!selectionFormat && util.onlyZeroWidthSpace(selectionNode.textContent) && util.isBreak(prev) && (util.isBreak(prev.previousSibling) || !util.onlyZeroWidthSpace(prev.previousSibling.textContent)) && (!next || (!util.isBreak(next) && util.onlyZeroWidthSpace(next.textContent))))) { if (selectionFormat) util.removeItem(children[offset - 1]); else util.removeItem(selectionNode); - const newEl = core.appendFormatTag(freeFormatEl, freeFormatEl.nextElementSibling ? freeFormatEl.nextElementSibling.nodeName : 'P'); + const newEl = core.appendFormatTag(freeFormatEl, freeFormatEl.nextElementSibling ? freeFormatEl.nextElementSibling : 'P'); util.copyFormatAttributes(newEl, freeFormatEl); core.setRange(newEl, 1, newEl, 1); break; @@ -4198,7 +4202,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (rangeEl && figcaption && util.getParentElement(rangeEl, util.isList)) { e.preventDefault(); - formatEl = core.appendFormatTag(formatEl); + formatEl = core.appendFormatTag(formatEl, null); core.setRange(formatEl, 0, formatEl, 0); } diff --git a/src/lib/history.js b/src/lib/history.js index bc28eb81f..4620259b8 100644 --- a/src/lib/history.js +++ b/src/lib/history.js @@ -162,6 +162,10 @@ export default function (core, change) { if (!ignoreChangeEvent) change(); }, + /** + * @description Remove all stacks and remove the timeout function. + * @private + */ _destroy: function () { if (pushDelay) _w.clearTimeout(pushDelay); stack = null; From 1f638dd05b69bf19b8d1c8524999e98c0a1ee35a Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Wed, 26 Feb 2020 17:55:15 +0900 Subject: [PATCH 53/99] fix: typo --- src/lib/core.js | 104 ++++++++++++++++++++++++------------------------ 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/src/lib/core.js b/src/lib/core.js index 2de3c9a4b..a18309ae5 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -20,10 +20,10 @@ import notice from '../plugins/modules/notice'; * @param context * @param plugins * @param lang - * @param _options + * @param options * @returns {Object} UserFunction Object */ -export default function (context, pluginCallButtons, plugins, lang, _options) { +export default function (context, pluginCallButtons, plugins, lang, options) { const _d = context.element.originElement.ownerDocument || document; const _w = _d.defaultView || window; const util = _util; @@ -447,7 +447,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { focus: function () { if (context.element.wysiwygFrame.style.display === 'none') return; - if (context.option.iframe) { + if (options.iframe) { this._nativeFocus(); } else { try { @@ -2838,8 +2838,8 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { util.toggleClass(target, 'active'); break; case 'save': - if (typeof context.option.callBackSave === 'function') { - context.option.callBackSave(this.getContents(false)); + if (typeof options.callBackSave === 'function') { + options.callBackSave(this.getContents(false)); } else if (typeof userFunction.save === 'function') { userFunction.save(); } else { @@ -2926,13 +2926,13 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { this._variable._codeOriginCssText = this._variable._codeOriginCssText.replace(/(\s?display(\s+)?:(\s+)?)[a-zA-Z]+(?=;)/, 'display: none'); this._variable._wysiwygOriginCssText = this._variable._wysiwygOriginCssText.replace(/(\s?display(\s+)?:(\s+)?)[a-zA-Z]+(?=;)/, 'display: block'); - if (context.option.height === 'auto' && !context.option.codeMirrorEditor) context.element.code.style.height = '0px'; + if (options.height === 'auto' && !options.codeMirrorEditor) context.element.code.style.height = '0px'; this._variable.isCodeView = false; if (!this._variable.isFullScreen) { this._notHideToolbar = false; - if (/balloon/i.test(context.option.mode)) { + if (/balloon/i.test(options.mode)) { context.element._arrow.style.display = ''; this._isInline = false; this._isBalloon = true; @@ -2951,8 +2951,8 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { this._variable._codeOriginCssText = this._variable._codeOriginCssText.replace(/(\s?display(\s+)?:(\s+)?)[a-zA-Z]+(?=;)/, 'display: block'); this._variable._wysiwygOriginCssText = this._variable._wysiwygOriginCssText.replace(/(\s?display(\s+)?:(\s+)?)[a-zA-Z]+(?=;)/, 'display: none'); - if (context.option.height === 'auto' && !context.option.codeMirrorEditor) context.element.code.style.height = context.element.code.scrollHeight > 0 ? (context.element.code.scrollHeight + 'px') : 'auto'; - if (context.option.codeMirrorEditor) context.option.codeMirrorEditor.refresh(); + if (options.height === 'auto' && !options.codeMirrorEditor) context.element.code.style.height = context.element.code.scrollHeight > 0 ? (context.element.code.scrollHeight + 'px') : 'auto'; + if (options.codeMirrorEditor) options.codeMirrorEditor.refresh(); this._variable.isCodeView = true; @@ -2981,7 +2981,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { _setCodeDataToEditor: function () { const code_html = this._getCodeView(); - if (context.option.fullPage) { + if (options.fullPage) { const parseDocument = (new this._w.DOMParser()).parseFromString(code_html, 'text/html'); const headChildren = parseDocument.head.children; @@ -3014,7 +3014,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { const codeContents = util.convertHTMLForCodeView(context.element.wysiwyg, this._variable.codeIndent); let codeValue = ''; - if (context.option.fullPage) { + if (options.fullPage) { const attrs = util.getAttributesToString(this._wd.body, null); codeValue = '\n\n' + this._wd.head.outerHTML.replace(/>(?!\n)/g, '>\n') + '\n' + codeContents + '\n'; } else { @@ -3083,7 +3083,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { util.removeClass(element.firstElementChild, 'se-icon-expansion'); util.addClass(element.firstElementChild, 'se-icon-reduction'); - if (context.option.iframe && context.option.height === 'auto') { + if (options.iframe && options.height === 'auto') { editorArea.style.overflow = 'auto'; this._iframeAutoHeight(); } @@ -3098,7 +3098,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { topArea.style.cssText = _var._originCssText; _d.body.style.overflow = _var._bodyOverflow; - if (context.option.stickyToolbar > -1) { + if (options.stickyToolbar > -1) { util.removeClass(toolbar, 'se-toolbar-sticky'); } @@ -3130,9 +3130,9 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { const printDocument = util.getIframeDocument(iframe); const contentsHTML = this.getContents(true); - if (context.option.iframe) { + if (options.iframe) { const wDocument = util.getIframeDocument(context.element.wysiwygFrame); - const arrts = context.option.fullPage ? util.getAttributesToString(wDocument.body, ['contenteditable']) : 'class="sun-editor-editable"'; + const arrts = options.fullPage ? util.getAttributesToString(wDocument.body, ['contenteditable']) : 'class="sun-editor-editable"'; printDocument.write('' + '' + @@ -3183,9 +3183,9 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { const windowObject = _w.open('', '_blank'); windowObject.mimeType = 'text/html'; - if (context.option.iframe) { + if (options.iframe) { const wDocument = util.getIframeDocument(context.element.wysiwygFrame); - const arrts = context.option.fullPage ? util.getAttributesToString(wDocument.body, ['contenteditable']) : 'class="sun-editor-editable"'; + const arrts = options.fullPage ? util.getAttributesToString(wDocument.body, ['contenteditable']) : 'class="sun-editor-editable"'; windowObject.document.write('' + '' + @@ -3247,7 +3247,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { figcaptions[i].removeAttribute('contenteditable'); } - if (context.option.fullPage && !onlyContents) { + if (options.fullPage && !onlyContents) { const attrs = util.getAttributesToString(this._wd.body, ['contenteditable']); return '' + this._wd.head.outerHTML + '' + renderHTML.innerHTML + ''; } else { @@ -3264,7 +3264,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { */ addDocEvent: function (type, listener, useCapture) { _d.addEventListener(type, listener, useCapture); - if (context.option.iframe) { + if (options.iframe) { this._wd.addEventListener(type, listener); } }, @@ -3277,7 +3277,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { */ removeDocEvent: function (type, listener) { _d.removeEventListener(type, listener); - if (context.option.iframe) { + if (options.iframe) { this._wd.removeEventListener(type, listener); } }, @@ -3293,7 +3293,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (!charCounter) return true; if (!nextCharCount || nextCharCount < 0) nextCharCount = 0; - const maxCharCount = context.option.maxCharCount; + const maxCharCount = options.maxCharCount; _w.setTimeout(function () { charCounter.textContent = context.element.wysiwyg.textContent.length; @@ -3363,8 +3363,8 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { * @private */ _setCodeView: function (value) { - if (context.option.codeMirrorEditor) { - context.option.codeMirrorEditor.getDoc().setValue(value); + if (options.codeMirrorEditor) { + options.codeMirrorEditor.getDoc().setValue(value); } else { context.element.code.value = value; } @@ -3375,7 +3375,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { * @private */ _getCodeView: function () { - return context.option.codeMirrorEditor ? context.option.codeMirrorEditor.getDoc().getValue() : context.element.code.value; + return options.codeMirrorEditor ? options.codeMirrorEditor.getDoc().getValue() : context.element.code.value; }, /** @@ -3383,7 +3383,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { * @private */ _init: function (reload) { - this._ww = context.option.iframe ? context.element.wysiwygFrame.contentWindow : _w; + this._ww = options.iframe ? context.element.wysiwygFrame.contentWindow : _w; this._wd = _d; _w.setTimeout(function () { @@ -3393,10 +3393,10 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { this.history.reset(true); - if (_options.iframe) { + if (options.iframe) { this._wd = context.element.wysiwygFrame.contentDocument; context.element.wysiwyg = this._wd.body; - if (_options.height === 'auto') { + if (options.height === 'auto') { this._iframeAuto = this._wd.body; } this._iframeAutoHeight(); @@ -3405,12 +3405,12 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { if (typeof userFunction.onload === 'function') return userFunction.onload(core, reload); }.bind(this)); - this.editorTagsWhitelistRegExp = util.createTagsWhitelist(context.option._editorTagsWhitelist); - this.pasteTagsWhitelistRegExp = util.createTagsWhitelist(context.option.pasteTagsWhitelist); + this.editorTagsWhitelistRegExp = util.createTagsWhitelist(options._editorTagsWhitelist); + this.pasteTagsWhitelistRegExp = util.createTagsWhitelist(options.pasteTagsWhitelist); this.codeViewDisabledButtons = context.element.toolbar.querySelectorAll('.se-toolbar button:not([class~="code-view-enabled"])'); - this._isInline = /inline/i.test(context.option.mode); - this._isBalloon = /balloon/i.test(context.option.mode); + this._isInline = /inline/i.test(options.mode); + this._isBalloon = /balloon/i.test(options.mode); this.commandMap = { SIZE: context.tool.fontSize, @@ -3619,7 +3619,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { core._variable.currentNodes = currentNodes.reverse(); /** Displays the current node structure to resizingBar */ - if (context.option.showPathLabel) context.element.navigation.textContent = core._variable.currentNodes.join(' > '); + if (options.showPathLabel) context.element.navigation.textContent = core._variable.currentNodes.join(' > '); }, _cancelCaptionEdit: function () { @@ -3887,7 +3887,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { const toolbar = context.element.toolbar; toolbar.style.visibility = 'hidden'; toolbar.style.display = 'block'; - core._inlineToolbarAttr.width = toolbar.style.width = context.option.toolbarWidth; + core._inlineToolbarAttr.width = toolbar.style.width = options.toolbarWidth; core._inlineToolbarAttr.top = toolbar.style.top = (-1 - toolbar.offsetHeight) + 'px'; if (typeof userFunction.showInline === 'function') userFunction.showInline(toolbar, context, core); @@ -4388,11 +4388,11 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { }, onScroll_window: function () { - if (core._variable.isFullScreen || context.element.toolbar.offsetWidth === 0 || context.option.stickyToolbar < 0) return; + if (core._variable.isFullScreen || context.element.toolbar.offsetWidth === 0 || options.stickyToolbar < 0) return; const element = context.element; const editorHeight = element.editorArea.offsetHeight; - const y = (this.scrollY || _d.documentElement.scrollTop) + context.option.stickyToolbar; + const y = (this.scrollY || _d.documentElement.scrollTop) + options.stickyToolbar; const editorTop = event._getStickyOffsetTop() - (core._isInline ? element.toolbar.offsetHeight : 0); if (y < editorTop) { @@ -4400,7 +4400,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { } else if (y + core._variable.minResizingSize >= editorHeight + editorTop) { if (!core._sticky) event._onStickyToolbar(); - element.toolbar.style.top = (editorHeight + editorTop + context.option.stickyToolbar -y - core._variable.minResizingSize) + 'px'; + element.toolbar.style.top = (editorHeight + editorTop + options.stickyToolbar -y - core._variable.minResizingSize) + 'px'; } else if (y >= editorTop) { event._onStickyToolbar(); @@ -4427,7 +4427,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { element._stickyDummy.style.display = 'block'; } - element.toolbar.style.top = context.option.stickyToolbar + 'px'; + element.toolbar.style.top = options.stickyToolbar + 'px'; element.toolbar.style.width = core._isInline ? core._inlineToolbarAttr.width : element.toolbar.offsetWidth + 'px'; util.addClass(element.toolbar, 'se-toolbar-sticky'); core._sticky = true; @@ -4536,7 +4536,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { }, _addEvent: function () { - const eventWysiwyg = _options.iframe ? core._ww : context.element.wysiwyg; + const eventWysiwyg = options.iframe ? core._ww : context.element.wysiwyg; /** toolbar event */ context.element.toolbar.addEventListener('mousedown', event.onMouseDown_toolbar, false); @@ -4563,7 +4563,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { } /** code view area auto line */ - if (context.option.height === 'auto' && !context.option.codeMirrorEditor) { + if (options.height === 'auto' && !options.codeMirrorEditor) { context.element.code.addEventListener('keydown', event._codeViewAutoHeight, false); context.element.code.addEventListener('keyup', event._codeViewAutoHeight, false); context.element.code.addEventListener('paste', event._codeViewAutoHeight, false); @@ -4571,7 +4571,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { /** resizingBar */ if (context.element.resizingBar) { - if (/\d+/.test(context.option.height)) { + if (/\d+/.test(options.height)) { context.element.resizingBar.addEventListener('mousedown', event.onMouseDown_resizingBar, false); } else { util.addClass(context.element.resizingBar, 'se-resizing-none'); @@ -4588,13 +4588,13 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { _w.removeEventListener('scroll', event.onScroll_window); _w.addEventListener('resize', event.onResize_window, false); - if (context.option.stickyToolbar > -1) { + if (options.stickyToolbar > -1) { _w.addEventListener('scroll', event.onScroll_window, false); } }, _removeEvent: function () { - const eventWysiwyg = _options.iframe ? core._ww : context.element.wysiwyg; + const eventWysiwyg = options.iframe ? core._ww : context.element.wysiwyg; context.element.toolbar.removeEventListener('mousedown', event.onMouseDown_toolbar); context.element.toolbar.removeEventListener('click', event.onClick_toolbar); @@ -4708,7 +4708,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { event._removeEvent(); core.plugins = options.plugins || core.plugins; - const mergeOptions = [context.option, options].reduce(function (init, option) { + const mergeOptions = [options, options].reduce(function (init, option) { for (let key in option) { if (key === 'plugins' && option[key] && init[key]) { let i = init[key], o = option[key]; @@ -4722,7 +4722,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { return init; }, {}); - const cons = _Constructor._setOptions(mergeOptions, context, core.plugins, context.option); + const cons = _Constructor._setOptions(mergeOptions, context, core.plugins, options); if (cons.callButtons) { pluginCallButtons = cons.callButtons; @@ -4752,9 +4752,9 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { _arrow: el._arrow }; - _options = mergeOptions; - core.lang = lang = _options.lang; - core.context = context = _Context(context.element.originElement, constructed, _options); + options = mergeOptions; + core.lang = lang = options.lang; + core.context = context = _Context(context.element.originElement, constructed, options); core._imagesInfoReset = true; core._init(true); @@ -4892,8 +4892,8 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { context.tool.cover.style.display = 'block'; context.element.wysiwyg.setAttribute('contenteditable', false); - if (context.option.codeMirrorEditor) { - context.option.codeMirrorEditor.setOption('readOnly', true); + if (options.codeMirrorEditor) { + options.codeMirrorEditor.setOption('readOnly', true); } else { context.element.code.setAttribute('disabled', 'disabled'); } @@ -4906,8 +4906,8 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { context.tool.cover.style.display = 'none'; context.element.wysiwyg.setAttribute('contenteditable', true); - if (context.option.codeMirrorEditor) { - context.option.codeMirrorEditor.setOption('readOnly', false); + if (options.codeMirrorEditor) { + options.codeMirrorEditor.setOption('readOnly', false); } else { context.element.code.removeAttribute('disabled'); } @@ -4918,7 +4918,7 @@ export default function (context, pluginCallButtons, plugins, lang, _options) { */ show: function () { const topAreaStyle = context.element.topArea.style; - if (topAreaStyle.display === 'none') topAreaStyle.display = context.option.display; + if (topAreaStyle.display === 'none') topAreaStyle.display = options.display; }, /** From a0546f2b81452e9e696fe78bbd2bf68693be7c53 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Wed, 26 Feb 2020 18:49:59 +0900 Subject: [PATCH 54/99] delete: whitelist - dl --- README.md | 2 +- sample/html/out/document-editor.html | 2 +- sample/html/out/document-util.html | 10 +++++----- src/lib/constructor.js | 2 +- src/lib/core.js | 2 +- src/lib/util.js | 12 ++++++------ 6 files changed, 15 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 81c84c152..e23428507 100644 --- a/README.md +++ b/README.md @@ -315,7 +315,7 @@ plugins: [ ] : Plugins array. default: null {Array} // Tags whitelist--------------------------------------å--------------------------------------------------------- -// _defaultTagsWhitelist : 'br|p|div|pre|blockquote|h[1-6]|ol|ul|dl|li|hr|figure|figcaption|img|iframe|audio|video|table|thead|tbody|tr|th|td|a|b|strong|var|i|em|u|ins|s|span|strike|del|sub|sup' +// _defaultTagsWhitelist : 'br|p|div|pre|blockquote|h[1-6]|ol|ul|li|hr|figure|figcaption|img|iframe|audio|video|table|thead|tbody|tr|th|td|a|b|strong|var|i|em|u|ins|s|span|strike|del|sub|sup' addTagsWhitelist : Add tags to the default tags whitelist of editor. default: '' {String} ex) 'mark|canvas|label|select|option|input' // _editorTagsWhitelist : _defaultTagsWhitelist + addTagsWhitelist diff --git a/sample/html/out/document-editor.html b/sample/html/out/document-editor.html index b4f8f3cb7..aa310b133 100644 --- a/sample/html/out/document-editor.html +++ b/sample/html/out/document-editor.html @@ -1159,7 +1159,7 @@
    Parameters:
    Element - Element of wrap the arguments (PRE, BLOCKQUOTE...) + Element of wrap the arguments (BLOCKQUOTE...) diff --git a/sample/html/out/document-util.html b/sample/html/out/document-util.html index 6d3dfeb95..3e611edc9 100644 --- a/sample/html/out/document-util.html +++ b/sample/html/out/document-util.html @@ -364,7 +364,7 @@
    Parameters:

    isFormatElement(element) → {Boolean}

    - It is judged whether it is the format element. (P, DIV, H1-6, PRE, LI)
    + It is judged whether it is the format element. (P, DIV, H[1-6], PRE, LI)
    Format element also contain "free format Element"
    Parameters:
    @@ -393,7 +393,7 @@

    i class="type-signature"> → {Boolean}

    It is judged whether it is the range format element. (BLOCKQUOTE, OL, UL, FIGCAPTION, TABLE, THEAD, TBODY, TR, TH, TD)
    - Range format element is wrap the format element (P, DIV, H1-6, PRE, LI) + Range format element is wrap the format element (util.isFormatElement)
    Parameters:
    @@ -476,7 +476,7 @@
    Parameters:

    getFormatElement(element, validation) → {Element}

    - If a parent node that contains an argument node finds a format node (P, DIV, H[1-6], LI), it returns that node. + If a parent node that contains an argument node finds a format node (util.isFormatElement), it returns that node.
    Parameters:
    @@ -510,7 +510,7 @@
    Parameters:

    getRangeFormatElement(element, validation) → {Element|null}

    - If a parent node that contains an argument node finds a format node (BLOCKQUOTE, TABLE, TH, TD, OL, UL, PRE), it returns that node. + If a parent node that contains an argument node finds a format node (util.isRangeFormatElement), it returns that node.
    Parameters:
    @@ -544,7 +544,7 @@
    Parameters:

    getFreeFormatElement(element, validation) → {Element|null}

    - If a parent node that contains an argument node finds a free format node (PRE), it returns that node. + If a parent node that contains an argument node finds a free format node (util.isFreeFormatElement), it returns that node.
    Parameters:
    diff --git a/src/lib/constructor.js b/src/lib/constructor.js index 42ccf73c9..b9d4b44a1 100755 --- a/src/lib/constructor.js +++ b/src/lib/constructor.js @@ -386,7 +386,7 @@ export default { /** user options */ options.lang = options.lang || _defaultLang; /** Tags whitelist */ - options._defaultTagsWhitelist = typeof options._defaultTagsWhitelist === 'string' ? options._defaultTagsWhitelist : 'br|p|div|pre|blockquote|h[1-6]|ol|ul|dl|li|hr|figure|figcaption|img|iframe|audio|video|table|thead|tbody|tr|th|td|a|b|strong|var|i|em|u|ins|s|span|strike|del|sub|sup'; + options._defaultTagsWhitelist = typeof options._defaultTagsWhitelist === 'string' ? options._defaultTagsWhitelist : 'br|p|div|pre|blockquote|h[1-6]|ol|ul|li|hr|figure|figcaption|img|iframe|audio|video|table|thead|tbody|tr|th|td|a|b|strong|var|i|em|u|ins|s|span|strike|del|sub|sup'; options._editorTagsWhitelist = options._defaultTagsWhitelist + (typeof options.addTagsWhitelist === 'string' && options.addTagsWhitelist.length > 0 ? '|' + options.addTagsWhitelist : ''); options.pasteTagsWhitelist = typeof options.pasteTagsWhitelist === 'string' ? options.pasteTagsWhitelist : options._editorTagsWhitelist; /** Layout */ diff --git a/src/lib/core.js b/src/lib/core.js index a18309ae5..65f10ceaf 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -982,7 +982,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { /** * @description Appended all selected format Element to the argument element and insert - * @param {Element} rangeElement Element of wrap the arguments (PRE, BLOCKQUOTE...) + * @param {Element} rangeElement Element of wrap the arguments (BLOCKQUOTE...) */ applyRangeFormatElement: function (rangeElement) { const rangeLines = this.getSelectedElementsAndComponents(); diff --git a/src/lib/util.js b/src/lib/util.js index 913d87497..66225a1f6 100755 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -303,7 +303,7 @@ const util = { }, /** - * @description It is judged whether it is the format element (P, DIV, H1-6, PRE, LI) + * @description It is judged whether it is the format element (P, DIV, H[1-6], PRE, LI) * Format element also contain "free format Element" * @param {Element} element The element to check * @returns {Boolean} @@ -315,7 +315,7 @@ const util = { /** * @description It is judged whether it is the range format element. (BLOCKQUOTE, OL, UL, FIGCAPTION, TABLE, THEAD, TBODY, TR, TH, TD) - * * Range format element is wrap the format element (P, DIV, H1-6, PRE, LI) + * * Range format element is wrap the format element (util.isFormatElement) * @param {Element} element The element to check * @returns {Boolean} */ @@ -346,7 +346,7 @@ const util = { }, /** - * @description If a parent node that contains an argument node finds a format node (P, DIV, H[1-6], PRE, LI), it returns that node. + * @description If a parent node that contains an argument node finds a format node (util.isFormatElement), it returns that node. * @param {Element} element Reference element if null or no value, it is relative to the current focus node. * @param {Function|null} validation Additional validation function. * @returns {Element} @@ -369,7 +369,7 @@ const util = { }, /** - * @description If a parent node that contains an argument node finds a format node (BLOCKQUOTE, TABLE, TH, TD, OL, UL, TH, TD), it returns that node. + * @description If a parent node that contains an argument node finds a format node (util.isRangeFormatElement), it returns that node. * @param {Element} element Reference element if null or no value, it is relative to the current focus node. * @param {Function|null} validation Additional validation function. * @returns {Element|null} @@ -390,7 +390,7 @@ const util = { }, /** - * @description If a parent node that contains an argument node finds a free format node (PRE), it returns that node. + * @description If a parent node that contains an argument node finds a free format node (util.isFreeFormatElement), it returns that node. * @param {Element} element Reference element if null or no value, it is relative to the current focus node. * @param {Function|null} validation Additional validation function. * @returns {Element} @@ -609,7 +609,7 @@ const util = { * @returns {Boolean} */ isList: function (node) { - return node && /^(OL|UL|DL)$/i.test(typeof node === 'string' ? node : node.nodeName); + return node && /^(OL|UL)$/i.test(typeof node === 'string' ? node : node.nodeName); }, /** From fa7e683abc80e5e13a87a7a6c0c528954f6668ce Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Thu, 27 Feb 2020 03:35:12 +0900 Subject: [PATCH 55/99] update: #217 applyRangeFormatElement - nested tags update: nested list css style add: core-splitNestedElement change: util-removeNestedTags > mergeNestedTags --- sample/html/out/document-editor.html | 41 ++++++++++++-- sample/html/out/document-util.html | 18 ++++-- src/assets/css/suneditor-contents.css | 13 +++++ src/assets/css/suneditor.css | 28 +++++----- src/lib/core.js | 79 ++++++++++++++++++++++----- src/lib/util.js | 14 +++-- src/plugins/command/blockquote.js | 2 +- 7 files changed, 151 insertions(+), 44 deletions(-) diff --git a/sample/html/out/document-editor.html b/sample/html/out/document-editor.html index aa310b133..c2a5134ce 100644 --- a/sample/html/out/document-editor.html +++ b/sample/html/out/document-editor.html @@ -904,7 +904,7 @@

    getSe

    getSelectedElements(validation) → {Array}

    - Returns a "formatElement"(P, DIV, H[1-6], LI) array from the currently selected range. + Returns a "formatElement"(util.isFormatElement) array from the currently selected range.
    Parameters:
    @@ -921,7 +921,7 @@
    Parameters:
    - +
    Function|null The validation function. (Replaces the default validation function-util.isFormatElement(current))The validation function. (Replaces the default validation function-util.isFormatElement)
    @@ -1054,7 +1054,7 @@
    Parameters:
    Boolean - When true, it does not update the history stack and the selection object and return EdgeNodes (util.getEdgeChildNodes) + When true, it does not update the history stack and the selection object and return EdgeNodes (util.getEdgeChildNodes) @@ -1139,6 +1139,34 @@

    removeNode<
    +

    splitNestedElement(beforeTag) → {Element}

    +
    + Split all nested tags based on "beforeTag"
    + Returns the last element of the splited tag. +
    +
    Parameters:
    + + + + + + + + + + + + + + + +
    NameTypeDescription
    beforeTag + Element + Criteria element
    +
    + +

    applyRangeFormatElement(rangeElement)

    @@ -1170,7 +1198,7 @@

    The elements of the "selectedFormats" array are detached from the "rangeElement" element. ("LI" tags are converted to "P" tags)
    - When "selectedFormats" is null, all elements are detached and return {cc: parentNode, sc: nextSibling, ec: previousSibling}. + When "selectedFormats" is null, all elements are detached and return {cc: parentNode, sc: previousSibling, ec: nextSibling}.
    Parameters:
    @@ -1195,7 +1223,7 @@
    Parameters:
    Array|null + If null, Applies to all elements and return {cc: parentNode, sc: previousSibling, ec: nextSibling} @@ -1216,7 +1244,7 @@
    Parameters:
    - +
    Array of format elements (P, DIV, LI...) to remove.
    - If null, Applies to all elements and return {cc: parentNode, sc: nextSibling, ec: previousSibling}
    newRangeElement Boolean When true, it does not update the history stack and the selection object and return EdgeNodes (util.getEdgeChildNodes)When true, it does not update the history stack and the selection object and return EdgeNodes (util.getEdgeChildNodes)
    @@ -1605,6 +1633,7 @@

    core

  • selectComponent
  • insertNode
  • removeNode
  • +
  • splitNestedElement
  • applyRangeFormatElement
  • detachRangeFormatElement
  • nodeChange
  • diff --git a/sample/html/out/document-util.html b/sample/html/out/document-util.html index 3e611edc9..4ce70f533 100644 --- a/sample/html/out/document-util.html +++ b/sample/html/out/document-util.html @@ -1189,7 +1189,8 @@

    getEle

    Returns the number of parents nodes.
    - "0" when the parent node is the WYSIWYG area. + "0" when the parent node is the WYSIWYG area.
    + "-1" when the element argument is the WYSIWYG area.
    Parameters:
    @@ -1660,7 +1661,7 @@
    Parameters:
    -

    removeItemAllParents(item, validation)removeItemAllParents(item, validation, stopParent) → {Object|null}

    Delete all parent nodes that match the condition.
    @@ -1690,15 +1691,22 @@
    Parameters:
    + + + + +
    Validation function. default(Deleted if it only have breakLine and blanks)
    stopParent + Element|null + Stop when the parent node reaches stopParent
    -

    removeNestedTags(element, validation)mergeNestedTags(element, validation)

    - Remove nested tags without other child nodes. + Merge nested tags without other child nodes.
    Parameters:
    @@ -1892,7 +1900,7 @@

    util

  • toggleClass
  • removeItem
  • removeItemAllParents
  • -
  • removeNestedTags
  • +
  • mergeNestedTags
  • removeEmptyNode
  • cleanHTML
  • createTagsWhitelist
  • diff --git a/src/assets/css/suneditor-contents.css b/src/assets/css/suneditor-contents.css index 83241dc32..dfab77317 100644 --- a/src/assets/css/suneditor-contents.css +++ b/src/assets/css/suneditor-contents.css @@ -107,6 +107,19 @@ text-align: -webkit-match-parent; margin-bottom: 5px; } +/* nested ol, ul */ +.sun-editor-editable ol ol, .sun-editor-editable ul ol { + list-style-type: lower-alpha; +} +.sun-editor-editable ol ol ol, .sun-editor-editable ul ol ol, .sun-editor-editable ul ul ol { + list-style-type: upper-roman; +} +.sun-editor-editable ul ul, .sun-editor-editable ol ul { + list-style-type: circle; +} +.sun-editor-editable ul ul ul, .sun-editor-editable ol ul ul, .sun-editor-editable ol ol ul { + list-style-type: square; +} /* sub, sup */ .sun-editor-editable sub, .sun-editor-editable sup { diff --git a/src/assets/css/suneditor.css b/src/assets/css/suneditor.css index 7225673ef..4bf36868e 100755 --- a/src/assets/css/suneditor.css +++ b/src/assets/css/suneditor.css @@ -137,11 +137,11 @@ .sun-editor button {color:#000;} /** --- se-btn button */ -.sun-editor .se-btn {float:left; width:35px; height:35px; border:0; border-radius:3px; margin:1px !important; padding:0; font-size:12px; line-height:27px;} +.sun-editor .se-btn {float:left; width:35px; height:35px; border:0; border-radius:4px; margin:1px !important; padding:0; font-size:12px; line-height:27px;} .sun-editor .se-btn:enabled:hover, .sun-editor .se-btn:enabled:focus {background-color:#e1e1e1; border-color:#d1d1d1; outline:0 none;} .sun-editor .se-btn:enabled:active {background-color:#d1d1d1; border-color:#c1c1c1; -webkit-box-shadow:inset 0 3px 5px #c1c1c1; box-shadow:inset 0 3px 5px #c1c1c1;} /** --- primary button */ -.sun-editor .se-btn-primary {color:#000; background-color:#c7deff; border:1px solid #80bdff; border-radius:3px;} +.sun-editor .se-btn-primary {color:#000; background-color:#c7deff; border:1px solid #80bdff; border-radius:4px;} .sun-editor .se-btn-primary:hover, .sun-editor .se-btn-primary:focus {color:#000; background-color:#80bdff; border-color:#3f9dff; outline:0 none;} .sun-editor .se-btn-primary:active {color:#fff; background-color:#3f9dff; border-color:#4592ff; -webkit-box-shadow:inset 0 3px 5px #4592ff; box-shadow:inset 0 3px 5px #4592ff;} @@ -174,7 +174,7 @@ /** --- tool bar module group ---------------------------------------------------------- */ .sun-editor .se-btn-module {display:inline-block;} -.sun-editor .se-btn-module-border {border:1px solid #dadada; border-radius:3px;} +.sun-editor .se-btn-module-border {border:1px solid #dadada; border-radius:4px;} .sun-editor .se-btn-module-enter {display:block; width:100%; height:1px; margin-bottom:5px; background-color:transparent;} /* module innser ul */ .sun-editor .se-menu-list {float:left; padding:0; margin:0;} @@ -188,7 +188,7 @@ .sun-editor .se-btn-select.se-btn-tool-size {width:80px;} /** --- submenu layer ---------------------------------------------------------- */ -.sun-editor .se-list-layer {display:none; position:absolute; top:37px; z-index:4; left:1px; border:1px solid #bababa; border-radius:3px; padding:5px 0; background-color:#fff; -webkit-box-shadow:0 3px 9px rgba(0, 0, 0, .5); box-shadow:0 3px 9px rgba(0, 0, 0, .5); outline:0 none;} +.sun-editor .se-list-layer {display:none; position:absolute; top:37px; z-index:4; left:1px; border:1px solid #bababa; border-radius:4px; padding:6px 0; background-color:#fff; -webkit-box-shadow:0 3px 9px rgba(0, 0, 0, .5); box-shadow:0 3px 9px rgba(0, 0, 0, .5); outline:0 none;} .sun-editor .se-list-layer .se-list-inner {padding:0; margin:0; overflow-x:initial; overflow-y:initial; overflow:visible;} .sun-editor .se-list-layer button {margin:0; width:100%;} /* submenu layer - common list form */ @@ -222,7 +222,7 @@ .sun-editor .se-list-layer .se-list-format h5 {font-size:0.83em; font-weight:bold; color:#333;} .sun-editor .se-list-layer .se-list-format h6 {font-size:0.67em; font-weight:bold; color:#333;} .sun-editor .se-list-layer .se-list-format blockquote {font-size:13px; color:#999; height:22px; margin:0; background-color:transparent; line-height:1.5; border-style:solid; border-color:#b1b1b1; padding:0 0 0 7px; border-left-width:5px;} -.sun-editor .se-list-layer .se-list-format pre {font-size:13px; color:#666; padding:4px 11px; margin:0; background-color:#f9f9f9; border:1px solid #e1e1e1; border-radius:3px;} +.sun-editor .se-list-layer .se-list-format pre {font-size:13px; color:#666; padding:4px 11px; margin:0; background-color:#f9f9f9; border:1px solid #e1e1e1; border-radius:4px;} /* submenu layer - font size */ .sun-editor .se-list-layer .se-list-font-size {min-width:140px; max-height:300px; overflow-x:hidden; overflow-y:auto;} /* submenu layer - hr */ @@ -233,7 +233,7 @@ /* submenu layer - paragraph style, text style */ .sun-editor .se-list-layer .se-list-format div {padding:4px 2px;} /* submenu layer --- table selector */ -.sun-editor .se-selector-table {display:none; position:absolute; top:34px; left:1px; z-index:4; padding:5px 0; float:left; margin:2px 0 0; font-size:14px; text-align:left; list-style:none; background-color:#fff; -webkit-background-clip:padding-box; background-clip:padding-box; border:1px solid #ccc; border-radius:3px; -webkit-box-shadow:0 6px 12px rgba(0, 0, 0, .175); box-shadow:0 6px 12px rgba(0, 0, 0, .175);} +.sun-editor .se-selector-table {display:none; position:absolute; top:34px; left:1px; z-index:4; padding:5px 0; float:left; margin:2px 0 0; font-size:14px; text-align:left; list-style:none; background-color:#fff; -webkit-background-clip:padding-box; background-clip:padding-box; border:1px solid #ccc; border-radius:4px; -webkit-box-shadow:0 6px 12px rgba(0, 0, 0, .175); box-shadow:0 6px 12px rgba(0, 0, 0, .175);} .sun-editor .se-selector-table .se-table-size {font-size:18px; padding:0 5px;} .sun-editor .se-selector-table .se-table-size-picker {position:absolute !important; z-index:3; font-size:18px; width:10em; height:10em; cursor:pointer;} .sun-editor .se-selector-table .se-table-size-highlighted {position:absolute !important; z-index:2; font-size:18px; width:1em; height:1em; background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo4QTZCNzMzN0I3RUYxMUU4ODcwQ0QwMjM1NTgzRTJDNyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo4QTZCNzMzNkI3RUYxMUU4ODcwQ0QwMjM1NTgzRTJDNyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0MzYyNEUxRUI3RUUxMUU4ODZGQzgwRjNBODgyNTdFOSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0MzYyNEUxRkI3RUUxMUU4ODZGQzgwRjNBODgyNTdFOSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pl0yAuwAAABBSURBVDhPY/wPBAxUAGCDGvdBeWSAeicIDTfIXREiQArYeR9hEBOEohyMGkQYjBpEGAxjg6ib+yFMygCVvMbAAABj0hwMTNeKJwAAAABJRU5ErkJggg==') repeat;} @@ -281,7 +281,7 @@ .sun-editor .se-dialog .se-dialog-back {position:absolute; width:100%; height:100%; top:0; left:0; background-color:#222; opacity:0.5;} /* dialog - modal */ .sun-editor .se-dialog .se-dialog-inner {position:absolute; width:100%; height:100%; top:0; left:0;} -.sun-editor .se-dialog .se-dialog-inner .se-dialog-content {position:relative; width:auto; max-width:500px; margin:20px auto; background-color:#fff; -webkit-background-clip:padding-box; background-clip:padding-box; border:1px solid rgba(0, 0, 0, .2); border-radius:3px; outline:0; -webkit-box-shadow:0 3px 9px rgba(0, 0, 0, .5); box-shadow:0 3px 9px rgba(0, 0, 0, .5);} +.sun-editor .se-dialog .se-dialog-inner .se-dialog-content {position:relative; width:auto; max-width:500px; margin:20px auto; background-color:#fff; -webkit-background-clip:padding-box; background-clip:padding-box; border:1px solid rgba(0, 0, 0, .2); border-radius:4px; outline:0; -webkit-box-shadow:0 3px 9px rgba(0, 0, 0, .5); box-shadow:0 3px 9px rgba(0, 0, 0, .5);} @media screen and (max-width:509px) { .sun-editor .se-dialog .se-dialog-inner .se-dialog-content {width:100%;} } .sun-editor .se-dialog .se-dialog-inner .se-dialog-header {height:50px; padding:6px 15px 6px 15px; border-bottom:1px solid #e5e5e5;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-header .se-dialog-close {float:right; font-weight:bold; text-shadow:0 1px 0 #fff; -webkit-appearance:none; filter:alpha(opacity=100); opacity:1;} @@ -295,7 +295,7 @@ .sun-editor .se-dialog .se-dialog-inner .se-dialog-size-text .size-h {width:70px; text-align:center;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-size-x {margin:0 8px 0 8px; width:25px; text-align:center;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-content label {display:inline-block; max-width:100%; margin-bottom:5px; font-weight:bold;} -.sun-editor .se-dialog .se-dialog-inner .se-dialog-content .se-btn-primary {display:inline-block; padding:6px 12px; margin:0 0 10px 0 !important; font-size:14px; font-weight:normal; line-height:1.42857143; text-align:center; white-space:nowrap; vertical-align:middle; -ms-touch-action:manipulation; touch-action:manipulation; border-radius:3px;} +.sun-editor .se-dialog .se-dialog-inner .se-dialog-content .se-btn-primary {display:inline-block; padding:6px 12px; margin:0 0 10px 0 !important; font-size:14px; font-weight:normal; line-height:1.42857143; text-align:center; white-space:nowrap; vertical-align:middle; -ms-touch-action:manipulation; touch-action:manipulation; border-radius:4px;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-footer {padding:10px 15px 0px 15px; text-align:right; border-top:1px solid #e5e5e5;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-footer > div {float:left;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-footer > div > label {margin-top:5px;} @@ -303,9 +303,9 @@ .sun-editor .se-dialog .se-dialog-inner .se-dialog-btn-check {margin-left:12px; margin-right:4px;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-form-footer .se-dialog-btn-check {margin-left:0; margin-right:4px;} /* dialog - modal - input */ -.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-select {display:inline-block; width:70px; height:34px; font-size:14px; text-align:center; line-height:1.42857143; color:#000; border:1px solid #ccc; border-radius:3px; transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;} -.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-control {display:inline-block; width:70px; height:34px; font-size:14px; text-align:center; line-height:1.42857143; color:#000; border:1px solid #ccc; border-radius:3px; transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;} -.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-form {display:block; width:100%; height:34px; font-size:14px; line-height:1.42857143; padding:0 4px; color:#000; border:1px solid #ccc; border-radius:3px; transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;} +.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-select {display:inline-block; width:70px; height:34px; font-size:14px; text-align:center; line-height:1.42857143; color:#000; border:1px solid #ccc; border-radius:4px; transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;} +.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-control {display:inline-block; width:70px; height:34px; font-size:14px; text-align:center; line-height:1.42857143; color:#000; border:1px solid #ccc; border-radius:4px; transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;} +.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-form {display:block; width:100%; height:34px; font-size:14px; line-height:1.42857143; padding:0 4px; color:#000; border:1px solid #ccc; border-radius:4px; transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-form input:focus, .sun-editor .se-dialog .se-dialog-inner .se-dialog-form select:focus, .sun-editor .se-dialog .se-dialog-inner .se-dialog-form textarea:focus {border-color:#80bdff; outline:0; -webkit-box-shadow:0 0 0 0.2rem #c7deff; box-shadow:0 0 0 0.2rem #c7deff;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-video-ratio {margin-left:4px;} .sun-editor .se-dialog .se-dialog-inner .se-dialog-form a {color:#004cff;} @@ -326,13 +326,13 @@ /** --- controller ---------------------------------------------------------- */ .sun-editor .se-controller .se-arrow.se-arrow-up {border-bottom-color:rgba(0, 0, 0, .25);} -.sun-editor .se-controller {position:absolute; display:none; overflow:visible; z-index:4; border:1px solid rgba(0, 0, 0, .25); border-radius:3px; text-align:start; text-decoration:none; text-shadow:none; text-transform:none; letter-spacing:normal; word-break:normal; word-spacing:normal; word-wrap:normal; white-space:normal; background-color:#fff; -webkit-background-clip:padding-box; background-clip:padding-box; -webkit-box-shadow:0 5px 10px rgba(0, 0, 0, .2); box-shadow:0 5px 10px rgba(0, 0, 0, .2); line-break:auto;} +.sun-editor .se-controller {position:absolute; display:none; overflow:visible; z-index:4; border:1px solid rgba(0, 0, 0, .25); border-radius:4px; text-align:start; text-decoration:none; text-shadow:none; text-transform:none; letter-spacing:normal; word-break:normal; word-spacing:normal; word-wrap:normal; white-space:normal; background-color:#fff; -webkit-background-clip:padding-box; background-clip:padding-box; -webkit-box-shadow:0 5px 10px rgba(0, 0, 0, .2); box-shadow:0 5px 10px rgba(0, 0, 0, .2); line-break:auto;} /* controller - button group */ .sun-editor .se-controller .se-btn-group {position:relative; display:flex; vertical-align:middle; padding:2px 2px 2px 0; top:0; left:0;} .sun-editor .se-controller .se-btn-group .se-btn-group-sub {left:50%; min-width:auto; width:max-content; display:none;/* display: inline-table; */} .sun-editor .se-controller .se-btn-group .se-btn-group-sub button {margin:0; min-width:72px;} -.sun-editor .se-controller .se-btn-group button {position:relative; min-height:35px; height:auto; border:none; border-radius:3px; border-top-right-radius:0; border-bottom-right-radius:0; margin:0 0 0 2px; padding:5px 10px; font-size:12px; line-height:1.5; display:inline-block; font-weight:normal; text-align:center; white-space:nowrap; vertical-align:middle; -ms-touch-action:manipulation; touch-action:manipulation;} +.sun-editor .se-controller .se-btn-group button {position:relative; min-height:35px; height:auto; border:none; border-radius:4px; border-top-right-radius:0; border-bottom-right-radius:0; margin:0 0 0 2px; padding:5px 10px; font-size:12px; line-height:1.5; display:inline-block; font-weight:normal; text-align:center; white-space:nowrap; vertical-align:middle; -ms-touch-action:manipulation; touch-action:manipulation;} .sun-editor .se-controller .se-btn-group button:hover:enabled, .sun-editor .se-controller .se-btn-group button:focus:enabled {background-color:#e1e1e1; border-color:#d1d1d1; outline:0 none;} .sun-editor .se-controller .se-btn-group button:active:enabled {background-color:#d1d1d1; border-color:#c1c1c1; -webkit-box-shadow:inset 0 3px 5px #c1c1c1; box-shadow:inset 0 3px 5px #c1c1c1;} .sun-editor .se-controller .se-btn-group button span {display:block; padding:0; margin:0;} @@ -360,7 +360,7 @@ .sun-editor .se-resizing-container .se-resize-dot > span.th {left:50%; top:-7px; cursor:n-resize;} .sun-editor .se-resizing-container .se-resize-dot > span.rw {right:-7px; bottom:50%; cursor:e-resize;} .sun-editor .se-resizing-container .se-resize-dot > span.bh {right:50%; bottom:-7px; cursor:s-resize;} -.sun-editor .se-resizing-container .se-resize-display {position:absolute; right:0; bottom:0; padding:5px; margin:5px; font-size:12px; color:#fff; background-color:#333; border-radius:3px;} +.sun-editor .se-resizing-container .se-resize-display {position:absolute; right:0; bottom:0; padding:5px; margin:5px; font-size:12px; color:#fff; background-color:#333; border-radius:4px;} /* controller - table */ .sun-editor .se-controller-table {width:auto; padding:0; font-size:14px; font-style:normal; font-weight:normal; line-height:1.42857143;} .sun-editor .se-controller-table-cell {width:auto; padding:0; font-size:14px; font-style:normal; font-weight:normal; line-height:1.42857143;} diff --git a/src/lib/core.js b/src/lib/core.js index 65f10ceaf..44a794f00 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -594,7 +594,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { }, /** - * @description Returns a "formatElement"(P, DIV, H[1-6], LI) array from the currently selected range. + * @description Returns a "formatElement"(util.isFormatElement) array from the currently selected range. * @param {Function|null} validation The validation function. (Replaces the default validation function-util.isFormatElement(current)) * @returns {Array} */ @@ -980,6 +980,43 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } }, + /** + * @description Split all nested tags based on "beforeTag" + * Returns the last element of the splited tag. + * @param {Element} beforeTag Criteria element + * @returns {Element} + */ + splitNestedElement: function (beforeTag) { + const bp = beforeTag.parentNode; + const children = bp.childNodes; + const index = util.getPositionIndex(beforeTag); + let newRange = bp.cloneNode(false); + while (children[index]) { + newRange.appendChild(children[index]); + } + + let depthParent = bp; + let newRangeTemp = null; + while (util.getElementDepth(depthParent) > 0) { + newRangeTemp = depthParent.cloneNode(false); + newRangeTemp.appendChild(newRange); + newRange = newRangeTemp; + depthParent = depthParent.parentNode; + } + + const pElement = depthParent.parentNode; + depthParent = depthParent.nextElementSibling; + this._mergeSameTags(newRange, null, null, false); + util.mergeNestedTags(newRange, function (current) { return this.isList(current); }.bind(util)); + + if (newRange.childNodes.length > 0) pElement.insertBefore(newRange, depthParent); + else newRange = depthParent; + + if (bp.childNodes.length === 0) util.removeItem(bp); + + return newRange; + }, + /** * @description Appended all selected format Element to the argument element and insert * @param {Element} rangeElement Element of wrap the arguments (BLOCKQUOTE...) @@ -1011,7 +1048,8 @@ export default function (context, pluginCallButtons, plugins, lang, options) { const removeItems = function (parent, origin, before) { let cc = null; if (parent !== origin && !util.isTable(origin)) { - cc = util.removeItemAllParents(origin, null); + if (origin && util.getElementDepth(parent) === util.getElementDepth(origin)) return before; + cc = util.removeItemAllParents(origin, null, parent); } return cc ? cc.ec : before; @@ -1042,15 +1080,16 @@ export default function (context, pluginCallButtons, plugins, lang, options) { if (parentDepth >= depth) { parentDepth = depth; pElement = edge.cc; - beforeTag = removeItems(pElement, originParent, depth > 1 ? edge.sc : edge.ec); + beforeTag = removeItems(pElement, originParent, edge.ec); if (beforeTag) pElement = beforeTag.parentNode; } else if (pElement === edge.cc) { beforeTag = edge.ec; } if (pElement !== edge.cc) { - before = removeItems(pElement, edge.cc); + before = removeItems(pElement, edge.cc, before); if (before !== undefined) beforeTag = before; + else beforeTag = edge.cc; } rangeElement.appendChild(listParent); @@ -1074,12 +1113,18 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } this._mergeSameTags(rangeElement, null, null, false); - util.removeNestedTags(rangeElement, function (current) { return this.isList(current); }.bind(util)); - pElement.insertBefore(rangeElement, beforeTag); - removeItems(rangeElement, beforeTag); + util.mergeNestedTags(rangeElement, function (current) { return this.isList(current); }.bind(util)); - // history stack - this.history.push(false); + // Nested list + if (beforeTag && util.getElementDepth(beforeTag) > 0 && util.isList(beforeTag.parentNode)) { + const splitRange = this.splitNestedElement(beforeTag); + splitRange.parentNode.insertBefore(rangeElement, splitRange); + } + // basic + else { + pElement.insertBefore(rangeElement, beforeTag); + removeItems(rangeElement, beforeTag); + } const edge = util.getEdgeChildNodes(rangeElement.firstElementChild, rangeElement.lastElementChild); if (rangeLines.length > 1) { @@ -1087,6 +1132,9 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } else { this.setRange(edge.ec, edge.ec.textContent.length, edge.ec, edge.ec.textContent.length); } + + // history stack + this.history.push(false); }, /** @@ -1203,17 +1251,21 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } const rangeParent = rangeElement.parentNode; - const rangeRight = rangeElement.nextSibling; + let rangeRight = rangeElement.nextSibling; if (rangeEl && rangeEl.children.length > 0) { rangeParent.insertBefore(rangeEl, rangeRight); } + + if (newRangeElement) firstNode = newRangeElement.previousSibling; + else firstNode = rangeElement.previousSibling; + rangeRight = rangeElement.nextSibling; util.removeItem(rangeElement); const edge = remove ? { cc: rangeParent, sc: firstNode, - ec: firstNode && firstNode.parentNode ? firstNode.nextSibling : rangeEl && rangeEl.children.length > 0 ? rangeEl : rangeRight ? rangeRight : null + ec: rangeRight, } : util.getEdgeChildNodes(firstNode, lastNode); if (notHistoryPush) return edge; @@ -1594,9 +1646,10 @@ export default function (context, pluginCallButtons, plugins, lang, options) { next = children[i + 1]; if (!child) break; if((onlyText && inst.util._isIgnoreNodeChange(child)) || (!onlyText && inst.util.isFormatElement(child) && !inst.util.isFreeFormatElement(child))) continue; - if (len === 1 && current.nodeName === child.nodeName) { + if (len === 1 && current.nodeName === child.nodeName && current.parentNode) { inst.util.copyTagAttributes(child, current); - current.parentNode.replaceChild(child, current); + current.parentNode.insertBefore(child, current); + inst.util.removeItem(current); // update nodePath if (nodePath_s && nodePath_s[depth] === i) { diff --git a/src/lib/util.js b/src/lib/util.js index 66225a1f6..8e61fe24e 100755 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -491,7 +491,7 @@ const util = { */ getPositionIndex: function (node) { let idx = 0; - while (!!(node = node.previousSibling)) { + while ((node = node.previousSibling)) { idx += 1; } return idx; @@ -736,10 +736,13 @@ const util = { /** * @description Returns the number of parents nodes. * "0" when the parent node is the WYSIWYG area. + * "-1" when the element argument is the WYSIWYG area. * @param {Element} element The element to check * @returns {Number} */ getElementDepth: function (element) { + if (this.isWysiwygDiv(element)) return -1; + let depth = 0; element = element.parentNode; @@ -1008,14 +1011,15 @@ const util = { * Returns an {sc: previousSibling, ec: nextSibling}(the deleted node reference) or null. * @param {Element} item Element to be remove * @param {Function|null} validation Validation function. default(Deleted if it only have breakLine and blanks) + * @param {Element|null} stopParent Stop when the parent node reaches stopParent * @returns {Object|null} {sc: previousSibling, ec: nextSibling} */ - removeItemAllParents: function (item, validation) { + removeItemAllParents: function (item, validation, stopParent) { if (!item) return null; let cc = null; if (!validation) { validation = function (current) { - if (this.isComponent(current)) return false; + if (current === stopParent || this.isComponent(current)) return false; const text = current.textContent.trim(); return text.length === 0 || /^(\n|\u200B)+$/.test(text); }.bind(this); @@ -1043,7 +1047,7 @@ const util = { * @param {Element} element Element object * @param {Function|String|null} validation Validation function / String("tag1|tag2..") / If null, all tags are applicable. */ - removeNestedTags: function (element, validation) { + mergeNestedTags: function (element, validation) { if (typeof validation === 'string') { validation = function (current) { return this.test(current.tagName); }.bind(new this._w.RegExp('^(' + (validation ? validation : '.+') + ')$', 'i')); } else if (typeof validation !== 'function') { @@ -1052,7 +1056,7 @@ const util = { (function recursionFunc(current) { let children = current.children; - if (element !== current && children.length === 1 && children[0].nodeName === current.nodeName && validation(current)) { + if (children.length === 1 && children[0].nodeName === current.nodeName && validation(current)) { const temp = children[0]; children = temp.children; while (children[0]) { diff --git a/src/plugins/command/blockquote.js b/src/plugins/command/blockquote.js index 2c0fa2245..cc180a902 100644 --- a/src/plugins/command/blockquote.js +++ b/src/plugins/command/blockquote.js @@ -33,7 +33,7 @@ export default { const currentBlockquote = this.util.getParentElement(this.getSelectionNode(), 'blockquote'); if (currentBlockquote) { - this.detachRangeFormatElement(currentBlockquote, this.getSelectedElements(), null, false, false); + this.detachRangeFormatElement(currentBlockquote, null, null, false, false); } else { this.applyRangeFormatElement(this.context.blockquote.tag.cloneNode(false)); } From f7b9dd23c17357171418e0181f3e9c571d5a6d98 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Thu, 27 Feb 2020 20:56:03 +0900 Subject: [PATCH 56/99] modify: core-splitNestedElement > splitElement modify: core-removeNode --- sample/html/out/document-editor.html | 22 ++- src/lib/core.js | 252 ++++++++++++++++----------- test/dev/suneditor_build_test.html | 2 + 3 files changed, 167 insertions(+), 109 deletions(-) diff --git a/sample/html/out/document-editor.html b/sample/html/out/document-editor.html index c2a5134ce..7e257a1bc 100644 --- a/sample/html/out/document-editor.html +++ b/sample/html/out/document-editor.html @@ -1134,15 +1134,16 @@
    Parameters:

    removeNode()

    - Delete the currently selected node + Delete the currently selected nodes and reset selection range
    + Returns {container: "the last element after deletion", offset: "offset"}
    -

    splitNestedElement(beforeTag)splitElement(beforeNode, offset) → {Element}

    - Split all nested tags based on "beforeTag"
    + Split all tags based on "beforeNode"
    Returns the last element of the splited tag.
    Parameters:
    @@ -1156,11 +1157,18 @@
    Parameters:
    - + + + + + + - +
    beforeTagbeforeNode - Element + Node + Element or text node on which to base
    offset + Number|null Criteria elementText offset of "beforeNode" (Only valid when "beforeNode" is a text node)
    @@ -1633,7 +1641,7 @@

    core

  • selectComponent
  • insertNode
  • removeNode
  • -
  • splitNestedElement
  • +
  • splitElement
  • applyRangeFormatElement
  • detachRangeFormatElement
  • nodeChange
  • diff --git a/src/lib/core.js b/src/lib/core.js index 44a794f00..d4d7d895c 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -732,8 +732,8 @@ export default function (context, pluginCallButtons, plugins, lang, options) { insertComponent: function (element, notHistoryPush) { let oNode = null; const selectionNode = this.getSelectionNode(); - const formatEl = util.getFormatElement(selectionNode); - + let formatEl = util.getFormatElement(selectionNode); + if (util.isListCell(formatEl)) { if (/^HR$/i.test(element.nodeName)) { const newLi = util.createElement('LI'); @@ -748,8 +748,15 @@ export default function (context, pluginCallButtons, plugins, lang, options) { formatEl.parentNode.insertBefore(oNode, formatEl.nextElementSibling); } } else { + // split element + const r = this.removeNode(); + if (this.getRange().collapsed && r.container.nodeType === 3) { + oNode = this.splitElement(r.container, r.offset); + formatEl = oNode.previousSibling; + } + this.insertNode(element, formatEl); - oNode = this.appendFormatTag(element, null); + if (!oNode) oNode = this.appendFormatTag(element, util.isFormatElement(formatEl) ? formatEl : null); } // history stack @@ -892,129 +899,170 @@ export default function (context, pluginCallButtons, plugins, lang, options) { }, /** - * @description Delete the currently selected node + * @description Delete the currently selected nodes and reset selection range + * Returns {container: "the last element after deletion", offset: "offset"} + * @returns {Object} */ removeNode: function () { const range = this.getRange(); + let container, offset; + // native function if (range.deleteContents) { range.deleteContents(); + container = range.endContainer || range.startContainer; - // history stack - this.history.push(false); - return; - } - - const startCon = range.startContainer; - const startOff = range.startOffset; - const endCon = range.endContainer; - const endOff = range.endOffset; - const commonCon = range.commonAncestorContainer; - - let beforeNode = null; - let afterNode = null; - - const childNodes = util.getListChildNodes(commonCon); - let startIndex = util.getArrayIndex(childNodes, startCon); - let endIndex = util.getArrayIndex(childNodes, endCon); - - for (let i = startIndex + 1, startNode = startCon; i >= 0; i--) { - if (childNodes[i] === startNode.parentNode && childNodes[i].firstChild === startNode && startOff === 0) { - startIndex = i; - startNode = startNode.parentNode; - } - } - - for (let i = endIndex - 1, endNode = endCon; i > startIndex; i--) { - if (childNodes[i] === endNode.parentNode && childNodes[i].nodeType === 1) { - childNodes.splice(i, 1); - endNode = endNode.parentNode; - --endIndex; + if (container.nodeType === 3) { + offset = container.textContent.length; + } else { + container = util.getEdgeChildNodes((range.endContainer ? range.endContainer.childNodes[range.endOffset] : range.startContainer.childNodes[range.startOffset]), null).ec; + offset = 0; } } - - for (let i = startIndex; i <= endIndex; i++) { - const item = childNodes[i]; - - if (item.length === 0 || (item.nodeType === 3 && item.data === undefined)) { - util.removeItem(item); - continue; - } - - if (item === startCon) { - if (startCon.nodeType === 1) { - beforeNode = util.createTextNode(startCon.textContent); - } else { - beforeNode = util.createTextNode(startCon.substringData(0, startOff)); + // hard coding + else { + let startCon = range.startContainer; + let endCon = range.endContainer; + const startOff = range.startOffset; + const endOff = range.endOffset; + const commonCon = range.commonAncestorContainer; + + let beforeNode = null; + let afterNode = null; + + const childNodes = util.getListChildNodes(commonCon); + let startIndex = util.getArrayIndex(childNodes, startCon); + let endIndex = util.getArrayIndex(childNodes, endCon); + + if (childNodes.length > 0) { + for (let i = startIndex + 1, startNode = startCon; i >= 0; i--) { + if (childNodes[i] === startNode.parentNode && childNodes[i].firstChild === startNode && startOff === 0) { + startIndex = i; + startNode = startNode.parentNode; + } } - - if (beforeNode.length > 0) { - startCon.data = beforeNode.data; - } else { - util.removeItem(startCon); + + for (let i = endIndex - 1, endNode = endCon; i > startIndex; i--) { + if (childNodes[i] === endNode.parentNode && childNodes[i].nodeType === 1) { + childNodes.splice(i, 1); + endNode = endNode.parentNode; + --endIndex; + } } - - continue; + } else { + childNodes.push(commonCon); + startIndex = endIndex = 0; + startCon = endCon = null; } - - if (item === endCon) { - if (endCon.nodeType === 1) { - afterNode = util.createTextNode(endCon.textContent); - } else { - afterNode = util.createTextNode(endCon.substringData(endOff, (endCon.length - endOff))); + + for (let i = startIndex; i <= endIndex; i++) { + const item = childNodes[i]; + + if (item.length === 0 || (item.nodeType === 3 && item.data === undefined)) { + util.removeItem(item); + continue; } - - if (afterNode.length > 0) { - endCon.data = afterNode.data; - } else { - util.removeItem(endCon); + + if (item === startCon) { + if (startCon.nodeType === 1) { + beforeNode = util.createTextNode(startCon.textContent); + } else { + beforeNode = util.createTextNode(startCon.substringData(0, startOff)); + } + + if (beforeNode.length > 0) { + startCon.data = beforeNode.data; + } else { + util.removeItem(startCon); + } + + continue; } - - continue; + + if (item === endCon) { + if (endCon.nodeType === 1) { + afterNode = util.createTextNode(endCon.textContent); + } else { + afterNode = util.createTextNode(endCon.substringData(endOff, (endCon.length - endOff))); + } + + if (afterNode.length > 0) { + endCon.data = afterNode.data; + } else { + util.removeItem(endCon); + } + + continue; + } + + util.removeItem(item); } - util.removeItem(item); - - // history stack - this.history.push(false); + container = endCon || startCon || range.endContainer || range.startContainer; + offset = 0; } + + // set range + this.setRange(container, offset, container, offset); + + // history stack + this.history.push(true); + + return { + container: container, + offset: offset + }; }, /** - * @description Split all nested tags based on "beforeTag" + * @description Split all tags based on "beforeNode" * Returns the last element of the splited tag. - * @param {Element} beforeTag Criteria element + * @param {Node} beforeNode Element or text node on which to base + * @param {Number|null} offset Text offset of "beforeNode" (Only valid when "beforeNode" is a text node) * @returns {Element} */ - splitNestedElement: function (beforeTag) { - const bp = beforeTag.parentNode; - const children = bp.childNodes; - const index = util.getPositionIndex(beforeTag); - let newRange = bp.cloneNode(false); - while (children[index]) { - newRange.appendChild(children[index]); - } - - let depthParent = bp; - let newRangeTemp = null; - while (util.getElementDepth(depthParent) > 0) { - newRangeTemp = depthParent.cloneNode(false); - newRangeTemp.appendChild(newRange); - newRange = newRangeTemp; - depthParent = depthParent.parentNode; - } - - const pElement = depthParent.parentNode; - depthParent = depthParent.nextElementSibling; - this._mergeSameTags(newRange, null, null, false); - util.mergeNestedTags(newRange, function (current) { return this.isList(current); }.bind(util)); + splitElement: function (beforeNode, offset) { + const bp = beforeNode.parentNode; + let index = 0, newEl, children, temp; + let next = true; + + if (offset > 0 && beforeNode.nodeType === 3) { + index = util.getPositionIndex(beforeNode); + beforeNode.splitText(offset); + const after = util.getNodeFromPath([index + 1], bp); + if (util.onlyZeroWidthSpace(after)) after.data = util.zeroWidthSpace; + } else { + if (!beforeNode.previousSibling) next = false; + else beforeNode = beforeNode.previousSibling; + } + + let depthEl = beforeNode; + while (util.getElementDepth(depthEl) > 0) { + index = util.getPositionIndex(depthEl) + 1; + depthEl = depthEl.parentNode; + + temp = newEl; + newEl = depthEl.cloneNode(false); + children = depthEl.childNodes; + + if (temp) newEl.appendChild(temp); + while (children[index]) { + newEl.appendChild(children[index]); + } + } + + const pElement = depthEl.parentNode; + if (next) depthEl = depthEl.nextElementSibling; + + this._mergeSameTags(newEl, null, null, false); + util.mergeNestedTags(newEl, function (current) { return this.isList(current); }.bind(util)); - if (newRange.childNodes.length > 0) pElement.insertBefore(newRange, depthParent); - else newRange = depthParent; + if (newEl.childNodes.length > 0) pElement.insertBefore(newEl, depthEl); + else newEl = depthEl; if (bp.childNodes.length === 0) util.removeItem(bp); - return newRange; + return newEl; }, /** @@ -1117,7 +1165,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { // Nested list if (beforeTag && util.getElementDepth(beforeTag) > 0 && util.isList(beforeTag.parentNode)) { - const splitRange = this.splitNestedElement(beforeTag); + const splitRange = this.splitElement(beforeTag); splitRange.parentNode.insertBefore(rangeElement, splitRange); } // basic @@ -4202,7 +4250,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { (!selectionFormat && util.onlyZeroWidthSpace(selectionNode.textContent) && util.isBreak(prev) && (util.isBreak(prev.previousSibling) || !util.onlyZeroWidthSpace(prev.previousSibling.textContent)) && (!next || (!util.isBreak(next) && util.onlyZeroWidthSpace(next.textContent))))) { if (selectionFormat) util.removeItem(children[offset - 1]); else util.removeItem(selectionNode); - const newEl = core.appendFormatTag(freeFormatEl, freeFormatEl.nextElementSibling ? freeFormatEl.nextElementSibling : 'P'); + const newEl = core.appendFormatTag(freeFormatEl, util.isFormatElement(freeFormatEl.nextElementSibling) ? freeFormatEl.nextElementSibling : null); util.copyFormatAttributes(newEl, freeFormatEl); core.setRange(newEl, 1, newEl, 1); break; @@ -4245,7 +4293,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { const range = core.getRange(); if (!range.commonAncestorContainer.nextElementSibling && util.onlyZeroWidthSpace(formatEl.innerText.trim())) { e.preventDefault(); - const newEl = core.appendFormatTag(rangeEl, util.isList(rangeEl.parentNode) ? 'LI' : util.isCell(rangeEl.parentNode) ? 'DIV' : util.isListCell(formatEl) ? 'P' : null); + const newEl = core.appendFormatTag(rangeEl, util.isList(rangeEl.parentNode) ? 'LI' : util.isCell(rangeEl.parentNode) ? 'DIV' : null); util.copyFormatAttributes(newEl, formatEl); util.removeItemAllParents(formatEl, null); core.setRange(newEl, 1, newEl, 1); diff --git a/test/dev/suneditor_build_test.html b/test/dev/suneditor_build_test.html index 75ca7beaa..4d50b1381 100644 --- a/test/dev/suneditor_build_test.html +++ b/test/dev/suneditor_build_test.html @@ -155,6 +155,8 @@
    diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index 28e59fbe9..b26c61268 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -24,10 +24,11 @@ const align = require('../../src/plugins/submenu/align') suneditor.create("sample1", { plugins: plugins, - mode: "balloon", + // mode: "balloon", // iframe: true, + imageFileInput: false, buttonList: [ - ["undo", "redo"], + ["undo", "image", "video"], ["font", "fontSize", "formatBlock"], ["paragraphStyle", "table"] ] @@ -52,7 +53,7 @@ let s1 = suneditor.create('editor', { 'preview', 'print', 'save', 'template'] ], width: '100%', - height: 'auto', + height: '500', // fullPage: true, // pasteTagsWhitelist: 'p|h[1-6]', formats: [ From f7b0bc2263c65257dd07c18d4c1138b0e350d27b Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Mon, 2 Mar 2020 15:59:57 +0900 Subject: [PATCH 60/99] fix: #229 add util.isMediaComponent --- sample/html/out/document-util.html | 30 +++++++++++++++++++++++++++++- src/lib/util.js | 11 ++++++++++- src/plugins/dialog/image.js | 10 +++++----- src/plugins/dialog/video.js | 8 ++++---- 4 files changed, 48 insertions(+), 11 deletions(-) diff --git a/sample/html/out/document-util.html b/sample/html/out/document-util.html index 36ea5728a..b6931c933 100644 --- a/sample/html/out/document-util.html +++ b/sample/html/out/document-util.html @@ -449,7 +449,34 @@
    Parameters:

    isComponent(element) → {Boolean}

    - It is judged whether it is the component(img, iframe cover, table, hr) element - ".sun-editor-id-comp" + It is judged whether it is the component [img, iframe] cover(element className - ".se-component") and table, hr +
    +
    Parameters:
    + + + + + + + + + + + + + + + +
    NameTypeDescription
    element + Element + The element to check
    +
    + + +

    isMediaComponent(element) → {Boolean}

    +
    + It is judged whether it is the component [img, iframe] cover(element className - ".se-component")
    Parameters:
    @@ -1956,6 +1983,7 @@

    util

  • isRangeFormatElement
  • isFreeFormatElement
  • isComponent
  • +
  • isMediaComponent
  • getFormatElement
  • getRangeFormatElement
  • getFreeFormatElement
  • diff --git a/src/lib/util.js b/src/lib/util.js index c9946d941..57097e4fe 100755 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -337,7 +337,7 @@ const util = { }, /** - * @description It is judged whether it is the component(img, iframe cover, table, hr) element - ".se-component" + * @description It is judged whether it is the component [img, iframe] cover(element className - ".se-component") and table, hr * @param {Element} element The element to check * @returns {Boolean} */ @@ -345,6 +345,15 @@ const util = { return element && (/se-component/.test(element.className) || /^(TABLE|HR)$/.test(element.nodeName)); }, + /** + * @description It is judged whether it is the component [img, iframe] cover(element className - ".se-component") + * @param {Element} element The element to check + * @returns {Boolean} + */ + isMediaComponent: function (element) { + return element && /se-component/.test(element.className); + }, + /** * @description If a parent node that contains an argument node finds a format node (util.isFormatElement), it returns that node. * @param {Element} element Reference element if null or no value, it is relative to the current focus node. diff --git a/src/plugins/dialog/image.js b/src/plugins/dialog/image.js index ddc28c7de..72a7ebc1f 100644 --- a/src/plugins/dialog/image.js +++ b/src/plugins/dialog/image.js @@ -514,7 +514,7 @@ export default { img.setAttribute('origin-size', img.naturalWidth + ',' + img.naturalHeight); } if (!img.getAttribute('data-origin')) { - const container = this.util.getParentElement(img, this.util.isComponent); + const container = this.util.getParentElement(img, this.util.isMediaComponent); const cover = this.util.getParentElement(img, 'FIGURE'); const w = this.plugins.resizing._module_getSizeX.call(this, this.context.image, img, cover, container); @@ -553,10 +553,10 @@ export default { for (let i = 0, len = imagesInfo.length; i < len; i++) { infoIndex[i] = imagesInfo[i].index; } - + for (let i = 0, len = images.length, img; i < len; i++) { img = images[i]; - if (!this.util.getParentElement(img, this.util.isComponent)) { + if (!this.util.getParentElement(img, this.util.isMediaComponent)) { currentImages.push(this._variable._imageIndex); imagePlugin.onModifyMode.call(this, img, null); imagePlugin.openModify.call(this, true); @@ -777,7 +777,7 @@ export default { contextImage._linkElement = /^A$/i.test(element.parentNode.nodeName) ? element.parentNode : null; contextImage._element = element; contextImage._cover = this.util.getParentElement(element, 'FIGURE'); - contextImage._container = this.util.getParentElement(element, this.util.isComponent); + contextImage._container = this.util.getParentElement(element, this.util.isMediaComponent); contextImage._caption = this.util.getChildElement(contextImage._cover, 'FIGCAPTION'); contextImage._align = element.getAttribute('data-align') || 'none'; @@ -982,7 +982,7 @@ export default { destroy: function (element) { const imageEl = element || this.context.image._element; - const imageContainer = this.util.getParentElement(imageEl, this.util.isComponent) || imageEl; + const imageContainer = this.util.getParentElement(imageEl, this.util.isMediaComponent) || imageEl; const dataIndex = imageEl.getAttribute('data-index') * 1; let focusEl = (imageContainer.previousElementSibling || imageContainer.nextElementSibling); diff --git a/src/plugins/dialog/video.js b/src/plugins/dialog/video.js index f4ba482d5..e6a6c9afa 100644 --- a/src/plugins/dialog/video.js +++ b/src/plugins/dialog/video.js @@ -286,7 +286,7 @@ export default { setVideosInfo: function (frame) { if (!frame.getAttribute('data-origin')) { - const container = this.util.getParentElement(frame, this.util.isComponent); + const container = this.util.getParentElement(frame, this.util.isMediaComponent); const cover = this.util.getParentElement(frame, 'FIGURE'); const w = this.plugins.resizing._module_getSizeX.call(this, this.context.video, frame, cover, container); @@ -323,7 +323,7 @@ export default { oIframe.allowFullscreen = true; oIframe.onload = oIframe.addEventListener('load', this.plugins.video._onload_video.bind(this, oIframe)); - const existElement = this.util.getParentElement(oIframe, this.util.isComponent) || + const existElement = this.util.getParentElement(oIframe, this.util.isMediaComponent) || this.util.getParentElement(oIframe, function (current) { return this.isWysiwygDiv(current.parentNode); }.bind(this.util)); @@ -351,7 +351,7 @@ export default { const contextVideo = this.context.video; contextVideo._element = element; contextVideo._cover = this.util.getParentElement(element, 'FIGURE'); - contextVideo._container = this.util.getParentElement(element, this.util.isComponent); + contextVideo._container = this.util.getParentElement(element, this.util.isMediaComponent); contextVideo._align = element.getAttribute('data-align') || 'none'; @@ -427,7 +427,7 @@ export default { for (let i = 0, len = this._variable._videosCnt, video, container; i < len; i++) { video = videos[i]; - container = this.util.getParentElement(video, this.util.isComponent); + container = this.util.getParentElement(video, this.util.isMediaComponent); if (!container || container.getElementsByTagName('figcaption').length > 0 || !video.style.width) { videoPlugin._update_videoCover.call(this, video); } From 76a668f22e843189dfcb66db14a108680d1e12d8 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Mon, 2 Mar 2020 22:16:22 +0900 Subject: [PATCH 61/99] modify: formatBlock --- src/lib/core.js | 112 +++++++++++++++++++++++------ src/plugins/submenu/formatBlock.js | 6 +- test/dev/Resolutions.js | 99 +++++++++++++++++++++++++ test/dev/suneditor_build_test.html | 26 +++++-- 4 files changed, 216 insertions(+), 27 deletions(-) create mode 100644 test/dev/Resolutions.js diff --git a/src/lib/core.js b/src/lib/core.js index b760d4a64..42ef1e823 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -1184,21 +1184,52 @@ export default function (context, pluginCallButtons, plugins, lang, options) { * @param {Boolean} remove Delete without detached. * @param {Boolean} notHistoryPush When true, it does not update the history stack and the selection object and return EdgeNodes (util.getEdgeChildNodes) */ - detachRangeFormatElement: function (rangeElement, selectedFormats, newRangeElement, remove, notHistoryPush) { + detachRangeFormatElement: function (rangeElement, selectedFormats, newRangeElement, remove, notHistoryPush, removeNestedList) { const range = this.getRange(); const so = range.startOffset; const eo = range.endOffset; - const children = rangeElement.childNodes; - const parent = rangeElement.parentNode; + let children = util.getListChildNodes(rangeElement, function (current) { return current.parentNode === rangeElement; }); + let parent = rangeElement.parentNode; let firstNode = null; let lastNode = null; let rangeEl = rangeElement.cloneNode(false); const newList = util.isList(newRangeElement); let insertedNew = false; + let reset = false; - function appendNode (parent, insNode, sibling) { + function _deleteNestedList (originNode) { + let sibling = originNode.parentNode; + let parent = sibling.parentNode; + let liSibling, liParent, child, index, c; + + while (util.isListCell(parent)) { + index = util.getPositionIndex(originNode); + liSibling = parent.nextElementSibling; + liParent = parent.parentNode; + child = sibling; + while(child) { + sibling = sibling.nextSibling; + if (util.isList(child)) { + c = child.childNodes; + while (c[index]) { + liParent.insertBefore(c[index], liSibling); + } + if (c.length === 0) util.removeItem(child); + } else { + liParent.appendChild(child); + } + child = sibling; + } + sibling = liParent; + parent = liParent.parentNode; + } + + return liParent; + } + + function appendNode (parent, insNode, sibling, originNode) { if (util.onlyZeroWidthSpace(insNode)) insNode.innerHTML = util.zeroWidthSpace; if (insNode.nodeType === 3) { @@ -1206,13 +1237,13 @@ export default function (context, pluginCallButtons, plugins, lang, options) { return insNode; } - const children = insNode.childNodes; + const insChildren = insNode.childNodes; let format = insNode.cloneNode(false); let first = null; let c = null; - while (children[0]) { - c = children[0]; + while (insChildren[0]) { + c = insChildren[0]; if (util._notTextNode(c) && !util.isBreak(c) && !util.isListCell(format)) { if (format.childNodes.length > 0) { if (!first) first = format; @@ -1228,12 +1259,36 @@ export default function (context, pluginCallButtons, plugins, lang, options) { if (format.childNodes.length > 0) { if (util.isListCell(parent) && util.isListCell(format) && util.isList(sibling)) { - first = sibling; - while(sibling) { - format.appendChild(sibling); - sibling = sibling.nextSibling; + if (!removeNestedList) { + first = sibling; + while(sibling) { + format.appendChild(sibling); + sibling = sibling.nextSibling; + } + parent.parentNode.insertBefore(format, parent.nextElementSibling); + } else { + reset = true; + + const rNode = _deleteNestedList(originNode); + rangeElement = rNode.cloneNode(false); + const c = rNode.childNodes; + const index = util.getPositionIndex(originNode); + while (c[index]) { + rangeElement.appendChild(c[index]); + } + + const rChildren = util.getListChildren(rangeElement, function (current) { return this.isListCell(current) && !current.previousElementSibling; }.bind(util)); + for (let i = 0, len = rChildren.length, n; i < len; i++) { + n = _deleteNestedList(rChildren[i]); + if (n && n.childNodes.length === 0) { + util.removeItem(n); + i--; len--; + } + } + + rNode.parentNode.insertBefore(rangeElement, rNode.nextSibling); + if (c.length === 0) util.removeItem(rNode); } - parent.parentNode.insertBefore(format, parent.nextElementSibling); } else { parent.insertBefore(format, sibling); } @@ -1257,7 +1312,6 @@ export default function (context, pluginCallButtons, plugins, lang, options) { if (selectedFormats && selectedFormats.indexOf(insNode) === -1) { if (!rangeEl) rangeEl = rangeElement.cloneNode(false); rangeEl.appendChild(insNode); - i--, len--; } else { if (rangeEl && rangeEl.children.length > 0) { @@ -1280,11 +1334,22 @@ export default function (context, pluginCallButtons, plugins, lang, options) { parent.insertBefore(newRangeElement, rangeElement); insertedNew = true; } - insNode = appendNode(newRangeElement, insNode, null); + insNode = appendNode(newRangeElement, insNode, null, children[i]); } else { - insNode = appendNode(parent, insNode, rangeElement); + insNode = appendNode(parent, insNode, rangeElement, children[i]); } - + + if (reset) { + reset = false; + children = util.getListChildNodes(rangeElement, function (current) { return current.parentNode === rangeElement; }); + rangeEl = rangeElement.cloneNode(false); + parent = rangeElement.parentNode; + firstNode = lastNode = null; + i = -1; + len = children.length; + continue; + } + if (selectedFormats) { lastNode = insNode; if (!firstNode) { @@ -4037,14 +4102,18 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } const selectedFormats = core.getSelectedElements(); - const lines = [], cells = []; - const fc = util.isListCell(selectedFormats[0]), lc = util.isListCell(selectedFormats[selectedFormats.length - 1]); + const cells = []; + let lines = []; + let fc = util.isListCell(selectedFormats[0]), lc = util.isListCell(selectedFormats[selectedFormats.length - 1]); let r = {sc: null, so: null, ec: null, eo: null}; for (let i = 0, len = selectedFormats.length, f; i < len; i++) { f = selectedFormats[i]; if (util.isListCell(f)) { - if (!f.previousElementSibling && !shift) continue; - cells.push(f); + if (!f.previousElementSibling && !shift) { + lines.push(f); + } else { + cells.push(f); + } } else { lines.push(f); } @@ -4063,6 +4132,9 @@ export default function (context, pluginCallButtons, plugins, lang, options) { r.eo = listRange.eo; } }); + } else { + lines = lines.concat(cells); + fc = lc = null; } // Lines tab(4) diff --git a/src/plugins/submenu/formatBlock.js b/src/plugins/submenu/formatBlock.js index bd58ee1ce..a399ed18c 100644 --- a/src/plugins/submenu/formatBlock.js +++ b/src/plugins/submenu/formatBlock.js @@ -183,7 +183,7 @@ export default { if (i === 0) listFirst = true; } else if (r && isList) { if (r !== o) { - const edge = this.detachRangeFormatElement(rangeArr.r, rangeArr.f, null, false, true); + const edge = this.detachRangeFormatElement(rangeArr.f[0].parentNode, rangeArr.f, null, false, true, true); if (listFirst) { first = edge.sc; listFirst = false; @@ -191,7 +191,7 @@ export default { if (lastIndex) last = edge.ec; if (isList) { - r = o; + r = o = null; rangeArr = {r: r, f: [util.getParentElement(selectedFormsts[i], 'LI')]}; if (lastIndex) listLast = true; } else { @@ -204,7 +204,7 @@ export default { } if (lastIndex && util.isList(r)) { - const edge = this.detachRangeFormatElement(rangeArr.r, rangeArr.f, null, false, true); + const edge = this.detachRangeFormatElement(rangeArr.f[0].parentNode, rangeArr.f, null, false, true, true); if (listLast || len === 1) last = edge.ec; if (listFirst) first = edge.sc || last; } diff --git a/test/dev/Resolutions.js b/test/dev/Resolutions.js new file mode 100644 index 000000000..bbd97dbcc --- /dev/null +++ b/test/dev/Resolutions.js @@ -0,0 +1,99 @@ +// Plugin to append resolution contents to the WYSIWYG editor +export default { + // plugin name + name: 'Resolutions', + command: 'submenu', + + // add function - It is called only once when the plugin is first run. + // This function generates HTML to append and register the event. + // arguments - (core : core object, targetElement : clicked button element) + add: function (core, targetElement) { + + // Registering a namespace for caching as a plugin name in the context object + const context = core.context; + context.custom = { + textElement: null + }; + + // Generate submenu HTML + // Always bind "core" when calling a plugin function + let listDiv = this.setSubmenu.call(core); + + // Input tag caching + context.custom.textElement = listDiv.getElementsByTagName('TEXTAREA')[0]; + + // You must bind "core" object when registering an event. + /** add event listeners */ + listDiv.getElementsByTagName('BUTTON')[0].addEventListener('click', this.onClick.bind(core)); + + /** append html */ + targetElement.parentNode.appendChild(listDiv); + }, + + setSubmenu: function () { + const listDiv = this.util.createElement('DIV'); + + listDiv.className = 'se-list-layer'; + listDiv.innerHTML = '' + + '
    ' + + '
    ' + + '
      ' + + '
    • ' + + '
    • ' + + '
    ' + + ' ' + + '
    '; + + return listDiv; + }, + + // Called after the submenu has been rendered + on: function () { + this.context.custom.textElement.focus(); + }, + + onClick: function () { + this.history.push(true); + + const initialEditorContent = this.getContents(); + + const title = initialEditorContent.search('Resolutions') === -1 ? '

    Resolutions

    ' : ''; + + + if(this.context.custom.textElement.value.length > 0) { + // const parser = new this._w.DOMParser(); + // parser.parseFromString(title, 'text/html') + // Get Input value + const value = title.concat('

    ', this.context.custom.textElement.value, '

    '); + + const template = this.util.createElement('DIV'); + template.innerHTML = value; + + // insert + const children = template.children; + let after, child; + while (children[0]) { + child = children[0]; + this.insertNode(child, after); + after = child; + } + + // set range + // this.setRange(value, value.length, value, value.length); + + // clear content + this.context.custom.textElement.value = null; + } + + // submenu off + this.submenuOff(); + + // focus + this.focus(); + } +}; \ No newline at end of file diff --git a/test/dev/suneditor_build_test.html b/test/dev/suneditor_build_test.html index fc699acfc..edf457d3a 100644 --- a/test/dev/suneditor_build_test.html +++ b/test/dev/suneditor_build_test.html @@ -166,16 +166,34 @@
  • bbbb
    1. AAAAA
    2. -
    3. BBBBB
    4. -
    5. CCCC
    6. +
    7. BBBBB +
        +
      1. dasddsaddadas
      2. +
      3. dad +
          +
        1. asdasdsadsadas
        2. +
        3. ppppppppppppppppppppppppp
        4. +
        5. 000000aada
        6. +
        7. 11111
        8. +
        +
      4. +
      +
    8. +
    9. 2222222CCCC
  • -
  • cccccc
  • -
  • ddddd
  • +
  • 33333cccccc
  • +
  • 4444444ddddd
  • wroo

    +

    wroo

    +

    wroo

    +

    wroo

    +

    wroo

    +

    wroo

    +

    wroo

    1. 11111
    2. 22222
    3. From 218a3f227d14fdb0e73f03e497c895bfc008b1ff Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Tue, 3 Mar 2020 04:29:14 +0900 Subject: [PATCH 62/99] add: util-getArrayItem, detachNestedList --- sample/html/out/document-util.html | 82 ++++++++++++++++++- src/lib/core.js | 107 ++++++++---------------- src/lib/util.js | 127 +++++++++++++++++++++++++---- src/plugins/submenu/formatBlock.js | 7 +- test/dev/Resolutions.js | 2 - test/dev/suneditor_build_test.js | 17 +++- 6 files changed, 239 insertions(+), 103 deletions(-) diff --git a/sample/html/out/document-util.html b/sample/html/out/document-util.html index b6931c933..9af77d0d5 100644 --- a/sample/html/out/document-util.html +++ b/sample/html/out/document-util.html @@ -670,6 +670,50 @@
      Parameters:
      +

      getArrayItem(array, validation, multi) → {Array|Object}

      +
      + Get the item from the array that matches the condition. +
      +
      Parameters:
      +
    + + + + + + + + + + + + + + + + + + + + + + + + +
    NameTypeDescription
    array + Array + Array to get item
    validation + Function|null + Conditional function
    multi + Boolean + + If true, returns all items that meet the criteria otherwise, returns an empty array.
    + If false, returns only one item that meet the criteria otherwise return null. +
    +
    + +

    getArrayIndex(array, element) → {Number}

    @@ -1730,10 +1774,38 @@
    Parameters:
    -

    splitElement(beforeNode, offset, depth)detachNestedList(baseNode) → {Element}

    +
    + Detach Nested list all nested lists under the "baseNode".
    + Returns a list with nested removed. +
    +
    Parameters:
    + + + + + + + + + + + + + + + +
    NameTypeDescription
    baseNode + Element + Element on which to base.
    +
    + + +

    splitElement(baseNode, offset, depth) → {Element}

    - Split all tags based on "beforeNode"
    + Split all tags based on "baseNode"
    Returns the last element of the splited tag.
    Parameters:
    @@ -1747,7 +1819,7 @@
    Parameters:
    - beforeNode + baseNode Node @@ -1758,7 +1830,7 @@
    Parameters:
    Number|null - Text offset of "beforeNode" (Only valid when "beforeNode" is a text node) + Text offset of "baseNode" (Only valid when "baseNode" is a text node) depth @@ -1989,6 +2061,7 @@

    util

  • getFreeFormatElement
  • copyTagAttributes
  • copyFormatAttributes
  • +
  • getArrayItem
  • getArrayIndex
  • nextIdx
  • prevIdx
  • @@ -2020,6 +2093,7 @@

    util

  • toggleClass
  • removeItem
  • removeItemAllParents
  • +
  • detachNestedList
  • splitElement
  • mergeSameTags
  • mergeNestedTags
  • diff --git a/src/lib/core.js b/src/lib/core.js index 42ef1e823..04c7a63f4 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -756,7 +756,8 @@ export default function (context, pluginCallButtons, plugins, lang, options) { formatEl.parentNode.insertBefore(newLi, formatEl.nextElementSibling); this.setRange(textNode, 1, textNode, 1); } else { - this.insertNode(element, selectionNode === formatEl ? null : selectionNode); + this.insertNode(element, selectionNode === formatEl ? null : r.container.nextSibling); + if (!element.nextSibling) element.parentNode.appendChild(util.createElement('BR')); oNode = util.createElement('LI'); formatEl.parentNode.insertBefore(oNode, formatEl.nextElementSibling); } @@ -883,9 +884,9 @@ export default function (context, pluginCallButtons, plugins, lang, options) { parentNode = afterNode; afterNode = null; } else { - const depthFormat = util.getParentElement(afterNode, function (current) { return this.isRangeFormatElement(current); }.bind(util)); - afterNode = util.splitElement(afterNode, 0, !depthFormat ? 0 : util.getElementDepth(depthFormat) + 1); - parentNode = afterNode.parentNode; + const r = this.removeNode(); + parentNode = r.container.parentNode; + afterNode = r.container.nextSibling; } } parentNode.insertBefore(oNode, afterNode); @@ -1058,7 +1059,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { * @param {Element} rangeElement Element of wrap the arguments (BLOCKQUOTE...) */ applyRangeFormatElement: function (rangeElement) { - const rangeLines = this.getSelectedElementsAndComponents(true); + const rangeLines = this.getSelectedElementsAndComponents(false); if (!rangeLines || rangeLines.length === 0) return; let last = rangeLines[rangeLines.length - 1]; @@ -1111,7 +1112,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { list = list.parentNode; } - const edge = this.detachRangeFormatElement(originParent, lineArr, null, true, true); + const edge = this.detachRangeFormatElement(originParent, lineArr, null, false, true); if (parentDepth >= depth) { parentDepth = depth; @@ -1184,7 +1185,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { * @param {Boolean} remove Delete without detached. * @param {Boolean} notHistoryPush When true, it does not update the history stack and the selection object and return EdgeNodes (util.getEdgeChildNodes) */ - detachRangeFormatElement: function (rangeElement, selectedFormats, newRangeElement, remove, notHistoryPush, removeNestedList) { + detachRangeFormatElement: function (rangeElement, selectedFormats, newRangeElement, remove, notHistoryPush) { const range = this.getRange(); const so = range.startOffset; const eo = range.endOffset; @@ -1199,36 +1200,6 @@ export default function (context, pluginCallButtons, plugins, lang, options) { let insertedNew = false; let reset = false; - function _deleteNestedList (originNode) { - let sibling = originNode.parentNode; - let parent = sibling.parentNode; - let liSibling, liParent, child, index, c; - - while (util.isListCell(parent)) { - index = util.getPositionIndex(originNode); - liSibling = parent.nextElementSibling; - liParent = parent.parentNode; - child = sibling; - while(child) { - sibling = sibling.nextSibling; - if (util.isList(child)) { - c = child.childNodes; - while (c[index]) { - liParent.insertBefore(c[index], liSibling); - } - if (c.length === 0) util.removeItem(child); - } else { - liParent.appendChild(child); - } - child = sibling; - } - sibling = liParent; - parent = liParent.parentNode; - } - - return liParent; - } - function appendNode (parent, insNode, sibling, originNode) { if (util.onlyZeroWidthSpace(insNode)) insNode.innerHTML = util.zeroWidthSpace; @@ -1259,7 +1230,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { if (format.childNodes.length > 0) { if (util.isListCell(parent) && util.isListCell(format) && util.isList(sibling)) { - if (!removeNestedList) { + if (newList) { first = sibling; while(sibling) { format.appendChild(sibling); @@ -1268,26 +1239,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { parent.parentNode.insertBefore(format, parent.nextElementSibling); } else { reset = true; - - const rNode = _deleteNestedList(originNode); - rangeElement = rNode.cloneNode(false); - const c = rNode.childNodes; - const index = util.getPositionIndex(originNode); - while (c[index]) { - rangeElement.appendChild(c[index]); - } - - const rChildren = util.getListChildren(rangeElement, function (current) { return this.isListCell(current) && !current.previousElementSibling; }.bind(util)); - for (let i = 0, len = rChildren.length, n; i < len; i++) { - n = _deleteNestedList(rChildren[i]); - if (n && n.childNodes.length === 0) { - util.removeItem(n); - i--; len--; - } - } - - rNode.parentNode.insertBefore(rangeElement, rNode.nextSibling); - if (c.length === 0) util.removeItem(rNode); + rangeElement = util.detachNestedList(originNode); } } else { parent.insertBefore(format, sibling); @@ -1320,15 +1272,20 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } if (!newList && util.isListCell(insNode)) { - const inner = insNode; - insNode = util.createElement((util.isList(rangeElement.parentNode) || util.isListCell(rangeElement.parentNode)) ? 'LI' : util.isCell(rangeElement.parentNode) ? 'DIV' : 'P'); - insNode.innerHTML = inner.innerHTML; - util.copyFormatAttributes(insNode, inner); + if (util.isListCell(parent) || util.getArrayItem(insNode.children, util.isList, false)) { + reset = true; + rangeElement = util.detachNestedList(insNode); + } else { + const inner = insNode; + insNode = util.createElement((util.isList(rangeElement.parentNode) || util.isListCell(rangeElement.parentNode)) ? 'LI' : util.isCell(rangeElement.parentNode) ? 'DIV' : 'P'); + insNode.innerHTML = inner.innerHTML; + util.copyFormatAttributes(insNode, inner); + } } else { insNode = insNode.cloneNode(true); } - if (!remove) { + if (!remove && !reset) { if (newRangeElement) { if (!insertedNew) { parent.insertBefore(newRangeElement, rangeElement); @@ -1339,17 +1296,6 @@ export default function (context, pluginCallButtons, plugins, lang, options) { insNode = appendNode(parent, insNode, rangeElement, children[i]); } - if (reset) { - reset = false; - children = util.getListChildNodes(rangeElement, function (current) { return current.parentNode === rangeElement; }); - rangeEl = rangeElement.cloneNode(false); - parent = rangeElement.parentNode; - firstNode = lastNode = null; - i = -1; - len = children.length; - continue; - } - if (selectedFormats) { lastNode = insNode; if (!firstNode) { @@ -1359,6 +1305,17 @@ export default function (context, pluginCallButtons, plugins, lang, options) { firstNode = lastNode = insNode; } } + + if (reset) { + reset = false; + children = util.getListChildNodes(rangeElement, function (current) { return current.parentNode === rangeElement; }); + rangeEl = rangeElement.cloneNode(false); + parent = rangeElement.parentNode; + firstNode = lastNode = null; + i = -1; + len = children.length; + continue; + } } } @@ -1369,7 +1326,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } if (newRangeElement) firstNode = newRangeElement.previousSibling; - else firstNode = rangeElement.previousSibling; + else if (!firstNode) firstNode = rangeElement.previousSibling; rangeRight = rangeElement.nextSibling; util.removeItem(rangeElement); diff --git a/src/lib/util.js b/src/lib/util.js index 57097e4fe..d81366eaf 100755 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -451,6 +451,31 @@ const util = { this.copyTagAttributes(originEl, copyEl); }, + /** + * @description Get the item from the array that matches the condition. + * @param {Array} array Array to get item + * @param {Function|null} validation Conditional function + * @param {Boolean} multi If true, returns all items that meet the criteria otherwise, returns an empty array. + * If false, returns only one item that meet the criteria otherwise return null. + * @returns {Array|Object} + */ + getArrayItem: function (array, validation, multi) { + if (!array || array.length === 0) return null; + + validation = validation || function () { return true; }; + const arr = []; + + for (let i = 0, len = array.length, a; i < len; i++) { + a = array[i]; + if (validation(a)) { + if (!multi) return a; + else arr.push(a); + } + } + + return !multi ? null : arr; + }, + /** * @description Get the index of the argument value in the element array * @param {Array} array element array @@ -720,7 +745,7 @@ const util = { /** * @description Get all child nodes of the argument value element (Include text nodes) * @param {Element} element element to get child node - * @param {(function|null)} validation Conditional function + * @param {function|null} validation Conditional function * @returns {Array} */ getListChildNodes: function (element, validation) { @@ -1052,35 +1077,107 @@ const util = { }, /** - * @description Split all tags based on "beforeNode" + * @description Detach Nested list all nested lists under the "baseNode". + * Returns a list with nested removed. + * @param {Element} baseNode Element on which to base. + * @returns {Element} + */ + detachNestedList: function (baseNode) { + const rNode = this.__deleteNestedList(baseNode); + let rangeElement, cNodes; + + if (rNode) { + rangeElement = rNode.cloneNode(false); + cNodes = rNode.childNodes; + const index = this.getPositionIndex(baseNode); + while (cNodes[index]) { + rangeElement.appendChild(cNodes[index]); + } + } else { + rangeElement = baseNode; + } + + const rChildren = this.getListChildren(rangeElement, function (current) { return this.isListCell(current) && !current.previousElementSibling; }.bind(this)); + for (let i = 0, len = rChildren.length, n; i < len; i++) { + n = this.__deleteNestedList(rChildren[i]); + if (n && n.childNodes.length === 0) { + this.removeItem(n); + i--; len--; + } + } + + if (rNode) { + rNode.parentNode.insertBefore(rangeElement, rNode.nextSibling); + if (cNodes && cNodes.length === 0) this.removeItem(rNode); + } + + return rangeElement === baseNode ? rangeElement.parentNode : rangeElement; + }, + + /** + * @description Sub function of util.detachNestedList method. + * @private + */ + __deleteNestedList: function (baseNode) { + let sibling = baseNode.parentNode; + let parent = sibling.parentNode; + let liSibling, liParent, child, index, c; + + while (this.isListCell(parent)) { + index = this.getPositionIndex(baseNode); + liSibling = parent.nextElementSibling; + liParent = parent.parentNode; + child = sibling; + while(child) { + sibling = sibling.nextSibling; + if (this.isList(child)) { + c = child.childNodes; + while (c[index]) { + liParent.insertBefore(c[index], liSibling); + } + if (c.length === 0) this.removeItem(child); + } else { + liParent.appendChild(child); + } + child = sibling; + } + sibling = liParent; + parent = liParent.parentNode; + } + + return liParent; + }, + + /** + * @description Split all tags based on "baseNode" * Returns the last element of the splited tag. - * @param {Node} beforeNode Element or text node on which to base - * @param {Number|null} offset Text offset of "beforeNode" (Only valid when "beforeNode" is a text node) + * @param {Node} baseNode Element or text node on which to base + * @param {Number|null} offset Text offset of "baseNode" (Only valid when "baseNode" is a text node) * @param {Number} depth The nesting depth of the element being split. (default: 0) * @returns {Element} */ - splitElement: function (beforeNode, offset, depth) { - const bp = beforeNode.parentNode; + splitElement: function (baseNode, offset, depth) { + const bp = baseNode.parentNode; let index = 0, newEl, children, temp; let next = true; if (!depth || depth < 0) depth = 0; - if (beforeNode.nodeType === 3) { - index = this.getPositionIndex(beforeNode); + if (baseNode.nodeType === 3) { + index = this.getPositionIndex(baseNode); if (offset >= 0) { - beforeNode.splitText(offset); + baseNode.splitText(offset); const after = this.getNodeFromPath([index + 1], bp); if (this.onlyZeroWidthSpace(after)) after.data = this.zeroWidthSpace; } - } else if (beforeNode.nodeType === 1) { - if (!beforeNode.previousSibling) { - if (this.getElementDepth(beforeNode) === depth) next = false; + } else if (baseNode.nodeType === 1) { + if (!baseNode.previousSibling) { + if (this.getElementDepth(baseNode) === depth) next = false; } else { - beforeNode = beforeNode.previousSibling; + baseNode = baseNode.previousSibling; } } - let depthEl = beforeNode; + let depthEl = baseNode; while (this.getElementDepth(depthEl) > depth) { index = this.getPositionIndex(depthEl) + 1; depthEl = depthEl.parentNode; @@ -1096,7 +1193,7 @@ const util = { } const pElement = depthEl.parentNode; - if (next) depthEl = depthEl.nextElementSibling; + if (next) depthEl = depthEl.nextSibling; if (!newEl) return depthEl; this.mergeSameTags(newEl, null, null, false); diff --git a/src/plugins/submenu/formatBlock.js b/src/plugins/submenu/formatBlock.js index a399ed18c..2995ab1ec 100644 --- a/src/plugins/submenu/formatBlock.js +++ b/src/plugins/submenu/formatBlock.js @@ -183,7 +183,8 @@ export default { if (i === 0) listFirst = true; } else if (r && isList) { if (r !== o) { - const edge = this.detachRangeFormatElement(rangeArr.f[0].parentNode, rangeArr.f, null, false, true, true); + const edge = this.detachRangeFormatElement(rangeArr.f[0].parentNode, rangeArr.f, null, false, true); + o = selectedFormsts[i].parentNode; if (listFirst) { first = edge.sc; listFirst = false; @@ -191,7 +192,7 @@ export default { if (lastIndex) last = edge.ec; if (isList) { - r = o = null; + r = o; rangeArr = {r: r, f: [util.getParentElement(selectedFormsts[i], 'LI')]}; if (lastIndex) listLast = true; } else { @@ -204,7 +205,7 @@ export default { } if (lastIndex && util.isList(r)) { - const edge = this.detachRangeFormatElement(rangeArr.f[0].parentNode, rangeArr.f, null, false, true, true); + const edge = this.detachRangeFormatElement(rangeArr.f[0].parentNode, rangeArr.f, null, false, true); if (listLast || len === 1) last = edge.ec; if (listFirst) first = edge.sc || last; } diff --git a/test/dev/Resolutions.js b/test/dev/Resolutions.js index bbd97dbcc..d398d4d40 100644 --- a/test/dev/Resolutions.js +++ b/test/dev/Resolutions.js @@ -61,10 +61,8 @@ export default { this.history.push(true); const initialEditorContent = this.getContents(); - const title = initialEditorContent.search('Resolutions') === -1 ? '

    Resolutions

    ' : ''; - if(this.context.custom.textElement.value.length > 0) { // const parser = new this._w.DOMParser(); // parser.parseFromString(title, 'text/html') diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index b26c61268..4cdf41bce 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -9,6 +9,7 @@ import { ko } from '../../src/lang'; import lang from '../../src/lang'; import custom_plugin_submenu from './custom_plugin_submenu'; +import Resolutions from './Resolutions'; import 'codemirror/lib/codemirror.css'; import 'codemirror/mode/htmlmixed/htmlmixed'; @@ -23,14 +24,22 @@ const align = require('../../src/plugins/submenu/align') suneditor.create("sample1", { - plugins: plugins, + plugins: [Resolutions], // mode: "balloon", // iframe: true, + width: '100%', imageFileInput: false, buttonList: [ - ["undo", "image", "video"], - ["font", "fontSize", "formatBlock"], - ["paragraphStyle", "table"] + [ + { + name: 'Resolutions', + dataCommand: 'Resolutions', + buttonClass:'', + title:'Resolutions', + dataDisplay:'submenu', + innerHTML:'' + } + ] ] }); From b7028d4ed4e7f3d64332fd2fac1ccfb46c441503 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Tue, 3 Mar 2020 21:05:48 +0900 Subject: [PATCH 63/99] update: core-insertNode, --- sample/html/out/document-util.html | 11 ++++++-- src/lib/constructor.js | 2 +- src/lib/core.js | 40 +++++++++++++++++++----------- src/lib/util.js | 25 +++++++++++-------- 4 files changed, 50 insertions(+), 28 deletions(-) diff --git a/sample/html/out/document-util.html b/sample/html/out/document-util.html index 9af77d0d5..9f7bb8015 100644 --- a/sample/html/out/document-util.html +++ b/sample/html/out/document-util.html @@ -1774,10 +1774,10 @@
    Parameters:
    -

    detachNestedList(baseNode)detachNestedList(baseNode, all) → {Element}

    - Detach Nested list all nested lists under the "baseNode".
    + Detach Nested all nested lists under the "baseNode".
    Returns a list with nested removed.
    Parameters:
    @@ -1797,6 +1797,13 @@
    Parameters:
    Element on which to base. + + all + + Boolean + + If true, it also detach all nested lists of a returned list. +
    diff --git a/src/lib/constructor.js b/src/lib/constructor.js index b9d4b44a1..4251f63e0 100755 --- a/src/lib/constructor.js +++ b/src/lib/constructor.js @@ -542,7 +542,7 @@ export default { /** plugins - command */ blockquote: ['', lang.toolbar.tag_blockquote, 'blockquote', 'command', - '' + '' ], /** plugins - submenu */ diff --git a/src/lib/core.js b/src/lib/core.js index 04c7a63f4..689cdb0b2 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -896,15 +896,15 @@ export default function (context, pluginCallButtons, plugins, lang, options) { if (oNode.nodeType === 3) { const previous = oNode.previousSibling; const next = oNode.nextSibling; - const previousText = (!previous || util.onlyZeroWidthSpace(previous)) ? '' : previous.textContent; - const nextText = (!next || util.onlyZeroWidthSpace(next)) ? '' : next.textContent; + const previousText = (!previous || previous.nodeType !== 3 || util.onlyZeroWidthSpace(previous)) ? '' : previous.textContent; + const nextText = (!next || next.nodeType !== 3 || util.onlyZeroWidthSpace(next)) ? '' : next.textContent; - if (previous) { + if (previous && previousText.length > 0) { oNode.textContent = previousText + oNode.textContent; util.removeItem(previous); } - if (next) { + if (next && next.length > 0) { oNode.textContent += nextText; util.removeItem(next); } @@ -1112,7 +1112,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { list = list.parentNode; } - const edge = this.detachRangeFormatElement(originParent, lineArr, null, false, true); + const edge = this.detachRangeFormatElement(originParent, lineArr, null, true, true); if (parentDepth >= depth) { parentDepth = depth; @@ -1238,8 +1238,11 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } parent.parentNode.insertBefore(format, parent.nextElementSibling); } else { - reset = true; - rangeElement = util.detachNestedList(originNode); + const detachRange = util.detachNestedList(originNode, false); + if (rangeElement !== detachRange) { + rangeElement = detachRange; + reset = true; + } } } else { parent.insertBefore(format, sibling); @@ -1273,8 +1276,11 @@ export default function (context, pluginCallButtons, plugins, lang, options) { if (!newList && util.isListCell(insNode)) { if (util.isListCell(parent) || util.getArrayItem(insNode.children, util.isList, false)) { - reset = true; - rangeElement = util.detachNestedList(insNode); + const detachRange = util.detachNestedList(insNode, false); + if (rangeElement !== detachRange) { + rangeElement = detachRange; + reset = true; + } } else { const inner = insNode; insNode = util.createElement((util.isList(rangeElement.parentNode) || util.isListCell(rangeElement.parentNode)) ? 'LI' : util.isCell(rangeElement.parentNode) ? 'DIV' : 'P'); @@ -1331,11 +1337,17 @@ export default function (context, pluginCallButtons, plugins, lang, options) { util.removeItem(rangeElement); - const edge = remove ? { - cc: rangeParent, - sc: firstNode, - ec: rangeRight, - } : util.getEdgeChildNodes(firstNode, (!lastNode.parentNode ? firstNode : lastNode)); + let edge = null; + if (remove) { + edge = { + cc: rangeParent, + sc: firstNode, + ec: rangeRight, + }; + } else { + edge = util.getEdgeChildNodes(firstNode, (!lastNode.parentNode ? firstNode : lastNode)); + edge.cc = (edge.sc || edge.ec).parentNode; + } if (notHistoryPush) return edge; diff --git a/src/lib/util.js b/src/lib/util.js index d81366eaf..50ee064c9 100755 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -1077,12 +1077,13 @@ const util = { }, /** - * @description Detach Nested list all nested lists under the "baseNode". + * @description Detach Nested all nested lists under the "baseNode". * Returns a list with nested removed. * @param {Element} baseNode Element on which to base. + * @param {Boolean} all If true, it also detach all nested lists of a returned list. * @returns {Element} */ - detachNestedList: function (baseNode) { + detachNestedList: function (baseNode, all) { const rNode = this.__deleteNestedList(baseNode); let rangeElement, cNodes; @@ -1097,13 +1098,12 @@ const util = { rangeElement = baseNode; } - const rChildren = this.getListChildren(rangeElement, function (current) { return this.isListCell(current) && !current.previousElementSibling; }.bind(this)); - for (let i = 0, len = rChildren.length, n; i < len; i++) { - n = this.__deleteNestedList(rChildren[i]); - if (n && n.childNodes.length === 0) { - this.removeItem(n); - i--; len--; - } + const rChildren = !all ? + this.getListChildren(baseNode, function (current) { return this.isListCell(current) && !current.previousElementSibling; }.bind(this)) : + this.getListChildren(rangeElement, function (current) { return this.isListCell(current) && !current.previousElementSibling; }.bind(this)); + + for (let i = 0, len = rChildren.length; i < len; i++) { + this.__deleteNestedList(rChildren[i]); } if (rNode) { @@ -1119,7 +1119,8 @@ const util = { * @private */ __deleteNestedList: function (baseNode) { - let sibling = baseNode.parentNode; + const baseParent = baseNode.parentNode; + let sibling = baseParent; let parent = sibling.parentNode; let liSibling, liParent, child, index, c; @@ -1145,6 +1146,8 @@ const util = { parent = liParent.parentNode; } + if (baseParent.children.length === 0) this.removeItem(baseParent); + return liParent; }, @@ -1228,7 +1231,7 @@ const util = { child = children[i]; next = children[i + 1]; if (!child) break; - if((onlyText && inst._isIgnoreNodeChange(child)) || (!onlyText && inst.isFormatElement(child) && !inst.isFreeFormatElement(child))) continue; + if((onlyText && inst._isIgnoreNodeChange(child)) || (!onlyText && (inst.isTable(child) || inst.isListCell(child) || (inst.isFormatElement(child) && !inst.isFreeFormatElement(child))))) continue; if (len === 1 && current.nodeName === child.nodeName && current.parentNode) { inst.copyTagAttributes(child, current); current.parentNode.insertBefore(child, current); From dcabdbac4219e5e891152d656531aa0628a454f2 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Tue, 3 Mar 2020 22:02:40 +0900 Subject: [PATCH 64/99] add: core-detachList --- sample/html/out/document-editor.html | 38 +++++++++++++++- src/lib/core.js | 65 ++++++++++++++++++++++++++-- src/plugins/submenu/formatBlock.js | 45 ++----------------- 3 files changed, 102 insertions(+), 46 deletions(-) diff --git a/sample/html/out/document-editor.html b/sample/html/out/document-editor.html index 4b8843286..c1f77d2e9 100644 --- a/sample/html/out/document-editor.html +++ b/sample/html/out/document-editor.html @@ -1229,7 +1229,7 @@
    Parameters:
    Boolean - Delete without detached. + If true, deleted without detached. notHistoryPush @@ -1243,6 +1243,41 @@
    Parameters:
    +

    detachList(selectedFormats, remove){Object}{sc: <LI>, ec: <LI>}

    +
    + "selectedFormats" array are detached from the list element.
    + The return value is applied when the first and last lines of "selectedFormats" are "LI" respectively. +
    +
    Parameters:
    + + + + + + + + + + + + + + + + + + + + +
    NameTypeDescription
    selectedFormats + Array + Array of format elements (LI, P...) to remove.
    remove + Boolean + If true, deleted without detached.
    +
    + +

    nodeChange(appendNode, styleArray, removeNodeArray, strictRemove)

    @@ -1627,6 +1662,7 @@

    core

  • removeNode
  • applyRangeFormatElement
  • detachRangeFormatElement
  • +
  • detachList
  • nodeChange
  • commandHandler
  • removeFormat
  • diff --git a/src/lib/core.js b/src/lib/core.js index 689cdb0b2..25ff25f2a 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -1182,7 +1182,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { * @param {Array|null} selectedFormats Array of format elements (P, DIV, LI...) to remove. * If null, Applies to all elements and return {cc: parentNode, sc: nextSibling, ec: previousSibling} * @param {Element|null} newRangeElement The node(rangeElement) to replace the currently wrapped node. - * @param {Boolean} remove Delete without detached. + * @param {Boolean} remove If true, deleted without detached. * @param {Boolean} notHistoryPush When true, it does not update the history stack and the selection object and return EdgeNodes (util.getEdgeChildNodes) */ detachRangeFormatElement: function (rangeElement, selectedFormats, newRangeElement, remove, notHistoryPush) { @@ -1238,7 +1238,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } parent.parentNode.insertBefore(format, parent.nextElementSibling); } else { - const detachRange = util.detachNestedList(originNode, false); + const detachRange = util.detachNestedList(originNode, true); if (rangeElement !== detachRange) { rangeElement = detachRange; reset = true; @@ -1276,7 +1276,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { if (!newList && util.isListCell(insNode)) { if (util.isListCell(parent) || util.getArrayItem(insNode.children, util.isList, false)) { - const detachRange = util.detachNestedList(insNode, false); + const detachRange = util.detachNestedList(insNode, true); if (rangeElement !== detachRange) { rangeElement = detachRange; reset = true; @@ -1365,6 +1365,65 @@ export default function (context, pluginCallButtons, plugins, lang, options) { event._applyTagEffects(); }, + /** + * @description "selectedFormats" array are detached from the list element. + * The return value is applied when the first and last lines of "selectedFormats" are "LI" respectively. + * @param {Array} selectedFormats Array of format elements (LI, P...) to remove. + * @param {Boolean} remove If true, deleted without detached. + * @returns {Object} {sc:
  • , ec:
  • }. + */ + detachList: function (selectedFormats, remove) { + let rangeArr = {}; + let listFirst = false; + let listLast = false; + let first = null; + let last = null; + const passComponent = function (current) { return !this.isComponent(current); }.bind(util); + + for (let i = 0, len = selectedFormats.length, r, o, lastIndex, isList; i < len; i++) { + lastIndex = i === len - 1; + o = util.getRangeFormatElement(selectedFormats[i], passComponent); + isList = util.isList(o); + if (!r && isList) { + r = o; + rangeArr = {r: r, f: [util.getParentElement(selectedFormats[i], 'LI')]}; + if (i === 0) listFirst = true; + } else if (r && isList) { + if (r !== o) { + const edge = this.detachRangeFormatElement(rangeArr.f[0].parentNode, rangeArr.f, null, remove, true); + o = selectedFormats[i].parentNode; + if (listFirst) { + first = edge.sc; + listFirst = false; + } + if (lastIndex) last = edge.ec; + + if (isList) { + r = o; + rangeArr = {r: r, f: [util.getParentElement(selectedFormats[i], 'LI')]}; + if (lastIndex) listLast = true; + } else { + r = null; + } + } else { + rangeArr.f.push(util.getParentElement(selectedFormats[i], 'LI')); + if (lastIndex) listLast = true; + } + } + + if (lastIndex && util.isList(r)) { + const edge = this.detachRangeFormatElement(rangeArr.f[0].parentNode, rangeArr.f, null, remove, true); + if (listLast || len === 1) last = edge.ec; + if (listFirst) first = edge.sc || last; + } + } + + return { + sc: first, + ec: last + }; + }, + /** * @description Add, update, and delete nodes from selected text. * 1. If there is a node in the "appendNode" argument, a node with the same tags and attributes as "appendNode" is added to the selection text. diff --git a/src/plugins/submenu/formatBlock.js b/src/plugins/submenu/formatBlock.js index 2995ab1ec..335d620f8 100644 --- a/src/plugins/submenu/formatBlock.js +++ b/src/plugins/submenu/formatBlock.js @@ -168,48 +168,9 @@ export default { const lastPath = util.getNodePath(range.endContainer, last, null); // remove selected list - let rangeArr = {}; - let listFirst = false; - let listLast = false; - const passComponent = function (current) { return !this.isComponent(current); }.bind(util); - - for (let i = 0, len = selectedFormsts.length, r, o, lastIndex, isList; i < len; i++) { - lastIndex = i === len - 1; - o = util.getRangeFormatElement(selectedFormsts[i], passComponent); - isList = util.isList(o); - if (!r && isList) { - r = o; - rangeArr = {r: r, f: [util.getParentElement(selectedFormsts[i], 'LI')]}; - if (i === 0) listFirst = true; - } else if (r && isList) { - if (r !== o) { - const edge = this.detachRangeFormatElement(rangeArr.f[0].parentNode, rangeArr.f, null, false, true); - o = selectedFormsts[i].parentNode; - if (listFirst) { - first = edge.sc; - listFirst = false; - } - if (lastIndex) last = edge.ec; - - if (isList) { - r = o; - rangeArr = {r: r, f: [util.getParentElement(selectedFormsts[i], 'LI')]}; - if (lastIndex) listLast = true; - } else { - r = null; - } - } else { - rangeArr.f.push(util.getParentElement(selectedFormsts[i], 'LI')); - if (lastIndex) listLast = true; - } - } - - if (lastIndex && util.isList(r)) { - const edge = this.detachRangeFormatElement(rangeArr.f[0].parentNode, rangeArr.f, null, false, true); - if (listLast || len === 1) last = edge.ec; - if (listFirst) first = edge.sc || last; - } - } + const rlist = this.detachList(selectedFormsts, false); + if (rlist.sc) first = rlist.sc; + if (rlist.ec) last = rlist.ec; // change format tag this.setRange(util.getNodeFromPath(firstPath, first), startOffset, util.getNodeFromPath(lastPath, last), endOffset); From f72655a3e5a3d9eab588150f0ed4b8c370f1ed90 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Wed, 4 Mar 2020 00:51:37 +0900 Subject: [PATCH 65/99] fix: util functions --- src/lib/core.js | 16 ++++++++++------ src/lib/util.js | 16 ++++++++++------ 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/src/lib/core.js b/src/lib/core.js index 25ff25f2a..e7266df88 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -1238,8 +1238,9 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } parent.parentNode.insertBefore(format, parent.nextElementSibling); } else { - const detachRange = util.detachNestedList(originNode, true); - if (rangeElement !== detachRange) { + const originNext = originNode.nextElementSibling; + const detachRange = util.detachNestedList(originNode, false); + if ((rangeElement !== detachRange) || (originNext !== originNode.nextElementSibling)) { rangeElement = detachRange; reset = true; } @@ -1276,15 +1277,19 @@ export default function (context, pluginCallButtons, plugins, lang, options) { if (!newList && util.isListCell(insNode)) { if (util.isListCell(parent) || util.getArrayItem(insNode.children, util.isList, false)) { - const detachRange = util.detachNestedList(insNode, true); - if (rangeElement !== detachRange) { + const insNext = insNode.nextElementSibling; + const detachRange = util.detachNestedList(insNode, false); + if ((rangeElement !== detachRange) || insNext !== insNode.nextElementSibling) { rangeElement = detachRange; reset = true; } } else { const inner = insNode; insNode = util.createElement((util.isList(rangeElement.parentNode) || util.isListCell(rangeElement.parentNode)) ? 'LI' : util.isCell(rangeElement.parentNode) ? 'DIV' : 'P'); - insNode.innerHTML = inner.innerHTML; + const innerChildren = inner.childNodes; + while (innerChildren[0]) { + insNode.appendChild(innerChildren[0]); + } util.copyFormatAttributes(insNode, inner); } } else { @@ -1317,7 +1322,6 @@ export default function (context, pluginCallButtons, plugins, lang, options) { children = util.getListChildNodes(rangeElement, function (current) { return current.parentNode === rangeElement; }); rangeEl = rangeElement.cloneNode(false); parent = rangeElement.parentNode; - firstNode = lastNode = null; i = -1; len = children.length; continue; diff --git a/src/lib/util.js b/src/lib/util.js index 50ee064c9..4cbb4901d 100755 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -1098,9 +1098,13 @@ const util = { rangeElement = baseNode; } - const rChildren = !all ? - this.getListChildren(baseNode, function (current) { return this.isListCell(current) && !current.previousElementSibling; }.bind(this)) : - this.getListChildren(rangeElement, function (current) { return this.isListCell(current) && !current.previousElementSibling; }.bind(this)); + let rChildren; + if (!all) { + const depth = this.getElementDepth(baseNode) + 2; + rChildren = this.getListChildren(baseNode, function (current) { return this.isListCell(current) && !current.previousElementSibling && this.getElementDepth(current) === depth; }.bind(this)); + } else { + rChildren = this.getListChildren(rangeElement, function (current) { return this.isListCell(current) && !current.previousElementSibling; }.bind(this)); + } for (let i = 0, len = rChildren.length; i < len; i++) { this.__deleteNestedList(rChildren[i]); @@ -1427,7 +1431,7 @@ const util = { * @private */ _isIgnoreNodeChange: function (element) { - return element.nodeType !== 3 && (element.getAttribute('contenteditable') === 'false' || !/^(span|font|b|strong|var|i|em|u|ins|s|strike|del|sub|sup|mark|a|label)$/i.test(element.nodeName)); + return element.nodeType !== 3 && (element.getAttribute('contenteditable') === 'false' || !/^(span|font|b|strong|var|i|em|u|ins|s|strike|del|sub|sup|mark|a|label)$/i.test(typeof element === 'string' ? element : element.nodeName)); }, /** @@ -1437,7 +1441,7 @@ const util = { * @private */ _isMaintainedNode: function (element) { - return element.nodeType !== 3 && /^(a|label)$/i.test(element.nodeName); + return element.nodeType !== 3 && /^(a|label)$/i.test(typeof element === 'string' ? element : element.nodeName); }, /** @@ -1447,7 +1451,7 @@ const util = { * @private */ _notTextNode: function (element) { - return element.nodeType !== 3 && (this.isComponent(element) || /^(br|input|select|canvas|img|iframe|audio|video)$/i.test(element.nodeName)); + return element.nodeType !== 3 && (this.isComponent(element) || /^(br|input|select|canvas|img|iframe|audio|video)$/i.test(typeof element === 'string' ? element : element.nodeName)); }, /** From 5845b88372155bd32bd1acdbe0f9a099900a64dd Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Wed, 4 Mar 2020 02:30:06 +0900 Subject: [PATCH 66/99] modify: core-detachRangeFormatElement return value --- sample/html/out/document-editor.html | 4 +- src/lib/core.js | 96 +++++++++++++++------------- src/plugins/submenu/template.js | 5 +- test/dev/suneditor_build_test.html | 15 ----- 4 files changed, 56 insertions(+), 64 deletions(-) diff --git a/sample/html/out/document-editor.html b/sample/html/out/document-editor.html index c1f77d2e9..5121bed97 100644 --- a/sample/html/out/document-editor.html +++ b/sample/html/out/document-editor.html @@ -1187,10 +1187,10 @@
    Parameters:

    detachRangeFormatElement(rangeElement, selectedFormats, newRangeElement, remove, notHistoryPush)

    + class="type-signature">{Object}
  • The elements of the "selectedFormats" array are detached from the "rangeElement" element. ("LI" tags are converted to "P" tags)
    - When "selectedFormats" is null, all elements are detached and return {cc: parentNode, sc: previousSibling, ec: nextSibling}. + When "selectedFormats" is null, all elements are detached and return {cc: parentNode, sc: previousSibling, ec: nextSibling, removeArray: [Array of removed elements]}.
    Parameters:
    diff --git a/src/lib/core.js b/src/lib/core.js index e7266df88..81bdd7fdc 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -1099,8 +1099,6 @@ export default function (context, pluginCallButtons, plugins, lang, options) { if (util.isList(originParent)) { if (listParent === null) listParent = util.createElement(originParent.nodeName); - - listParent.innerHTML += line.outerHTML; lineArr.push(line); if (i === len - 1 || rangeLines[i + 1].parentNode !== originParent) { @@ -1129,6 +1127,10 @@ export default function (context, pluginCallButtons, plugins, lang, options) { else beforeTag = edge.cc; } + for (let c = 0, cLen = edge.removeArray.length; c < cLen; c++) { + listParent.innerHTML += edge.removeArray[c].outerHTML; + } + rangeElement.appendChild(listParent); listParent = null; } @@ -1177,13 +1179,14 @@ export default function (context, pluginCallButtons, plugins, lang, options) { /** * @description The elements of the "selectedFormats" array are detached from the "rangeElement" element. ("LI" tags are converted to "P" tags) - * When "selectedFormats" is null, all elements are detached and return {cc: parentNode, sc: nextSibling, ec: previousSibling}. + * When "selectedFormats" is null, all elements are detached and return {cc: parentNode, sc: nextSibling, ec: previousSibling, removeArray: [Array of removed elements]}. * @param {Element} rangeElement Range format element (PRE, BLOCKQUOTE, OL, UL...) * @param {Array|null} selectedFormats Array of format elements (P, DIV, LI...) to remove. * If null, Applies to all elements and return {cc: parentNode, sc: nextSibling, ec: previousSibling} * @param {Element|null} newRangeElement The node(rangeElement) to replace the currently wrapped node. * @param {Boolean} remove If true, deleted without detached. * @param {Boolean} notHistoryPush When true, it does not update the history stack and the selection object and return EdgeNodes (util.getEdgeChildNodes) + * @returns {Object} */ detachRangeFormatElement: function (rangeElement, selectedFormats, newRangeElement, remove, notHistoryPush) { const range = this.getRange(); @@ -1196,6 +1199,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { let lastNode = null; let rangeEl = rangeElement.cloneNode(false); + const removeArray = []; const newList = util.isList(newRangeElement); let insertedNew = false; let reset = false; @@ -1255,6 +1259,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { return first; } + // detach loop for (let i = 0, len = children.length, insNode; i < len; i++) { insNode = children[i]; if (remove && i === 0) { @@ -1285,7 +1290,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } } else { const inner = insNode; - insNode = util.createElement((util.isList(rangeElement.parentNode) || util.isListCell(rangeElement.parentNode)) ? 'LI' : util.isCell(rangeElement.parentNode) ? 'DIV' : 'P'); + insNode = util.createElement(remove ? inner.nodeName : (util.isList(rangeElement.parentNode) || util.isListCell(rangeElement.parentNode)) ? 'LI' : util.isCell(rangeElement.parentNode) ? 'DIV' : 'P'); const innerChildren = inner.childNodes; while (innerChildren[0]) { insNode.appendChild(innerChildren[0]); @@ -1296,28 +1301,30 @@ export default function (context, pluginCallButtons, plugins, lang, options) { insNode = insNode.cloneNode(true); } - if (!remove && !reset) { - if (newRangeElement) { - if (!insertedNew) { - parent.insertBefore(newRangeElement, rangeElement); - insertedNew = true; + if (!reset) { + if (!remove) { + if (newRangeElement) { + if (!insertedNew) { + parent.insertBefore(newRangeElement, rangeElement); + insertedNew = true; + } + insNode = appendNode(newRangeElement, insNode, null, children[i]); + } else { + insNode = appendNode(parent, insNode, rangeElement, children[i]); } - insNode = appendNode(newRangeElement, insNode, null, children[i]); - } else { - insNode = appendNode(parent, insNode, rangeElement, children[i]); - } - - if (selectedFormats) { - lastNode = insNode; - if (!firstNode) { - firstNode = insNode; + + if (selectedFormats) { + lastNode = insNode; + if (!firstNode) { + firstNode = insNode; + } + } else if (!firstNode) { + firstNode = lastNode = insNode; } - } else if (!firstNode) { - firstNode = lastNode = insNode; + } else { + removeArray.push(insNode); } - } - - if (reset) { + } else { reset = false; children = util.getListChildNodes(rangeElement, function (current) { return current.parentNode === rangeElement; }); rangeEl = rangeElement.cloneNode(false); @@ -1347,6 +1354,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { cc: rangeParent, sc: firstNode, ec: rangeRight, + removeArray: removeArray }; } else { edge = util.getEdgeChildNodes(firstNode, (!lastNode.parentNode ? firstNode : lastNode)); @@ -4111,28 +4119,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { if (ctrl || alt || util.isWysiwygDiv(selectionNode)) break; core.controllersOff(); - - // table - let currentNode = selectionNode; - while (!util.isCell(currentNode) && !util.isWysiwygDiv(currentNode)) { - currentNode = currentNode.parentNode; - } - - if (currentNode && util.isCell(currentNode)) { - const table = util.getParentElement(currentNode, 'table'); - const cells = util.getListChildren(table, util.isCell); - let idx = shift ? util.prevIdx(cells, currentNode) : util.nextIdx(cells, currentNode); - - if (idx === cells.length && !shift) idx = 0; - if (idx === -1 && shift) idx = cells.length - 1; - - const moveCell = cells[idx]; - if (!moveCell) return false; - - core.setRange(moveCell, 0, moveCell, 0); - break; - } - + const isEdge = (!range.collapsed || core.isEdgePoint(range.startContainer, range.startOffset)); const selectedFormats = core.getSelectedElements(); const cells = []; let lines = []; @@ -4152,7 +4139,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } // Nested list - if (cells.length > 0 && (!range.collapsed || core.isEdgePoint(range.startContainer, range.startOffset)) && core.plugins.list) { + if (cells.length > 0 && isEdge && core.plugins.list) { core.callPlugin('list', function () { const listRange = core.plugins.list.editInsideList.call(core, shift, cells); if (fc) { @@ -4165,6 +4152,23 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } }); } else { + // table + const tableCell = util.getParentElement(selectionNode, util.isCell); + if (tableCell && isEdge) { + const table = util.getParentElement(tableCell, 'table'); + const cells = util.getListChildren(table, util.isCell); + let idx = shift ? util.prevIdx(cells, tableCell) : util.nextIdx(cells, tableCell); + + if (idx === cells.length && !shift) idx = 0; + if (idx === -1 && shift) idx = cells.length - 1; + + const moveCell = cells[idx]; + if (!moveCell) return false; + + core.setRange(moveCell, 0, moveCell, 0); + break; + } + lines = lines.concat(cells); fc = lc = null; } diff --git a/src/plugins/submenu/template.js b/src/plugins/submenu/template.js index 9d66b97ec..6fcc6aded 100644 --- a/src/plugins/submenu/template.js +++ b/src/plugins/submenu/template.js @@ -29,8 +29,11 @@ export default { setSubmenu: function () { const templateList = this.context.option.templates; - const listDiv = this.util.createElement('DIV'); + if (!templateList || templateList.length === 0) { + throw Error('[SUNEDITOR.plugins.template.fail] To use the "template" plugin, please define the "templates" option.'); + } + const listDiv = this.util.createElement('DIV'); listDiv.className = 'se-list-layer'; let list = '
    ' + diff --git a/test/dev/suneditor_build_test.html b/test/dev/suneditor_build_test.html index edf457d3a..d4a5b5bbc 100644 --- a/test/dev/suneditor_build_test.html +++ b/test/dev/suneditor_build_test.html @@ -194,21 +194,6 @@

    wroo

    wroo

    wroo

    -
      -
    1. 11111
    2. -
    3. 22222
    4. -
        -
      1. aaaaa
      2. -
      3. bbbb
      4. -
          -
        1. AAAAA
        2. -
        3. BBBBB
        4. -
        5. CCCC
        6. -
        -
      5. cccccc
      6. -
      7. ddddd
      8. -
      -

    aaaaaaa

    From d77cc05a3cf6d958a3702fb3832b88832d30717e Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Wed, 4 Mar 2020 04:01:14 +0900 Subject: [PATCH 67/99] modify: list --- src/plugins/submenu/list.js | 101 ++++++++++++++++++++---------------- 1 file changed, 57 insertions(+), 44 deletions(-) diff --git a/src/plugins/submenu/list.js b/src/plugins/submenu/list.js index 5f54d390e..6d8f0faa5 100644 --- a/src/plugins/submenu/list.js +++ b/src/plugins/submenu/list.js @@ -103,23 +103,23 @@ export default { } }, - editList: function (command, selectedCells) { - const selectedFormsts = !selectedCells ? this.getSelectedElementsAndComponents(false) : selectedCells; - if (!selectedFormsts || selectedFormsts.length === 0) return; + editList: function (command, selectedCells, detach) { + const selectedFormats = !selectedCells ? this.getSelectedElementsAndComponents(false) : selectedCells; + if (!selectedFormats || selectedFormats.length === 0) return; let isRemove = true; let edgeFirst = null; let edgeLast = null; // merge - const firstSel = selectedFormsts[0]; - const lastSel = selectedFormsts[selectedFormsts.length - 1]; + const firstSel = selectedFormats[0]; + const lastSel = selectedFormats[selectedFormats.length - 1]; let topEl = (this.util.isListCell(firstSel) || this.util.isComponent(firstSel)) && !firstSel.previousElementSibling ? firstSel.parentNode.previousElementSibling : firstSel.previousElementSibling; let bottomEl = (this.util.isListCell(lastSel) || this.util.isComponent(lastSel)) && !lastSel.nextElementSibling ? lastSel.parentNode.nextElementSibling : lastSel.nextElementSibling; - for (let i = 0, len = selectedFormsts.length; i < len; i++) { - if (!this.util.isList(this.util.getRangeFormatElement(selectedFormsts[i], function (current) { - return this.getRangeFormatElement(current) && current !== selectedFormsts[i]; + for (let i = 0, len = selectedFormats.length; i < len; i++) { + if (!this.util.isList(this.util.getRangeFormatElement(selectedFormats[i], function (current) { + return this.getRangeFormatElement(current) && current !== selectedFormats[i]; }.bind(this.util)))) { isRemove = false; break; @@ -127,37 +127,50 @@ export default { } if (isRemove && (!topEl || (firstSel.tagName !== topEl.tagName || command !== topEl.tagName.toUpperCase())) && (!bottomEl || (lastSel.tagName !== bottomEl.tagName || command !== bottomEl.tagName.toUpperCase()))) { - const currentFormat = this.util.getRangeFormatElement(firstSel); - const cancel = currentFormat && currentFormat.tagName === command; - let rangeArr, tempList; - const passComponent = function (current) { - return !this.isComponent(current); - }.bind(this.util); - - if (!cancel) tempList = this.util.createElement(command); - - for (let i = 0, len = selectedFormsts.length, r, o; i < len; i++) { - o = this.util.getRangeFormatElement(selectedFormsts[i], passComponent); - if (!o || !this.util.isList(o)) continue; - - if (!r) { - r = o; - rangeArr = {r: r, f: [this.util.getParentElement(selectedFormsts[i], 'LI')]}; - } else { - if (r !== o) { - const edge = this.detachRangeFormatElement(rangeArr.r, rangeArr.f, tempList, false, true); - if (!edgeFirst) edgeFirst = edge; - if (!cancel) tempList = this.util.createElement(command); + if (detach) { + for (let i = 0, len = selectedFormats.length; i < len; i++) { + for (let j = i - 1; j >= 0; j--) { + if (selectedFormats[j].contains(selectedFormats[i])) { + selectedFormats.splice(i, 1); + i--; len--; + break; + } + } + } + } else { + const currentFormat = this.util.getRangeFormatElement(firstSel); + const cancel = currentFormat && currentFormat.tagName === command; + let rangeArr, tempList; + const passComponent = function (current) { + return !this.isComponent(current); + }.bind(this.util); + + if (!cancel) tempList = this.util.createElement(command); + + for (let i = 0, len = selectedFormats.length, r, o; i < len; i++) { + o = this.util.getRangeFormatElement(selectedFormats[i], passComponent); + if (!o || !this.util.isList(o)) continue; + + if (!r) { r = o; - rangeArr = {r: r, f: [this.util.getParentElement(selectedFormsts[i], 'LI')]}; + rangeArr = {r: r, f: [this.util.getParentElement(selectedFormats[i], 'LI')]}; } else { - rangeArr.f.push(this.util.getParentElement(selectedFormsts[i], 'LI')); + if (r !== o) { + const edge = this.detachRangeFormatElement(rangeArr.f[0].parentNode, rangeArr.f, tempList, false, true); + o = selectedFormats[i].parentNode; + if (!edgeFirst) edgeFirst = edge; + if (!cancel) tempList = this.util.createElement(command); + r = o; + rangeArr = {r: r, f: [this.util.getParentElement(selectedFormats[i], 'LI')]}; + } else { + rangeArr.f.push(this.util.getParentElement(selectedFormats[i], 'LI')); + } + } + + if (i === len - 1) { + edgeLast = this.detachRangeFormatElement(rangeArr.f[0].parentNode, rangeArr.f, tempList, false, true); + if (!edgeFirst) edgeFirst = edgeLast; } - } - - if (i === len - 1) { - edgeLast = this.detachRangeFormatElement(rangeArr.r, rangeArr.f, tempList, false, true); - if (!edgeFirst) edgeFirst = edgeLast; } } } else { @@ -179,13 +192,13 @@ export default { return !this.isComponent(current) && !this.isList(current); }.bind(this.util); - for (let i = 0, len = selectedFormsts.length, newCell, fTag, isCell, next, originParent, nextParent, parentTag, siblingTag, rangeTag; i < len; i++) { - fTag = selectedFormsts[i]; + for (let i = 0, len = selectedFormats.length, newCell, fTag, isCell, next, originParent, nextParent, parentTag, siblingTag, rangeTag; i < len; i++) { + fTag = selectedFormats[i]; if (fTag.childNodes.length === 0 && !this.util._isIgnoreNodeChange(fTag)) { this.util.removeItem(fTag); continue; } - next = selectedFormsts[i + 1]; + next = selectedFormats[i + 1]; originParent = fTag.parentNode; nextParent = next ? next.parentNode : null; isCell = this.util.isListCell(fTag); @@ -239,8 +252,8 @@ export default { this.submenuOff(); return { - sc: selectedFormsts.length > 1 ? edgeFirst.sc : edgeFirst.ec, - so: selectedFormsts.length > 1 ? 0 : edgeFirst.ec.textContent.length, + sc: selectedFormats.length > 1 ? edgeFirst.sc : edgeFirst.ec, + so: selectedFormats.length > 1 ? 0 : edgeFirst.ec.textContent.length, ec: edgeLast.ec, eo: edgeLast.ec.textContent.length }; @@ -263,14 +276,14 @@ export default { let range = null; if (remove) { - if (originList !== lastCell.parentNode && lastCell.nextElementSibling) { + if (originList !== lastCell.parentNode && this.util.isList(lastCell.parentNode.parentNode) && lastCell.nextElementSibling) { lastCell = lastCell.nextElementSibling; while (lastCell) { selectedCells.push(lastCell); lastCell = lastCell.nextElementSibling; } } - range = this.plugins.list.editList.call(this, originList.nodeName.toUpperCase(), selectedCells); + range = this.plugins.list.editList.call(this, originList.nodeName.toUpperCase(), selectedCells, true); } else { range = { sc: selectedCells[0], so: cellsLen > 1 || !this.getRange().collapsed ? 0 : 1, ec: lastCell, eo: 1 }; let innerList = this.util.createElement(originList.nodeName); @@ -348,7 +361,7 @@ export default { if (!command) return; - const range = this.plugins.list.editList.call(this, command, null, null); + const range = this.plugins.list.editList.call(this, command, null, false); this.setRange(range.sc, range.so, range.ec, range.eo); // history stack From 34a6a7f7ae24aa269163aa4ffca5fa0b7dd01d93 Mon Sep 17 00:00:00 2001 From: Yao Zhao Date: Wed, 4 Mar 2020 14:02:56 +0800 Subject: [PATCH 68/99] fix: fix lacking of class --- sample/html/customPlugins.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sample/html/customPlugins.html b/sample/html/customPlugins.html index 01724f037..c9e9daf11 100644 --- a/sample/html/customPlugins.html +++ b/sample/html/customPlugins.html @@ -202,7 +202,7 @@

    Add new plugin

    listDiv.className = 'se-submenu se-list-layer'; listDiv.innerHTML = '' + - '
    ' + + '
    ' + '
      ' + '
    • ' + '
    + + + + + + + + + + + + + + + + + + + +
    NameTypeDescription
    array + Array + Array object
    des + Boolean + true: descending order / false: ascending order
    +
    + +

    cleanHTML(html, whitelist) → {String}

    @@ -2105,6 +2139,7 @@

    util

  • mergeSameTags
  • mergeNestedTags
  • removeEmptyNode
  • +
  • sortByDepth
  • cleanHTML
  • createTagsWhitelist
  • diff --git a/src/lib/core.js b/src/lib/core.js index 549f23aa7..faff271e3 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -1187,16 +1187,31 @@ export default function (context, pluginCallButtons, plugins, lang, options) { return cc ? cc.ec : before; }; - for (let i = 0, len = rangeLines.length, line, originParent, depth, before; i < len; i++) { + for (let i = 0, len = rangeLines.length, line, originParent, depth, before, nextLine, nextList, nested; i < len; i++) { line = rangeLines[i]; originParent = line.parentNode; depth = util.getElementDepth(line); if (util.isList(originParent)) { - if (listParent === null) listParent = util.createElement(originParent.nodeName); + if (listParent === null) { + if (nextList) { + listParent = nextList; + nested = true; + nextList = null; + } else { + listParent = originParent.cloneNode(false); + } + } + lineArr.push(line); + nextLine = rangeLines[i + 1]; + + if (i === len - 1 || (nextLine && rangeLines[i + 1].parentNode !== originParent)) { + // nested list + if (nextLine && line.contains(rangeLines[i + 1].parentNode)) { + nextList = nextLine.parentNode.cloneNode(false); + } - if (i === len - 1 || rangeLines[i + 1].parentNode !== originParent) { let list = originParent.parentNode, p; while (util.isList(list)) { p = util.createElement(list.nodeName); @@ -1223,11 +1238,13 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } for (let c = 0, cLen = edge.removeArray.length; c < cLen; c++) { - listParent.innerHTML += edge.removeArray[c].outerHTML; + listParent.appendChild(edge.removeArray[c]); } - rangeElement.appendChild(listParent); + if (!nested) rangeElement.appendChild(listParent); + if (nextList) edge.removeArray[edge.removeArray.length - 1].appendChild(nextList); listParent = null; + nested = false; } } else { @@ -1421,6 +1438,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } } else { removeArray.push(insNode); + util.removeItem(children[i]); } } else { reset = moveComplete = false; @@ -3621,7 +3639,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { * @description event function */ const event = { - _directionKeyCode: new _w.RegExp('^(8|13|32|46|3[3-9]|40|46)$'), + _directionKeyCode: new _w.RegExp('^(8|13|3[2-9]|40|46)$'), _nonTextKeyCode: new _w.RegExp('^(8|13|1[6-9]|20|27|3[3-9]|40|45|46|11[2-9]|12[0-3]|144|145)$'), _historyIgnoreKeyCode: new _w.RegExp('^(1[6-9]|20|27|3[3-9]|40|45|11[2-9]|12[0-3]|144|145)$'), _onButtonsCheck: new _w.RegExp('^(STRONG|INS|EM|DEL|SUB|SUP)$'), @@ -4105,6 +4123,31 @@ export default function (context, pluginCallButtons, plugins, lang, options) { const commonCon = range.commonAncestorContainer; if (range.startOffset === 0 && range.endOffset === 0) { if (rangeEl && formatEl && !util.isCell(rangeEl) && !/^FIGCAPTION$/i.test(rangeEl.nodeName)) { + if (util.isListCell(formatEl) && util.isList(rangeEl) && (util.isListCell(rangeEl.parentNode) || formatEl.previousElementSibling) && (selectionNode === formatEl || (selectionNode.nodeType === 3 && !selectionNode.previousSibling && range.collapsed && range.startOffset === 0))) { + if (util.getArrayItem(formatEl.children, util.isList, false)) { + const prev = formatEl.previousElementSibling || rangeEl.parentNode; + if (util.isListCell(prev)) { + e.preventDefault(); + + const con = prev === rangeEl.parentNode ? rangeEl.previousSibling : prev.lastChild; + const offset = con.nodeType === 3 ? con.textContent.length : 1; + const children = formatEl.childNodes; + let after = con; + let child = children[0]; + while ((child = children[0])) { + prev.insertBefore(child, after.nextSibling); + after = child; + } + + util.removeItem(formatEl); + if (rangeEl.children.length === 0) util.removeItem(rangeEl); + + core.setRange(con, offset, con, offset); + } + } + break; + } + let detach = true; let comm = commonCon; while (comm && comm !== rangeEl && !util.isWysiwygDiv(comm)) { @@ -4119,8 +4162,8 @@ export default function (context, pluginCallButtons, plugins, lang, options) { e.preventDefault(); core.detachRangeFormatElement(rangeEl, (util.isListCell(formatEl) ? [formatEl] : null), null, false, false); break; - } - } + } + } if (util.isComponent(commonCon.previousSibling) || (commonCon.nodeType === 3 && !commonCon.previousSibling && range.startOffset === 0 && range.endOffset === 0 && util.isComponent(formatEl.previousSibling))) { const previousEl = formatEl.previousSibling; @@ -4464,8 +4507,9 @@ export default function (context, pluginCallButtons, plugins, lang, options) { core._checkComponents(); - const historyKey = !ctrl && !alt && !event._historyIgnoreKeyCode.test(keyCode); - if (historyKey && util.zeroWidthRegExp.test(selectionNode.textContent)) { + + const textKey = !ctrl && !alt && !event._nonTextKeyCode.test(keyCode); + if (textKey && selectionNode.nodeType === 3 && util.zeroWidthRegExp.test(selectionNode.textContent)) { let so = range.startOffset, eo = range.endOffset; const frontZeroWidthCnt = (selectionNode.textContent.substring(0, eo).match(event._frontZeroWidthReg) || '').length; so = range.startOffset - frontZeroWidthCnt; @@ -4474,7 +4518,6 @@ export default function (context, pluginCallButtons, plugins, lang, options) { core.setRange(selectionNode, so < 0 ? 0 : so, selectionNode, eo < 0 ? 0 : eo); } - const textKey = !ctrl && !alt && !event._nonTextKeyCode.test(keyCode); if (!core._charCount(1, textKey)) { if (e.key.length === 1) { e.preventDefault(); @@ -4484,6 +4527,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } // history stack + const historyKey = !ctrl && !alt && !event._historyIgnoreKeyCode.test(keyCode); if (historyKey) { core.history.push(true); } diff --git a/src/lib/util.js b/src/lib/util.js index 4cbb4901d..d9a8daf5f 100755 --- a/src/lib/util.js +++ b/src/lib/util.js @@ -21,8 +21,8 @@ const util = { * @private */ _tagConvertor: function (text) { - const ec = {'b': 'strong', 'i': 'em', 'var': 'em', 'u': 'ins', 'strike': 'del', 's': 'del'}; - return text.replace(/(<\/?)(b|strong|var|i|em|u|ins|s|strike|del)\b\s*(?:[^>^<]+)?\s*(?=>)/ig, function (m, t, n) { + const ec = {'b': 'strong', 'i': 'em', 'u': 'ins', 'strike': 'del', 's': 'del'}; + return text.replace(/(<\/?)(b|strong|i|em|u|ins|s|strike|del)\b\s*(?:[^>^<]+)?\s*(?=>)/ig, function (m, t, n) { return t + ((typeof ec[n] === 'string') ? ec[n] : n); }); }, @@ -231,7 +231,7 @@ const util = { if (text.length > 0) returnHTML += '

    ' + text + '

    '; } } else { - returnHTML += baseHtml.replace(/(?!>)\s+(?=<)/g, ' '); + returnHTML += baseHtml.replace(/(?!>)\s+(?=<)/g, ''); } } @@ -1389,6 +1389,23 @@ const util = { if (element.childNodes.length === 0) element.innerHTML = '
    '; }, + /** + * @description Sort a element array by depth of element. + * @param {Array} array Array object + * @param {Boolean} des true: descending order / false: ascending order + */ + sortByDepth: function (array, des) { + const t = !des ? -1 : 1; + const f = t * -1; + + array.sort(function (a, b) { + if (!this.isListCell(a) || !this.isListCell(b)) return 0; + a = this.getElementDepth(a); + b = this.getElementDepth(b); + return a > b ? t : a < b ? f : 0; + }.bind(this)); + }, + /** * @description Gets the clean HTML code for editor * @param {String} html HTML string diff --git a/src/plugins/submenu/list.js b/src/plugins/submenu/list.js index 40959af55..2b909aaaf 100644 --- a/src/plugins/submenu/list.js +++ b/src/plugins/submenu/list.js @@ -108,12 +108,7 @@ export default { if (!selectedFormats || selectedFormats.length === 0) return; const util = this.util; - selectedFormats.sort(function (a, b) { - if (!this.isListCell(a) || !this.isListCell(b)) return 0; - a = this.getElementDepth(a); - b = this.getElementDepth(b); - return a > b ? 1 : a < b ? -1 : 0; - }.bind(util)); + util.sortByDepth(selectedFormats, true); let isRemove = true; let edgeFirst = null; @@ -272,8 +267,8 @@ export default { } return { - sc: selectedFormats.length > 1 ? edgeFirst.sc : edgeFirst.ec, - so: selectedFormats.length > 1 ? 0 : edgeFirst.ec.textContent.length, + sc: edgeFirst.sc, + so: 0, ec: edgeLast.ec, eo: edgeLast.ec.textContent.length }; @@ -291,9 +286,9 @@ export default { parentNode.insertBefore(cells[c], sibling); } - if (originList.children.length > 0) { + if (next && originList.children.length > 0) { const newList = originList.cloneNode(false); - const children = originList.children; + const children = originList.childNodes; const index = this.util.getPositionIndex(next); while (children[index]) { newList.appendChild(children[index]); From b09f19aca6374d42f37bc404bacdedd21df69884 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Fri, 6 Mar 2020 14:15:55 +0900 Subject: [PATCH 71/99] update: #217 key event - nested list --- src/lib/core.js | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/lib/core.js b/src/lib/core.js index faff271e3..c8cd6c5d2 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -4198,11 +4198,28 @@ export default function (context, pluginCallButtons, plugins, lang, options) { core.selectComponent(nextEl.querySelector('iframe'), 'video'); } } - break; } } - + + if (util.isListCell(formatEl) && util.isList(rangeEl) && (util.isListCell(rangeEl.parentNode) || formatEl.previousElementSibling) && (selectionNode === formatEl || (selectionNode.nodeType === 3 && !selectionNode.nextSibling && range.collapsed && range.endOffset === selectionNode.textContent.length))) { + const next = formatEl.nextElementSibling; + if (next && util.getArrayItem(next.children, util.isList, false)) { + e.preventDefault(); + + const con = next.firstChild; + const children = next.childNodes; + let child = children[0]; + while ((child = children[0])) { + formatEl.appendChild(child); + } + + util.removeItem(next); + core.setRange(con, 0, con, 0); + } + break; + } + break; case 9: /** tab key */ e.preventDefault(); @@ -4506,7 +4523,6 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } core._checkComponents(); - const textKey = !ctrl && !alt && !event._nonTextKeyCode.test(keyCode); if (textKey && selectionNode.nodeType === 3 && util.zeroWidthRegExp.test(selectionNode.textContent)) { From 15bb3afbe8ba028e9f5cf47eaca6738ac055606c Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Fri, 6 Mar 2020 18:34:02 +0900 Subject: [PATCH 72/99] add: #235 core-functions --- sample/html/out/document-editor.html | 8 ++++++++ src/lib/core.js | 21 ++++++++++++++++----- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/sample/html/out/document-editor.html b/sample/html/out/document-editor.html index 5121bed97..cdc6067fa 100644 --- a/sample/html/out/document-editor.html +++ b/sample/html/out/document-editor.html @@ -68,6 +68,14 @@

    util +

    functions

    + +
    + +

    notice

    diff --git a/src/lib/core.js b/src/lib/core.js index c8cd6c5d2..7f0d91928 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -53,6 +53,11 @@ export default function (context, pluginCallButtons, plugins, lang, options) { */ util: util, + /** + * @description Functions object + */ + functions: null, + /** * @description Notice object */ @@ -723,10 +728,13 @@ export default function (context, pluginCallButtons, plugins, lang, options) { const onlyTable = function (current) { return util.isTable(current) ? /^TABLE$/i.test(current.nodeName) : true; }; - const startRangeEl = util.getRangeFormatElement(startLine, onlyTable); - const endRangeEl = util.getRangeFormatElement(endLine, onlyTable); - const sameRange = startRangeEl === endRangeEl; + + let startRangeEl = util.getRangeFormatElement(startLine, onlyTable); + let endRangeEl = util.getRangeFormatElement(endLine, onlyTable); + if (startRangeEl && util.isListCell(startRangeEl.parentNode)) startRangeEl = startRangeEl.parentNode; + if (endRangeEl && util.isListCell(endRangeEl.parentNode)) endRangeEl = endRangeEl.parentNode; + const sameRange = startRangeEl === endRangeEl; for (let i = 0, len = lineNodes.length, line; i < len; i++) { line = lineNodes[i]; @@ -979,7 +987,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { afterNode = null; } else if (!afterNode) { const r = this.removeNode(); - const container = r.container.nodeType === 3 ? (util.getFormatElement(r.container) || r.container.parentNode) : r.container; + const container = r.container.nodeType === 3 ? (util.isListCell(util.getFormatElement(r.container)) ? r.container : (util.getFormatElement(r.container) || r.container.parentNode)) : r.container; parentNode = container.parentNode; afterNode = container.nextSibling; } @@ -4202,7 +4210,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } } - if (util.isListCell(formatEl) && util.isList(rangeEl) && (util.isListCell(rangeEl.parentNode) || formatEl.previousElementSibling) && (selectionNode === formatEl || (selectionNode.nodeType === 3 && !selectionNode.nextSibling && range.collapsed && range.endOffset === selectionNode.textContent.length))) { + if (util.isListCell(formatEl) && util.isList(rangeEl) && (selectionNode === formatEl || (selectionNode.nodeType === 3 && !selectionNode.nextSibling && range.collapsed && range.endOffset === selectionNode.textContent.length))) { const next = formatEl.nextElementSibling; if (next && util.getArrayItem(next.children, util.isList, false)) { e.preventDefault(); @@ -5220,5 +5228,8 @@ export default function (context, pluginCallButtons, plugins, lang, options) { event._addEvent(); core._charCount(0, false); + // functionss + core.functions = userFunction; + return userFunction; } \ No newline at end of file From 4d918c8f1584f8ddab31ef94495e95a0e3e7741a Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Fri, 6 Mar 2020 23:22:52 +0900 Subject: [PATCH 73/99] add: #238 event-onFocus --- sample/css/sample.css | 9 +-------- src/lib/core.js | 14 ++++++++------ test/dev/suneditor_build_test.js | 5 ++++- 3 files changed, 13 insertions(+), 15 deletions(-) diff --git a/sample/css/sample.css b/sample/css/sample.css index de357087c..3b4814e76 100644 --- a/sample/css/sample.css +++ b/sample/css/sample.css @@ -1,12 +1,5 @@ body { - background-color:black; - background-image: - radial-gradient(white, rgba(255,255,255,.2) 2px, transparent 40px), - radial-gradient(white, rgba(255,255,255,.15) 1px, transparent 30px), - radial-gradient(white, rgba(255,255,255,.1) 2px, transparent 40px), - radial-gradient(rgba(255,255,255,.4), rgba(255,255,255,.1) 2px, transparent 30px); - background-size: 550px 550px, 350px 350px, 250px 250px, 150px 150px; - background-position: 0 0, 40px 60px, 130px 270px, 70px 100px; + background-color: #000; } .content { diff --git a/src/lib/core.js b/src/lib/core.js index 7f0d91928..f4af6a9f2 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -4565,6 +4565,11 @@ export default function (context, pluginCallButtons, plugins, lang, options) { if (userFunction.onScroll) userFunction.onScroll(e, core); }, + onFocus_wysiwyg: function (e) { + if (core._isInline) event._showToolbarInline(); + if (userFunction.onFocus) userFunction.onFocus(e, core); + }, + onBlur_wysiwyg: function (e) { if (core._isInline || core._isBalloon) event._hideToolbar(); if (userFunction.onBlur) userFunction.onBlur(e, core); @@ -4778,6 +4783,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { eventWysiwyg.addEventListener('dragover', event.onDragOver_wysiwyg, false); eventWysiwyg.addEventListener('drop', event.onDrop_wysiwyg, false); eventWysiwyg.addEventListener('scroll', event.onScroll_wysiwyg, false); + eventWysiwyg.addEventListener('focus', event.onFocus_wysiwyg, false); eventWysiwyg.addEventListener('blur', event.onBlur_wysiwyg, false); /** Events are registered only a balloon mode or when there is a table plugin. */ @@ -4805,11 +4811,6 @@ export default function (context, pluginCallButtons, plugins, lang, options) { util.addClass(context.element.resizingBar, 'se-resizing-none'); } } - - /** inline editor */ - if (core._isInline) { - eventWysiwyg.addEventListener('focus', event._showToolbarInline, false); - } /** window event */ _w.removeEventListener('resize', event.onResize_window); @@ -4839,7 +4840,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { eventWysiwyg.removeEventListener('mousedown', event.onMouseDown_wysiwyg); eventWysiwyg.removeEventListener('touchstart', event.onMouseDown_wysiwyg, {passive: true, useCapture: false}); - eventWysiwyg.removeEventListener('focus', event._showToolbarInline); + eventWysiwyg.removeEventListener('focus', event.onFocus_wysiwyg); eventWysiwyg.removeEventListener('blur', event.onBlur_wysiwyg); context.element.code.removeEventListener('keydown', event._codeViewAutoHeight); @@ -4876,6 +4877,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { onDrop: null, onChange: null, onPaste: null, + onFocus: null, onBlur: null, showInline: null, diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index 4cdf41bce..7c94db382 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -143,7 +143,7 @@ let ss = window.ss = suneditor.create(document.getElementById('editor1'), { fullPage: true, addTagsWhitelist: 'mark|canvas|label|select|option|input|style|nav|button', imageUploadUrl: 'http://localhost:3000/files/upload', - // mode: 'inline' + mode: 'inline' // videoHeightShow: false, // videoRatioShow: false, // imageHeightShow: false, @@ -164,6 +164,9 @@ ss.onScroll = function (e) { ss.onClick = function (e) { console.log('onClick', e); }; +ss.onFocus = function (e, core) { + console.log('onFocus', e); +}; ss.onBlur = function (e, core) { console.log('onBlur', e); }; From 2ca3fd981510c5a42ce8e3ee7a4a005e0508fbf9 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Fri, 6 Mar 2020 23:23:07 +0900 Subject: [PATCH 74/99] update: sample --- README.md | 96 ++--- sample/html/examples.html | 16 +- sample/html/getting-started.html | 614 +---------------------------- sample/html/out/document-user.html | 241 ++++++++++- 4 files changed, 305 insertions(+), 662 deletions(-) diff --git a/README.md b/README.md index e23428507..4894b2ecc 100644 --- a/README.md +++ b/README.md @@ -689,6 +689,8 @@ editor.onDrop = function (e, core) { console.log('onDrop', e) } editor.onChange = function (contents, core) { console.log('onChange', contents) } +editor.onFocus = function (e, core) { console.log('onFocus', e) } + editor.onBlur = function (e, core) { console.log('onBlur', e) } // onload event @@ -708,6 +710,53 @@ editor.onload = function (core, reload) { */ editor.onPaste = function (e, cleanData, maxCharCount, core) { console.log('onPaste', e) } +// Called before the image is uploaded +// If false is returned, no image upload is performed. +/** + * files: Files array + * info: Input information + * core: Core object + * return {Boolean} + */ +editor.onImageUploadBefore: function (files, info, core) { + console.log('files', files); + console.log('info', info); + return Boolean +} + +// Called when the image is uploaded or the uploaded image is deleted. +/** + * targetImgElement: Current img element + * index: Uploaded index (key value) + * state: Upload status ('create', 'update', 'delete') + * imageInfo: { + * - index: data index + * - name: file name + * - size: file size + * - select: select function + * - delete: delete function + * } + * remainingFilesCount: Count of remaining image files + * core: Core object +*/ +editor.onImageUpload = function (targetImgElement, index, state, imageInfo, remainingFilesCount, core) { + console.log(`targetImgElement:${targetImgElement}, index:${index}, state('create', 'update', 'delete'):${state}`) + console.log(`imageInfo:${imageInfo}, remainingFilesCount:${remainingFilesCount}`) +} + +// Called when the image is upload failed. +// If you return false, the default notices are not called. +/** + * errorMessage: Error message to show + * result: Result object + * core: Core object + * return {Boolean} +*/ +editor.onImageUploadError = function (errorMessage, result, core) { + alert(errorMessage) + return Boolean +} + // It replaces the default callback function of the image upload /** * response: Response object @@ -760,53 +809,6 @@ editor.imageUploadHandler = function (response, info, core) { } } -// Called before the image is uploaded -// If false is returned, no image upload is performed. -/** - * files: Files array - * info: Input information - * core: Core object - * return {Boolean} - */ -editor.onImageUploadBefore: function (files, info, core) { - console.log('files', files); - console.log('info', info); - return Boolean -} - -// Called when the image is uploaded or the uploaded image is deleted. -/** - * targetImgElement: Current img element - * index: Uploaded index (key value) - * state: Upload status ('create', 'update', 'delete') - * imageInfo: { - * - index: data index - * - name: file name - * - size: file size - * - select: select function - * - delete: delete function - * } - * remainingFilesCount: Count of remaining image files - * core: Core object -*/ -editor.onImageUpload = function (targetImgElement, index, state, imageInfo, remainingFilesCount, core) { - console.log(`targetImgElement:${targetImgElement}, index:${index}, state('create', 'update', 'delete'):${state}`) - console.log(`imageInfo:${imageInfo}, remainingFilesCount:${remainingFilesCount}`) -} - -// Called when the image is upload failed. -// If you return false, the default notices are not called. -/** - * errorMessage: Error message to show - * result: Result object - * core: Core object - * return {Boolean} -*/ -editor.onImageUploadError = function (errorMessage, result, core) { - alert(errorMessage) - return Boolean -} - /** * toolbar: Toolbar Element * context: The editor's context object (editor.getContext()) diff --git a/sample/html/examples.html b/sample/html/examples.html index d0c7ff967..ba3f5d8b2 100644 --- a/sample/html/examples.html +++ b/sample/html/examples.html @@ -157,9 +157,9 @@

    @@ -490,6 +490,8 @@ editor.onChange = function (contents, core) { console.log('onChange', contents) } +editor.onFocus = function (e, core) { console.log('onFocus', e) } + editor.onBlur = function (e, core) { console.log('onBlur', e) } // onload event @@ -537,6 +539,13 @@ alert(errorMessage) } +// Called before the image is uploaded. +// If false is returned, no image upload is performed. +editor.onImageUploadBefore = null + +// It replaces the default callback function of the image upload. +editor.imageUploadHandler = null + /** * toolbar: Toolbar Element * context: The editor's context object (editor.getContext()) @@ -798,6 +807,9 @@ suneditor.onKeyUp = function (e) { console.log('onKeyUp', e) } suneditor.onDrop = function (e) { console.log('onDrop', e) } suneditor.onChange = function (contents) { console.log('onChange', contents) } + suneditor.onPaste = function (e, cleanData, maxCharCount, core) { console.log('onPaste', e, cleanData, maxCharCount) } + suneditor.onFocus = function (contents) { console.log('onFocus', contents) } + suneditor.onBlur = function (contents) { console.log('onBlur', contents) } suneditor.onImageUpload = function (targetImgElement, index, state, imageInfo, remainingFilesCount) { console.log('targetImgElement:' + targetImgElement + ', index:' + index + ', state("create","update","delete"):' + state + ', imageInfo:' + imageInfo + ', remainingFilesCount:' + remainingFilesCount) } diff --git a/sample/html/getting-started.html b/sample/html/getting-started.html index 22ff65080..c72ee46ab 100644 --- a/sample/html/getting-started.html +++ b/sample/html/getting-started.html @@ -10,7 +10,11 @@ - +
    -
    -

    CDN

    -
    <link href="https://cdn.jsdelivr.net/npm/suneditor@latest/dist/css/suneditor.min.css" rel="stylesheet">
    -<!-- <link href="https://cdn.jsdelivr.net/npm/suneditor@latest/assets/css/suneditor.css" rel="stylesheet"> -->
    -<!-- <link href="https://cdn.jsdelivr.net/npm/suneditor@latest/assets/css/suneditor-contents.css" rel="stylesheet"> -->
    -<script src="https://cdn.jsdelivr.net/npm/suneditor@latest/dist/suneditor.min.js"></script>
    -<!-- languages (Basic Language: English/en) -->
    -<script src="https://cdn.jsdelivr.net/npm/suneditor@latest/src/lang/ko.js"></script>
    +
    +

    README

    -

    1. Target Element

    -
    <textarea id="sample">Hi</textarea>
    - -

    2. Create

    -
    /**
    -* ID : 'suneditor_sample'
    -* ClassName : 'sun-eidtor'
    -*/
    -// ID or DOM object
    -const suneditor = SUNEDITOR.create((document.getElementById('sample') || 'sample'),{
    -    // All of the plugins are loaded in the "window.SUNEDITOR" object in dist/suneditor.min.js file
    -    // Insert options
    -    // Language global object (default: en)
    -    lang: SUNEDITOR_LANG['ko']
    -});
    - -

    3. Contents display

    -
    When you display a document created by suneditor
    -You need to include "src/assets/css/suneditor-contents.css" or "dist/css/suneditor.min.css" file.
    -Then add "sun-editor-editable" to the class name of the Tag element that displays the content.
    -In "suneditor-contents.css", you can define the style of all the tags created in suneditor.
    - -

    Use import statement

    -

    - -

    1. Load only what you want

    -
    import 'suneditor/dist/css/suneditor.min.css'
    -// import 'suneditor/assets/css/suneditor.css'
    -// import 'suneditor/assets/css/suneditor-contents.css'
    -import suneditor from 'suneditor'
    -
    -// How to import plugins
    -import image from 'suneditor/src/plugins/dialog/link'
    -import list from 'suneditor/src/plugins/submenu/list'
    -import {font, video} from 'suneditor/src/plugins'
    -
    -// How to import language files (default: en)
    -import lang from 'suneditor/src/lang'
    -import {ko} from 'suneditor/src/lang'
    -import de from 'suneditor/src/lang/de'
    -
    -suneditor.create('sample', {
    -    plugins: [font, video, image, list],
    -    buttonList: [
    -        ['font', 'video', 'image', 'list']
    -    ],
    -    lang: lang.ko
    -});
    - -

    2. Load all plugins

    -
    import 'suneditor/dist/css/suneditor.min.css'
    -import suneditor from 'suneditor'
    -import plugins from 'suneditor/src/plugins'
    -
    -suneditor.create('sample', {
    -    plugins: plugins,
    -    buttonList: [
    -        ['undo', 'redo'],
    -        ['font', 'fontSize', 'formatBlock'],
    -        ['paragraphStyle'],
    -        ['bold', 'underline', 'italic', 'strike', 'subscript', 'superscript'],
    -        ['fontColor', 'hiliteColor', 'textStyle'],
    -        ['removeFormat'],
    -        '/', // Line break
    -        ['outdent', 'indent'],
    -        ['align', 'horizontalRule', 'list', 'lineHeight'],
    -        ['table', 'link', 'image', 'video'],
    -        ['fullScreen', 'showBlocks', 'codeView'],
    -        ['preview', 'print'],
    -        ['save', 'template']
    -    ]
    -})
    -
    -// You can also load what you want
    -suneditor.create('sample', {
    -    plugins: [plugins.font],
    -    // Plugins can be used directly in the button list
    -    buttonList: [
    -        ['font', plugins.image]
    -    ]
    -})
    - -

    3. Plugins can be used directly in the button list

    -
    import 'suneditor/dist/css/suneditor.min.css'
    -import suneditor from 'suneditor'
    -import {align, font, fontSize, fontColor, hiliteColor, horizontalRule, list, lineHeight, 
    -    table, template, formatBlock, paragraphStyle, textStyle, link, image, video} from 'suneditor/src/plugins'
    -
    -suneditor.create('sample', {
    -    buttonList: [
    -        ['undo', 'redo', 'removeFormat'],
    -        [font, fontSize, formatBlock],
    -        [paragraphStyle, textStyle, fontColor, hiliteColor],
    -        [align, horizontalRule, list, lineHeight],
    -        [table, link, image, video, template]
    -    ],
    -})
    - -

    Init function

    -
    The init function can be used by predefining options and calling the create function on the returned object.
    -The value of the option argument put in the "create" function call takes precedence
    -
    -
    import 'suneditor/dist/css/suneditor.min.css'
    -import suneditor from 'suneditor'
    -import plugins from 'suneditor/src/plugins'
    -
    -// all plugins
    -const initEditor = suneditor.init({
    -    plugins: plugins,
    -    height: 200,
    -    buttonList: [
    -        ['undo', 'redo',
    -        'font', 'fontSize', 'formatBlock',
    -        'paragraphStyle',
    -        'bold', 'underline', 'italic', 'strike', 'subscript', 'superscript',
    -        'fontColor', 'hiliteColor', 'textStyle',
    -        'removeFormat',
    -        'outdent', 'indent',
    -        'align', 'horizontalRule', 'list', 'lineHeight',
    -        'table', 'link', 'image', 'video',
    -        'fullScreen', 'showBlocks', 'codeView',
    -        'preview', 'print', 'save', 'template']
    -    ]
    -});
    -
    -initEditor.create('sample_1', {
    -    // The value of the option argument put in the "create" function call takes precedence
    -});
    -
    -initEditor.create('sample_2', {
    -    // The value of the option argument put in the "create" function call takes precedence
    -    height: 'auto',
    -    buttonList: [
    -        ['bold', 'underline', 'italic'],
    -        ['removeFormat'],
    -        ['preview', 'print']
    -    ]
    -});
    - -

    Use CodeMirror

    -
    <!-- codeMirror (^5.0.0) -->
    -<!-- Use version 5.0.0 or later. -->
    -<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/codemirror@5.49.0/lib/codemirror.min.css">
    -<script src="https://cdn.jsdelivr.net/npm/codemirror@5.49.0/lib/codemirror.min.js"></script>
    -<script src="https://cdn.jsdelivr.net/npm/codemirror@5.49.0/mode/htmlmixed/htmlmixed.js"></script>
    -<script src="https://cdn.jsdelivr.net/npm/codemirror@5.49.0/mode/xml/xml.js"></script>
    -<script src="https://cdn.jsdelivr.net/npm/codemirror@5.49.0/mode/css/css.js"></script>
    - -
    import 'suneditor/dist/css/suneditor.min.css'
    -import suneditor from 'suneditor'
    -// Import codeMirror
    -import CodeMirror from 'codemirror'
    -import 'codemirror/mode/htmlmixed/htmlmixed'
    -import 'codemirror/lib/codemirror.css'
    -
    -suneditor.create('sample', {
    -    codeMirror: CodeMirror,
    -    // Set options
    -    // codeMirror: {
    -    //     src: CodeMirror,
    -    //     options: {...}
    -    // }
    -    buttonList: [
    -        ['codeView']
    -    ],
    -    height: 400
    -});
    - -

    Options

    -
    plugins: [
    -    // Submenu
    -    align,
    -    font,
    -    fontColor,
    -    fontSize,
    -    formatBlock,
    -    hiliteColor,
    -    horizontalRule,
    -    lineHeight,
    -    list,
    -    paragraphStyle,
    -    table,
    -    template,
    -    textStyle,
    -    // Dialog
    -    image,
    -    link,
    -    video
    -]               : Plugins array.     default: null {Array}
    -
    -// Layout-------------------------------------------------------------------------------------------------------
    -lang            : language object.   default : en {Object}
    -mode            : The mode of the editor ('classic', 'inline', 'balloon'). default: 'classic' {String}
    -toolbarWidth    : The width of the toolbar. Applies only when the editor mode is 
    -                  'inline' or 'balloon' mode. default: 'auto' {Number|String}
    -stickyToolbar   : Reference height value that should be changed to sticky toolbar mode.
    -                  It can also be used when there is another fixed toolbar at the top.
    -                  Set to 0, '0px', '50px', etc.
    -                  If set to -1 or false or null to turn off.        default: 0 {Number|String|Boolean}
    -iframe          : Content will be placed in an iframe and isolated from the rest of the page.  default: false {Boolean}
    -fullPage        : Allows the usage of HTML, HEAD, BODY tags and DOCTYPE declaration.  default: false {Boolean}
    -iframeCSSFileName : Name or Array of the CSS file to apply inside the iframe.
    -                    Applied by searching by filename in the link tag of document,
    -                    or put the URL value.                                        default: 'suneditor' {Array|String}
    -                    ex) 'main' or ['suneditor', 'http://suneditor.com/sample/css/sample.css']
    -codeMirror      : If you put the CodeMirror object as an option, you can do Codeview using CodeMirror. default: null {Object}
    -                  Use version 5.0.0 or later.
    -                  ex) codeMirror: CodeMirror // Default option
    -                      codeMirror: { // Custom option
    -                        src: CodeMirror,
    -                        options: {
    -                            /** default options **
    -                            * mode: 'htmlmixed',
    -                            * htmlMode: true,
    -                            * lineNumbers: true
    -                            * lineWrapping: true
    -                            */
    -                        }
    -                      }
    -
    -// Display-------------------------------------------------------------------------------------------------------
    -position        : The position property of suneditor.               default: null {String}
    -display         : The display property of suneditor.                default: 'block' {String}
    -popupDisplay    : Size of background area when activating dialog window ('full'||'local') default: 'full' {String}
    -
    -// Bottom resizing bar-------------------------------------------------------------------------------------------
    -resizingBar     : Show the bottom resizing bar.
    -                  If 'height' value is 'auto', it will not be resized. default: true {Boolean}
    -showPathLabel   : Displays the current node structure to resizingBar.  default: true {Boolean}
    -charCounter     : Shows the number of characters in the editor.     
    -                  If the maxCharCount option has a value, it becomes true. default: false {Boolean}
    -maxCharCount    : The maximum number of characters allowed to be inserted into the editor. default: null {Number}
    -
    -// Width size----------------------------------------------------------------------------------------------------
    -width           : The width size of the editor.                     default: clientWidth||'100%' {Number|String}
    -minWidth        : The min-width size of the editor.
    -                  Used when 'width' value is 'auto' or '~%'.        default: null {Number|String}
    -maxWidth        : The max-width size of the editor.
    -                  Used when 'width' value is 'auto' or '~%'.        default: null {Number|String}
    -
    -// Height size---------------------------------------------------------------------------------------------------
    -height          : The height size of the editor.                    default: clientHeight||'auto' {Number|String}
    -minHeight       : The min-height size of the editor.
    -                  Used when 'height' value is 'auto'.               default: null {Number|String}
    -maxHeight       : The max-height size of the editor.
    -                  Used when 'height' value is 'auto'.               default: null {Number|String}
    -
    -// Defining menu items-------------------------------------------------------------------------------------------
    -font            : Change default font-family array.                 default: [...] {Array}
    -                  Default value: [
    -                    'Arial', 'Comic Sans MS', 'Courier New', 'Impact',
    -                    'Georgia','tahoma', 'Trebuchet MS', 'Verdana'
    -                  ]
    -fontSize        : Change default font-size array.                   default: [...] {Array}
    -                  Default value: [
    -                    8, 9, 10, 11, 12, 14, 16, 18, 20, 22, 24, 26, 28, 36, 48, 72
    -                  ]
    -fontSizeUnit    : The font size unit.                               default: 'px' {String}
    -formats         : Change default formatBlock array.                 default: [...] {Array}
    -                  Default value: [
    -                    'p', 'div', 'blockquote', 'pre', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'
    -                    // "blockquote": range format, "pre": free format, "Other tags": replace format
    -                  ],
    -                  Custom: [{
    -                    tag: 'div', // Tag name
    -                    name: 'Custom div' || null, // default: tag name
    -                    command: 'replace' || 'range', // default: "replace"
    -                    class: '__se__format__replace_xxx' || '__se__format__range_xxx' || '__se__format__free_xxx'
    -                    // Class names must always begin with "__se__format__(replace, range, free)_"
    -                  }]
    -colorList       : Change default color array of color picker.       default: [..[..]..] {Array}
    -                  Default value: [
    -                    '#ff0000', '#ff5e00', '#ffe400', '#abf200', '#00d8ff', '#0055ff', '#6600ff', '#ff00dd', '#000000',
    -                    '#ffd8d8', '#fae0d4', '#faf4c0', '#e4f7ba', '#d4f4fa', '#d9e5ff', '#e8d9ff', '#ffd9fa', '#f1f1f1',
    -                    '#ffa7a7', '#ffc19e', '#faed7d', '#cef279', '#b2ebf4', '#b2ccff', '#d1b2ff', '#ffb2f5', '#bdbdbd',
    -                    '#f15f5f', '#f29661', '#e5d85c', '#bce55c', '#5cd1e5', '#6699ff', '#a366ff', '#f261df', '#8c8c8c',
    -                    '#980000', '#993800', '#998a00', '#6b9900', '#008299', '#003399', '#3d0099', '#990085', '#353535',
    -                    '#670000', '#662500', '#665c00', '#476600', '#005766', '#002266', '#290066', '#660058', '#222222'
    -                  ]
    -                  ex) [
    -                    ['#ccc', '#dedede', 'OrangeRed', 'Orange', 'RoyalBlue', 'SaddleBrown'], // Line break
    -                    ['SlateGray', 'BurlyWood', 'DeepPink', 'FireBrick', 'Gold', 'SeaGreen']
    -                  ]
    -lineHeights     : Change default line-height array.                 default: [{}..] {Array}
    -                  Default value: [
    -                    {text: '1', value: 1},
    -                    {text: '1.15', value: 1.15},
    -                    {text: '1.5', value: 1.5},
    -                    {text: '2', value: 2}
    -                  ]
    -                  ex) [
    -                    {text: 'Single', value: 1},
    -                    {text: 'Double', value: 2}
    -                  ]
    -paragraphStyles : You can apply custom class to format.
    -                  ex) '.sun-editor-editable .__se__customClass'
    -                      '.sun-editor .__se__customClass' // If you want to apply styles to menu items as well
    -                  Default value: [
    -                    {
    -                        name: 'Spaced', // Format style name
    -                        class: '__se__p-spaced', // Define style for used class (Class names must always begin with "__se__")
    -                        _class: '' // You can control the style of the tags displayed in the menu by putting a class on the button of the menu.
    -                    },
    -                    {
    -                        name: 'Bordered',
    -                        class: '__se__p-bordered'
    -                    },
    -                    {
    -                        name: 'Neon',
    -                        class: '__se__p-neon'
    -                    }
    -                  ]
    -                  ex) [
    -                      'spaced', 'neon', // The default value is called by name only and the name is called in the language file.
    -                      {
    -                          name: 'Custom',
    -                          class: '__se__customClass'
    -                      }
    -                  ]
    -textStyles      : You can apply custom style or class to selected text.
    -                  ex(using a class)) '.sun-editor-editable .__se__customClass'
    -                                     '.sun-editor .__se__customClass' // If you want to apply styles to menu items as well
    -                  Default value: [
    -                    {
    -                        name: 'Translucent', // Text style name
    -                        style: 'opacity: 0.5;', // Style query
    -                        tag: 'span', // Style tag name (default: span)
    -                        _class: '' // You can control the style of the tags displayed in the menu by putting a class on the button of the menu.
    -                    },
    -                    {
    -                        name: 'Shadow',
    -                        class: '__se__t-shadow', // Class names (Class names must always begin with "__se__")
    -                        tag: 'span'
    -                    }
    -                  ]
    -                  ex) [
    -                      'translucent', // The default value is called by name only and the name is called in the language file.
    -                      {
    -                          name: 'Emphasis',
    -                          style: '-webkit-text-emphasis: filled;',
    -                          tag: 'span'
    -                      }
    -                  ]
    -
    -// Image---------------------------------------------------------------------------------------------------------
    -imageResizing   : Can resize the image.                               default: true {Boolean}
    -imageHeightShow : Choose whether the image height input is visible.   default: true {Boolean}
    -imageWidth      : The default width size of the image frame.          default: 'auto' {String}
    -imageSizeOnlyPercentage : If true, image size can only be scaled by percentage.   default: false {Boolean}
    -imageRotation   : Choose whether to image rotation buttons display.
    -                  When "imageSizeOnlyPercentage" is "true" or  or "imageHeightShow" is "false" the default value is false.                       
    -                  If you want the button to be visible, put it a true.     default: true {Boolean}
    -imageFileInput  : Choose whether to create a file input tag in the image upload window.  default: true {Boolean}
    -imageUrlInput   : Choose whether to create a image url input tag in the image upload window.
    -                  If the value of imageFileInput is false, it will be unconditionally.   default: true {Boolean}
    -imageUploadHeader : Http Header when uploading images.              default: null {Object}
    -imageUploadUrl  : The image upload to server mapping address.       default: null {String}
    -                  ex) "/editor/uploadImage.ajax"
    -                  When not used, it enters base64 data
    -                  return {
    -                            "errorMessage": "insert error message",
    -                            "result": [
    -                                {
    -                                    "url": "/download/editorImg/test_image.jpg",
    -                                    "name": "test_image.jpg",
    -                                    "size": "561276"
    -                                }
    -                            ]
    -                        }
    -imageUploadSizeLimit: The size of the total uploadable images (in bytes).
    -                      Invokes the "onImageUploadError" method.  default: null {Number}
    -
    -// Video----------------------------------------------------------------------------------------------------------
    -videoResizing   : Can resize the video iframe.                         default: true {Boolean}
    -videoHeightShow : Choose whether the video height input is visible.    default: true {Boolean}
    -videoRatioShow  : Choose whether the video ratio options is visible.   default: true {Boolean}
    -videoWidth      : The default width size of the video frame.           default: '100%' {String}
    -videoSizeOnlyPercentage : If true, video size can only be scaled by percentage.   default: false {Boolean}
    -videoRotation   : Choose whether to video rotation buttons display.
    -                  When "videoSizeOnlyPercentage" is "true" or "videoHeightShow" is "false" the default value is false.
    -                  If you want the button to be visible, put it a true.     default: true {Boolean}
    -videoRatio      : The default aspect ratio of the video.
    -                  Up to four decimal places are allowed.             default: 0.5625 (16:9) {Float}
    -videoRatioList  : Video ratio selection options.
    -                  default: [
    -                    {name: '16:9', value: 0.5625},
    -                    {name: '4:3', value: 0.75},
    -                    {name: '21:9', value: 0.4285}
    -                  ],
    -                  ex) [
    -                    {name: 'Classic Film 3:2', value: 0.6666},
    -                    {name: 'HD', value: 0.5625}
    -                  ]
    -youtubeQuery    : The query string of a YouTube embedded URL.        default: '' {String}
    -                  It takes precedence over the value user entered.
    -                  ex) 'autoplay=1&mute=1&enablejsapi=1&controls=0&rel=0&modestbranding=1'
    -                    // https://developers.google.com/youtube/player_parameters
    -
    -// Defining save button-------------------------------------------------------------------------------------------
    -callBackSave    : Callback functions that is called when the Save button is clicked. 
    -                  Arguments - (contents).                            default: userFunction.save {Function}
    -
    -// Templates Array------------------------------------------------------------------------------------------------
    -templates       : If you use a template plugin, add it.
    -                  Defines a list of templates.                       default: null {Array} 
    -                  ex) [
    -                    {
    -                        name: 'Template-1',
    -                        html: '<p>HTML source1</p>'
    -                    },
    -                    {
    -                        name: 'Template-2',
    -                        html: '<p>HTML source2</p>'
    -                    }
    -                  ]
    -
    -// ETC------------------------------------------------------------------------------------------------------------
    -placeholder     : The placeholder text.                              default: null {String}
    -
    -// Buttons--------------------------------------------------------------------------------------------------------
    -buttonList      : Defines button list to array {Array}
    -                  default: [
    -                    ['undo', 'redo'],
    -                    // ['font', 'fontSize', 'formatBlock'],
    -                    // ['paragraphStyle'],
    -                    ['bold', 'underline', 'italic', 'strike', 'subscript', 'superscript'],
    -                    // ['fontColor', 'hiliteColor', 'textStyle'],
    -                    ['removeFormat'],
    -                    ['outdent', 'indent'],
    -                    // ['align', 'horizontalRule', 'list', 'lineHeight'],
    -                    // ['table', 'link', 'image', 'video'],
    -                    ['fullScreen', 'showBlocks', 'codeView'],
    -                    ['preview', 'print'],
    -                    // ['save', 'template'],
    -                    // '/', Line break
    -                  ]
    - -

    Functions

    -
    import suneditor from 'suneditor'
    -
    -const editor = suneditor.create('example');
    -
    -// Add or reset option property
    -editor.setOptions({
    -    minHeight: '300px',
    -    buttonList: [
    -        ['fontColor', 'hiliteColor']
    -    ],
    -    colorList: [
    -        ['#ccc', '#dedede', 'OrangeRed', 'Orange', 'RoyalBlue', 'SaddleBrown']
    -    ]
    -});
    -
    -// Open a notice area
    -editor.noticeOpen('test notice');
    -
    -// Close a notice area
    -editor.noticeClose();
    -
    -// Copies the contents of the suneditor into a [textarea]
    -editor.save();
    -
    -// Gets the suneditor's context object. Contains settings, plugins, and cached element objects
    -editor.getContext();
    -
    -// Gets the contents of the suneditor
    -// onlyContents {Boolean}: Return only the contents of the body without headers when the "fullPage" option is true
    -editor.getContents(onlyContents: Boolean);
    -
    -// Gets a list of images uploaded to the editor
    -/** 
    - * {
    - *  element: image element
    - *  src: imgage src
    - *  index: data index
    - *  name: file name
    - *  size: file size
    - *  select: select function
    - *  delete: delete function
    - * }
    - **/
    -editor.getImagesInfo();
    -
    -// Upload images using image plugin
    -// document.getElementById('example_files_input').files
    -editor.insertImage(FileList);
    -
    -// Inserts an HTML element or HTML string or plain string at the current cursor position
    -editor.insertHTML('<img src="http://suneditor.com/sample/img/sunset.jpg">');
    -
    -// Change the contents of the suneditor
    -editor.setContents('set contents');
    -
    -// Add content to the suneditor
    -editor.appendContents('append contents');
    -
    -// Disable the suneditor
    -editor.disabled();
    -
    -// Enabled the suneditor
    -editor.enabled();
    -
    -// Hide the suneditor
    -editor.hide();
    -
    -// Show the suneditor
    -editor.show();
    -    
    -// Destroy the suneditor
    -editor.destroy();
    -
    -// Toolbar methods
    -// Disable the suneditor
    -editor.toolbar.disabled();
    -
    -// Enabled the suneditor
    -editor.toolbar.enabled();
    -
    -// Hide the suneditor
    -editor.toolbar.hide();
    -
    -// Show the suneditor
    -editor.toolbar.show();
    -
    -// Event functions -------------------------------------------------------------------------------------
    -// It can be redefined by receiving event object as parameter.
    -// It is not called in exceptional cases and is called after the default event function has finished.
    -editor.onScroll = function (e, core) { console.log('onScroll', e) }
    -
    -editor.onClick = function (e, core) { console.log('onClick', e) }
    -
    -editor.onKeyDown = function (e, core) { console.log('onKeyDown', e) }
    -
    -editor.onKeyUp = function (e, core) { console.log('onKeyUp', e) }
    -
    -editor.onDrop = function (e, core) { console.log('onDrop', e) }
    -
    -editor.onChange = function (contents, core) { console.log('onChange', contents) }
    -
    -editor.onBlur = function (e, core) { console.log('onBlur', e) }
    -
    -// onload event
    -// When reloaded with the "setOptions" method, the value of the "reload" argument is true.
    -editor.onload = function (core, reload) { 
    -    console.log('onload-core', core)
    -    console.log('onload-reload', reload)
    -}
    -
    -// Paste event.
    -// Called before the editor's default event action.
    -// If it returns false, it stops without executing the rest of the action.
    -/**
    - * cleanData : HTML string modified for editor format
    - * maxCharCount : maxChartCount option (true if max character is exceeded)
    -*/
    -editor.onPaste = function (e, cleanData, maxCharCount, core) { console.log('onPaste', e, cleanData, maxCharCount) }
    -
    -// Called when the image is uploaded or the uploaded image is deleted.
    -/**
    - * targetImgElement: Current img element
    - * index: Uploaded index (key value)
    - * state: Upload status ('create', 'update', 'delete')
    - * imageInfo: {
    - * * index: data index
    - * * name: file name
    - * * size: file size
    - * * select: select function
    - * * delete: delete function
    - * }
    - * remainingFilesCount: Count of remaining image files
    -*/
    -editor.onImageUpload = function (targetImgElement, index, state, imageInfo, remainingFilesCount, core) {
    -    console.log(`targetImgElement:${targetImgElement}, index:${index}, state('create', 'update', 'delete'):${state}`)
    -    console.log(`imageInfo:${imageInfo}, remainingFilesCount:${remainingFilesCount}`)
    -}
    -
    -// Called when the image is upload failed.
    -// If you return false, the default notices are not called.
    -/**
    - * errorMessage: Error message to show
    - * result: Result object 
    -*/
    -editor.onImageUploadError = function (errorMessage, result, core) {
    -    alert(errorMessage)
    -}
    -
    -/**
    - * toolbar: Toolbar Element
    - * context: The editor's context object (editor.getContext())
    -*/
    -editor.showInline = function (toolbar, context, core) {
    -    console.log('toolbar', toolbar);
    -    console.log('context', context);
    -}
    - + + +
    diff --git a/sample/html/out/document-user.html b/sample/html/out/document-user.html index d1ca75bef..2f778a529 100644 --- a/sample/html/out/document-user.html +++ b/sample/html/out/document-user.html @@ -373,7 +373,7 @@

    onloadonScroll(event)

    + class="signature">(event, core)

    Scroll event
    @@ -393,13 +393,20 @@

    onScroll Event Object + + core + + Object + + Core Object +

    onClick(event)

    + class="signature">(event, core)

    Click event
    @@ -419,13 +426,20 @@

    onClick Event Object + + core + + Object + + Core Object +

    onKeyDown(event)

    + class="signature">(event, core)

    KeyDown event
    @@ -445,13 +459,20 @@

    onKeyDown Event Object + + core + + Object + + Core Object +

    onKeyUp(event)

    + class="signature">(event, core)

    KeyUp event
    @@ -471,13 +492,20 @@

    onKeyUp Event Object + + core + + Object + + Core Object +

    onDrop(event)

    + class="signature">(event, core)

    Drop event
    @@ -497,13 +525,20 @@

    onDrop Event Object + + core + + Object + + Core Object +

    onChange(contents)

    + class="signature">(contents, core)

    When the contents change
    @@ -523,13 +558,86 @@

    onChange HTML string + + core + + Object + + Core Object + + + +
    + + +

    onFocus(event, core)

    +
    + Focus event +
    + + + + + + + + + + + + + + + + + + + + +
    NameTypeDescription
    event + Object + Event Object
    core + Object + Core Object
    +
    + + +

    onBlur(event, core)

    +
    + Focus event +
    + + + + + + + + + + + + + + + + + + +
    NameTypeDescription
    event + Object + Event Object
    core + Object + Core Object

    onPaste(event, cleanData, maxCharCount)

    + class="signature">(event, cleanData, maxCharCount, core)

    Paste event.
    Called before the editor's default event action.
    @@ -565,13 +673,61 @@

    onPaste maxCharCount option (true if max character is exceeded) + + core + + Object + + Core Object + + + +
    + + +

    onImageUploadBefore(files, info, core) → {Boolean}

    +
    + Called before the image is uploaded.
    + If false is returned, no image upload is performed. +
    + + + + + + + + + + + + + + + + + + + + + + + +
    NameTypeDescription
    files + FileList + Files array
    info + Object + Input information
    core + Object + Core Object

    onImageUpload(targetImgElement, index, state, imageInfo, remainingFilesCount)

    + class="signature">(targetImgElement, index, state, imageInfo, remainingFilesCount, core)

    Called when the image is uploaded or the uploaded image is deleted
    @@ -626,13 +782,20 @@

    onImageU Count of remaining image files + + core + + Object + + Core Object +

    onImageUploadError(errorMessage, result)

    + class="signature">(errorMessage, result, core) → {Boolean}
    Called when the image is uploaded or the uploaded image is deleted
    @@ -659,6 +822,62 @@

    onI Result object + + core + + Object + + Core Object + + + +
    + + +

    imageUploadHandler(response, info, core)

    +
    + It replaces the default callback function of the image upload. +
    + + + + + + + + + + + + + + + + + + + + + + + +
    NameTypeDescription
    response + Response + Response object
    info + Object + + -- Input information --
    + linkValue: Link url value
    + linkNewWindow: Open in new window Check Value
    + inputWidth: Value of width input
    + inputHeight: Value of height input
    + align: Align Check Value
    + isUpdate: Update image if true, create image if false
    + currentImage: If isUpdate is true, the currently selected image. +
    core + Object + Core Object
    @@ -734,9 +953,13 @@

    Useable events

  • onKeyUp
  • onDrop
  • onChange
  • +
  • onFocus
  • +
  • onBlur
  • onPaste
  • +
  • onImageUploadBefore
  • onImageUpload
  • onImageUploadError
  • +
  • imageUploadHandler
  • showInline
  • From 35ccf20105f67f7b068724b1c2a6d432e1558322 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Sat, 7 Mar 2020 02:42:58 +0900 Subject: [PATCH 75/99] moodify: style --- src/assets/css/suneditor.css | 7 +++++-- src/plugins/modules/colorPicker.js | 2 +- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/assets/css/suneditor.css b/src/assets/css/suneditor.css index 4bf36868e..5bf7abfaf 100755 --- a/src/assets/css/suneditor.css +++ b/src/assets/css/suneditor.css @@ -249,10 +249,13 @@ .sun-editor .se-list-layer .se-selector-color .se-color-pallet button:focus {border:3px solid #fff;} /* submenu layer - form group (color selector) */ .sun-editor .se-submenu-form-group {display:flex; width:100%; height:auto; padding:4px;} -.sun-editor .se-submenu-form-group input {flex:auto; display:inline-block; width:72px; height:33px; color:#555; font-size:12px; margin:1px 0 1px 0; padding:0; border-radius:0.25rem; border-bottom:2px solid #b1b1b1; outline:none; text-transform:uppercase;} -.sun-editor .se-submenu-form-group input:focus {outline:none; border-bottom:3px solid #b1b1b1;} +.sun-editor .se-submenu-form-group input {flex:auto; display:inline-block; width:auto; height:33px; color:#555; font-size:12px; margin:1px 0 1px 0; padding:0; border-radius:0.25rem; border:1px solid #ccc;} +.sun-editor .se-submenu-form-group input:focus {border-color:#80bdff; outline:0; -webkit-box-shadow:0 0 0 0.2rem #c7deff; box-shadow:0 0 0 0.2rem #c7deff;} .sun-editor .se-submenu-form-group button {float:right; width:35px; height:35px; padding:0; margin:0 0 0 4px !important;} .sun-editor .se-submenu-form-group button.se-btn {border:1px solid #ccc;} +/** submenu layer - color input */ +.sun-editor .se-submenu-form-group .se-color-input {width:72px; text-transform:uppercase; border:none; border-bottom:2px solid #b1b1b1; outline:none;} +.sun-editor .se-submenu-form-group .se-color-input:focus {outline:none; border-bottom:3px solid #b1b1b1; -webkit-box-shadow:none; box-shadow:none;} /** --- editor area */ .sun-editor .se-wrapper {position:relative !important; width:100%; height:auto; overflow:hidden; z-index:1;} diff --git a/src/plugins/modules/colorPicker.js b/src/plugins/modules/colorPicker.js index afd62962f..f9cc899c7 100755 --- a/src/plugins/modules/colorPicker.js +++ b/src/plugins/modules/colorPicker.js @@ -61,7 +61,7 @@ export default { } list += '' + '
    ' + - '' + + '' + ' - + +
    @@ -112,40 +113,50 @@

    The Suneditor is based on pure JavaScript, with no dependencies.

    -
    +
    - + +
    + -
    -
    - +
    +
    - +
    +
    -
    @@ -201,18 +212,6 @@

    The Suneditor is based on pure JavaScript, with no dependencies.

    codeMirror: CodeMirror }); - SUNEDITOR.create('editor_balloon', { - mode: 'balloon', - display: 'block', - width: '100%', - height: 'auto', - popupDisplay: 'full', - buttonList: [ - ['fontSize', 'fontColor', 'bold', 'align', 'horizontalRule', 'table', 'codeView'] - ], - placeholder: 'Start typing something...' - }); - SUNEDITOR.create('editor_inline1', { mode: 'inline', display: 'block', @@ -249,6 +248,30 @@

    The Suneditor is based on pure JavaScript, with no dependencies.

    placeholder: 'Start typing something...' }); + SUNEDITOR.create('editor_balloon', { + mode: 'balloon', + display: 'block', + width: '100%', + height: 'auto', + popupDisplay: 'full', + buttonList: [ + ['fontSize', 'fontColor', 'bold', 'underline', 'align', 'horizontalRule', 'table', 'codeView'] + ], + placeholder: 'Start typing something...' + }); + + SUNEDITOR.create('editor_balloon_always', { + mode: 'balloon-always', + display: 'block', + width: '100%', + height: 'auto', + popupDisplay: 'full', + buttonList: [ + ['bold', 'italic', 'link', 'undo', 'redo'] + ], + placeholder: 'Start typing something...' + }); + function openTab(evt, tabName) { // Declare all variables diff --git a/src/lib/constructor.js b/src/lib/constructor.js index 90adfb10c..bf327b65c 100755 --- a/src/lib/constructor.js +++ b/src/lib/constructor.js @@ -391,7 +391,7 @@ export default { options.pasteTagsWhitelist = typeof options.pasteTagsWhitelist === 'string' ? options.pasteTagsWhitelist : options._editorTagsWhitelist; options.addAttributesWhitelist = typeof options.addAttributesWhitelist === 'string' ? options.addAttributesWhitelist : ''; /** Layout */ - options.mode = options.mode || 'classic'; // classic, inline, balloon + options.mode = options.mode || 'classic'; // classic, inline, balloon, balloon-always options.toolbarWidth = options.toolbarWidth ? (util.isNumber(options.toolbarWidth) ? options.toolbarWidth + 'px' : options.toolbarWidth) : 'auto'; options.stickyToolbar = /balloon/i.test(options.mode) ? -1 : options.stickyToolbar === undefined ? 0 : (/^\d+/.test(options.stickyToolbar) ? util.getNumber(options.stickyToolbar, 0) : -1); // options.fullPage = options.fullPage; diff --git a/src/lib/core.js b/src/lib/core.js index c9492661b..3d2ea9cde 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -98,6 +98,11 @@ export default function (context, pluginCallButtons, plugins, lang, options) { */ submenu: null, + /** + * @description Boolean value of whether the editor has focus + */ + hasFocus: false, + /** * @description current resizing component name * @private @@ -173,11 +178,17 @@ export default function (context, pluginCallButtons, plugins, lang, options) { _isInline: null, /** - * @description Is balloon mode? + * @description Is balloon|balloon-always mode? * @private */ _isBalloon: null, + /** + * @description Is balloon-always mode? + * @private + */ + _isBalloonAlways: null, + /** * @description Required value when using inline mode to sticky toolbar * @private @@ -3146,7 +3157,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { if (!this._variable.isFullScreen) { this._notHideToolbar = false; - if (/balloon/i.test(options.mode)) { + if (/balloon|balloon-always/i.test(options.mode)) { context.element._arrow.style.display = ''; this._isInline = false; this._isBalloon = true; @@ -3660,7 +3671,8 @@ export default function (context, pluginCallButtons, plugins, lang, options) { this.codeViewDisabledButtons = context.element.toolbar.querySelectorAll('.se-toolbar button:not([class~="code-view-enabled"])'); this._isInline = /inline/i.test(options.mode); - this._isBalloon = /balloon/i.test(options.mode); + this._isBalloon = /balloon|balloon-always/i.test(options.mode); + this._isBalloonAlways = /balloon-always/i.test(options.mode); this.commandMap = { STRONG: context.tool.bold, @@ -3931,7 +3943,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { if (!command && !display) return; if (target.disabled) return; - core.focus(); + if (!core.hasFocus) core.focus(); /** call plugins */ if (display) { @@ -3982,6 +3994,8 @@ export default function (context, pluginCallButtons, plugins, lang, options) { if (core._isBalloon) { event._hideToolbar(); } + + if (userFunction.onMouseDown) userFunction.onMouseDown(e, core); }, onClick_wysiwyg: function (e) { @@ -4024,6 +4038,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } core._editorRange(); + _w.setTimeout(core._editorRange.bind(core)); const selectionNode = core.getSelectionNode(); const formatEl = util.getFormatElement(selectionNode); @@ -4043,14 +4058,27 @@ export default function (context, pluginCallButtons, plugins, lang, options) { event._applyTagEffects(); } - if (core._isBalloon) _w.setTimeout(event._toggleToolbarBalloon); + if (core._isBalloon) _w.setTimeout(event._toggleToolbarBalloon); if (userFunction.onClick) userFunction.onClick(e, core); }, + _balloonDelay: null, + _showToolbarBalloonDelay: function () { + if (event._balloonDelay) { + _w.clearTimeout(event._balloonDelay); + } + + event._balloonDelay = _w.setTimeout(function () { + _w.clearTimeout(this._balloonDelay); + this._balloonDelay = null; + this._showToolbarBalloon(); + }.bind(event), 300); + }, + _toggleToolbarBalloon: function () { core._editorRange(); const range = core.getRange(); - if (range.collapsed) event._hideToolbar(); + if (core.currentControllerName === 'table' || (!core._isBalloonAlways && range.collapsed)) event._hideToolbar(); else event._showToolbarBalloon(range); }, @@ -4062,7 +4090,9 @@ export default function (context, pluginCallButtons, plugins, lang, options) { const selection = core.getSelection(); let isDirTop; - if (selection.focusNode === selection.anchorNode) { + if (util.getParentElement(core.getSelectionNode(), util.isAnchor)) { + isDirTop = true; + } else if (selection.focusNode === selection.anchorNode) { isDirTop = selection.focusOffset < selection.anchorOffset; } else { const childNodes = util.getListChildNodes(range.commonAncestorContainer); @@ -4097,6 +4127,21 @@ export default function (context, pluginCallButtons, plugins, lang, options) { const toolbarWidth = toolbar.offsetWidth; const toolbarHeight = toolbar.offsetHeight; + if (!rects) { + const node = core.getSelectionNode(); + const nodeOffset = util.getOffset(node, context.element.wysiwygFrame); + rects = { + left: nodeOffset.left, + top: nodeOffset.top, + right: nodeOffset.left, + bottom: nodeOffset.top + node.offsetHeight, + noText: true + }; + scrollLeft = 0; + scrollTop = 0; + isDirTop = true; + } + const iframeRects = /iframe/i.test(context.element.wysiwygFrame.nodeName) ? context.element.wysiwygFrame.getClientRects()[0] : null; if (iframeRects) { rects = { @@ -4118,12 +4163,12 @@ export default function (context, pluginCallButtons, plugins, lang, options) { _setToolbarOffset: function (isDirTop, rects, toolbar, editorLeft, editorWidth, scrollLeft, scrollTop, stickyTop, arrowMargin) { const padding = 1; const toolbarWidth = toolbar.offsetWidth; - const toolbarHeight = toolbar.offsetHeight; + const toolbarHeight = rects.noText && !isDirTop ? 0 : toolbar.offsetHeight; const absoluteLeft = (isDirTop ? rects.left : rects.right) - editorLeft - (toolbarWidth / 2) + scrollLeft; const overRight = absoluteLeft + toolbarWidth - editorWidth; - const t = (isDirTop ? rects.top - toolbarHeight - arrowMargin : rects.bottom + arrowMargin) - stickyTop + scrollTop; + const t = (isDirTop ? rects.top - toolbarHeight - arrowMargin : rects.bottom + arrowMargin) - (rects.noText ? 0 : stickyTop) + scrollTop; let l = absoluteLeft < 0 ? padding : overRight < 0 ? absoluteLeft : absoluteLeft - overRight - padding - 1; toolbar.style.left = _w.Math.floor(l) + 'px'; @@ -4238,32 +4283,34 @@ export default function (context, pluginCallButtons, plugins, lang, options) { // history stack core.history.push(true); } else { - const prev = formatEl.previousElementSibling || rangeEl.parentNode; + let prev = formatEl.previousElementSibling || rangeEl.parentNode; if (util.isListCell(prev)) { - if (util.isListCell(prev)) { - e.preventDefault(); - - let con = prev === rangeEl.parentNode ? rangeEl.previousSibling : prev.lastChild; - if (!con) { - con = util.createTextNode(util.zeroWidthSpace); - rangeEl.parentNode.insertBefore(con, rangeEl.parentNode.firstChild); - } - const offset = con.nodeType === 3 ? con.textContent.length : 1; - const children = formatEl.childNodes; - let after = con; - let child = children[0]; - while ((child = children[0])) { - prev.insertBefore(child, after.nextSibling); - after = child; - } - - util.removeItem(formatEl); - if (rangeEl.children.length === 0) util.removeItem(rangeEl); - - core.setRange(con, offset, con, offset); - // history stack - core.history.push(true); + e.preventDefault(); + const prevLast = prev.lastElementChild; + if (util.isList(prevLast)) { + prev = prevLast.lastElementChild; } + + let con = prev === rangeEl.parentNode ? rangeEl.previousSibling : prev.lastChild; + if (!con) { + con = util.createTextNode(util.zeroWidthSpace); + rangeEl.parentNode.insertBefore(con, rangeEl.parentNode.firstChild); + } + const offset = con.nodeType === 3 ? con.textContent.length : 1; + const children = formatEl.childNodes; + let after = con; + let child = children[0]; + while ((child = children[0])) { + prev.insertBefore(child, after.nextSibling); + after = child; + } + + util.removeItem(formatEl); + if (rangeEl.children.length === 0) util.removeItem(rangeEl); + + core.setRange(con, offset, con, offset); + // history stack + core.history.push(true); } } @@ -4336,7 +4383,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { if (range.startContainer !== range.endContainer) core.removeNode(); let next = util.getArrayItem(formatEl.children, util.isList, false); - next = next || formatEl.nextElementSibling; + next = next || formatEl.nextElementSibling || rangeEl.parentNode.nextElementSibling; if (next && (util.isList(next) || util.getArrayItem(next.children, util.isList, false))) { e.preventDefault(); @@ -4633,8 +4680,9 @@ export default function (context, pluginCallButtons, plugins, lang, options) { const alt = e.altKey; let selectionNode = core.getSelectionNode(); - if (core._isBalloon && !range.collapsed) { - event._showToolbarBalloon(); + if (core._isBalloon && ((core._isBalloonAlways && keyCode !== 27) || !range.collapsed)) { + if (core._isBalloonAlways) event._showToolbarBalloonDelay(); + else event._showToolbarBalloon(); return; } @@ -4705,11 +4753,13 @@ export default function (context, pluginCallButtons, plugins, lang, options) { }, onFocus_wysiwyg: function (e) { + core.hasFocus = true; if (core._isInline) event._showToolbarInline(); if (userFunction.onFocus) userFunction.onFocus(e, core); }, onBlur_wysiwyg: function (e) { + core.hasFocus = false; if (core._isInline || core._isBalloon) event._hideToolbar(); if (userFunction.onBlur) userFunction.onBlur(e, core); }, @@ -4914,6 +4964,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { context.element.toolbar.addEventListener('mousedown', event.onMouseDown_toolbar, false); context.element.toolbar.addEventListener('click', event.onClick_toolbar, false); /** editor area */ + eventWysiwyg.addEventListener('mousedown', event.onMouseDown_wysiwyg, false); eventWysiwyg.addEventListener('click', event.onClick_wysiwyg, false); eventWysiwyg.addEventListener('keydown', event.onKeyDown_wysiwyg, false); eventWysiwyg.addEventListener('keyup', event.onKeyUp_wysiwyg, false); @@ -4925,11 +4976,6 @@ export default function (context, pluginCallButtons, plugins, lang, options) { eventWysiwyg.addEventListener('focus', event.onFocus_wysiwyg, false); eventWysiwyg.addEventListener('blur', event.onBlur_wysiwyg, false); - /** Events are registered only a balloon mode or when there is a table plugin. */ - if (core._isBalloon || core.plugins.table) { - eventWysiwyg.addEventListener('mousedown', event.onMouseDown_wysiwyg, false); - } - /** Events are registered only when there is a table plugin. */ if (core.plugins.table) { eventWysiwyg.addEventListener('touchstart', event.onMouseDown_wysiwyg, {passive: true, useCapture: false}); @@ -5010,6 +5056,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { */ onload: null, onScroll: null, + onMouseDown: null, onClick: null, onKeyDown: null, onKeyUp: null, diff --git a/src/lib/history.js b/src/lib/history.js index 4620259b8..281b8412a 100644 --- a/src/lib/history.js +++ b/src/lib/history.js @@ -102,7 +102,7 @@ export default function (core, change) { _w.clearTimeout(pushDelay); pushDelay = null; pushStack(); - }, 500); + }, 300); }, /** diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index 5e7b4db4f..d9704f5fb 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -46,7 +46,7 @@ suneditor.create("sample1", { let s1 = suneditor.create('editor', { plugins: plugins, - // mode: 'balloon', + mode: 'balloon-always', katex: Katex, // addAttributesWhitelist: 'style', buttonList: [ @@ -122,7 +122,7 @@ window.sun_create1 = function () { let ss = window.ss = suneditor.create(document.getElementById('editor1'), { // lang: lang.ko, plugins: plugins, - // mode: 'balloon', + mode: 'balloon', buttonList: [ ['undo', 'redo', 'font', 'fontSize', 'formatBlock', From 78410c5106aeaac4778c0eab9c103932aae89c71 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Mon, 9 Mar 2020 05:50:32 +0900 Subject: [PATCH 82/99] fix: core-selection --- src/lib/core.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/lib/core.js b/src/lib/core.js index 3d2ea9cde..4dcdf80b9 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -1458,13 +1458,13 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } } - lineIndex = selectedFormats.indexOf(insNode); + if (selectedFormats) lineIndex = selectedFormats.indexOf(insNode); if (selectedFormats && lineIndex === -1) { if (!rangeEl) rangeEl = rangeElement.cloneNode(false); rangeEl.appendChild(insNode); } else { - next = selectedFormats[lineIndex + 1]; + if (selectedFormats) next = selectedFormats[lineIndex + 1]; if (rangeEl && rangeEl.children.length > 0) { parent.insertBefore(rangeEl, rangeElement); rangeEl = null; @@ -3902,7 +3902,6 @@ export default function (context, pluginCallButtons, plugins, lang, options) { onMouseDown_toolbar: function (e) { let target = e.target; - core._editorRange(); if (util.getParentElement(target, '.se-submenu')) { e.stopPropagation(); @@ -3944,6 +3943,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { if (target.disabled) return; if (!core.hasFocus) core.focus(); + core._editorRange(); /** call plugins */ if (display) { From 19d1c5f62ec84862f14010faebf61b85ba6f3a4e Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Mon, 9 Mar 2020 23:33:50 +0900 Subject: [PATCH 83/99] update: #241 balloon-always mode --- README.md | 15 +-------------- src/lib/core.js | 9 ++++++--- test/dev/suneditor_build_test.js | 2 +- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 19f1c468d..f9c0b053f 100644 --- a/README.md +++ b/README.md @@ -35,11 +35,6 @@ Pure javscript based WYSIWYG web editor, with no dependencies - [Functions](#functions) - [Plugins list](#plugins-list) - [Examples](#examples) - - [Defining menu items](#defining-menu-items) - - [Char count, Button groups](#char-count-button-groups) - - [Iframe, fullPage and use CodeMirror](#iframe-fullpage-and-use-codemirror) - - [Image management](#image-management) - - [User Functions](#user-functions) - [Options template](#options-template) - [Custom plugins](#custom-plugins) - [Document](#document) @@ -894,15 +889,7 @@ editor.showInline = function (toolbar, context, core) { ## Examples - [Defining menu items](http://suneditor.com/sample/html/examples.html#setting) - - [Char count, Button groups](http://suneditor.com/sample/html/examples.html#groups) - - [Iframe, fullPage and use CodeMirror](http://suneditor.com/sample/html/examples.html#CodeMirror) - - [Image management](http://suneditor.com/sample/html/examples.html#image) - - [User Functions](http://suneditor.com/sample/html/examples.html#functions) +[Examples](http://suneditor.com/sample/html/examples.html) ## Options template [Options template](http://suneditor.com/sample/html/options.html) diff --git a/src/lib/core.js b/src/lib/core.js index 4dcdf80b9..aa1d4256f 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -4681,9 +4681,12 @@ export default function (context, pluginCallButtons, plugins, lang, options) { let selectionNode = core.getSelectionNode(); if (core._isBalloon && ((core._isBalloonAlways && keyCode !== 27) || !range.collapsed)) { - if (core._isBalloonAlways) event._showToolbarBalloonDelay(); - else event._showToolbarBalloon(); - return; + if (core._isBalloonAlways) { + event._showToolbarBalloonDelay(); + } else { + event._showToolbarBalloon(); + return; + } } /** when format tag deleted */ diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index d9704f5fb..6a0db67df 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -122,7 +122,7 @@ window.sun_create1 = function () { let ss = window.ss = suneditor.create(document.getElementById('editor1'), { // lang: lang.ko, plugins: plugins, - mode: 'balloon', + mode: 'balloon-always', buttonList: [ ['undo', 'redo', 'font', 'fontSize', 'formatBlock', From 60f29a02abad9c3438d2f0ba7e73accb352af813 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Tue, 10 Mar 2020 00:13:39 +0900 Subject: [PATCH 84/99] fix: balloon-always --- src/lib/core.js | 25 ++++--------------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/src/lib/core.js b/src/lib/core.js index aa1d4256f..90a7c1800 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -4090,9 +4090,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { const selection = core.getSelection(); let isDirTop; - if (util.getParentElement(core.getSelectionNode(), util.isAnchor)) { - isDirTop = true; - } else if (selection.focusNode === selection.anchorNode) { + if (selection.focusNode === selection.anchorNode) { isDirTop = selection.focusOffset < selection.anchorOffset; } else { const childNodes = util.getListChildNodes(range.commonAncestorContainer); @@ -4101,6 +4099,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { let rects = range.getClientRects(); rects = rects[isDirTop ? 0 : rects.length - 1]; + if (!rects) return; let scrollLeft = 0; let scrollTop = 0; @@ -4126,22 +4125,6 @@ export default function (context, pluginCallButtons, plugins, lang, options) { const arrowMargin = _w.Math.round(context.element._arrow.offsetWidth / 2); const toolbarWidth = toolbar.offsetWidth; const toolbarHeight = toolbar.offsetHeight; - - if (!rects) { - const node = core.getSelectionNode(); - const nodeOffset = util.getOffset(node, context.element.wysiwygFrame); - rects = { - left: nodeOffset.left, - top: nodeOffset.top, - right: nodeOffset.left, - bottom: nodeOffset.top + node.offsetHeight, - noText: true - }; - scrollLeft = 0; - scrollTop = 0; - isDirTop = true; - } - const iframeRects = /iframe/i.test(context.element.wysiwygFrame.nodeName) ? context.element.wysiwygFrame.getClientRects()[0] : null; if (iframeRects) { rects = { @@ -4163,12 +4146,12 @@ export default function (context, pluginCallButtons, plugins, lang, options) { _setToolbarOffset: function (isDirTop, rects, toolbar, editorLeft, editorWidth, scrollLeft, scrollTop, stickyTop, arrowMargin) { const padding = 1; const toolbarWidth = toolbar.offsetWidth; - const toolbarHeight = rects.noText && !isDirTop ? 0 : toolbar.offsetHeight; + const toolbarHeight = toolbar.offsetHeight; const absoluteLeft = (isDirTop ? rects.left : rects.right) - editorLeft - (toolbarWidth / 2) + scrollLeft; const overRight = absoluteLeft + toolbarWidth - editorWidth; - const t = (isDirTop ? rects.top - toolbarHeight - arrowMargin : rects.bottom + arrowMargin) - (rects.noText ? 0 : stickyTop) + scrollTop; + const t = (isDirTop ? rects.top - toolbarHeight - arrowMargin : rects.bottom + arrowMargin) - stickyTop + scrollTop; let l = absoluteLeft < 0 ? padding : overRight < 0 ? absoluteLeft : absoluteLeft - overRight - padding - 1; toolbar.style.left = _w.Math.floor(l) + 'px'; From 7174f6861550634e0053cfa1d2e5629756d25606 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Tue, 10 Mar 2020 02:25:08 +0900 Subject: [PATCH 85/99] update: icons style --- src/assets/css/suneditor.css | 9 ++++++++- src/lib/constructor.js | 2 +- src/lib/core.js | 4 +++- src/lib/history.js | 2 +- test/dev/suneditor_build_test.js | 4 ++-- 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/assets/css/suneditor.css b/src/assets/css/suneditor.css index 5bf7abfaf..064ae8e77 100755 --- a/src/assets/css/suneditor.css +++ b/src/assets/css/suneditor.css @@ -45,9 +45,16 @@ text-rendering:auto; font-size: 15px; } -.sun-editor .se-toolbar [class*='se-icon-']::before { + +.sun-editor button > svg { + width: 25px; + height: 25px; + margin: 5px; +} +.sun-editor .se-toolbar button > i::before { line-height: 2.1; } + .sun-editor .se-icon-align-justify::before{content:'\0041';} .sun-editor .se-icon-align-left::before{content:'\0042';} .sun-editor .se-icon-align-right::before{content:'\0043';} diff --git a/src/lib/constructor.js b/src/lib/constructor.js index bf327b65c..969abe715 100755 --- a/src/lib/constructor.js +++ b/src/lib/constructor.js @@ -543,7 +543,7 @@ export default { /** plugins - command */ blockquote: ['', lang.toolbar.tag_blockquote, 'blockquote', 'command', - '' + '' ], /** plugins - submenu */ diff --git a/src/lib/core.js b/src/lib/core.js index 90a7c1800..5b23d9119 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -1337,6 +1337,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } } + core._lastEffectNode = null; util.mergeSameTags(rangeElement, null, null, false); util.mergeNestedTags(rangeElement, function (current) { return this.isList(current); }.bind(util)); @@ -1557,6 +1558,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { }; } + core._lastEffectNode = null; if (notHistoryPush) return edge; if (!remove && edge) { @@ -4072,7 +4074,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { _w.clearTimeout(this._balloonDelay); this._balloonDelay = null; this._showToolbarBalloon(); - }.bind(event), 300); + }.bind(event), 350); }, _toggleToolbarBalloon: function () { diff --git a/src/lib/history.js b/src/lib/history.js index 281b8412a..3fd75b5dc 100644 --- a/src/lib/history.js +++ b/src/lib/history.js @@ -102,7 +102,7 @@ export default function (core, change) { _w.clearTimeout(pushDelay); pushDelay = null; pushStack(); - }, 300); + }, 350); }, /** diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index 6a0db67df..db4a83caf 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -122,7 +122,7 @@ window.sun_create1 = function () { let ss = window.ss = suneditor.create(document.getElementById('editor1'), { // lang: lang.ko, plugins: plugins, - mode: 'balloon-always', + // mode: 'balloon-always', buttonList: [ ['undo', 'redo', 'font', 'fontSize', 'formatBlock', @@ -142,7 +142,7 @@ let ss = window.ss = suneditor.create(document.getElementById('editor1'), { youtubeQuery :'autoplay=1&mute=1&enablejsapi=1', placeholder: 'SSSFdjskfdsff.f.fdsa.f...', fullPage: true, - addTagsWhitelist: 'mark|canvas|label|select|option|input|style|nav|button', + addTagsWhitelist: 'mark|canvas|label|select|option|input|nav|button', imageUploadUrl: 'http://localhost:3000/files/upload', // mode: 'inline', // videoHeightShow: false, From 2e905ece3cbddfacc6673cef1f3bf5bde36f76fe Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Tue, 10 Mar 2020 04:59:46 +0900 Subject: [PATCH 86/99] modify: plugin call --- sample/html/customPlugins.html | 12 ++- sample/html/out/document-editor.html | 11 ++- src/assets/css/suneditor.css | 5 +- src/lib/core.js | 16 ++-- test/dev/custom_container.js | 116 +++++++++++++++++++++++++++ test/dev/suneditor_build_test.js | 11 +-- 6 files changed, 153 insertions(+), 18 deletions(-) create mode 100644 test/dev/custom_container.js diff --git a/sample/html/customPlugins.html b/sample/html/customPlugins.html index 125c03e40..6218173bc 100644 --- a/sample/html/customPlugins.html +++ b/sample/html/customPlugins.html @@ -85,7 +85,7 @@ }, // @Overriding - // Plug-ins with active methods load immediately when the editor loads. + // Plugins with active methods load immediately when the editor loads. // Called each time the selection is moved. active: function (element) { if (!element) { @@ -98,6 +98,8 @@ return false; }, + // @Required + // The behavior of the "command plugin" must be defined in the "action" method. action: function () { const rangeTag = this.util.getRangeFormatElement(this.getSelectionNode()); @@ -201,7 +203,7 @@ }, // @Overriding - // Plug-ins with active methods load immediately when the editor loads. + // Plugins with active methods load immediately when the editor loads. // Called each time the selection is moved. active: function (element) { // If no tag matches, the "element" argument is called with a null value. @@ -321,7 +323,7 @@ }, // @Overriding - // Plug-ins with active methods load immediately when the editor loads. + // Plugins with active methods load immediately when the editor loads. // Called each time the selection is moved. active: function (element) { if (!element) { @@ -334,6 +336,8 @@ return false; }, + // @Required + // The behavior of the "command plugin" must be defined in the "action" method. action: function () { const rangeTag = this.util.getRangeFormatElement(this.getSelectionNode()); @@ -417,7 +421,7 @@ }, // @Overriding - // Plug-ins with active methods load immediately when the editor loads. + // Plugins with active methods load immediately when the editor loads. // Called each time the selection is moved. active: function (element) { // If no tag matches, the "element" argument is called with a null value. diff --git a/sample/html/out/document-editor.html b/sample/html/out/document-editor.html index 2e8dbbd28..e7ca85103 100644 --- a/sample/html/out/document-editor.html +++ b/sample/html/out/document-editor.html @@ -629,7 +629,7 @@
    Properties:

    Methods

    -

    callPlugin(pluginName, callBackFunction)callPlugin(pluginName, callBackFunction, _target)

    If the plugin is not added, add the plugin and call the 'add' function.
    @@ -655,10 +655,17 @@
    Parameters:
    callBackFunction - function + Function Function to be executed immediately after module call + + _target + + Element|null + + Plugin target button (This is not necessary if you have a button list when creating the editor) +
    diff --git a/src/assets/css/suneditor.css b/src/assets/css/suneditor.css index 064ae8e77..951a56518 100755 --- a/src/assets/css/suneditor.css +++ b/src/assets/css/suneditor.css @@ -126,6 +126,9 @@ .sun-editor .se-icon-line-height::before{content:'\0027';} .sun-editor .se-icon-text-style::before{content:'\0028';} +/** relative */ +.sun-editor .se-list-inner li * {position:relative;} + /** --- arrow icon ---------------------------------------------------------- */ .sun-editor .se-arrow, .sun-editor .se-arrow::after {position:absolute; display:block; width:0; height:0; border:11px solid transparent;} /* arrow up */ @@ -258,7 +261,7 @@ .sun-editor .se-submenu-form-group {display:flex; width:100%; height:auto; padding:4px;} .sun-editor .se-submenu-form-group input {flex:auto; display:inline-block; width:auto; height:33px; color:#555; font-size:12px; margin:1px 0 1px 0; padding:0; border-radius:0.25rem; border:1px solid #ccc;} .sun-editor .se-submenu-form-group input:focus {border-color:#80bdff; outline:0; -webkit-box-shadow:0 0 0 0.2rem #c7deff; box-shadow:0 0 0 0.2rem #c7deff;} -.sun-editor .se-submenu-form-group button {float:right; width:35px; height:35px; padding:0; margin:0 0 0 4px !important;} +.sun-editor .se-submenu-form-group button {float:right; width:35px; height:35px; margin:0 0 0 4px !important;} .sun-editor .se-submenu-form-group button.se-btn {border:1px solid #ccc;} /** submenu layer - color input */ .sun-editor .se-submenu-form-group .se-color-input {width:72px; text-transform:uppercase; border:none; border-bottom:2px solid #b1b1b1; outline:none;} diff --git a/src/lib/core.js b/src/lib/core.js index 5b23d9119..eb67571f0 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -312,14 +312,20 @@ export default function (context, pluginCallButtons, plugins, lang, options) { * If the plugin is added call callBack function. * @param {String} pluginName The name of the plugin to call * @param {function} callBackFunction Function to be executed immediately after module call + * @param {Element|null} _target Plugin target button (This is not necessary if you have a button list when creating the editor) */ - callPlugin: function (pluginName, callBackFunction) { + callPlugin: function (pluginName, callBackFunction, _target) { if (!this.plugins[pluginName]) { throw Error('[SUNEDITOR.core.callPlugin.fail] The called plugin does not exist or is in an invalid format. (pluginName:"' + pluginName + '")'); } else if (!this.initPlugins[pluginName]){ - this.plugins[pluginName].add(this, pluginCallButtons[pluginName]); + this.plugins[pluginName].add(this, _target || pluginCallButtons[pluginName]); this.initPlugins[pluginName] = true; } + + if (this.plugins[pluginName].active) { + this.commandMap[pluginName] = _target || pluginCallButtons[pluginName]; + this.activePlugins.push(pluginName); + } if (typeof callBackFunction === 'function') callBackFunction(); }, @@ -3688,15 +3694,13 @@ export default function (context, pluginCallButtons, plugins, lang, options) { }; // Command plugins registration - const activePlugins = this.activePlugins = []; + this.activePlugins = []; let c, button; for (let key in plugins) { c = plugins[key]; button = pluginCallButtons[key]; if (c.active && button) { - core.callPlugin(key, button); - core.commandMap[c.name] = button; - activePlugins.push(c.name); + core.callPlugin(key, null, button); } } diff --git a/test/dev/custom_container.js b/test/dev/custom_container.js new file mode 100644 index 000000000..85960d493 --- /dev/null +++ b/test/dev/custom_container.js @@ -0,0 +1,116 @@ +export default { + // @Required + // plugin name + name: 'custom_container', + + // @Required + // data display + display: 'submenu', + + // @Required + // add function - It is called only once when the plugin is first run. + // This function generates HTML to append and register the event. + // arguments - (core : core object, targetElement : clicked button element) + add: function (core, targetElement) { + + // Registering a namespace for caching as a plugin name in the context object + const context = core.context; + context.customContainer = {}; + + // Generate submenu HTML + // Always bind "core" when calling a plugin function + let listDiv = this.setSubmenu.call(core); + + listDiv.querySelector('ul').addEventListener('click', this.onClick.bind(core)); + + /** append html */ + targetElement.parentNode.appendChild(listDiv); + }, + + setSubmenu: function () { + const listDiv = this.util.createElement('DIV'); + + listDiv.className = 'se-submenu se-list-layer'; + listDiv.innerHTML = '' + + '
    ' + + '
      ' + + '
    • ' + + '
      ' + + '
      ' + + '' + + '
      ' + + '
      ' + + '' + + '
      ' + + '
      ' + + '' + + '
      ' + + '
      ' + + '' + + '
      ' + + '
      ' + + '
    • ' + + '
    ' + + '
    '; + + return listDiv; + }, + + onClick: function (e) { + e.preventDefault(); + e.stopPropagation(); + + let target = e.target; + let command = ''; + + while (!command && !/^UL$/i.test(target.tagName)) { + command = target.getAttribute('data-command'); + if (command) break; + target = target.parentNode; + } + + if (!command) return; + + const plugin = this.plugins[command]; + + if (plugin.display === 'submenu' && (this.nextElementSibling === null || target !== this.submenuActiveButton)) { + this.callPlugin(command, function () { + this.submenuOn(target); + }.bind(this), target); + + return; + } + else if (plugin.display === 'dialog') { + this.callPlugin(command, function () { + plugin.dialog.open.call(this, command, command === this.currentControllerName); + }.bind(this), target); + } + else if (plugin.display === 'command') { + this.callPlugin(command, function () { + plugin.action.call(this); + }.bind(this), target); + } + + this.submenuOff(); + } +}; \ No newline at end of file diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index db4a83caf..918a09cc7 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -10,6 +10,7 @@ import lang from '../../src/lang'; import custom_plugin_submenu from './custom_plugin_submenu'; import Resolutions from './Resolutions'; +import custom_container from './custom_container'; import 'codemirror/lib/codemirror.css'; import 'codemirror/mode/htmlmixed/htmlmixed'; @@ -24,7 +25,7 @@ const align = require('../../src/plugins/submenu/align') suneditor.create("sample1", { - plugins: [Resolutions], + plugins: [custom_container, plugins.blockquote, plugins.link, plugins.table, plugins.textStyle], // mode: "balloon", // iframe: true, width: '100%', @@ -32,10 +33,10 @@ suneditor.create("sample1", { buttonList: [ [ { - name: 'Resolutions', - dataCommand: 'Resolutions', - buttonClass:'', - title:'Resolutions', + name: 'custom_container', + dataCommand: 'custom_container', + buttonClass:'se-menu-container', + title:'custom_container', dataDisplay:'submenu', innerHTML:'' } From fe94aa46821f785ba2011b18a831225aa64aa2fc Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Tue, 10 Mar 2020 05:32:06 +0900 Subject: [PATCH 87/99] modify: call dialog plugin --- src/assets/css/suneditor.css | 3 --- src/lib/core.js | 2 +- src/plugins/dialog/image.js | 4 ++++ src/plugins/dialog/link.js | 4 ++++ src/plugins/dialog/math.js | 4 ++++ src/plugins/dialog/video.js | 4 ++++ test/dev/custom_container.js | 10 +++++----- 7 files changed, 22 insertions(+), 9 deletions(-) diff --git a/src/assets/css/suneditor.css b/src/assets/css/suneditor.css index 951a56518..7a239e231 100755 --- a/src/assets/css/suneditor.css +++ b/src/assets/css/suneditor.css @@ -126,9 +126,6 @@ .sun-editor .se-icon-line-height::before{content:'\0027';} .sun-editor .se-icon-text-style::before{content:'\0028';} -/** relative */ -.sun-editor .se-list-inner li * {position:relative;} - /** --- arrow icon ---------------------------------------------------------- */ .sun-editor .se-arrow, .sun-editor .se-arrow::after {position:absolute; display:block; width:0; height:0; border:11px solid transparent;} /* arrow up */ diff --git a/src/lib/core.js b/src/lib/core.js index eb67571f0..117b6f985 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -3961,7 +3961,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } else if (/dialog/.test(display)) { core.callPlugin(command, function () { - core.plugins.dialog.open.call(core, command, command === core.currentControllerName); + core.plugins[command].open.call(core); }); return; } diff --git a/src/plugins/dialog/image.js b/src/plugins/dialog/image.js index 72a7ebc1f..b6871d4e9 100644 --- a/src/plugins/dialog/image.js +++ b/src/plugins/dialog/image.js @@ -194,6 +194,10 @@ export default { return dialog; }, + open: function () { + this.plugins.dialog.open.call(this, 'image', 'image' === this.currentControllerName); + }, + openTab: function (e) { const modal = this.context.image.modal; const targetElement = (e === 'init' ? modal.querySelector('._se_tab_link') : e.target); diff --git a/src/plugins/dialog/link.js b/src/plugins/dialog/link.js index 2afc1137c..8facd6313 100644 --- a/src/plugins/dialog/link.js +++ b/src/plugins/dialog/link.js @@ -111,6 +111,10 @@ export default { return link_btn; }, + open: function () { + this.plugins.dialog.open.call(this, 'link', 'link' === this.currentControllerName); + }, + submit: function (e) { this.showLoading(); diff --git a/src/plugins/dialog/math.js b/src/plugins/dialog/math.js index 5ef43cf72..40e817680 100644 --- a/src/plugins/dialog/math.js +++ b/src/plugins/dialog/math.js @@ -116,6 +116,10 @@ export default { return math_btn; }, + open: function () { + this.plugins.dialog.open.call(this, 'math', 'math' === this.currentControllerName); + }, + _renderMathExp: function (e) { this.previewElement.innerHTML = this._renderer(e.target.value); }, diff --git a/src/plugins/dialog/video.js b/src/plugins/dialog/video.js index e6a6c9afa..f917b48ce 100644 --- a/src/plugins/dialog/video.js +++ b/src/plugins/dialog/video.js @@ -154,6 +154,10 @@ export default { return dialog; }, + + open: function () { + this.plugins.dialog.open.call(this, 'video', 'video' === this.currentControllerName); + }, setVideoRatio: function (e) { const contextVideo = this.context.video; diff --git a/test/dev/custom_container.js b/test/dev/custom_container.js index 85960d493..d8f65ebb6 100644 --- a/test/dev/custom_container.js +++ b/test/dev/custom_container.js @@ -36,7 +36,7 @@ export default { '
      ' + '
    • ' + '
      ' + - '
      ' + + '
      ' + '' + '
      ' + - '
      ' + + '
      ' + '' + '
      ' + - '
      ' + + '
      ' + '' + '
      ' + - '
      ' + + '
      ' + '' + + '
      ' + + '
      ' + + '
      @@ -1835,6 +1889,8 @@

      core

    • cleanHTML
    • addDocEvent
    • removeDocEvent
    • +
    • convertContentsForEditor
    • +
    • convertHTMLForCodeView
    diff --git a/sample/html/out/document-util.html b/sample/html/out/document-util.html index 283972b6e..97957fa5e 100644 --- a/sample/html/out/document-util.html +++ b/sample/html/out/document-util.html @@ -263,77 +263,6 @@
    Parameters:
    -

    convertContentsForEditor(contents, whitelist) → {String}

    -
    - Converts contents into a format that can be placed in an editor. -
    -
    Parameters:
    - - - - - - - - - - - - - - - - - - - - -
    NameTypeDescription
    contents - String - Contents
    whitelist - String|RegExp - - Regular expression of allowed tags.
    - RegExp object is create by util.createTagsWhitelist method. (core.editorTagsWhitelistRegExp, core.pasteTagsWhitelistRegExp) -
    -
    - - -

    convertHTMLForCodeView(html, indentSize) → {String}

    -
    - Converts wysiwyg area element into a format that can be placed in an editor of code view mode -
    -
    Parameters:
    - - - - - - - - - - - - - - - - - - - - -
    NameTypeDescription
    html - Element|String - WYSIWYG element (context.element.wysiwyg) or HTML string
    indentSize - Number|null - The indent size of the tag (default: 0)
    -
    - -

    isWysiwygDiv(element) → {Boolean}

    @@ -2052,8 +1981,6 @@

    util

  • getPageStyle
  • getIframeDocument
  • getAttributesToString
  • -
  • convertContentsForEditor
  • -
  • convertHTMLForCodeView
  • isWysiwygDiv
  • isFormatElement
  • isRangeFormatElement
  • diff --git a/src/lib/core.js b/src/lib/core.js index a0299201f..9b8c97c62 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -350,15 +350,19 @@ export default function (context, pluginCallButtons, plugins, lang, options) { * @param {Element|null} _target Plugin target button (This is not necessary if you have a button list when creating the editor) */ callPlugin: function (pluginName, callBackFunction, _target) { + _target = _target || pluginCallButtons[pluginName]; + if (!this.plugins[pluginName]) { throw Error('[SUNEDITOR.core.callPlugin.fail] The called plugin does not exist or is in an invalid format. (pluginName:"' + pluginName + '")'); } else if (!this.initPlugins[pluginName]){ - this.plugins[pluginName].add(this, _target || pluginCallButtons[pluginName]); + if(!_target) return false; + this.plugins[pluginName].add(this, _target); this.initPlugins[pluginName] = true; } - if (this.plugins[pluginName].active) { - this.commandMap[pluginName] = _target || pluginCallButtons[pluginName]; + if (this.plugins[pluginName].active && !this.commandMap[pluginName]) { + if(!_target) return false; + this.commandMap[pluginName] = _target; this.activePlugins.push(pluginName); } @@ -1920,18 +1924,23 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } // multi line else { - // start - start = this._nodeChange_startLine(lineNodes[0], newNode, validation, startCon, startOff, isRemoveFormat, isRemoveNode, _removeCheck, _getMaintainedNode, _isMaintainedNode); - // mid - for (let i = 1; i < endLength; i++) { - newNode = appendNode.cloneNode(false); - this._nodeChange_middleLine(lineNodes[i], newNode, validation, isRemoveFormat, isRemoveNode, _removeCheck); - } // end if (endLength > 0) { newNode = appendNode.cloneNode(false); end = this._nodeChange_endLine(lineNodes[endLength], newNode, validation, endCon, endOff, isRemoveFormat, isRemoveNode, _removeCheck, _getMaintainedNode, _isMaintainedNode); - } else { + } + + // mid + for (let i = endLength - 1; i > 0; i--) { + newNode = appendNode.cloneNode(false); + this._nodeChange_middleLine(lineNodes[i], newNode, validation, isRemoveFormat, isRemoveNode, _removeCheck); + } + + // start + newNode = appendNode.cloneNode(false); + start = this._nodeChange_startLine(lineNodes[0], newNode, validation, startCon, startOff, isRemoveFormat, isRemoveNode, _removeCheck, _getMaintainedNode, _isMaintainedNode); + + if (endLength <= 0) { end = start; } } @@ -2707,6 +2716,8 @@ export default function (context, pluginCallButtons, plugins, lang, options) { if (child.nodeName === newNodeName) { child.style.cssText += newCssText; util.addClass(child, newClass); + } else if (util._isIgnoreNodeChange(child)) { + continue; } else if (len === 1) { children = child.childNodes; len = children.length; @@ -3682,7 +3693,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { returnHTML = '

    ' + (contents.length > 0 ? contents : '
    ') + '

    '; } - return this.cleanHTML(util._tagConvertor(returnHTML.replace(this.editorTagsWhitelistRegExp, '')), null); + return util._tagConvertor(returnHTML.replace(this.editorTagsWhitelistRegExp, '')); }, /** @@ -4170,7 +4181,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { const tableCell = util.getParentElement(e.target, util.isCell); if (tableCell) { const tablePlugin = core.plugins.table; - if (tableCell !== tablePlugin._fixedCell && !tablePlugin._shift) { + if (tablePlugin && tableCell !== tablePlugin._fixedCell && !tablePlugin._shift) { core.callPlugin('table', function () { tablePlugin.onTableCellMultiSelect.call(core, tableCell, false); }); diff --git a/test/dev/suneditor_build_test.html b/test/dev/suneditor_build_test.html index d4a5b5bbc..29d9fff29 100644 --- a/test/dev/suneditor_build_test.html +++ b/test/dev/suneditor_build_test.html @@ -126,11 +126,17 @@
    diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index be2b7d9fb..e6deab3ae 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -29,6 +29,7 @@ suneditor.create("sample1", { // mode: "balloon", // iframe: true, width: '100%', + height: '500px', imageFileInput: false, buttonList: [ [ @@ -39,7 +40,8 @@ suneditor.create("sample1", { title:'custom_container', dataDisplay:'container', innerHTML:'' - } + }, + 'bold' ] ] }); From d3c3077d246ec505179e6d3e82a1709e099c19fe Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Wed, 11 Mar 2020 00:56:04 +0900 Subject: [PATCH 92/99] fix: core-nodeChange --- src/lib/core.js | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/src/lib/core.js b/src/lib/core.js index 9b8c97c62..372ad8b7b 100755 --- a/src/lib/core.js +++ b/src/lib/core.js @@ -1726,7 +1726,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { * @param {Boolean|null} strictRemove If true, only nodes with all styles and classes removed from the nodes of "removeNodeArray" are removed. */ nodeChange: function (appendNode, styleArray, removeNodeArray, strictRemove) { - const range = this.getRange(); + let range = this.getRange(); styleArray = styleArray && styleArray.length > 0 ? styleArray : false; removeNodeArray = removeNodeArray && removeNodeArray.length > 0 ? removeNodeArray : false; @@ -1741,6 +1741,32 @@ export default function (context, pluginCallButtons, plugins, lang, options) { return; } + if (range.collapsed) { + if (startCon.nodeType === 1 && !util.isBreak(startCon)) { + let afterNode = null; + const focusNode = startCon.childNodes[startOff]; + + if (focusNode !== null && util.isBreak(focusNode)) { + if (!focusNode.nextSibling) { + startCon.removeChild(focusNode); + afterNode = null; + } else { + afterNode = focusNode.nextSibling; + } + } + + const zeroWidth = util.createTextNode(util.zeroWidthSpace); + startCon.insertBefore(zeroWidth, afterNode); + this.setRange(zeroWidth, 1, zeroWidth, 1); + + range = this.getRange(); + startCon = range.startContainer; + startOff = range.startOffset; + endCon = range.endContainer; + endOff = range.endOffset; + } + } + if (isRemoveNode) { appendNode = util.createElement('DIV'); } From ce1e2b92c1ee91af7e112bb057029364dcc5314b Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Wed, 11 Mar 2020 03:45:41 +0900 Subject: [PATCH 93/99] update sample --- README.md | 15 +- sample/css/bootstrap.css | 5 +- sample/html/customPlugins.html | 341 ++++++++++++++++++++++- sample/html/getting-started.html | 13 +- sample/html/options.html | 23 +- sample/html/out/styles/jsdoc-default.css | 26 +- sample/index.html | 36 ++- sample/js/common.js | 4 +- src/assets/css/suneditor.css | 1 + src/lib/core.js | 14 +- test/dev/custom_container.js | 4 + test/dev/suneditor_build_test.html | 1 + test/dev/suneditor_build_test.js | 2 +- 13 files changed, 437 insertions(+), 48 deletions(-) diff --git a/README.md b/README.md index f9c0b053f..00af537bf 100644 --- a/README.md +++ b/README.md @@ -139,7 +139,7 @@ suneditor.create('sample', { buttonList: [ ['undo', 'redo'], ['font', 'fontSize', 'formatBlock'], - ['blockquote', 'paragraphStyle'], + ['paragraphStyle', 'blockquote'], ['bold', 'underline', 'italic', 'strike', 'subscript', 'superscript'], ['fontColor', 'hiliteColor', 'textStyle'], ['removeFormat'], @@ -196,7 +196,7 @@ const initEditor = suneditor.init({ buttonList: [ ['undo', 'redo', 'font', 'fontSize', 'formatBlock', - 'blockquote', 'paragraphStyle', + 'paragraphStyle', 'blockquote', 'bold', 'underline', 'italic', 'strike', 'subscript', 'superscript', 'fontColor', 'hiliteColor', 'textStyle', 'removeFormat', @@ -316,8 +316,13 @@ addTagsWhitelist : Add tags to the default tags whitelist of editor. defaul // _editorTagsWhitelist : _defaultTagsWhitelist + addTagsWhitelist pasteTagsWhitelist : Whitelist of tags when pasting. default: _editorTagsWhitelist {String} ex) 'p|h[1-6]' -addAttributesWhitelist: Add attributes whitelist of tags that should be kept undeleted from the editor. - ex) 'style|name' +attributesWhitelist : Add attributes whitelist of tags that should be kept undeleted from the editor. + // Base whitelist: 'contenteditable|colspan|rowspan|target|href|src|class|type' + // Attributes used in the editor: 'data-format|data-size|data-file-size|data-file-name|data-origin|data-align|data-image-link|data-rotate|data-proportion|data-percentage|origin-size' + ex) { + 'all': 'style', // Apply to all tags + 'input': 'checked' // Apply to input tag + } // Layout------------------------------------------------------------------------------------------------------- lang : language object. default : en {Object} mode : The mode of the editor ('classic', 'inline', 'balloon', 'balloon-always'). default: 'classic' {String} @@ -567,7 +572,7 @@ buttonList : Defines button list to array {Array} default: [ ['undo', 'redo'], // ['font', 'fontSize', 'formatBlock'], - // ['blockquote', 'paragraphStyle'], + // ['paragraphStyle', 'blockquote'], ['bold', 'underline', 'italic', 'strike', 'subscript', 'superscript'], // ['fontColor', 'hiliteColor', 'textStyle'], ['removeFormat'], diff --git a/sample/css/bootstrap.css b/sample/css/bootstrap.css index aeecab023..c9b319448 100644 --- a/sample/css/bootstrap.css +++ b/sample/css/bootstrap.css @@ -727,7 +727,7 @@ input[type="button"].btn-block { float: left; height: 50px; padding: 15px 15px; - font-size: 18px; + font-size: 22px; line-height: 20px; } .navbar-brand:hover, @@ -795,7 +795,8 @@ input[type="button"].btn-block { .navbar-inverse { background-color: #f4b124; border-color: #ffebc1; - padding-top: 10px; + padding-top: 5px; + padding-bottom: 5px; } .navbar-inverse .navbar-brand { color: #333; diff --git a/sample/html/customPlugins.html b/sample/html/customPlugins.html index 6218173bc..3ed65b66f 100644 --- a/sample/html/customPlugins.html +++ b/sample/html/customPlugins.html @@ -12,6 +12,44 @@ @@ -65,9 +70,9 @@
    diff --git a/sample/html/options.html b/sample/html/options.html index 3b1734b6a..3328c379d 100644 --- a/sample/html/options.html +++ b/sample/html/options.html @@ -57,8 +57,11 @@

    --Whitelist



    - - +
    + {
    +   all: 'style',
    +   input: 'checked'
    + }

    --Layout

    @@ -95,7 +98,8 @@

    --Layout



    - { codeMirror: CodeMirror } + { codeMirror: CodeMirror }
    + { katex: katex } // Use "math" plugin

    --Display

    @@ -302,6 +306,9 @@

    Applied options

    + + + @@ -86,7 +107,7 @@ -
    +
    @@ -154,6 +175,7 @@

    The Suneditor is based on pure JavaScript, with no dependencies.

    ",t},setController_MathButton:function(){const e=this.lang,t=this.util.createElement("DIV");return t.className="se-controller se-controller-link",t.innerHTML='
    ",t},open:function(){this.plugins.dialog.open.call(this,"math","math"===this.currentControllerName)},_renderMathExp:function(e){this.previewElement.innerHTML=this._renderer(e.target.value)},submit:function(e){this.showLoading(),e.preventDefault(),e.stopPropagation();const t=function(){if(0===this.context.math.focusElement.value.trim().length)return!1;const e=this.context.math,t=e.focusElement.value,i=e.previewElement.querySelector(".katex");if(!i)return!1;if(i.setAttribute("contenteditable",!1),i.setAttribute("data-exp",t),i.setAttribute("data-font-size",e.fontSizeElement.value),i.style.fontSize=e.fontSizeElement.value,this.context.dialog.updateModal){const t=function(e,i){if(e.classList.contains(i))return e;const n=e.parentNode;return n!==document.body?n.classList.contains(i)?n:void t(n,i):void 0},n=t(e._mathExp,"katex");n.parentNode.replaceChild(i,n),this.setRange(i,0,i,1)}else{const e=this.getSelectedElements();if(e.length>1){const t=this.util.createElement(e[0].nodeName);t.appendChild(i),this.insertNode(t)}else this.insertNode(i);const t=this.util.createTextNode(this.util.zeroWidthSpace);i.parentNode.insertBefore(t,i.nextSibling),this.setRange(i,0,i,1)}return e.focusElement.value="",e.fontSizeElement.value="1em",e.previewElement.style.fontSize="1em",e.previewElement.innerHTML="",!0}.bind(this);try{t()&&(this.plugins.dialog.close.call(this),this.history.push(!1))}catch(e){this.plugins.dialog.close.call(this)}finally{this.closeLoading()}return!1},active:function(e){if(e){if(e.getAttribute("data-exp"))return this.controllerArray[0]!==this.context.math.mathBtn&&(this.setRange(e,0,e,1),this.plugins.math.call_controller_mathButton.call(this,e)),!0}else this.controllerArray[0]===this.context.math.mathBtn&&this.controllersOff();return!1},on:function(e){const t=this.context.math;if(t._mathExp&&e){const e=t._mathExp.getAttribute("data-exp"),i=t._mathExp.getAttribute("data-font-size")||"1em";this.context.dialog.updateModal=!0,t.focusElement.value=e,t.fontSizeElement.value=i,t.previewElement.innerHTML=t._renderer(e),t.previewElement.style.fontSize=i}},call_controller_mathButton:function(e){this.context.math._mathExp=e;const t=this.context.math.mathBtn,i=this.util.getOffset(e,this.context.element.wysiwygFrame);t.style.top=i.top+e.offsetHeight+10+"px",t.style.left=i.left-this.context.element.wysiwygFrame.scrollLeft+"px",t.style.display="block";const n=this.context.element.wysiwygFrame.offsetWidth-(t.offsetLeft+t.offsetWidth);n<0?(t.style.left=t.offsetLeft+n+"px",t.firstElementChild.style.left=20-n+"px"):t.firstElementChild.style.left="20px",this.controllersOn(t,this.plugins.math.init.bind(this),"math")},onClick_mathBtn:function(e){e.stopPropagation();const t=e.target.getAttribute("data-command")||e.target.parentNode.getAttribute("data-command");t&&(e.preventDefault(),/update/.test(t)?(this.context.math.focusElement.value=this.context.math._mathExp.getAttribute("data-exp"),this.plugins.dialog.open.call(this,"math",!0)):(this.util.removeItem(this.context.math._mathExp),this.context.math._mathExp=null,this.focus(),this.history.push(!1)),this.controllersOff())},init:function(){if(!/math/i.test(this.context.dialog.kind)){const e=this.context.math;e.mathBtn.style.display="none",e._mathExp=null,e.focusElement.value="",e.previewElement.innerHTML=""}}}},r=i("P6u4"),c=i.n(r);const d={_d:document,_w:window,_tagConvertor:function(e){const t={b:"strong",i:"em",u:"ins",strike:"del",s:"del"};return e.replace(/(<\/?)(b|strong|i|em|u|ins|s|strike|del)\b\s*(?:[^>^<]+)?\s*(?=>)/gi,(function(e,i,n){return i+("string"==typeof t[n]?t[n]:n)}))},_HTMLConvertor:function(e){const t={"&":"&"," ":" ","'":""","<":"<",">":">"};return e.replace(/&|\u00A0|'|<|>/g,(function(e){return"string"==typeof t[e]?t[e]:e}))},zeroWidthSpace:"​",zeroWidthRegExp:new RegExp(String.fromCharCode(8203),"g"),onlyZeroWidthRegExp:new RegExp("^"+String.fromCharCode(8203)+"+$"),onlyZeroWidthSpace:function(e){return"string"!=typeof e&&(e=e.textContent),""===e||this.onlyZeroWidthRegExp.test(e)},getXMLHttpRequest:function(){if(!this._w.ActiveXObject)return this._w.XMLHttpRequest?new XMLHttpRequest:null;try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(e){try{return new ActiveXObject("Microsoft.XMLHTTP")}catch(e){return null}}},createElement:function(e){return this._d.createElement(e)},createTextNode:function(e){return this._d.createTextNode(e||"")},getIncludePath:function(e,t){let i="";const n=[],l="js"===t?"script":"link",s="js"===t?"src":"href";let o="(?:";for(let t=0,i=e.length;t0?n[0][s]:""),-1===i.indexOf(":/")&&"//"!==i.slice(0,2)&&(i=0===i.indexOf("/")?location.href.match(/^.*?:\/\/[^\/]*/)[0]+i:location.href.match(/^[^\?]*\/(?:)/)[0]+i),!i)throw"[SUNEDITOR.util.getIncludePath.fail] The SUNEDITOR installation path could not be automatically detected. (name: +"+name+", extension: "+t+")";return i},getPageStyle:function(e){let t="";const i=(e?this.getIframeDocument(e):this._d).styleSheets;for(let e,n=0,l=i.length;n-1||(n+=i[e].name+'="'+i[e].value+'" ');return n},isWysiwygDiv:function(e){return!(!e||1!==e.nodeType||!this.hasClass(e,"se-wrapper-wysiwyg")&&!/^BODY$/i.test(e.nodeName))},isFormatElement:function(e){return!(!e||1!==e.nodeType||!/^(P|DIV|H[1-6]|PRE|LI)$/i.test(e.nodeName)&&!this.hasClass(e,"(\\s|^)__se__format__replace_.+(\\s|$)|(\\s|^)__se__format__free_.+(\\s|$)")||this.isComponent(e)||this.isWysiwygDiv(e))},isRangeFormatElement:function(e){return!(!e||1!==e.nodeType||!/^(BLOCKQUOTE|OL|UL|FIGCAPTION|TABLE|THEAD|TBODY|TR|TH|TD)$/i.test(e.nodeName)&&!this.hasClass(e,"(\\s|^)__se__format__range_.+(\\s|$)"))},isFreeFormatElement:function(e){return!(!e||1!==e.nodeType||!/^PRE$/i.test(e.nodeName)&&!this.hasClass(e,"(\\s|^)__se__format__free_.+(\\s|$)")||this.isComponent(e)||this.isWysiwygDiv(e))},isComponent:function(e){return e&&(/se-component/.test(e.className)||/^(TABLE|HR)$/.test(e.nodeName))},isMediaComponent:function(e){return e&&/se-component/.test(e.className)},getFormatElement:function(e,t){if(!e)return null;for(t||(t=function(){return!0});e;){if(this.isWysiwygDiv(e))return null;if(this.isRangeFormatElement(e)&&e.firstElementChild,this.isFormatElement(e)&&t(e))return e;e=e.parentNode}return null},getRangeFormatElement:function(e,t){if(!e)return null;for(t||(t=function(){return!0});e;){if(this.isWysiwygDiv(e))return null;if(this.isRangeFormatElement(e)&&!/^(THEAD|TBODY|TR)$/i.test(e.nodeName)&&t(e))return e;e=e.parentNode}return null},getFreeFormatElement:function(e,t){if(!e)return null;for(t||(t=function(){return!0});e;){if(this.isWysiwygDiv(e))return null;if(this.isFreeFormatElement(e)&&t(e))return e;e=e.parentNode}return null},copyTagAttributes:function(e,t){t.style.cssText&&(e.style.cssText+=t.style.cssText);const i=t.classList;for(let t=0,n=i.length;t0&&!this.isBreak(e);)e=e.firstChild;for(;t&&1===t.nodeType&&t.childNodes.length>0&&!this.isBreak(t);)t=t.lastChild;return{sc:e,ec:t||e}}},getOffset:function(e,t){let i=0,n=0,l=3===e.nodeType?e.parentElement:e;const s=this.getParentElement(e,this.isWysiwygDiv.bind(this));for(;l&&!this.hasClass(l,"se-container")&&l!==s;)i+=l.offsetLeft,n+=l.offsetTop,l=l.offsetParent;const o=t&&/iframe/i.test(t.nodeName);return{left:i+(o?t.parentElement.offsetLeft:0),top:n-s.scrollTop+(o?t.parentElement.offsetTop:0)}},getOverlapRangeAtIndex:function(e,t,i,n){if(e<=n?ti)return 0;const l=(e>i?e:i)-(t0?" ":"")+t)},removeClass:function(e,t){if(!e)return;const i=new this._w.RegExp("(\\s|^)"+t+"(\\s|$)");e.className=e.className.replace(i," ").trim(),e.className.trim()||e.removeAttribute("class")},toggleClass:function(e,t){if(!e)return;const i=new this._w.RegExp("(\\s|^)"+t+"(\\s|$)");i.test(e.className)?e.className=e.className.replace(i," ").trim():e.className+=" "+t,e.className.trim()||e.removeAttribute("class")},removeItem:function(e){if(e)try{e.remove()}catch(t){e.parentNode.removeChild(e)}},removeItemAllParents:function(e,t,i){if(!e)return null;let n=null;return t||(t=function(e){if(e===i||this.isComponent(e))return!1;const t=e.textContent.trim();return 0===t.length||/^(\n|\u200B)+$/.test(t)}.bind(this)),function e(i){if(!d.isWysiwygDiv(i)){const l=i.parentNode;l&&t(i)&&(n={sc:i.previousElementSibling,ec:i.nextElementSibling},d.removeItem(i),e(l))}}(e),n},detachNestedList:function(e,t){const i=this.__deleteNestedList(e);let n,l,s;if(i){n=i.cloneNode(!1),l=i.childNodes;const t=this.getPositionIndex(e);for(;l[t];)n.appendChild(l[t])}else n=e;if(t)s=this.getListChildren(n,function(e){return this.isListCell(e)&&!e.previousElementSibling}.bind(this));else{const t=this.getElementDepth(e)+2;s=this.getListChildren(e,function(e){return this.isListCell(e)&&!e.previousElementSibling&&this.getElementDepth(e)===t}.bind(this))}for(let e=0,t=s.length;e=0){e.splitText(t);const i=this.getNodeFromPath([a+1],n);this.onlyZeroWidthSpace(i)&&(i.data=this.zeroWidthSpace)}}else 1===e.nodeType&&(e.previousSibling?e=e.previousSibling:this.getElementDepth(e)===i&&(r=!1));let c=e;for(;this.getElementDepth(c)>i;)for(a=this.getPositionIndex(c)+1,c=c.parentNode,o=l,l=c.cloneNode(!1),s=c.childNodes,o&&(this.isListCell(l)&&this.isList(o)&&o.firstElementChild&&(l.innerHTML=o.firstElementChild.innerHTML,d.removeItem(o.firstElementChild),o.children.length>0&&l.appendChild(o)),l.appendChild(o));s[a];)l.appendChild(s[a]);const u=c.parentNode;return r&&(c=c.nextSibling),l?(this.mergeSameTags(l,null,null,!1),this.mergeNestedTags(l,function(e){return this.isList(e)}.bind(this)),l.childNodes.length>0?u.insertBefore(l,c):l=c,0===n.childNodes.length&&this.removeItem(n),l):c},mergeSameTags:function(e,t,i,n){const l=this,s={a:0,b:0};return function e(o,a,r,c,d){const u=o.childNodes;for(let h,p,g=0,m=u.length;g0&&n++;const o=h.lastChild,u=p.firstChild;if(o&&u){const e=3===o.nodeType&&3===u.nodeType;let l=o.textContent.length,h=o.previousSibling;for(;h&&3===h.nodeType;)l+=h.textContent.length,h=h.previousSibling;n>0&&3===o.nodeType&&3===u.nodeType&&(o.textContent.length>0||u.textContent.length>0)&&n--,c&&t&&t[a]>g&&(a>0&&t[a-1]!==r?c=!1:(t[a]-=1,t[a+1]>=0&&t[a]===g&&(t[a+1]+=n,e&&o&&3===o.nodeType&&u&&3===u.nodeType&&(s.a+=l)))),d&&i&&i[a]>g&&(a>0&&i[a-1]!==r?d=!1:(i[a]-=1,i[a+1]>=0&&i[a]===g&&(i[a+1]+=n,e&&o&&3===o.nodeType&&u&&3===u.nodeType&&(s.b+=l))))}3===h.nodeType?h.textContent+=p.textContent:h.innerHTML+=p.innerHTML,l.removeItem(p),g--}else 1===h.nodeType&&e(h,a+1,g,c,d)}}(e,0,0,!0,!0),s},mergeNestedTags:function(e,t){"string"==typeof t?t=function(e){return this.test(e.tagName)}.bind(new this._w.RegExp("^("+(t||".+")+")$","i")):"function"!=typeof t&&(t=function(){return!0}),function e(i){let n=i.children;if(1===n.length&&n[0].nodeName===i.nodeName&&t(i)){const e=n[0];for(n=e.children;n[0];)i.appendChild(n[0]);i.removeChild(e)}for(let t=0,n=i.children.length;t")},sortByDepth:function(e,t){const i=t?1:-1,n=-1*i;e.sort(function(e,t){return this.isListCell(e)&&this.isListCell(t)?(e=this.getElementDepth(e))>(t=this.getElementDepth(t))?i:e'}return i}()+("auto"===e.height?"":"");l.allowFullscreen=!0,l.frameBorder=0,l.addEventListener("load",(function(){this.setAttribute("scrolling","auto"),this.contentDocument.head.innerHTML=''+t,this.contentDocument.body.className="sun-editor-editable",this.contentDocument.body.setAttribute("contenteditable",!0)}))}else l.setAttribute("contenteditable",!0),l.setAttribute("scrolling","auto"),l.className+=" sun-editor-editable";l.style.height=e.height,l.style.minHeight=e.minHeight,l.style.maxHeight=e.maxHeight;const s=document.createElement("TEXTAREA");s.className="se-wrapper-inner se-wrapper-code",s.style.display="none",s.style.height=e.height,s.style.minHeight=e.minHeight,s.style.maxHeight=e.maxHeight,"auto"===e.height&&(s.style.overflow="hidden");let o=null,a=null,r=null;if(e.resizingBar&&(o=document.createElement("DIV"),o.className="se-resizing-bar sun-editor-common",a=document.createElement("DIV"),a.className="se-navigation sun-editor-common",o.appendChild(a),e.charCounter)){const t=document.createElement("DIV");if(t.className="se-char-counter-wrapper",r=document.createElement("SPAN"),r.className="se-char-counter",r.textContent="0",t.appendChild(r),e.maxCharCount>0){const i=document.createElement("SPAN");i.textContent=" / "+e.maxCharCount,t.appendChild(i)}o.appendChild(t)}let c=null;return e.placeholder&&(c=document.createElement("SPAN"),c.className="se-placeholder",c.innerText=e.placeholder),{bottomBar:{resizingBar:o,navigation:a,charCounter:r},wysiwygFrame:l,codeView:s,placeholder:c}},_initOptions:function(e,t){t.lang=t.lang||c.a,t._defaultTagsWhitelist="string"==typeof t._defaultTagsWhitelist?t._defaultTagsWhitelist:"br|p|div|pre|blockquote|h[1-6]|ol|ul|li|hr|figure|figcaption|img|iframe|audio|video|table|thead|tbody|tr|th|td|a|b|strong|var|i|em|u|ins|s|span|strike|del|sub|sup",t._editorTagsWhitelist=t._defaultTagsWhitelist+("string"==typeof t.addTagsWhitelist&&t.addTagsWhitelist.length>0?"|"+t.addTagsWhitelist:""),t.pasteTagsWhitelist="string"==typeof t.pasteTagsWhitelist?t.pasteTagsWhitelist:t._editorTagsWhitelist,t.attributesWhitelist=t.attributesWhitelist&&"object"==typeof t.attributesWhitelist?t.attributesWhitelist:null,t.mode=t.mode||"classic",t.toolbarWidth=t.toolbarWidth?u.isNumber(t.toolbarWidth)?t.toolbarWidth+"px":t.toolbarWidth:"auto",t.stickyToolbar=/balloon/i.test(t.mode)?-1:void 0===t.stickyToolbar?0:/^\d+/.test(t.stickyToolbar)?u.getNumber(t.stickyToolbar,0):-1,t.iframe=t.fullPage||t.iframe,t.iframeCSSFileName=t.iframe?"string"==typeof t.iframeCSSFileName?[t.iframeCSSFileName]:t.iframeCSSFileName||["suneditor"]:null,t.codeMirror=t.codeMirror?t.codeMirror.src?t.codeMirror:{src:t.codeMirror}:null,t.display=t.display||("none"!==e.style.display&&e.style.display?e.style.display:"block"),t.popupDisplay=t.popupDisplay||"full",t.resizingBar=void 0===t.resizingBar?!/inline|balloon/i.test(t.mode):t.resizingBar,t.showPathLabel=!!t.resizingBar&&("boolean"!=typeof t.showPathLabel||t.showPathLabel),t.charCounter=t.maxCharCount>0||"boolean"==typeof t.charCounter&&t.charCounter,t.maxCharCount=u.isNumber(t.maxCharCount)&&t.maxCharCount>-1?1*t.maxCharCount:null,t.width=t.width?u.isNumber(t.width)?t.width+"px":t.width:e.clientWidth?e.clientWidth+"px":"100%",t.minWidth=(u.isNumber(t.minWidth)?t.minWidth+"px":t.minWidth)||"",t.maxWidth=(u.isNumber(t.maxWidth)?t.maxWidth+"px":t.maxWidth)||"",t.height=t.height?u.isNumber(t.height)?t.height+"px":t.height:e.clientHeight?e.clientHeight+"px":"auto",t.minHeight=(u.isNumber(t.minHeight)?t.minHeight+"px":t.minHeight)||"",t.maxHeight=(u.isNumber(t.maxHeight)?t.maxHeight+"px":t.maxHeight)||"",t.font=t.font?t.font:null,t.fontSize=t.fontSize?t.fontSize:null,t.formats=t.formats?t.formats:null,t.colorList=t.colorList?t.colorList:null,t.lineHeights=t.lineHeights?t.lineHeights:null,t.paragraphStyles=t.paragraphStyles?t.paragraphStyles:null,t.textStyles=t.textStyles?t.textStyles:null,t.fontSizeUnit="string"==typeof t.fontSizeUnit&&t.fontSizeUnit.trim()||"px",t.imageResizing=void 0===t.imageResizing||t.imageResizing,t.imageHeightShow=void 0===t.imageHeightShow||!!t.imageHeightShow,t.imageWidth=t.imageWidth?u.isNumber(t.imageWidth)?t.imageWidth+"px":t.imageWidth:"auto",t.imageSizeOnlyPercentage=!!t.imageSizeOnlyPercentage,t._imageSizeUnit=t.imageSizeOnlyPercentage?"%":"px",t.imageRotation=void 0!==t.imageRotation?t.imageRotation:!(t.imageSizeOnlyPercentage||!t.imageHeightShow),t.imageFileInput=void 0===t.imageFileInput||t.imageFileInput,t.imageUrlInput=void 0===t.imageUrlInput||!t.imageFileInput||t.imageUrlInput,t.imageUploadHeader=t.imageUploadHeader||null,t.imageUploadUrl=t.imageUploadUrl||null,t.imageUploadSizeLimit=/\d+/.test(t.imageUploadSizeLimit)?u.getNumber(t.imageUploadSizeLimit,0):null,t.videoResizing=void 0===t.videoResizing||t.videoResizing,t.videoHeightShow=void 0===t.videoHeightShow||!!t.videoHeightShow,t.videoRatioShow=void 0===t.videoRatioShow||!!t.videoRatioShow,t.videoWidth=t.videoWidth&&u.getNumber(t.videoWidth)?u.isNumber(t.videoWidth)?t.videoWidth+"px":t.videoWidth:"100%",t.videoSizeOnlyPercentage=!!t.videoSizeOnlyPercentage,t._videoSizeUnit=t.videoSizeOnlyPercentage?"%":"px",t.videoRotation=void 0!==t.videoRotation?t.videoRotation:!(t.videoSizeOnlyPercentage||!t.videoHeightShow),t.videoRatio=u.getNumber(t.videoRatio,4)||.5625,t.videoRatioList=t.videoRatioList?t.videoRatioList:null,t.youtubeQuery=(t.youtubeQuery||"").replace("?",""),t.callBackSave=t.callBackSave?t.callBackSave:null,t.templates=t.templates?t.templates:null,t.placeholder="string"==typeof t.placeholder?t.placeholder:null,t.katex=t.katex?t.katex.src?t.katex:{src:t.katex}:null,t.buttonList=t.buttonList||[["undo","redo"],["bold","underline","italic","strike","subscript","superscript"],["removeFormat"],["outdent","indent"],["fullScreen","showBlocks","codeView"],["preview","print"]]},_defaultButtons:function(e){return{bold:["_se_command_bold",e.toolbar.bold+" (CTRL+B)","STRONG","",''],underline:["_se_command_underline",e.toolbar.underline+" (CTRL+U)","INS","",''],italic:["_se_command_italic",e.toolbar.italic+" (CTRL+I)","EM","",''],strike:["_se_command_strike",e.toolbar.strike+" (CTRL+SHIFT+S)","DEL","",''],subscript:["_se_command_subscript",e.toolbar.subscript,"SUB","",''],superscript:["_se_command_superscript",e.toolbar.superscript,"SUP","",''],removeFormat:["",e.toolbar.removeFormat,"removeFormat","",''],indent:["_se_command_indent",e.toolbar.indent+" (CTRL+])","indent","",''],outdent:["_se_command_outdent",e.toolbar.outdent+" (CTRL+[)","outdent","",'',!0],fullScreen:["code-view-enabled",e.toolbar.fullScreen,"fullScreen","",''],showBlocks:["",e.toolbar.showBlocks,"showBlocks","",''],codeView:["code-view-enabled",e.toolbar.codeView,"codeView","",''],undo:["_se_command_undo",e.toolbar.undo+" (CTRL+Z)","undo","",'',!0],redo:["_se_command_redo",e.toolbar.redo+" (CTRL+Y / CTRL+SHIFT+Z)","redo","",'',!0],preview:["",e.toolbar.preview,"preview","",''],print:["",e.toolbar.print,"print","",''],save:["_se_command_save",e.toolbar.save,"save","",'',!0],blockquote:["",e.toolbar.tag_blockquote,"blockquote","command",''],font:["se-btn-select se-btn-tool-font",e.toolbar.font,"font","submenu",''+e.toolbar.font+''],formatBlock:["se-btn-select se-btn-tool-format",e.toolbar.formats,"formatBlock","submenu",''+e.toolbar.formats+''],fontSize:["se-btn-select se-btn-tool-size",e.toolbar.fontSize,"fontSize","submenu",''+e.toolbar.fontSize+''],fontColor:["",e.toolbar.fontColor,"fontColor","submenu",''],hiliteColor:["",e.toolbar.hiliteColor,"hiliteColor","submenu",''],align:["se-btn-align",e.toolbar.align,"align","submenu",''],list:["",e.toolbar.list,"list","submenu",''],horizontalRule:["btn_line",e.toolbar.horizontalRule,"horizontalRule","submenu",''],table:["",e.toolbar.table,"table","submenu",''],lineHeight:["",e.toolbar.lineHeight,"lineHeight","submenu",''],template:["",e.toolbar.template,"template","submenu",''],paragraphStyle:["",e.toolbar.paragraphStyle,"paragraphStyle","submenu",''],textStyle:["",e.toolbar.textStyle,"textStyle","submenu",''],link:["",e.toolbar.link,"link","dialog",''],image:["",e.toolbar.image,"image","dialog",''],video:["",e.toolbar.video,"video","dialog",''],math:["",e.toolbar.math,"math","dialog",'']}},_createModuleGroup:function(e){const t=u.createElement("DIV");t.className="se-btn-module"+(e?"":" se-btn-module-border");const i=u.createElement("UL");return i.className="se-menu-list",t.appendChild(i),{div:t,ul:i}},_createButton:function(e,t,i,n,l,s){const o=u.createElement("LI"),a=u.createElement("BUTTON");return a.setAttribute("type","button"),a.setAttribute("class","se-btn"+(e?" "+e:"")+" se-tooltip"),a.setAttribute("data-command",i),a.setAttribute("data-display",n),l+=''+t+"",s&&a.setAttribute("disabled",!0),a.innerHTML=l,o.appendChild(a),{li:o,button:a}},_createToolBar:function(e,t,i,n){const l=e.createElement("DIV");l.className="se-toolbar-separator-vertical";const s=e.createElement("DIV");s.className="se-toolbar sun-editor-common";const o=this._defaultButtons(n),a={},r={};if(i){const e=i.length?i:Object.keys(i).map((function(e){return i[e]}));for(let t,i=0,n=e.length;i0){for(let e=0;e":i),this.history.push(!0)},_nativeFocus:function(){const t=r.getParentElement(this.getSelectionNode(),"figcaption");t?t.focus():e.element.wysiwyg.focus(),this._editorRange()},focus:function(){if("none"!==e.element.wysiwygFrame.style.display){if(l.iframe)this._nativeFocus();else try{const e=this.getRange();this.setRange(e.startContainer,e.startOffset,e.endContainer,e.endOffset)}catch(e){this._nativeFocus()}d._applyTagEffects(),c._isBalloon&&d._toggleToolbarBalloon()}},focusEdge:function(e){if(r.isComponent(e)){const t=e.querySelector("IMG"),i=e.querySelector("IFRAME");t?this.selectComponent(t,"image"):i&&this.selectComponent(i,"video")}else e=r.getChildElement(e,(function(e){return 0===e.childNodes.length||3===e.nodeType}),!0),this.setRange(e,e.textContent.length,e,e.textContent.length)},setRange:function(e,t,i,n){if(!e||!i)return;t>e.textContent.length&&(t=e.textContent.length),n>i.textContent.length&&(n=i.textContent.length);const l=this._wd.createRange();l.setStart(e,t),l.setEnd(i,n);const s=this.getSelection();s.removeAllRanges&&s.removeAllRanges(),s.addRange(l),this._editorRange()},removeRange:function(){this.getSelection().removeAllRanges();const e=this.commandMap;r.removeClass(e.STRONG,"active"),r.removeClass(e.INS,"active"),r.removeClass(e.EM,"active"),r.removeClass(e.DEL,"active"),r.removeClass(e.SUB,"active"),r.removeClass(e.SUP,"active"),e.OUTDENT&&e.OUTDENT.setAttribute("disabled",!0),e.INDENT&&e.INDENT.removeAttribute("disabled")},getRange:function(){return this._variable._range||this._createDefaultRange()},getSelection:function(){return this._ww.getSelection()},getSelectionNode:function(){return this._variable._selectionNode&&!r.isWysiwygDiv(this._variable._selectionNode)||this._editorRange(),this._variable._selectionNode||e.element.wysiwyg.firstChild},_editorRange:function(){const e=this.getSelection();let t=null,i=null;t=e.rangeCount>0?e.getRangeAt(0):this._createDefaultRange(),this._variable._range=t,i=t.collapsed?t.commonAncestorContainer:e.extentNode||e.anchorNode,this._variable._selectionNode=i},_createDefaultRange:function(){e.element.wysiwyg.focus();const t=this._wd.createRange();return e.element.wysiwyg.firstChild||this.execCommand("formatBlock",!1,"P"),t.setStart(e.element.wysiwyg.firstChild,0),t.setEnd(e.element.wysiwyg.firstChild,0),t},_resetRangeToTextNode:function(){const t=this.getRange();let i,n,l,s=t.startContainer,o=t.startOffset,a=t.endContainer,c=t.endOffset;if(i=r.isWysiwygDiv(s)?e.element.wysiwyg.firstChild:s,n=o,r.isBreak(i)||1===i.nodeType&&i.childNodes.length>0){const e=r.isBreak(i);if(!e){for(;i&&!r.isBreak(i)&&1===i.nodeType;)i=i.childNodes[n]||i.nextElementSibling||i.nextSibling,n=0;let e=r.getFormatElement(i);e===r.getRangeFormatElement(e)&&(e=r.createElement(r.isCell(i)?"DIV":"P"),i.parentNode.insertBefore(e,i),e.appendChild(i))}if(r.isBreak(i)){const t=r.createTextNode(r.zeroWidthSpace);i.parentNode.insertBefore(t,i),i=t,e&&(s===a&&(a=i,c=1),r.removeItem(s))}}if(s=i,o=n,i=r.isWysiwygDiv(a)?e.element.wysiwyg.lastChild:a,n=c,r.isBreak(i)||1===i.nodeType&&i.childNodes.length>0){const e=r.isBreak(i);if(!e){for(;i&&!r.isBreak(i)&&1===i.nodeType&&(l=i.childNodes,0!==l.length);)i=l[n>0?n-1:n]||!/FIGURE/i.test(l[0].nodeName)?l[0]:i.previousElementSibling||i.previousSibling||s,n=n>0?i.textContent.length:n;let e=r.getFormatElement(i);e===r.getRangeFormatElement(e)&&(e=r.createElement(r.isCell(e)?"DIV":"P"),i.parentNode.insertBefore(e,i),e.appendChild(i))}if(r.isBreak(i)){const t=r.createTextNode(r.zeroWidthSpace);i.parentNode.insertBefore(t,i),i=t,n=1,e&&r.removeItem(a)}}a=i,c=n,this.setRange(s,o,a,c)},getSelectedElements:function(t){this._resetRangeToTextNode();let i=this.getRange();if(r.isWysiwygDiv(i.startContainer)){const t=e.element.wysiwyg.children;if(0===t.length)return null;this.setRange(t[0],0,t[t.length-1],t[t.length-1].textContent.trim().length),i=this.getRange()}const n=i.startContainer,l=i.endContainer,s=i.commonAncestorContainer,o=r.getListChildren(s,(function(e){return t?t(e):r.isFormatElement(e)}));if(r.isWysiwygDiv(s)||r.isRangeFormatElement(s)||o.unshift(r.getFormatElement(s)),n===l||1===o.length)return o;let a=r.getFormatElement(n),c=r.getFormatElement(l),d=null,u=null;const h=function(e){return!r.isTable(e)||/^TABLE$/i.test(e.nodeName)};let p=r.getRangeFormatElement(a,h),g=r.getRangeFormatElement(c,h);r.isTable(p)&&r.isListCell(p.parentNode)&&(p=p.parentNode),r.isTable(g)&&r.isListCell(g.parentNode)&&(g=g.parentNode);const m=p===g;for(let e,t=0,i=o.length;t=0;i--)if(n[i].contains(n[e])){n.splice(e,1),e--,t--;break}return n},isEdgePoint:function(e,t){return 0===t||!e.nodeValue&&1===t||t===e.nodeValue.length},showLoading:function(){e.element.loading.style.display="block"},closeLoading:function(){e.element.loading.style.display="none"},appendFormatTag:function(e,t){const i=r.getFormatElement(this.getSelectionNode()),n=t?"string"==typeof t?t:t.nodeName:r.isFormatElement(i)?i.nodeName:"P",l=r.createElement(n);return l.innerHTML="
    ",(t&&"string"!=typeof t||!t&&r.isFormatElement(i))&&r.copyTagAttributes(l,t||i),r.isCell(e)?e.insertBefore(l,e.nextElementSibling):e.parentNode.insertBefore(l,e.nextElementSibling),l},insertComponent:function(e,t){const i=this.removeNode();let n=null,l=this.getSelectionNode(),s=r.getFormatElement(l);if(r.isListCell(s))if(/^HR$/i.test(e.nodeName)){const t=r.createElement("LI"),i=r.createTextNode(r.zeroWidthSpace);t.appendChild(e),t.appendChild(i),s.parentNode.insertBefore(t,s.nextElementSibling),this.setRange(i,1,i,1)}else this.insertNode(e,l===s?null:i.container.nextSibling),e.nextSibling||e.parentNode.appendChild(r.createElement("BR")),n=r.createElement("LI"),s.parentNode.insertBefore(n,s.nextElementSibling);else{if(this.getRange().collapsed&&3===i.container.nodeType){const e=r.getParentElement(i.container,function(e){return this.isRangeFormatElement(e)}.bind(r));n=r.splitElement(i.container,i.offset,e?r.getElementDepth(e)+1:0),s=n.previousSibling}this.insertNode(e,s),n||(n=this.appendFormatTag(e,r.isFormatElement(s)?s:null))}return t||this.history.push(!1),n},selectComponent:function(e,t){if("image"===t){if(!c.plugins.image)return;c.removeRange(),c.callPlugin("image",(function(){const t=c.plugins.resizing.call_controller_resize.call(c,e,"image");c.plugins.image.onModifyMode.call(c,e,t),r.getParentElement(e,".se-image-container")||(c.plugins.image.openModify.call(c,!0),c.plugins.image.update_image.call(c,!0,!0,!0))}))}else if("video"===t){if(!c.plugins.video)return;c.removeRange(),c.callPlugin("video",(function(){const t=c.plugins.resizing.call_controller_resize.call(c,e,"video");c.plugins.video.onModifyMode.call(c,e,t)}))}},insertNode:function(e,t){const i=this.getRange();let n=null;if(t)n=t.parentNode,t=t.nextSibling;else{const e=i.startContainer,l=i.startOffset,s=i.endContainer,o=i.endOffset,a=i.commonAncestorContainer;if(n=e,3===e.nodeType&&(n=e.parentNode),i.collapsed)if(3===a.nodeType)t=a.textContent.length>o?a.splitText(o):a.nextSibling;else if(r.isBreak(n))t=n,n=n.parentNode;else{const e=n.childNodes[l];e?e.nextSibling?t=r.isBreak(e)?e.nextSibling:e:(n.removeChild(e),t=null):t=null}else{if(e===s){t=this.isEdgePoint(s,o)?s.nextSibling:s.splitText(o);let i=e;this.isEdgePoint(e,l)||(i=e.splitText(l)),n.removeChild(i)}else for(this.removeNode(),n=a,t=s;t.parentNode!==a;)t=t.parentNode}}try{if(r.isFormatElement(e)||r.isRangeFormatElement(e)||!r.isListCell(n)&&r.isComponent(e))if(r.isList(t))n=t,t=null;else if(!t){const e=this.removeNode(),i=3===e.container.nodeType?r.isListCell(r.getFormatElement(e.container))?e.container:r.getFormatElement(e.container)||e.container.parentNode:e.container;n=i.parentNode,t=i.nextSibling}n.insertBefore(e,t)}catch(t){n.appendChild(e)}finally{if(3===e.nodeType){const t=e.previousSibling,i=e.nextSibling,n=!t||3!==t.nodeType||r.onlyZeroWidthSpace(t)?"":t.textContent,l=!i||3!==i.nodeType||r.onlyZeroWidthSpace(i)?"":i.textContent;return t&&n.length>0&&(e.textContent=n+e.textContent,r.removeItem(t)),i&&i.length>0&&(e.textContent+=l,r.removeItem(i)),{startOffset:n.length,endOffset:e.textContent.length-l.length}}this.setRange(e,1,e,1),this.history.push(!0)}},removeNode:function(){const e=this.getRange();let t,i=0,n=e.startContainer,l=e.endContainer;const s=e.startOffset,o=e.endOffset,a=e.commonAncestorContainer;let c=null,d=null;const u=r.getListChildNodes(a);let h=r.getArrayIndex(u,n),p=r.getArrayIndex(u,l);if(u.length>0&&h>-1&&p>-1){for(let e=h+1,t=n;e>=0;e--)u[e]===t.parentNode&&u[e].firstChild===t&&0===s&&(h=e,t=t.parentNode);for(let e=p-1,t=l;e>h;e--)u[e]===t.parentNode&&1===u[e].nodeType&&(u.splice(e,1),t=t.parentNode,--p)}else{if(0===u.length)u.push(a),n=l=a;else if(n=l=u[0],r.isBreak(n))return{container:n,offset:0};h=p=0}function g(e){const t=r.getFormatElement(e);if(r.removeItem(e),r.isListCell(t)){const e=r.getArrayItem(t.children,r.isList,!1);if(e){const i=e.firstElementChild,n=i.childNodes;for(;n[0];)t.insertBefore(n[0],e);r.removeItemAllParents(i)}}}for(let e=h;e<=p;e++){const t=u[e];if(0===t.length||3===t.nodeType&&void 0===t.data)g(t);else if(t!==n)t!==l?g(t):(d=1===l.nodeType?r.createTextNode(l.textContent):r.createTextNode(l.substringData(o,l.length-o)),d.length>0?l.data=d.data:g(l));else if(1===n.nodeType?c=r.createTextNode(n.textContent):t===l?(c=r.createTextNode(n.substringData(0,s)+l.substringData(o,l.length-o)),i=s):c=r.createTextNode(n.substringData(0,s)),c.length>0?n.data=c.data:g(n),t===l)break}return t=l&&l.parentNode?l:n&&n.parentNode?n:e.endContainer||e.startContainer,this.setRange(t,i,t,i),this.history.push(!0),{container:t,offset:i}},applyRangeFormatElement:function(e){const t=this.getSelectedElementsAndComponents(!1);if(!t||0===t.length)return;e:for(let e,i,n,l,s,o,a=0,c=t.length;a-1&&(l=i.lastElementChild,t.indexOf(l)>-1)){let e=null;for(;e=l.lastElementChild;)if(r.isList(e)){if(!(t.indexOf(e.lastElementChild)>-1))continue e;l=e.lastElementChild}n=i.firstElementChild,s=t.indexOf(n),o=t.indexOf(l),t.splice(s,o-s+1),c=t.length}else;let i,n,l,s=t[t.length-1];i=r.isRangeFormatElement(s)||r.isFormatElement(s)?s:r.getRangeFormatElement(s)||r.getFormatElement(s),r.isCell(i)?(n=null,l=i):(n=i.nextSibling,l=i.parentNode);let o=r.getElementDepth(i),a=null;const d=[],u=function(e,t,i){let n=null;if(e!==t&&!r.isTable(t)){if(t&&r.getElementDepth(e)===r.getElementDepth(t))return i;n=r.removeItemAllParents(t,null,e)}return n?n.ec:i};for(let i,s,c,h,p,g,m,f=0,_=t.length;f<_;f++)if(i=t[f],s=i.parentNode,s&&!e.contains(s))if(c=r.getElementDepth(i),r.isList(s)){if(null===a&&(g?(a=g,m=!0,g=null):a=s.cloneNode(!1)),d.push(i),p=t[f+1],f===_-1||p&&p.parentNode!==s){p&&i.contains(p.parentNode)&&(g=p.parentNode.cloneNode(!1));let t,f=s.parentNode;for(;r.isList(f);)t=r.createElement(f.nodeName),t.appendChild(a),a=t,f=f.parentNode;const _=this.detachRangeFormatElement(s,d,null,!0,!0);o>=c?(o=c,l=_.cc,n=u(l,s,_.ec),n&&(l=n.parentNode)):l===_.cc&&(n=_.ec),l!==_.cc&&(h=u(l,_.cc,h),n=void 0!==h?h:_.cc);for(let e=0,t=_.removeArray.length;e=c&&(o=c,l=s,n=i.nextSibling),e.appendChild(i),l!==s&&(h=u(l,s),void 0!==h&&(n=h));if(c._lastEffectNode=null,r.mergeSameTags(e,null,null,!1),r.mergeNestedTags(e,function(e){return this.isList(e)}.bind(r)),n&&r.getElementDepth(n)>0&&(r.isList(n.parentNode)||r.isList(n.parentNode.parentNode))){const t=r.getParentElement(n,function(e){return this.isRangeFormatElement(e)&&!this.isList(e)}.bind(r)),i=r.splitElement(n,null,t?r.getElementDepth(t)+1:0);i.parentNode.insertBefore(e,i)}else l.insertBefore(e,n),u(e,n);const h=r.getEdgeChildNodes(e.firstElementChild,e.lastElementChild);t.length>1?this.setRange(h.sc,0,h.ec,h.ec.textContent.length):this.setRange(h.ec,h.ec.textContent.length,h.ec,h.ec.textContent.length),this.history.push(!1)},detachRangeFormatElement:function(e,t,i,n,l){const s=this.getRange(),o=s.startOffset,a=s.endOffset;let u=r.getListChildNodes(e,(function(t){return t.parentNode===e})),h=e.parentNode,p=null,g=null,m=e.cloneNode(!1);const f=[],_=r.isList(i);let b=!1,y=!1,v=!1;function x(t,i,n,l){if(r.onlyZeroWidthSpace(i)&&(i.innerHTML=r.zeroWidthSpace),3===i.nodeType)return t.insertBefore(i,n),i;const s=(v?i:l).childNodes;let o=i.cloneNode(!1),a=null,c=null;for(;s[0];)c=s[0],!r._notTextNode(c)||r.isBreak(c)||r.isListCell(o)?o.appendChild(c):(o.childNodes.length>0&&(a||(a=o),t.insertBefore(o,n),o=i.cloneNode(!1)),t.insertBefore(c,n),a||(a=c));if(o.childNodes.length>0){if(r.isListCell(t)&&r.isListCell(o)&&r.isList(n))if(_){for(a=n;n;)o.appendChild(n),n=n.nextSibling;t.parentNode.insertBefore(o,t.nextElementSibling)}else{const t=l.nextElementSibling,i=r.detachNestedList(l,!1);e===i&&t===l.nextElementSibling||(e=i,y=!0)}else t.insertBefore(o,n);a||(a=o)}return a}for(let l,s,o,a=0,c=u.length;a0&&(h.insertBefore(m,e),m=null),!_&&r.isListCell(l))if(r.getElementDepth(l)!==r.getElementDepth(o)&&(r.isListCell(h)||r.getArrayItem(l.children,r.isList,!1))){const t=l.nextElementSibling,i=r.detachNestedList(l,!1);e===i&&t===l.nextElementSibling||(e=i,y=!0)}else{const t=l;l=r.createElement(n?t.nodeName:r.isList(e.parentNode)||r.isListCell(e.parentNode)?"LI":r.isCell(e.parentNode)?"DIV":"P");const i=t.childNodes;for(;i[0];)l.appendChild(i[0]);r.copyFormatAttributes(l,t),v=!0}else l=l.cloneNode(!1);if(y){y=v=!1,u=r.getListChildNodes(e,(function(t){return t.parentNode===e})),m=e.cloneNode(!1),h=e.parentNode,a=-1,c=u.length;continue}n?(f.push(l),r.removeItem(u[a])):(i?(b||(h.insertBefore(i,e),b=!0),l=x(i,l,null,u[a])):l=x(h,l,e,u[a]),t?(g=l,p||(p=l)):p||(p=g=l))}const C=e.parentNode;let w=e.nextSibling;m&&m.children.length>0&&C.insertBefore(m,w),i?p=i.previousSibling:p||(p=e.previousSibling),w=e.nextSibling,r.removeItem(e);let N=null;if(n)N={cc:C,sc:p,ec:w,removeArray:f};else{const e=r.getEdgeChildNodes(p,g&&g.parentNode?g:p);N={cc:(e.sc||e.ec).parentNode,sc:e.sc,ec:e.ec}}if(c._lastEffectNode=null,l)return N;!n&&N&&(t?this.setRange(N.sc,o,N.ec,a):this.setRange(N.sc,0,N.sc,0)),this.history.push(!1),d._applyTagEffects()},detachList:function(e,t){let i={},n=!1,l=!1,s=null,o=null;const a=function(e){return!this.isComponent(e)}.bind(r);for(let c,d,u,h,p=0,g=e.length;p0)&&t,i=!!(i&&i.length>0)&&i;const s=!e,o=s&&!i&&!t;let c=l.startContainer,d=l.startOffset,u=l.endContainer,h=l.endOffset;if(o&&l.collapsed&&r.isFormatElement(c.parentNode)&&r.isFormatElement(u.parentNode)||c===u&&1===c.nodeType&&"false"===c.getAttribute("contenteditable"))return;if(l.collapsed&&1===c.nodeType&&!r.isBreak(c)){let e=null;const t=c.childNodes[d];t&&(t.nextSibling?e=r.isBreak(t)?t.nextSibling:t:(c.removeChild(t),e=null));const i=r.createTextNode(r.zeroWidthSpace);c.insertBefore(i,e),this.setRange(i,1,i,1),l=this.getRange(),c=l.startContainer,d=l.startOffset,u=l.endContainer,h=l.endOffset}s&&(e=r.createElement("DIV"));const p=e.nodeName;if(!o&&c===u&&!i&&e){let t=c,i=0;const n=[],l=e.style;for(let e=0,t=l.length;e0){for(;!r.isFormatElement(t)&&!r.isWysiwygDiv(t);){for(let l=0;l=n.length)return}}let g,m={},f={},_="",b="",y="";if(t){for(let e,i=0,n=t.length;i0&&(c=l.replace(_,"").trim(),c!==l&&(v.v=!0));const d=t.className;let u="";return b&&d.length>0&&(u=d.replace(b,"").trim(),u!==d&&(v.v=!0)),(!s||!b&&d||!_&&l||c||u||!i)&&(c||u||t.nodeName!==p||a.Boolean(_)!==a.Boolean(l)||a.Boolean(b)!==a.Boolean(d))?(_&&l.length>0&&(t.style.cssText=c),t.style.cssText||t.removeAttribute("style"),b&&d.length>0&&(t.className=u.trim()),t.className.trim()||t.removeAttribute("class"),t.style.cssText||t.className||t.nodeName!==p&&!i?t:(v.v=!0,null)):(v.v=!0,null)},C=this.getSelectedElements();r.getFormatElement(c)||(c=r.getChildElement(C[0],(function(e){return 3===e.nodeType})),d=0),r.getFormatElement(u)||(u=r.getChildElement(C[C.length-1],(function(e){return 3===e.nodeType})),h=u.textContent.length);const w=r.getFormatElement(c)===r.getFormatElement(u),N=C.length-(w?0:1);g=e.cloneNode(!1);const E=o||s&&function(e,t){for(let i=0,n=e.length;i0&&(g=e.cloneNode(!1),f=this._nodeChange_endLine(C[N],g,x,u,h,o,s,v,S,k));for(let t=N-1;t>0;t--)g=e.cloneNode(!1),this._nodeChange_middleLine(C[t],g,x,o,s,v);g=e.cloneNode(!1),m=this._nodeChange_startLine(C[0],g,x,c,d,o,s,v,S,k),N<=0&&(f=m)}this.controllersOff(),this.setRange(m.container,m.offset,f.container,f.offset),this.history.push(!1)},_stripRemoveNode:function(e){const t=e.parentNode;if(!e||3===e.nodeType||!t)return;const i=e.childNodes;for(;i[0];)t.insertBefore(i[0],e);t.removeChild(e)},_util_getMaintainedNode:function(e,t){return t&&!e?this.getParentElement(t,function(e){return this._isMaintainedNode(e)}.bind(this)):null},_util_isMaintainedNode:function(e,t){return t&&!e&&3!==t.nodeType&&this._isMaintainedNode(t)},_nodeChange_oneLine:function(e,t,i,n,l,s,o,c,d,u,h,p,g){let m=n.parentNode;for(;!(m.nextSibling||m.previousSibling||r.isFormatElement(m.parentNode)||r.isWysiwygDiv(m.parentNode))&&m.nodeName!==t.nodeName;)m=m.parentNode;if(!d&&m===s.parentNode&&m.nodeName===t.nodeName&&r.onlyZeroWidthSpace(n.textContent.slice(0,l))&&r.onlyZeroWidthSpace(s.textContent.slice(o))){const e=m.childNodes;let i=!0;for(let t,l,o,a,c=0,d=e.length;c0&&(i=t.test(e.style.cssText)),!i}if(function e(n,l){const s=n.childNodes;for(let n,o=0,a=s.length;o=S?T-S:E.data.length-S));if(N){const t=p(l);if(t&&t.parentNode!==e){let i=t,n=null;for(;i.parentNode!==e;){for(l=n=i.parentNode.cloneNode(!1);i.childNodes[0];)n.appendChild(i.childNodes[0]);i.appendChild(n),i=i.parentNode}i.parentNode.appendChild(t)}N=N.cloneNode(!1)}r.onlyZeroWidthSpace(s)||l.appendChild(s);const a=p(l);for(a&&(N=a),N&&(e=N),x=d,v=[],w="";x!==e&&x!==f&&null!==x;)n=g(x)?null:i(x),n&&1===x.nodeType&&A(x)&&(v.push(n),w+=x.style.cssText.substr(0,x.style.cssText.indexOf(":"))+"|"),x=x.parentNode;const c=v.pop()||o;for(C=x=c;v.length>0;)x=v.pop(),C.appendChild(x),C=x;if(t.appendChild(c),e.appendChild(t),N&&!p(k)&&(t=t.cloneNode(!1),b.appendChild(t),_.push(t)),E=o,S=0,z=!0,x!==o&&x.appendChild(E),!y)continue}if(L||d!==k){if(z){if(1===d.nodeType&&!r.isBreak(d)){r._isIgnoreNodeChange(d)?(b.appendChild(d),o--,a--,u||(t=t.cloneNode(!1),b.appendChild(t),_.push(t))):e(d,d);continue}x=d,v=[],w="";const s=[];for(;null!==x.parentNode&&x!==f&&x!==t;)n=L?x.cloneNode(!1):i(x),1===x.nodeType&&!r.isBreak(d)&&n&&A(x)&&(n&&(g(n)?N||s.push(n):v.push(n)),w+=x.style.cssText.substr(0,x.style.cssText.indexOf(":"))+"|"),x=x.parentNode;v=v.concat(s);const c=v.pop()||d;for(C=x=c;v.length>0;)x=v.pop(),C.appendChild(x),C=x;if(g(t.parentNode)&&!g(c)&&(t=t.cloneNode(!1),b.appendChild(t),_.push(t)),L||N||!g(c))c===d?l=L?b:t:L?(b.appendChild(c),l=x):(t.appendChild(c),l=x);else{t=t.cloneNode(!1);const e=c.childNodes;for(let i=0,n=e.length;i0?x:t}if(N&&3===d.nodeType)if(p(d)){const e=r.getParentElement(l,function(e){return this._isMaintainedNode(e.parentNode)||e.parentNode===b}.bind(r));N.appendChild(e),t=e.cloneNode(!1),_.push(t),b.appendChild(t)}else N=null}h=d.cloneNode(!1),l.appendChild(h),1!==d.nodeType||r.isBreak(d)||(m=h),e(d,m)}else{N=p(d);const e=r.createTextNode(1===k.nodeType?"":k.substringData(T,k.length-T)),l=r.createTextNode(y||1===k.nodeType?"":k.substringData(0,T));if(N?N=N.cloneNode(!1):g(t.parentNode)&&!N&&(t=t.cloneNode(!1),b.appendChild(t),_.push(t)),!r.onlyZeroWidthSpace(e)){x=d,w="",v=[];const t=[];for(;x!==b&&x!==f&&null!==x;)1===x.nodeType&&A(x)&&(g(x)?t.push(x.cloneNode(!1)):v.push(x.cloneNode(!1)),w+=x.style.cssText.substr(0,x.style.cssText.indexOf(":"))+"|"),x=x.parentNode;for(v=v.concat(t),h=C=x=v.pop()||e;v.length>0;)x=v.pop(),C.appendChild(x),C=x;b.appendChild(h),x.textContent=e.data}if(N&&h){const e=p(h);e&&(N=e)}for(x=d,v=[],w="";x!==b&&x!==f&&null!==x;)n=g(x)?null:i(x),n&&1===x.nodeType&&A(x)&&(v.push(n),w+=x.style.cssText.substr(0,x.style.cssText.indexOf(":"))+"|"),x=x.parentNode;const s=v.pop()||l;for(C=x=s;v.length>0;)x=v.pop(),C.appendChild(x),C=x;N?((t=t.cloneNode(!1)).appendChild(s),N.insertBefore(t,N.firstChild),b.appendChild(N),_.push(t),N=null):t.appendChild(s),k=l,T=l.data.length,L=!0,!c&&u&&(t=l,l.textContent=r.zeroWidthSpace),x!==l&&x.appendChild(k)}}}(e,b),d&&!c&&!h.v)return{startContainer:n,startOffset:l,endContainer:s,endOffset:o};if(c=c&&d)for(let e=0;e<_.length;e++){let t=_[e],i=r.createTextNode(u?r.zeroWidthSpace:t.textContent);b.replaceChild(i,t),0===e&&(E=k=i)}else{if(d)for(let e=0;e<_.length;e++)this._stripRemoveNode(_[e]);u&&(E=k=t)}r.removeEmptyNode(b,t),u&&(S=E.textContent.length,T=k.textContent.length);const B=c||0===k.textContent.length;0===k.textContent.length&&(r.removeItem(k),k=E),T=B?k.textContent.length:T;const I={s:0,e:0},R=r.getNodePath(E,b,I),D=!k.parentNode;D&&(k=E);const M={s:0,e:0},O=r.getNodePath(k,b,D||B?null:M);S+=I.s,T=u?S:D?E.textContent.length:B?T+I.s:T+M.s;const P=r.mergeSameTags(b,R,O,!0);return e.parentNode.replaceChild(b,e),E=r.getNodeFromPath(R,b),k=r.getNodeFromPath(O,b),{startContainer:E,startOffset:S+P.a,endContainer:k,endOffset:T+P.b}},_nodeChange_startLine:function(e,t,i,n,l,s,o,a,c,d){let u=n.parentNode;for(;!(u.nextSibling||u.previousSibling||r.isFormatElement(u.parentNode)||r.isWysiwygDiv(u.parentNode))&&u.nodeName!==t.nodeName;)u=u.parentNode;if(!o&&u.nodeName===t.nodeName&&!r.isFormatElement(u)&&!u.nextSibling&&r.onlyZeroWidthSpace(n.textContent.slice(0,l))){let e=!0,i=n.previousSibling;for(;i;){if(!r.onlyZeroWidthSpace(i)){e=!1;break}i=i.previousSibling}if(e)return r.copyTagAttributes(u,t),{container:n,offset:l}}a.v=!1;const h=e,p=[t],g=e.cloneNode(!1);let m,f,_,b,y=n,v=l,x=!1;if(function e(n,l){const s=n.childNodes;for(let n,o=0,a=s.length;o0,v=m.pop()||u;for(_=f=v;m.length>0;)f=m.pop(),_.appendChild(f),_=f;if(d(t.parentNode)&&!d(v)&&(t=t.cloneNode(!1),g.appendChild(t),p.push(t)),!b&&d(v)){t=t.cloneNode(!1);const e=v.childNodes;for(let i=0,n=e.length;i0;)f=m.pop(),_.appendChild(f),_=f;d!==l?(t.appendChild(d),l=f):l=t,r.isBreak(u)&&t.appendChild(u.cloneNode(!1)),e.appendChild(t),y=o,v=0,x=!0,l.appendChild(y)}}}(e,g),o&&!s&&!a.v)return{container:n,offset:l};if(s=s&&o)for(let e=0;e0&&c===d)return void(e.innerHTML=i.innerHTML)}s.v=!1;const o=e.cloneNode(!1),a=[t];let c=!0;if(function e(n,l){const s=n.childNodes;for(let n,d=0,u=s.length;d0&&(o.appendChild(t),t=t.cloneNode(!1)),o.appendChild(h),o.appendChild(t),a.push(t),l=t,d--,u--)}}(e,t),!c&&(!l||n||s.v)){if(o.appendChild(t),n&&l)for(let e=0;e0,y=m.pop()||a;for(_=f=y;m.length>0;)f=m.pop(),_.appendChild(f),_=f;if(d(t.parentNode)&&!d(y)&&(t=t.cloneNode(!1),g.insertBefore(t,g.firstChild),p.push(t)),!b&&d(y)){t=t.cloneNode(!1);const e=y.childNodes;for(let i=0,n=e.length;i0?f:t}else u?(t.insertBefore(y,t.firstChild),l=f):l=t;if(b&&3===a.nodeType)if(c(a)){const e=r.getParentElement(l,function(e){return this._isMaintainedNode(e.parentNode)||e.parentNode===g}.bind(r));b.appendChild(e),t=e.cloneNode(!1),p.push(t),g.insertBefore(t,g.firstChild)}else b=null}if(x||a!==y)n=x?i(a):a.cloneNode(!1),n&&(l.insertBefore(n,l.firstChild),1!==a.nodeType||r.isBreak(a)||(u=n)),e(a,u);else{b=c(a);const e=r.createTextNode(1===y.nodeType?"":y.substringData(v,y.length-v)),s=r.createTextNode(1===y.nodeType?"":y.substringData(0,v));if(b){b=b.cloneNode(!1);const e=c(l);if(e&&e.parentNode!==g){let t=e,i=null;for(;t.parentNode!==g;){for(l=i=t.parentNode.cloneNode(!1);t.childNodes[0];)i.appendChild(t.childNodes[0]);t.appendChild(i),t=t.parentNode}t.parentNode.insertBefore(e,t.parentNode.firstChild)}b=b.cloneNode(!1)}else d(t.parentNode)&&!b&&(t=t.cloneNode(!1),g.appendChild(t),p.push(t));for(r.onlyZeroWidthSpace(e)||l.insertBefore(e,l.firstChild),f=l,m=[];f!==g&&null!==f;)n=d(f)?null:i(f),n&&1===f.nodeType&&m.push(n),f=f.parentNode;const o=m.pop()||l;for(_=f=o;m.length>0;)f=m.pop(),_.appendChild(f),_=f;o!==l?(t.insertBefore(o,t.firstChild),l=f):l=t,r.isBreak(a)&&t.appendChild(a.cloneNode(!1)),b?(b.insertBefore(t,b.firstChild),g.insertBefore(b,g.firstChild),b=null):g.insertBefore(t,g.firstChild),y=s,v=s.data.length,x=!0,l.insertBefore(y,l.firstChild)}}}(e,g),o&&!s&&!a.v)return{container:n,offset:l};if(s=s&&o)for(let e=0;e0&&c.plugins.list.editInsideList.call(c,n,i),this._lastEffectNode=null,d._applyTagEffects(),this.history.push(!1)},toggleDisplayBlocks:function(){r.toggleClass(e.element.wysiwyg,"se-show-block"),this._resourcesStateChange()},toggleCodeView:function(){const t=this._variable.isCodeView,i=this.codeViewDisabledButtons;for(let e=0,n=i.length;e0?e.element.code.scrollHeight+"px":"auto"),l.codeMirrorEditor&&l.codeMirrorEditor.refresh(),this._variable.isCodeView=!0,this._variable.isFullScreen||(this._notHideToolbar=!0,this._isBalloon&&(e.element._arrow.style.display="none",e.element.toolbar.style.left="",this._isInline=!0,this._isBalloon=!1,d._showToolbarInline())),this._variable._range=null,e.element.code.focus()),this._checkPlaceholder()},_setCodeDataToEditor:function(){const t=this._getCodeView();if(l.fullPage){const e=(new this._w.DOMParser).parseFromString(t,"text/html"),i=e.head.children;for(let t=0,n=i.length;t0?this.convertContentsForEditor(t):"


    "},_setEditorDataToCodeView:function(){const t=this.convertHTMLForCodeView(e.element.wysiwyg);let i="";if(l.fullPage){const e=r.getAttributesToString(this._wd.body,null);i="\n\n"+this._wd.head.outerHTML.replace(/>(?!\n)/g,">\n")+"\n"+t+"\n"}else i=t;e.element.code.style.display="block",e.element.wysiwygFrame.style.display="none",this._setCodeView(i)},toggleFullScreen:function(t){const i=e.element.topArea,n=e.element.toolbar,o=e.element.editorArea,c=e.element.wysiwygFrame,u=e.element.code,h=this._variable;h.isFullScreen?(h.isFullScreen=!1,c.style.cssText=h._wysiwygOriginCssText,u.style.cssText=h._codeOriginCssText,n.style.cssText="",o.style.cssText=h._editorAreaOriginCssText,i.style.cssText=h._originCssText,s.body.style.overflow=h._bodyOverflow,l.stickyToolbar>-1&&r.removeClass(n,"se-toolbar-sticky"),h._fullScreenAttrs.sticky&&(h._fullScreenAttrs.sticky=!1,e.element._stickyDummy.style.display="block",r.addClass(n,"se-toolbar-sticky")),this._isInline=h._fullScreenAttrs.inline,this._isBalloon=h._fullScreenAttrs.balloon,this._isInline&&d._showToolbarInline(),d.onScroll_window(),r.removeClass(t.firstElementChild,"se-icon-reduction"),r.addClass(t.firstElementChild,"se-icon-expansion")):(h.isFullScreen=!0,h._fullScreenAttrs.inline=this._isInline,h._fullScreenAttrs.balloon=this._isBalloon,(this._isInline||this._isBalloon)&&(this._isInline=!1,this._isBalloon=!1),i.style.position="fixed",i.style.top="0",i.style.left="0",i.style.width="100%",i.style.height="100%",i.style.zIndex="2147483647",""!==e.element._stickyDummy.style.display&&(h._fullScreenAttrs.sticky=!0,e.element._stickyDummy.style.display="none",r.removeClass(n,"se-toolbar-sticky")),h._bodyOverflow=s.body.style.overflow,s.body.style.overflow="hidden",h._editorAreaOriginCssText=o.style.cssText,h._wysiwygOriginCssText=c.style.cssText,h._codeOriginCssText=u.style.cssText,o.style.cssText=n.style.cssText="",c.style.cssText=(c.style.cssText.match(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/)||[""])[0],u.style.cssText=(u.style.cssText.match(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/)||[""])[0],n.style.width=c.style.height=u.style.height="100%",n.style.position="relative",n.style.display="block",h.innerHeight_fullScreen=a.innerHeight-n.offsetHeight,o.style.height=h.innerHeight_fullScreen+"px",r.removeClass(t.firstElementChild,"se-icon-expansion"),r.addClass(t.firstElementChild,"se-icon-reduction"),l.iframe&&"auto"===l.height&&(o.style.overflow="auto",this._iframeAutoHeight()))},print:function(){const t=r.createElement("IFRAME");t.style.display="none",s.body.appendChild(t);const i=r.getIframeDocument(t),n=this.getContents(!0);if(l.iframe){const t=r.getIframeDocument(e.element.wysiwygFrame),s=l.fullPage?r.getAttributesToString(t.body,["contenteditable"]):'class="sun-editor-editable"';i.write(""+t.head.innerHTML+""+n+"")}else{const e=r.createElement("DIV"),t=r.createElement("STYLE");t.innerHTML=r.getPageStyle(),e.className="sun-editor-editable",e.innerHTML=n,i.head.appendChild(t),i.body.appendChild(e)}try{if(t.focus(),-1!==a.navigator.userAgent.indexOf("MSIE")||s.documentMode||a.StyleMedia)try{t.contentWindow.document.execCommand("print",!1,null)}catch(e){t.contentWindow.print()}else t.contentWindow.print()}catch(e){throw Error("[SUNEDITOR.core.print.fail] error: "+e)}finally{r.removeItem(t)}},preview:function(){const t=this.getContents(!0),i=a.open("","_blank");if(i.mimeType="text/html",l.iframe){const n=r.getIframeDocument(e.element.wysiwygFrame),s=l.fullPage?r.getAttributesToString(n.body,["contenteditable"]):'class="sun-editor-editable"';i.document.write(""+n.head.innerHTML+""+t+"")}else i.document.write(''+n.toolbar.preview+"'+t+"")},setContents:function(t){const i=this.convertContentsForEditor(t);if(this._resetComponents(),c._variable.isCodeView){const e=this.convertHTMLForCodeView(i);c._setCodeView(e)}else e.element.wysiwyg.innerHTML=i,c.history.push(!1)},getContents:function(t){const i=e.element.wysiwyg.innerHTML,n=r.createElement("DIV");n.innerHTML=i;const s=r.getListChildren(n,(function(e){return/FIGCAPTION/i.test(e.nodeName)}));for(let e=0,t=s.length;e"+this._wd.head.outerHTML+""+n.innerHTML+""}return n.innerHTML},cleanHTML:function(e,t){const i=new this._w.RegExp("^(meta|script|link|style|[a-z]+:[a-z]+)$","i"),n=this._d.createRange().createContextualFragment(e).childNodes;let l="";for(let e=0,t=n.length;e(\n|.)*<\/(script|style)>/g,"").replace(/(<[a-zA-Z0-9]+)[^>]*(?=>)/g,function(e,t){let i=null;const n=this._attributesTagsWhitelist[t.match(/(?!<)[a-zA-Z]+/)[0].toLowerCase()];if(i=n?e.match(n):e.match(this._attributesWhitelistRegExp),i)for(let e=0,n=i.length;e^<]*)>/g,""),r._tagConvertor(l?t?l.replace("string"==typeof t?r.createTagsWhitelist(t):t,""):l:e)},addDocEvent:function(e,t,i){s.addEventListener(e,t,i),l.iframe&&this._wd.addEventListener(e,t)},removeDocEvent:function(e,t){s.removeEventListener(e,t),l.iframe&&this._wd.removeEventListener(e,t)},convertContentsForEditor:function(e){let t="",i=this._d.createRange().createContextualFragment(e).childNodes;for(let e,n=0,l=i.length;n0&&(t+="

    "+n+"

    ")}else t+=e.replace(/<(?!span|font|b|strong|var|i|em|u|ins|s|strike|del|sub|sup|mark|a|label)[^>^<]+>\s+(?=<)/g,(function(e){return e.trim()}));return 0===t.length&&(t="

    "+((e=r._HTMLConvertor(e)).length>0?e:"
    ")+"

    "),r._tagConvertor(t.replace(this.editorTagsWhitelistRegExp,""))},convertHTMLForCodeView:function(e){let t="";const i=this._w.RegExp,n=new i("^(BLOCKQUOTE|PRE|TABLE|THEAD|TBODY|TR|TH|TD|OL|UL|IMG|IFRAME|VIDEO|AUDIO|FIGURE|FIGCAPTION|HR|BR|CANVAS|SELECT)$","i"),l=r.isFormatElement.bind(r),s="string"==typeof e?this._d.createRange().createContextualFragment(e):e;let o=1*this._variable.codeIndent;return o=o>0?new this._w.Array(o+1).join(" "):"",function e(s,a,c){const d=s.childNodes,u=n.test(s.nodeName),h=u?a:"";for(let p,g,m,f=0,_=d.length;f<_;f++){if(p=d[f],m=n.test(p.nodeName),g=m?"\n":"",c=!l(p)||u||/^(TH|TD)$/i.test(s.nodeName)?"":"\n",3===p.nodeType){t+=r._HTMLConvertor(/^\n+$/.test(p.data)?"":p.data);continue}if(0===p.childNodes.length){t+=(/^(HR)$/i.test(p.nodeName)?"\n":"")+h+p.outerHTML+g;continue}p.innerHTML=p.innerHTML;const _=p.nodeName.toLowerCase();t+=(c||(u?"":g))+(h||m?a:"")+p.outerHTML.match(i("<"+_+"[^>]*>","i"))[0]+g,e(p,a+o,""),t+=(m?a:"")+""+(c||g||u?"\n":/^(TH|TD)$/i.test(p.nodeName)?"\n":"")}}(s,"","\n"),t.trim()+"\n"},_charCount:function(t,i){const n=e.element.charCounter;if(!n)return!0;(!t||t<0)&&(t=0);const s=l.maxCharCount;if(a.setTimeout((function(){n.textContent=e.element.wysiwyg.textContent.length})),s>0){let l=!1;const o=e.element.wysiwyg.textContent.length;if(o>s){c._editorRange();const e=c.getRange(),t=e.endOffset-1,i=c.getSelectionNode().textContent;c.getSelectionNode().textContent=i.slice(0,e.endOffset-1)+i.slice(e.endOffset,i.length),c.setRange(e.endContainer,t,e.endContainer,t),l=!0}else o+t>s&&(l=!0);if(l)return i&&!r.hasClass(n,"se-blink")&&(r.addClass(n,"se-blink"),a.setTimeout((function(){r.removeClass(n,"se-blink")}),600)),!1}return!0},_checkComponents:function(){this.plugins.image&&(this.initPlugins.image?this.plugins.image.checkImagesInfo.call(this):this.callPlugin("image",this.plugins.image.checkImagesInfo.bind(this))),this.plugins.video&&(this.initPlugins.video?this.plugins.video.checkVideosInfo.call(this):this.callPlugin("video",this.plugins.video.checkVideosInfo.bind(this)))},_resetComponents:function(){this._variable._imagesInfo=[],this._variable._imageIndex=0,this._variable._videosCnt=0},_setCodeView:function(t){l.codeMirrorEditor?l.codeMirrorEditor.getDoc().setValue(t):e.element.code.value=t},_getCodeView:function(){return l.codeMirrorEditor?l.codeMirrorEditor.getDoc().getValue():e.element.code.value},_init:function(n,o){this._ww=l.iframe?e.element.wysiwygFrame.contentWindow:a,this._wd=s,a.setTimeout(function(){if(this._checkComponents(),this._imagesInfoInit=!1,this._imagesInfoReset=!1,this.history.reset(!0),l.iframe&&(this._wd=e.element.wysiwygFrame.contentDocument,e.element.wysiwyg=this._wd.body,"auto"===l.height&&(this._iframeAuto=this._wd.body),this._iframeAutoHeight()),"function"==typeof g.onload)return g.onload(c,n)}.bind(this)),this.editorTagsWhitelistRegExp=r.createTagsWhitelist(l._editorTagsWhitelist),this.pasteTagsWhitelistRegExp=r.createTagsWhitelist(l.pasteTagsWhitelist);const u=l.attributesWhitelist,h={};let p,m,f="";if(u){const e=a.Object.keys(u);for(let t,i=0,n=e.length;ir&&(c=c.slice(0,r),o&&o.setAttribute("disabled",!0)),c[r]={contents:i,s:{path:l.getNodePath(n.startContainer,null),offset:n.startOffset},e:{path:l.getNodePath(n.endContainer,null),offset:n.endOffset}},1===r&&s&&s.removeAttribute("disabled"),e._checkComponents(),e._charCount(0,!1),t()}return{stack:c,push:function(t){i.setTimeout(e._resourcesStateChange),t&&!a||(i.clearTimeout(a),t)?a=i.setTimeout((function(){i.clearTimeout(a),a=null,u()}),350):u()},undo:function(){r>0&&(r--,d())},redo:function(){c.length-1>r&&(r++,d())},go:function(e){r=e<0?c.length-1:e,d()},reset:function(i){s&&s.setAttribute("disabled",!0),o&&o.setAttribute("disabled",!0),e.context.tool.save&&e.context.tool.save.setAttribute("disabled",!0),c.splice(0),r=0,c[r]={contents:e.getContents(!0),s:{path:[0,0],offset:0},e:{path:[0,0],offset:0}},i||t()},_destroy:function(){a&&i.clearTimeout(a),c=null}}}(this,d._onChange_historyStack)},_resourcesStateChange:function(){c._iframeAutoHeight(),c._checkPlaceholder()},_iframeAutoHeight:function(){this._iframeAuto&&(e.element.wysiwygFrame.style.height=this._iframeAuto.offsetHeight+"px")},_checkPlaceholder:function(){if(this._placeholder){if(this._variable.isCodeView)return void(this._placeholder.style.display="none");const t=e.element.wysiwyg;!r.onlyZeroWidthSpace(t.textContent)||t.querySelector(".se-component, pre, blockquote, hr, li, table, img, iframe, video")||(t.innerText.match(/\n/g)||"").length>1?this._placeholder.style.display="none":this._placeholder.style.display="block"}}},d={_directionKeyCode:new a.RegExp("^(8|13|3[2-9]|40|46)$"),_nonTextKeyCode:new a.RegExp("^(8|13|1[6-9]|20|27|3[3-9]|40|45|46|11[2-9]|12[0-3]|144|145)$"),_historyIgnoreKeyCode:new a.RegExp("^(1[6-9]|20|27|3[3-9]|40|45|11[2-9]|12[0-3]|144|145)$"),_onButtonsCheck:new a.RegExp("^(STRONG|INS|EM|DEL|SUB|SUP)$"),_frontZeroWidthReg:new a.RegExp(r.zeroWidthSpace+"+",""),_keyCodeShortcut:{65:"A",66:"B",83:"S",85:"U",73:"I",89:"Y",90:"Z",219:"[",221:"]"},_shortcutCommand:function(e,t){let i=null;switch(d._keyCodeShortcut[e]){case"A":i="selectAll";break;case"B":i="STRONG";break;case"S":t&&(i="DEL");break;case"U":i="INS";break;case"I":i="EM";break;case"Z":i=t?"redo":"undo";break;case"Y":i="redo";break;case"[":i="outdent";break;case"]":i="indent"}return!!i&&(c.commandHandler(c.commandMap[i],i),!0)},_applyTagEffects:function(){let t=c.getSelectionNode();if(t===c._lastEffectNode)return;c._lastEffectNode=t;const n=c.commandMap,s=this._onButtonsCheck,o=[],a=[],d=c.activePlugins,u=d.length;let h="";for(;t.firstChild;)t=t.firstChild;for(let e=t;!r.isWysiwygDiv(e)&&e;e=e.parentNode)if(1===e.nodeType&&!r.isBreak(e)){h=e.nodeName.toUpperCase(),a.push(h);for(let t,n=0;n0)&&(o.push("OUTDENT"),n.OUTDENT.removeAttribute("disabled")),-1===o.indexOf("INDENT")&&n.INDENT&&r.isListCell(e)&&!e.previousElementSibling&&(o.push("INDENT"),n.INDENT.setAttribute("disabled",!0))):s.test(h)&&(o.push(h),r.addClass(n[h],"active"))}for(let e in n)o.indexOf(e)>-1||(d.indexOf(e)>-1?i[e].active.call(c,null):n.OUTDENT&&/^OUTDENT$/i.test(e)?n.OUTDENT.setAttribute("disabled",!0):n.INDENT&&/^INDENT$/i.test(e)?n.INDENT.removeAttribute("disabled"):r.removeClass(n[e],"active"));c._variable.currentNodes=a.reverse(),l.showPathLabel&&(e.element.navigation.textContent=c._variable.currentNodes.join(" > "))},_cancelCaptionEdit:function(){this.setAttribute("contenteditable",!1),this.removeEventListener("blur",d._cancelCaptionEdit)},onMouseDown_toolbar:function(e){let t=e.target;if(r.getParentElement(t,".se-submenu"))e.stopPropagation(),c._notHideToolbar=!0;else{e.preventDefault();let i=t.getAttribute("data-command"),n=t.className;for(;!i&&!/se-menu-list/.test(n)&&!/se-toolbar/.test(n);)t=t.parentNode,i=t.getAttribute("data-command"),n=t.className;i!==c._submenuName&&i!==c._containerName||e.stopPropagation()}},onClick_toolbar:function(e){e.preventDefault(),e.stopPropagation();let t=e.target,i=t.getAttribute("data-display"),n=t.getAttribute("data-command"),l=t.className;for(;!n&&!/se-menu-list/.test(l)&&!/se-toolbar/.test(l);)t=t.parentNode,n=t.getAttribute("data-command"),i=t.getAttribute("data-display"),l=t.className;(n||i)&&(t.disabled||(c.hasFocus||c.focus(),c._editorRange(),c.actionCall(n,i,t)))},onMouseDown_wysiwyg:function(t){if("false"===e.element.wysiwyg.getAttribute("contenteditable"))return;const i=r.getParentElement(t.target,r.isCell);if(i){const e=c.plugins.table;e&&i!==e._fixedCell&&!e._shift&&c.callPlugin("table",(function(){e.onTableCellMultiSelect.call(c,i,!1)}))}c._isBalloon&&d._hideToolbar(),g.onMouseDown&&g.onMouseDown(t,c)},onClick_wysiwyg:function(t){const i=t.target;if("false"===e.element.wysiwyg.getAttribute("contenteditable"))return;if(t.stopPropagation(),/^FIGURE$/i.test(i.nodeName)){const e=i.querySelector("IMG"),n=i.querySelector("IFRAME");if(e)return t.preventDefault(),void c.selectComponent(e,"image");if(n)return t.preventDefault(),void c.selectComponent(n,"video")}const n=r.getParentElement(i,"FIGCAPTION");if(n&&(!n.getAttribute("contenteditable")||"false"===n.getAttribute("contenteditable"))&&(t.preventDefault(),n.setAttribute("contenteditable",!0),n.focus(),c._isInline&&!c._inlineToolbarAttr.isShow)){d._showToolbarInline();const e=function(){d._hideToolbar(),n.removeEventListener("blur",e)};n.addEventListener("blur",e)}c._editorRange(),a.setTimeout(c._editorRange.bind(c));const l=c.getSelectionNode(),s=r.getFormatElement(l),o=r.getRangeFormatElement(l);if(!c.getRange().collapsed||s&&s!==o||"false"===i.getAttribute("contenteditable"))d._applyTagEffects();else{if(r.isList(o)){const e=r.createElement("LI"),t=l.nextElementSibling;e.appendChild(l),o.insertBefore(e,t)}else c.execCommand("formatBlock",!1,r.isRangeFormatElement(o)?"DIV":"P");t.preventDefault(),c.focus()}c._isBalloon&&a.setTimeout(d._toggleToolbarBalloon),g.onClick&&g.onClick(t,c)},_balloonDelay:null,_showToolbarBalloonDelay:function(){d._balloonDelay&&a.clearTimeout(d._balloonDelay),d._balloonDelay=a.setTimeout(function(){a.clearTimeout(this._balloonDelay),this._balloonDelay=null,this._showToolbarBalloon()}.bind(d),350)},_toggleToolbarBalloon:function(){c._editorRange();const e=c.getRange();"table"===c.currentControllerName||!c._isBalloonAlways&&e.collapsed?d._hideToolbar():d._showToolbarBalloon(e)},_showToolbarBalloon:function(t){if(!c._isBalloon)return;const i=t||c.getRange(),n=e.element.toolbar,l=c.getSelection();let s;if(l.focusNode===l.anchorNode)s=l.focusOffsetn.offsetWidth?n.offsetWidth-u:b",!o.nextElementSibling){const e=o.attributes;for(;e[0];)o.removeAttribute(e[0].name);c.execCommand("formatBlock",!1,"P")}return!1}}const i=u.commonAncestorContainer;if(m=r.getFormatElement(u.startContainer),f=r.getRangeFormatElement(m),f&&m&&!r.isCell(f)&&!/^FIGCAPTION$/i.test(f.nodeName)){if(r.isListCell(m)&&r.isList(f)&&(r.isListCell(f.parentNode)||m.previousElementSibling)&&(o===m||3===o.nodeType&&(!o.previousSibling||r.isList(o.previousSibling)))&&(r.getFormatElement(u.startContainer)!==r.getFormatElement(u.endContainer)?f.contains(u.startContainer):0===u.startOffset&&u.collapsed)){if(u.startContainer!==u.endContainer)t.preventDefault(),c.removeNode(),3===u.startContainer.nodeType&&c.setRange(u.startContainer,u.startContainer.textContent.length,u.startContainer,u.startContainer.textContent.length),c.history.push(!0);else{let e=m.previousElementSibling||f.parentNode;if(r.isListCell(e)){t.preventDefault();const i=e.lastElementChild;r.isList(i)&&(e=i.lastElementChild);let n=e===f.parentNode?f.previousSibling:e.lastChild;n||(n=r.createTextNode(r.zeroWidthSpace),f.parentNode.insertBefore(n,f.parentNode.firstChild));const l=3===n.nodeType?n.textContent.length:1,s=m.childNodes;let o=n,a=s[0];for(;a=s[0];)e.insertBefore(a,o.nextSibling),o=a;r.removeItem(m),0===f.children.length&&r.removeItem(f),c.setRange(n,l,n,l),c.history.push(!0)}}break}if(!h&&0===u.startOffset){let e=!0,n=i;for(;n&&n!==f&&!r.isWysiwygDiv(n);){if(n.previousSibling){e=!1;break}n=n.parentNode}if(e&&f.parentNode){t.preventDefault(),c.detachRangeFormatElement(f,r.isListCell(m)?[m]:null,null,!1,!1),c.history.push(!0);break}}}if(!h&&0===u.startOffset&&(r.isComponent(i.previousSibling)||3===i.nodeType&&!i.previousSibling&&0===u.startOffset&&0===u.endOffset&&r.isComponent(m.previousSibling))){const e=m.previousSibling;r.removeItem(e)}break;case 46:if(p){t.preventDefault(),t.stopPropagation(),c.plugins[p].destroy.call(c);break}if((r.isFormatElement(o)||null===o.nextSibling)&&u.startOffset===o.textContent.length){let e=m.nextElementSibling;if(r.isComponent(e)){t.preventDefault(),r.onlyZeroWidthSpace(m)&&r.removeItem(m),(r.hasClass(e,"se-component")||/^IMG$/i.test(e.nodeName))&&(t.stopPropagation(),r.hasClass(e,"se-image-container")||/^IMG$/i.test(e.nodeName)?(e=/^IMG$/i.test(e.nodeName)?e:e.querySelector("img"),c.selectComponent(e,"image")):r.hasClass(e,"se-video-container")&&c.selectComponent(e.querySelector("iframe"),"video"));break}}if(m=r.getFormatElement(u.startContainer),f=r.getRangeFormatElement(m),r.isListCell(m)&&r.isList(f)&&(o===m||3===o.nodeType&&(!o.nextSibling||r.isList(o.nextSibling))&&(r.getFormatElement(u.startContainer)!==r.getFormatElement(u.endContainer)?f.contains(u.endContainer):u.endOffset===o.textContent.length&&u.collapsed))){u.startContainer!==u.endContainer&&c.removeNode();let e=r.getArrayItem(m.children,r.isList,!1);if(e=e||m.nextElementSibling||f.parentNode.nextElementSibling,e&&(r.isList(e)||r.getArrayItem(e.children,r.isList,!1))){let i,n;if(t.preventDefault(),r.isList(e)){const t=e.firstElementChild;for(n=t.childNodes,i=n[0];n[0];)m.insertBefore(n[0],e);r.removeItem(t)}else{for(i=e.firstChild,n=e.childNodes;n[0];)m.appendChild(n[0]);r.removeItem(e)}c.setRange(i,0,i,0),c.history.push(!0)}break}break;case 9:if(t.preventDefault(),l||s||r.isWysiwygDiv(o))break;c.controllersOff();const g=!u.collapsed||c.isEdgePoint(u.startContainer,u.startOffset),_=c.getSelectedElements(),b=[];let y=[],v=r.isListCell(_[0]),x=r.isListCell(_[_.length-1]),C={sc:null,so:null,ec:null,eo:null};for(let e,t=0,i=_.length;t0&&g&&c.plugins.list){const e=c.plugins.list.editInsideList.call(c,n,b);v&&(C.sc=e.sc,C.so=e.so),x&&(C.ec=e.ec,C.eo=e.eo)}else{const e=r.getParentElement(o,r.isCell);if(e&&g){const t=r.getParentElement(e,"table"),i=r.getListChildren(t,r.isCell);let l=n?r.prevIdx(i,e):r.nextIdx(i,e);l!==i.length||n||(l=0),-1===l&&n&&(l=i.length-1);const s=i[l];if(!s)return!1;c.setRange(s,0,s,0);break}y=y.concat(b),v=x=null}if(y.length>0)if(n){const e=y.length-1;for(let t,i=0;i<=e;i++)t=y[i].firstChild,t&&(/^\s{1,4}$/.test(t.textContent)?r.removeItem(t):/^\s{1,4}/.test(t.textContent)&&(t.textContent=t.textContent.replace(/^\s{1,4}/,"")));const t=r.getChildElement(y[0],"text",!1),i=r.getChildElement(y[e],"text",!0);!v&&t&&(C.sc=t,C.so=0),!x&&i&&(C.ec=i,C.eo=i.textContent.length)}else{const e=r.createTextNode(new a.Array(c._variable.tabSize+1).join(" "));if(1===y.length){const t=c.insertNode(e);v||(C.sc=e,C.so=t.endOffset),x||(C.ec=e,C.eo=t.endOffset)}else{const t=y.length-1;for(let i,n=0;n<=t;n++)i=y[n].firstChild,i&&(r.isBreak(i)?y[n].insertBefore(e.cloneNode(!1),i):i.textContent=e.textContent+i.textContent);const i=r.getChildElement(y[0],"text",!1),n=r.getChildElement(y[t],"text",!0);!v&&i&&(C.sc=i,C.so=0),!x&&n&&(C.ec=n,C.eo=n.textContent.length)}}c.setRange(C.sc,C.so,C.ec,C.eo),c.history.push(!1);break;case 13:const w=r.getFreeFormatElement(o);if(!n&&w){t.preventDefault();const e=o===w,i=c.getSelection(),n=o.childNodes,l=i.focusOffset,s=o.previousElementSibling,a=o.nextSibling;if(e&&u.collapsed&&n.length-1<=l+1&&r.isBreak(n[l])&&(!n[l+1]||(!n[l+2]||r.onlyZeroWidthSpace(n[l+2].textContent))&&3===n[l+1].nodeType&&r.onlyZeroWidthSpace(n[l+1].textContent))&&l>0&&r.isBreak(n[l-1])||!e&&r.onlyZeroWidthSpace(o.textContent)&&r.isBreak(s)&&(r.isBreak(s.previousSibling)||!r.onlyZeroWidthSpace(s.previousSibling.textContent))&&(!a||!r.isBreak(a)&&r.onlyZeroWidthSpace(a.textContent))){e?r.removeItem(n[l-1]):r.removeItem(o);const t=c.appendFormatTag(w,r.isFormatElement(w.nextElementSibling)?w.nextElementSibling:null);r.copyFormatAttributes(t,w),c.setRange(t,1,t,1);break}if(e){c.execCommand("insertHTML",!1,"

    ");let e=i.focusNode;const t=i.focusOffset;e=w===e?e.childNodes[t-l>1?t-1:t]:e.previousSibling,c.setRange(e,1,e,1)}else{const e=i.focusNode.nextSibling,t=r.createElement("BR");c.insertNode(t);const n=t.previousSibling,l=t.nextSibling;r.isBreak(e)||r.isBreak(n)||l&&!r.onlyZeroWidthSpace(l)?c.setRange(l,0,l,0):(t.parentNode.insertBefore(t.cloneNode(!1),t),c.setRange(t,1,t,1))}d._onShortcutKey=!0;break}if(h)break;if(f&&m&&!r.isCell(f)&&!/^FIGCAPTION$/i.test(f.nodeName)){const e=c.getRange();if((3!==e.commonAncestorContainer.nodeType||!e.commonAncestorContainer.nextElementSibling)&&r.onlyZeroWidthSpace(m.innerText.trim())){t.preventDefault();let e=null;if(r.isListCell(f.parentNode)){f=m.parentNode.parentNode.parentNode;const t=r.splitElement(m,null,r.getElementDepth(m)-2);e=r.createElement("LI"),f.insertBefore(e,t)}else{const t=r.isCell(f.parentNode)?"DIV":r.isList(f.parentNode)?"LI":r.isFormatElement(f.nextElementSibling)?f.nextElementSibling.nodeName:r.isFormatElement(f.previousElementSibling)?f.previousElementSibling.nodeName:"P";e=r.createElement(t);const i=c.detachRangeFormatElement(f,[m],null,!0,!0);i.cc.insertBefore(e,i.ec)}e.innerHTML="
    ",r.copyFormatAttributes(e,m),r.removeItemAllParents(m,null),c.setRange(e,1,e,1);break}}if(f&&r.getParentElement(f,"FIGCAPTION")&&r.getParentElement(f,r.isList)&&(t.preventDefault(),m=c.appendFormatTag(m,null),c.setRange(m,0,m,0)),p){t.preventDefault(),t.stopPropagation();const i=e[p],n=i._container,l=n.previousElementSibling||n.nextElementSibling;let s=null;r.isListCell(n.parentNode)?s=r.createElement("BR"):(s=r.createElement(r.isFormatElement(l)?l.nodeName:"P"),s.innerHTML="
    "),n.parentNode.insertBefore(s,n),c.callPlugin(p,(function(){const e=c.plugins.resizing.call_controller_resize.call(c,i._element,p);c.plugins[p].onModifyMode.call(c,i._element,e)}))}}if(n&&/16/.test(i)){t.preventDefault(),t.stopPropagation();const e=c.plugins.table;if(e&&!e._shift&&!e._ref){const t=r.getParentElement(m,r.isCell);if(t)return void e.onTableCellMultiSelect.call(c,t,!0)}}const _=!(l||s||h||d._nonTextKeyCode.test(i));if(!c._charCount(1,_)&&_)return t.preventDefault(),t.stopPropagation(),!1;g.onKeyDown&&g.onKeyDown(t,c)},onKeyUp_wysiwyg:function(e){if(d._onShortcutKey)return;c._editorRange();const t=c.getRange(),i=e.keyCode,n=e.ctrlKey||e.metaKey||91===i||92===i,l=e.altKey;let s=c.getSelectionNode();if(c._isBalloon&&(c._isBalloonAlways&&27!==i||!t.collapsed)){if(!c._isBalloonAlways)return void d._showToolbarBalloon();d._showToolbarBalloonDelay()}if(8===i&&r.isWysiwygDiv(s)&&""===s.textContent){e.preventDefault(),e.stopPropagation(),s.innerHTML="";const t=r.createElement(r.isFormatElement(c._variable.currentNodes[0])?c._variable.currentNodes[0]:"P");return t.innerHTML="
    ",s.appendChild(t),c.setRange(t,0,t,0),d._applyTagEffects(),c._checkComponents(),void c.history.push(!1)}const o=r.getFormatElement(s),a=r.getRangeFormatElement(s);(!o&&t.collapsed||o===a)&&(c.execCommand("formatBlock",!1,r.isRangeFormatElement(a)?"DIV":"P"),c.focus(),s=c.getSelectionNode()),d._directionKeyCode.test(i)&&d._applyTagEffects(),c._checkComponents();const u=!n&&!l&&!d._nonTextKeyCode.test(i);if(u&&3===s.nodeType&&r.zeroWidthRegExp.test(s.textContent)){let e=t.startOffset,i=t.endOffset;const n=(s.textContent.substring(0,i).match(d._frontZeroWidthReg)||"").length;e=t.startOffset-n,i=t.endOffset-n,s.textContent=s.textContent.replace(r.zeroWidthRegExp,""),c.setRange(s,e<0?0:e,s,i<0?0:i)}if(!c._charCount(1,u)&&1===e.key.length)return e.preventDefault(),e.stopPropagation(),!1;!n&&!l&&!d._historyIgnoreKeyCode.test(i)&&c.history.push(!0),g.onKeyUp&&g.onKeyUp(e,c)},onScroll_wysiwyg:function(e){c.controllersOff(),c._isBalloon&&d._hideToolbar(),g.onScroll&&g.onScroll(e,c)},onFocus_wysiwyg:function(e){c.hasFocus=!0,c._isInline&&d._showToolbarInline(),g.onFocus&&g.onFocus(e,c)},onBlur_wysiwyg:function(e){c.hasFocus=!1,(c._isInline||c._isBalloon)&&d._hideToolbar(),g.onBlur&&g.onBlur(e,c)},onMouseDown_resizingBar:function(t){t.stopPropagation(),c._variable.resizeClientY=t.clientY,e.element.resizeBackground.style.display="block",s.addEventListener("mousemove",d._resize_editor),s.addEventListener("mouseup",(function t(){e.element.resizeBackground.style.display="none",s.removeEventListener("mousemove",d._resize_editor),s.removeEventListener("mouseup",t)}))},_resize_editor:function(t){const i=e.element.editorArea.offsetHeight+(t.clientY-c._variable.resizeClientY);e.element.wysiwygFrame.style.height=e.element.code.style.height=(i=i+o?(c._sticky||d._onStickyToolbar(),t.toolbar.style.top=i+o+l.stickyToolbar-n-c._variable.minResizingSize+"px"):n>=o&&d._onStickyToolbar()},_getStickyOffsetTop:function(){let t=e.element.topArea,i=0;for(;t;)i+=t.offsetTop,t=t.offsetParent;return i},_onStickyToolbar:function(){const t=e.element;c._isInline||(t._stickyDummy.style.height=t.toolbar.offsetHeight+"px",t._stickyDummy.style.display="block"),t.toolbar.style.top=l.stickyToolbar+"px",t.toolbar.style.width=c._isInline?c._inlineToolbarAttr.width:t.toolbar.offsetWidth+"px",r.addClass(t.toolbar,"se-toolbar-sticky"),c._sticky=!0},_offStickyToolbar:function(){const t=e.element;t._stickyDummy.style.display="none",t.toolbar.style.top=c._isInline?c._inlineToolbarAttr.top:"",t.toolbar.style.width=c._isInline?c._inlineToolbarAttr.width:"",t.editorArea.style.marginTop="",r.removeClass(t.toolbar,"se-toolbar-sticky"),c._sticky=!1},_codeViewAutoHeight:function(){e.element.code.style.height=e.element.code.scrollHeight+"px"},onPaste_wysiwyg:function(e){const t=e.clipboardData;if(!t)return!0;const i=c._charCount(t.getData("text/plain").length,!0),n=c.cleanHTML(t.getData("text/html"),c.pasteTagsWhitelistRegExp);return("function"!=typeof g.onPaste||g.onPaste(e,n,i,c))&&i?void(n?(e.stopPropagation(),e.preventDefault(),c.execCommand("insertHTML",!1,n)):c.history.push(!0)):(e.preventDefault(),e.stopPropagation(),!1)},onCut_wysiwyg:function(){a.setTimeout((function(){c._resourcesStateChange(),c._charCount(0,!1),c.history.push(!1)}))},onDragOver_wysiwyg:function(e){e.preventDefault()},onDrop_wysiwyg:function(t){const i=t.dataTransfer;if(!i)return!0;const n=i.files;if(n.length>0&&c.plugins.image)d._setDropLocationSelection(t),c.callPlugin("image",(function(){e.image.imgInputFile.files=n,c.plugins.image.onRender_imgInput.call(c),e.image.imgInputFile.files=null}));else{if(!c._charCount(i.getData("text/plain").length,!0))return t.preventDefault(),t.stopPropagation(),!1;{const e=c.cleanHTML(i.getData("text/html"),c.pasteTagsWhitelistRegExp);e&&(d._setDropLocationSelection(t),c.execCommand("insertHTML",!1,e))}}g.onDrop&&g.onDrop(t,c)},_setDropLocationSelection:function(e){e.stopPropagation(),e.preventDefault();const t=c.getRange();c.setRange(t.startContainer,t.startOffset,t.endContainer,t.endOffset)},_onChange_historyStack:function(){d._applyTagEffects(),e.tool.save&&e.tool.save.removeAttribute("disabled"),g.onChange&&g.onChange(c.getContents(!0),c)},_addEvent:function(){const t=l.iframe?c._ww:e.element.wysiwyg;e.element.toolbar.addEventListener("mousedown",d.onMouseDown_toolbar,!1),e.element.toolbar.addEventListener("click",d.onClick_toolbar,!1),t.addEventListener("mousedown",d.onMouseDown_wysiwyg,!1),t.addEventListener("click",d.onClick_wysiwyg,!1),t.addEventListener("keydown",d.onKeyDown_wysiwyg,!1),t.addEventListener("keyup",d.onKeyUp_wysiwyg,!1),t.addEventListener("paste",d.onPaste_wysiwyg,!1),t.addEventListener("cut",d.onCut_wysiwyg,!1),t.addEventListener("dragover",d.onDragOver_wysiwyg,!1),t.addEventListener("drop",d.onDrop_wysiwyg,!1),t.addEventListener("scroll",d.onScroll_wysiwyg,!1),t.addEventListener("focus",d.onFocus_wysiwyg,!1),t.addEventListener("blur",d.onBlur_wysiwyg,!1),c.plugins.table&&t.addEventListener("touchstart",d.onMouseDown_wysiwyg,{passive:!0,useCapture:!1}),"auto"!==l.height||l.codeMirrorEditor||(e.element.code.addEventListener("keydown",d._codeViewAutoHeight,!1),e.element.code.addEventListener("keyup",d._codeViewAutoHeight,!1),e.element.code.addEventListener("paste",d._codeViewAutoHeight,!1)),e.element.resizingBar&&(/\d+/.test(l.height)?e.element.resizingBar.addEventListener("mousedown",d.onMouseDown_resizingBar,!1):r.addClass(e.element.resizingBar,"se-resizing-none")),a.removeEventListener("resize",d.onResize_window),a.removeEventListener("scroll",d.onScroll_window),a.addEventListener("resize",d.onResize_window,!1),l.stickyToolbar>-1&&a.addEventListener("scroll",d.onScroll_window,!1)},_removeEvent:function(){const t=l.iframe?c._ww:e.element.wysiwyg;e.element.toolbar.removeEventListener("mousedown",d.onMouseDown_toolbar),e.element.toolbar.removeEventListener("click",d.onClick_toolbar),t.removeEventListener("click",d.onClick_wysiwyg),t.removeEventListener("keydown",d.onKeyDown_wysiwyg),t.removeEventListener("keyup",d.onKeyUp_wysiwyg),t.removeEventListener("paste",d.onPaste_wysiwyg),t.removeEventListener("cut",d.onCut_wysiwyg),t.removeEventListener("dragover",d.onDragOver_wysiwyg),t.removeEventListener("drop",d.onDrop_wysiwyg),t.removeEventListener("scroll",d.onScroll_wysiwyg),t.removeEventListener("mousedown",d.onMouseDown_wysiwyg),t.removeEventListener("touchstart",d.onMouseDown_wysiwyg,{passive:!0,useCapture:!1}),t.removeEventListener("focus",d.onFocus_wysiwyg),t.removeEventListener("blur",d.onBlur_wysiwyg),e.element.code.removeEventListener("keydown",d._codeViewAutoHeight),e.element.code.removeEventListener("keyup",d._codeViewAutoHeight),e.element.code.removeEventListener("paste",d._codeViewAutoHeight),e.element.resizingBar&&e.element.resizingBar.removeEventListener("mousedown",d.onMouseDown_resizingBar),a.removeEventListener("resize",d.onResize_window),a.removeEventListener("scroll",d.onScroll_window)}},g={core:c,util:r,onload:null,onScroll:null,onMouseDown:null,onClick:null,onKeyDown:null,onKeyUp:null,onDrop:null,onChange:null,onPaste:null,onFocus:null,onBlur:null,showInline:null,imageUploadHandler:null,onImageUploadBefore:null,onImageUpload:null,onImageUploadError:null,setOptions:function(s){d._removeEvent(),c.plugins=s.plugins||c.plugins;const o=[s,s].reduce((function(e,t){for(let i in t)if("plugins"===i&&t[i]&&e[i]){let n=e[i],l=t[i];n=n.length?n:a.Object.keys(n).map((function(e){return n[e]})),l=l.length?l:a.Object.keys(l).map((function(e){return l[e]})),e[i]=l.filter((function(e){return-1===n.indexOf(e)})).concat(n)}else e[i]=t[i];return e}),{}),r=h._setOptions(o,e,c.plugins,s);r.callButtons&&(t=r.callButtons,c.initPlugins={}),r.plugins&&(c.plugins=i=r.plugins);const u=e.element.wysiwyg.innerHTML,g=e.element,m={_top:g.topArea,_relative:g.relative,_toolBar:g.toolbar,_editorArea:g.editorArea,_wysiwygArea:g.wysiwygFrame,_codeArea:g.code,_placeholder:g.placeholder,_resizingBar:g.resizingBar,_navigation:g.navigation,_charCounter:g.charCounter,_loading:g.loading,_resizeBack:g.resizeBackground,_stickyDummy:g._stickyDummy,_arrow:g._arrow};l=o,c.lang=n=l.lang,c.context=e=p(e.element.originElement,m,l),c._imagesInfoReset=!0,c._init(!0,u),d._addEvent(),c._charCount(0,!1),d._offStickyToolbar(),d.onResize_window(),c.focus()},noticeOpen:function(e){c.addModule([o]),o.open.call(c,e)},noticeClose:function(){c.addModule([o]),o.close.call(c)},save:function(){e.element.originElement.value=c.getContents(!1)},getContext:function(){return e},getContents:function(e){return c.getContents(e)},getImagesInfo:function(){return c._variable._imagesInfo},insertImage:function(e){c.plugins.image&&e&&(c.initPlugins.image?c.plugins.image.submitAction.call(c,e):c.callPlugin("image",c.plugins.image.submitAction.bind(c,e)),c.focus())},insertHTML:function(e){if(!e.nodeType||1!==e.nodeType){const t=r.createElement("DIV");t.innerHTML=e,e=t.firstChild||t.content.firstChild}let t=null;(r.isFormatElement(e)||/^(IMG|IFRAME)$/i.test(e.nodeName))&&(t=r.getFormatElement(c.getSelectionNode())),r.isComponent(e)?c.insertComponent(e,!1):c.insertNode(e,t),c.focus()},setContents:function(e){c.setContents(e)},appendContents:function(t){const i=c.convertContentsForEditor(t);if(c._variable.isCodeView)c._setCodeView(c._getCodeView()+"\n"+c.convertHTMLForCodeView(i));else{const t=r.createElement("DIV");t.innerHTML=i;const n=e.element.wysiwyg,l=t.children;for(let e=0,t=l.length;e Date: Wed, 11 Mar 2020 04:36:39 +0900 Subject: [PATCH 95/99] update sample --- README.md | 2 +- sample/index.html | 12 +++++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 00af537bf..b2f0b6388 100644 --- a/README.md +++ b/README.md @@ -18,7 +18,7 @@ Pure javscript based WYSIWYG web editor, with no dependencies > - Can use CodeMirror, KaTeX. > - And.. many other features :) -![WYSIWYG HTML Editor](http://suneditor.com/docs/screen-main-w.png?v=2301) +![WYSIWYG HTML Editor](http://suneditor.com/docs/screen-main-w.png?v=2700) ## Table of contents - [Browser Support](#browser-support) diff --git a/sample/index.html b/sample/index.html index 3c56d3d2b..c927ce862 100644 --- a/sample/index.html +++ b/sample/index.html @@ -120,7 +120,7 @@
    From 75ffd8c67be64a1169cd22b0be8425819a1b2f7e Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Wed, 11 Mar 2020 22:15:17 +0900 Subject: [PATCH 96/99] fix: 2.26.0 - node change, focus, key action --- dist/css/suneditor.min.css | 2 +- dist/suneditor.min.js | 2 +- src/assets/css/suneditor-contents.css | 6 +- src/lib/core.js | 135 ++++++++++++++++++-------- src/plugins/dialog/image.js | 2 +- test/dev/suneditor_build_test.js | 2 +- 6 files changed, 101 insertions(+), 48 deletions(-) diff --git a/dist/css/suneditor.min.css b/dist/css/suneditor.min.css index 4fbdec122..a01df1e0b 100644 --- a/dist/css/suneditor.min.css +++ b/dist/css/suneditor.min.css @@ -1 +1 @@ -.sun-editor{width:auto;height:auto;box-sizing:border-box;font-family:Helvetica Neue,sans-serif;border:1px solid #dadada;text-align:left;background-color:#fff;color:#000;user-select:none;-o-user-select:none;-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-ms-user-select:none}.sun-editor *{box-sizing:border-box;-webkit-user-drag:none;overflow:visible}.sun-editor-common button,.sun-editor-common input,.sun-editor-common select,.sun-editor-common textarea{font-size:14px;line-height:1.5}.sun-editor-common blockquote,.sun-editor-common body,.sun-editor-common button,.sun-editor-common code,.sun-editor-common dd,.sun-editor-common div,.sun-editor-common dl,.sun-editor-common dt,.sun-editor-common fieldset,.sun-editor-common form,.sun-editor-common h1,.sun-editor-common h2,.sun-editor-common h3,.sun-editor-common h4,.sun-editor-common h5,.sun-editor-common h6,.sun-editor-common input,.sun-editor-common legend,.sun-editor-common li,.sun-editor-common ol,.sun-editor-common p,.sun-editor-common pre,.sun-editor-common select,.sun-editor-common td,.sun-editor-common textarea,.sun-editor-common th,.sun-editor-common ul{margin:0;padding:0;border:0}.sun-editor-common dl,.sun-editor-common li,.sun-editor-common menu,.sun-editor-common ol,.sun-editor-common ul{list-style:none!important}.sun-editor-common hr{margin:6px 0!important}.sun-editor textarea{resize:none!important;border:0!important}.sun-editor button{border:0;background-color:transparent;touch-action:manipulation;cursor:pointer;outline:none}.sun-editor button,.sun-editor input,.sun-editor select,.sun-editor textarea{vertical-align:middle}.sun-editor button span{display:block;margin:0;padding:0}.sun-editor button .txt{display:block;margin-top:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@font-face{font-family:Suneditor-icon;src:url(../fonts/435801d088c67acdd4c667e00037f080.eot);src:url(../fonts/435801d088c67acdd4c667e00037f080.eot?#iefix) format("embedded-opentype"),url(../fonts/54469d382ec66ca4460d57a5f4a49b05.woff2) format("woff2"),url(../fonts/1d63e86b832ddfc4008baf6e69e7c39b.woff) format("woff"),url(../fonts/773c0f21a6a926b07f111a3892134dec.ttf) format("truetype"),url(../fonts/0b8f27509021ddc0f7d4ee103181bc05.svg#Suneditor-icon) format("svg");font-weight:400;font-style:normal}.sun-editor [class*=se-icon-]:before{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Suneditor-icon;display:inline-block;font-style:normal;font-variant:normal;font-weight:400;text-rendering:auto;font-size:15px}.sun-editor button>svg{width:25px;height:25px;margin:5px}.sun-editor .se-toolbar button>i:before{line-height:2.1}.sun-editor .se-icon-align-justify:before{content:"A"}.sun-editor .se-icon-align-left:before{content:"B"}.sun-editor .se-icon-align-right:before{content:"C"}.sun-editor .se-icon-align-center:before{content:"D"}.sun-editor .se-icon-underline:before{content:"E"}.sun-editor .se-icon-bold:before{content:"F"}.sun-editor .se-icon-italic:before{content:"G"}.sun-editor .se-icon-strokethrough:before{content:"H"}.sun-editor .se-icon-subscript:before{content:"I"}.sun-editor .se-icon-superscript:before{content:"J"}.sun-editor .se-icon-redo:before{content:"K"}.sun-editor .se-icon-undo:before{content:"L"}.sun-editor .se-icon-erase:before{content:"M"}.sun-editor .se-icon-fontColor:before{content:"N"}.sun-editor .se-icon-hiliteColor:before{content:"O"}.sun-editor .se-icon-indent-left:before{content:"P"}.sun-editor .se-icon-indent-right:before{content:"Q"}.sun-editor .se-icon-list-bullets:before{content:"R"}.sun-editor .se-icon-list-number:before{content:"S"}.sun-editor .se-icon-grid:before{content:"T"}.sun-editor .se-icon-code-view:before{content:"U"}.sun-editor .se-icon-preview:before{content:"V"}.sun-editor .se-icon-showBlocks:before{content:"W"}.sun-editor .se-icon-expansion:before{content:"X"}.sun-editor .se-icon-reduction:before{content:"Y"}.sun-editor .se-icon-image:before{content:"Z"}.sun-editor .se-icon-link:before{content:"a"}.sun-editor .se-icon-auto-size:before{content:"b"}.sun-editor .se-icon-print:before{content:"c"}.sun-editor .se-icon-modify:before{content:"d"}.sun-editor .se-icon-revert:before{content:"e"}.sun-editor .se-icon-arrow-down:before{content:"f";font-size:10px}.sun-editor .se-icon-video:before{content:"g"}.sun-editor .se-icon-cancel:before{content:"h";font-size:10px}.sun-editor .se-icon-warning:before{content:"i"}.sun-editor .se-icon-insert-column-right:before{content:"j"}.sun-editor .se-icon-insert-row-below:before{content:"k"}.sun-editor .se-icon-insert-row-above:before{content:"l"}.sun-editor .se-icon-insert-column-left:before{content:"m"}.sun-editor .se-icon-delete-row:before{content:"n"}.sun-editor .se-icon-delete-column:before{content:"o"}.sun-editor .se-icon-unlink:before{content:"p"}.sun-editor .se-icon-empty-file:before{content:"q"}.sun-editor .se-icon-paragraph-style:before{content:"r"}.sun-editor .se-icon-delete:before{content:"s"}.sun-editor .se-icon-rotate-left:before{content:"t"}.sun-editor .se-icon-rotate-right:before{content:"u"}.sun-editor .se-icon-mirror-horizontal:before{content:"v"}.sun-editor .se-icon-mirror-vertical:before{content:"w"}.sun-editor .se-icon-save:before{content:"x"}.sun-editor .se-icon-hr:before{content:"y"}.sun-editor .se-icon-checked:before{content:"z"}.sun-editor .se-icon-table-header:before{content:"0"}.sun-editor .se-icon-merge-cell:before{content:"1"}.sun-editor .se-icon-split-cell:before{content:"2"}.sun-editor .se-icon-caption:before{content:"3"}.sun-editor .se-icon-edit:before{content:"4"}.sun-editor .se-icon-question:before{content:"5"}.sun-editor .se-icon-attachment:before{content:"6"}.sun-editor .se-icon-add:before{content:"7"}.sun-editor .se-icon-more-vertical:before{content:"8"}.sun-editor .se-icon-more-horizontal:before{content:"9"}.sun-editor .se-icon-map-pin:before{content:"!"}.sun-editor .se-icon-magic-stick:before{content:'"'}.sun-editor .se-icon-math:before{content:"#"}.sun-editor .se-icon-audio:before{content:"$"}.sun-editor .se-icon-emoji:before{content:"%"}.sun-editor .se-icon-template:before{content:"&"}.sun-editor .se-icon-line-height:before{content:"'"}.sun-editor .se-icon-text-style:before{content:"("}.sun-editor .se-arrow,.sun-editor .se-arrow:after{position:absolute;display:block;width:0;height:0;border:11px solid transparent}.sun-editor .se-arrow.se-arrow-up{top:-11px;left:20px;margin-left:-11px;border-top-width:0;border-bottom-color:rgba(0,0,0,.25)}.sun-editor .se-arrow.se-arrow-up:after{top:1px;margin-left:-11px;content:" ";border-top-width:0;border-bottom-color:#fff}.sun-editor .se-toolbar .se-arrow.se-arrow-up:after{border-bottom-color:#fafafa}.sun-editor .se-arrow.se-arrow-down{top:0;left:0;margin-left:-11px;border-bottom-width:0;border-top-color:rgba(0,0,0,.25)}.sun-editor .se-arrow.se-arrow-down:after{top:-12px;margin-left:-11px;content:" ";border-bottom-width:0;border-top-color:#fff}.sun-editor .se-toolbar .se-arrow.se-arrow-down:after{border-top-color:#fafafa}.sun-editor .se-container{position:relative;width:100%;height:100%}.sun-editor button{color:#000}.sun-editor .se-btn{float:left;width:35px;height:35px;border:0;border-radius:4px;margin:1px!important;padding:0;font-size:12px;line-height:27px}.sun-editor .se-btn:enabled:focus,.sun-editor .se-btn:enabled:hover{background-color:#e1e1e1;border-color:#d1d1d1;outline:0 none}.sun-editor .se-btn:enabled:active{background-color:#d1d1d1;border-color:#c1c1c1;-webkit-box-shadow:inset 0 3px 5px #c1c1c1;box-shadow:inset 0 3px 5px #c1c1c1}.sun-editor .se-btn-primary{color:#000;background-color:#c7deff;border:1px solid #80bdff;border-radius:4px}.sun-editor .se-btn-primary:focus,.sun-editor .se-btn-primary:hover{color:#000;background-color:#80bdff;border-color:#3f9dff;outline:0 none}.sun-editor .se-btn-primary:active{color:#fff;background-color:#3f9dff;border-color:#4592ff;-webkit-box-shadow:inset 0 3px 5px #4592ff;box-shadow:inset 0 3px 5px #4592ff}.sun-editor .se-btn:enabled.active{color:#4592ff;outline:0 none}.sun-editor .se-btn:enabled.active:focus,.sun-editor .se-btn:enabled.active:hover{background-color:#e1e1e1;border-color:#d1d1d1;outline:0 none}.sun-editor .se-btn:enabled.active:active{background-color:#d1d1d1;border-color:#c1c1c1;-webkit-box-shadow:inset 0 3px 5px #c1c1c1;box-shadow:inset 0 3px 5px #c1c1c1}.sun-editor .se-btn:enabled.on{background-color:#e1e1e1;border-color:#d1d1d1;outline:0 none}.sun-editor .se-btn:enabled.on:focus,.sun-editor .se-btn:enabled.on:hover{background-color:#d1d1d1;border-color:#c1c1c1;outline:0 none}.sun-editor .se-btn:enabled.on:active{background-color:#c1c1c1;border-color:#b1b1b1;-webkit-box-shadow:inset 0 3px 5px #b1b1b1;box-shadow:inset 0 3px 5px #b1b1b1}.sun-editor .se-btn-list:disabled,.sun-editor .se-btn:disabled,.sun-editor button:disabled{cursor:not-allowed;background-color:inherit;color:#bdbdbd}.sun-editor .se-loading-box{position:absolute;display:none;width:100%;height:100%;top:0;left:0;background-color:#fff;opacity:.7;filter:alpha(opacity=70);z-index:2147483647}.sun-editor .se-loading-box .se-loading-effect{position:absolute;display:block;top:50%;left:50%;height:25px;width:25px;border-top:2px solid #07d;border-right:2px solid transparent;border-radius:50%;animation:spinner .8s linear infinite;margin:-25px 0 0 -25px}.sun-editor .se-toolbar{display:block;position:relative;height:auto;width:100%;overflow:visible;padding:4px 3px 0;margin:0;background-color:#fafafa;outline:1px solid #dadada;z-index:5}.sun-editor .se-toolbar-cover{position:absolute;display:none;font-size:36px;width:100%;height:100%;top:0;left:0;background-color:#fefefe;opacity:.5;filter:alpha(opacity=50);cursor:not-allowed;z-index:4}.sun-editor .se-toolbar-separator-vertical{display:inline-block;height:0;width:0;margin:2px;vertical-align:top}.sun-editor .se-toolbar.se-toolbar-balloon,.sun-editor .se-toolbar.se-toolbar-inline{display:none;position:absolute;z-index:2147483647;box-shadow:0 3px 9px rgba(0,0,0,.5);-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5)}.sun-editor .se-toolbar.se-toolbar-balloon{width:auto}.sun-editor .se-toolbar.se-toolbar-sticky{position:fixed;top:0}.sun-editor .se-toolbar-sticky-dummy{display:none;position:static;z-index:-1}.sun-editor .se-btn-module{display:inline-block}.sun-editor .se-btn-module-border{border:1px solid #dadada;border-radius:4px}.sun-editor .se-btn-module-enter{display:block;width:100%;height:1px;margin-bottom:5px;background-color:transparent}.sun-editor .se-menu-list,.sun-editor .se-menu-list li{float:left;padding:0;margin:0}.sun-editor .se-menu-list li{position:relative}.sun-editor .se-btn-select{width:auto;display:flex;text-align:left;padding:4px 6px}.sun-editor .se-btn-select .txt{flex:5;float:left;text-align:left}.sun-editor .se-btn-select .se-icon-arrow-down{flex:1;float:right}.sun-editor .se-btn-select.se-btn-tool-font{width:100px}.sun-editor .se-btn-select.se-btn-tool-format,.sun-editor .se-btn-select.se-btn-tool-size{width:80px}.sun-editor .se-list-layer{display:none;position:absolute;top:37px;z-index:4;left:1px;border:1px solid #bababa;border-radius:4px;padding:6px 0;background-color:#fff;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);outline:0 none}.sun-editor .se-list-layer .se-list-inner{padding:0;margin:0;overflow-x:initial;overflow-y:initial;overflow:visible}.sun-editor .se-list-layer button{margin:0;width:100%}.sun-editor .se-list-inner .se-list-basic{width:100%;padding:0}.sun-editor .se-list-inner .se-list-basic li{width:100%}.sun-editor .se-list-inner .se-list-basic li>button{min-width:100%;width:max-content}.sun-editor .se-list-inner .se-list-basic li button.active{background-color:#80bdff;border:1px solid #3f9dff;border-left:0;border-right:0}.sun-editor .se-list-inner .se-list-basic li button.active:active{background-color:#3f9dff;border:1px solid #4592ff;border-left:0;border-right:0;-webkit-box-shadow:inset 0 3px 5px #4592ff;box-shadow:inset 0 3px 5px #4592ff}.sun-editor .se-btn-list{width:100%;height:auto;min-height:32px;max-height:100px;padding:0 14px;cursor:pointer;font-size:12px;line-height:normal;text-indent:0;text-decoration:none;text-align:left}.sun-editor .se-btn-list.default_value{background-color:#f3f3f3;border-top:1px dotted #b1b1b1;border-bottom:1px dotted #b1b1b1}.sun-editor .se-btn-list:focus,.sun-editor .se-btn-list:hover{background-color:#e1e1e1;border-color:#d1d1d1;outline:0 none}.sun-editor .se-btn-list:active{background-color:#d1d1d1;border-color:#c1c1c1;-webkit-box-shadow:inset 0 3px 5px #c1c1c1;box-shadow:inset 0 3px 5px #c1c1c1}.sun-editor .se-list-layer .se-list-font-family{min-width:156px}.sun-editor .se-list-layer .se-list-font-family .default{border-bottom:1px solid #ccc}.sun-editor .se-list-layer .se-list-format{min-width:156px}.sun-editor .se-list-layer .se-list-format li{padding:0;width:100%}.sun-editor .se-list-layer .se-list-format .se-btn-list{line-height:100%}.sun-editor .se-list-layer .se-list-format .se-btn-list[data-value=h1]{height:40px}.sun-editor .se-list-layer .se-list-format .se-btn-list[data-value=h2]{height:34px}.sun-editor .se-list-layer .se-list-format div,.sun-editor .se-list-layer .se-list-format p{font-size:13px}.sun-editor .se-list-layer .se-list-format h1{font-size:2em;font-weight:700;color:#333}.sun-editor .se-list-layer .se-list-format h2{font-size:1.5em;font-weight:700;color:#333}.sun-editor .se-list-layer .se-list-format h3{font-size:1.17em;font-weight:700;color:#333}.sun-editor .se-list-layer .se-list-format h4{font-size:1em;font-weight:700;color:#333}.sun-editor .se-list-layer .se-list-format h5{font-size:.83em;font-weight:700;color:#333}.sun-editor .se-list-layer .se-list-format h6{font-size:.67em;font-weight:700;color:#333}.sun-editor .se-list-layer .se-list-format blockquote{font-size:13px;color:#999;height:22px;margin:0;background-color:transparent;line-height:1.5;border-color:#b1b1b1;padding:0 0 0 7px;border-left:5px #b1b1b1;border-style:solid}.sun-editor .se-list-layer .se-list-format pre{font-size:13px;color:#666;padding:4px 11px;margin:0;background-color:#f9f9f9;border:1px solid #e1e1e1;border-radius:4px}.sun-editor .se-list-layer .se-list-font-size{min-width:140px;max-height:300px;overflow-x:hidden;overflow-y:auto}.sun-editor .se-list-layer .se-list-line{width:125px}.sun-editor .se-list-layer .se-list-align{left:9px;width:125px}.sun-editor .se-list-layer .se-list-align .se-btn-align>span{display:inline-block;width:14px;height:32px;margin:-1px 10px 0 0;vertical-align:middle}.sun-editor .se-list-layer .se-list-format div{padding:4px 2px}.sun-editor .se-selector-table{display:none;position:absolute;top:34px;left:1px;z-index:4;padding:5px 0;float:left;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.sun-editor .se-selector-table .se-table-size{font-size:18px;padding:0 5px}.sun-editor .se-selector-table .se-table-size-picker{position:absolute!important;z-index:3;font-size:18px;width:10em;height:10em;cursor:pointer}.sun-editor .se-selector-table .se-table-size-highlighted{position:absolute!important;z-index:2;font-size:18px;width:1em;height:1em;background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo4QTZCNzMzN0I3RUYxMUU4ODcwQ0QwMjM1NTgzRTJDNyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo4QTZCNzMzNkI3RUYxMUU4ODcwQ0QwMjM1NTgzRTJDNyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0MzYyNEUxRUI3RUUxMUU4ODZGQzgwRjNBODgyNTdFOSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0MzYyNEUxRkI3RUUxMUU4ODZGQzgwRjNBODgyNTdFOSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pl0yAuwAAABBSURBVDhPY/wPBAxUAGCDGvdBeWSAeicIDTfIXREiQArYeR9hEBOEohyMGkQYjBpEGAxjg6ib+yFMygCVvMbAAABj0hwMTNeKJwAAAABJRU5ErkJggg==") repeat}.sun-editor .se-selector-table .se-table-size-unhighlighted{position:relative!important;z-index:1;font-size:18px;width:5em;height:5em;background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASAgMAAAAroGbEAAAACVBMVEUAAIj4+Pjp6ekKlAqjAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfYAR0BKhmnaJzPAAAAG0lEQVQI12NgAAOtVatWMTCohoaGUY+EmIkEAEruEzK2J7tvAAAAAElFTkSuQmCC") repeat}.sun-editor .se-selector-table .se-table-size-display{padding-left:5px}.sun-editor .se-list-layer .se-selector-color{display:flex;width:max-content;max-width:270px;height:auto;padding:0;margin:auto}.sun-editor .se-list-layer .se-selector-color .se-color-pallet{width:100%;height:100%;padding:0}.sun-editor .se-list-layer .se-selector-color .se-color-pallet li{display:flex;float:left;position:relative;margin:0}.sun-editor .se-list-layer .se-selector-color .se-color-pallet button{display:block;cursor:default;width:30px;height:30px;text-indent:-9999px}.sun-editor .se-list-layer .se-selector-color .se-color-pallet button.active,.sun-editor .se-list-layer .se-selector-color .se-color-pallet button:focus,.sun-editor .se-list-layer .se-selector-color .se-color-pallet button:hover{border:3px solid #fff}.sun-editor .se-submenu-form-group{display:flex;width:100%;height:auto;padding:4px}.sun-editor .se-submenu-form-group input{flex:auto;display:inline-block;width:auto;height:33px;color:#555;font-size:12px;margin:1px 0;padding:0;border-radius:.25rem;border:1px solid #ccc}.sun-editor .se-submenu-form-group input:focus{border-color:#80bdff;outline:0;-webkit-box-shadow:0 0 0 .2rem #c7deff;box-shadow:0 0 0 .2rem #c7deff}.sun-editor .se-submenu-form-group button{float:right;width:35px;height:35px;margin:0 0 0 4px!important}.sun-editor .se-submenu-form-group button.se-btn{border:1px solid #ccc}.sun-editor .se-submenu-form-group>div{position:relative}.sun-editor .se-submenu-form-group .se-color-input{width:72px;text-transform:uppercase;border:none;border-bottom:2px solid #b1b1b1;outline:none}.sun-editor .se-submenu-form-group .se-color-input:focus{outline:none;border-bottom:3px solid #b1b1b1;-webkit-box-shadow:none;box-shadow:none}.sun-editor .se-wrapper{position:relative!important;width:100%;height:auto;overflow:hidden;z-index:1}.sun-editor .se-wrapper .se-wrapper-inner{width:100%;height:100%;min-height:65px;overflow-y:auto;overflow-x:auto;-webkit-overflow-scrolling:touch;user-select:text;-o-user-select:text;-moz-user-select:text;-khtml-user-select:text;-webkit-user-select:text;-ms-user-select:text}.sun-editor .se-wrapper .se-wrapper-inner:focus{outline:none}.sun-editor .se-wrapper .se-wrapper-code{background-color:#191919;color:#fff;font-size:13px;word-break:break-all;padding:0;margin:0}.sun-editor .se-wrapper .se-wrapper-wysiwyg{background-color:#fff}.sun-editor .se-wrapper .se-wrapper-code-mirror{font-size:13px}.sun-editor .se-wrapper .se-placeholder{position:absolute;display:none;white-space:nowrap;text-overflow:ellipsis;z-index:1;color:#b1b1b1;font-size:13px;line-height:1.5;top:0;left:0;right:0;overflow:hidden;margin-top:0;padding-top:16px;padding-left:16px;margin-left:0;padding-right:16px;margin-right:0;pointer-events:none;backface-visibility:hidden;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden}.sun-editor .se-resizing-bar{display:flex;width:auto;height:auto;min-height:16px;border-top:1px solid #dadada;padding:0 4px;background-color:#fafafa;cursor:ns-resize}.sun-editor .se-resizing-bar.se-resizing-none{cursor:default}.sun-editor .se-resizing-back{position:absolute;display:none;cursor:default;top:0;left:0;width:100%;height:100%;z-index:2147483647}.sun-editor .se-resizing-bar .se-navigation{flex:auto;position:relative;width:auto;height:auto;color:#666;margin:0;padding:0;font-size:10px;font-weight:700;line-height:1.5;background:transparent}.sun-editor .se-resizing-bar .se-char-counter-wrapper{flex:none;position:relative;display:block;width:auto;height:auto;margin:0;padding:0;font-size:10px;background:transparent}.sun-editor .se-resizing-bar .se-char-counter-wrapper span{color:#999;font-size:13px;font-family:Helvetica Neue,sans-serif}.sun-editor .se-resizing-bar .se-char-counter.se-blink{color:#b94a48;animation:blinker .2s linear infinite}.sun-editor .se-dialog{position:absolute;display:none;top:0;left:0;width:100%;height:100%;z-index:2147483647}.sun-editor .se-dialog button,.sun-editor .se-dialog input,.sun-editor .se-dialog label{font-size:14px;line-height:1.5;color:#111;margin:0}.sun-editor .se-dialog .se-dialog-back{background-color:#222;opacity:.5}.sun-editor .se-dialog .se-dialog-back,.sun-editor .se-dialog .se-dialog-inner{position:absolute;width:100%;height:100%;top:0;left:0}.sun-editor .se-dialog .se-dialog-inner .se-dialog-content{position:relative;width:auto;max-width:500px;margin:20px auto;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:4px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}@media screen and (max-width:509px){.sun-editor .se-dialog .se-dialog-inner .se-dialog-content{width:100%}}.sun-editor .se-dialog .se-dialog-inner .se-dialog-header{height:50px;padding:6px 15px;border-bottom:1px solid #e5e5e5}.sun-editor .se-dialog .se-dialog-inner .se-dialog-header .se-dialog-close{float:right;font-weight:700;text-shadow:0 1px 0 #fff;-webkit-appearance:none;filter:alpha(opacity=100);opacity:1}.sun-editor .se-dialog .se-dialog-inner .se-dialog-header .se-modal-title{font-size:14px;font-weight:700;margin:0;padding:0;line-height:2.5}.sun-editor .se-dialog .se-dialog-inner .se-dialog-body{position:relative;padding:15px}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form{margin-bottom:10px}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form-footer{margin-top:10px;margin-bottom:0}.sun-editor .se-dialog .se-dialog-inner input:disabled{background-color:#f3f3f3}.sun-editor .se-dialog .se-dialog-inner .se-dialog-size-text{width:100%}.sun-editor .se-dialog .se-dialog-inner .se-dialog-size-text .size-h,.sun-editor .se-dialog .se-dialog-inner .se-dialog-size-text .size-w{width:70px;text-align:center}.sun-editor .se-dialog .se-dialog-inner .se-dialog-size-x{margin:0 8px;width:25px;text-align:center}.sun-editor .se-dialog .se-dialog-inner .se-dialog-content label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}.sun-editor .se-dialog .se-dialog-inner .se-dialog-content .se-btn-primary{display:inline-block;padding:6px 12px;margin:0 0 10px!important;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;border-radius:4px}.sun-editor .se-dialog .se-dialog-inner .se-dialog-footer{padding:10px 15px 0;text-align:right;border-top:1px solid #e5e5e5}.sun-editor .se-dialog .se-dialog-inner .se-dialog-footer>div{float:left}.sun-editor .se-dialog .se-dialog-inner .se-dialog-footer>div>label{margin-top:5px}.sun-editor .se-dialog .se-dialog-inner .se-dialog-btn-radio{margin-left:12px;margin-right:6px}.sun-editor .se-dialog .se-dialog-inner .se-dialog-btn-check{margin-left:12px;margin-right:4px}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form-footer .se-dialog-btn-check{margin-left:0;margin-right:4px}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-control,.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-select{display:inline-block;width:70px;height:34px;font-size:14px;text-align:center;line-height:1.42857143;color:#000;border:1px solid #ccc;border-radius:4px;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-form{display:block;width:100%;height:34px;font-size:14px;line-height:1.42857143;padding:0 4px;color:#000;border:1px solid #ccc;border-radius:4px;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form input:focus,.sun-editor .se-dialog .se-dialog-inner .se-dialog-form select:focus,.sun-editor .se-dialog .se-dialog-inner .se-dialog-form textarea:focus{border-color:#80bdff;outline:0;-webkit-box-shadow:0 0 0 .2rem #c7deff;box-shadow:0 0 0 .2rem #c7deff}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-video-ratio{margin-left:4px}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form a{color:#004cff}.sun-editor .se-dialog .se-dialog-inner .se-dialog-btn-revert{border:1px solid #ccc}.sun-editor .se-dialog .se-dialog-inner .se-dialog-btn-revert:hover{background-color:#e1e1e1;border-color:#d1d1d1;outline:0 none}.sun-editor .se-dialog .se-dialog-inner .se-dialog-btn-revert:active{background-color:#d1d1d1;border-color:#c1c1c1;-webkit-box-shadow:inset 0 3px 5px #c1c1c1;box-shadow:inset 0 3px 5px #c1c1c1}.sun-editor .se-dialog-tabs{width:100%;height:25px;border-bottom:1px solid #e5e5e5}.sun-editor .se-dialog-tabs button{background-color:#e5e5e5;border-right:1px solid #e5e5e5;float:left;outline:none;padding:2px 13px;transition:.3s}.sun-editor .se-dialog-tabs button:hover{background-color:#fff}.sun-editor .se-dialog-tabs button.active{background-color:#fff;border-bottom:0}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-form.se-math-exp{resize:vertical!important;height:4rem;border:1px solid #ccc!important;font-size:13px}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-select.se-math-size{width:6em;height:28px;margin-left:1em}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-math-preview{font-size:13px}.sun-editor .se-controller .se-arrow.se-arrow-up{border-bottom-color:rgba(0,0,0,.25)}.sun-editor .se-controller{position:absolute;display:none;overflow:visible;z-index:4;border:1px solid rgba(0,0,0,.25);border-radius:4px;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.sun-editor .se-controller .se-btn-group{position:relative;display:flex;vertical-align:middle;padding:2px 2px 2px 0;top:0;left:0}.sun-editor .se-controller .se-btn-group .se-btn-group-sub{left:50%;min-width:auto;width:max-content;display:none}.sun-editor .se-controller .se-btn-group .se-btn-group-sub button{margin:0;min-width:72px}.sun-editor .se-controller .se-btn-group button{position:relative;min-height:35px;height:auto;border:none;border-radius:4px;border-top-right-radius:0;border-bottom-right-radius:0;margin:0 0 0 2px;padding:5px 10px;font-size:12px;line-height:1.5;display:inline-block;font-weight:400;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation}.sun-editor .se-controller .se-btn-group button:focus:enabled,.sun-editor .se-controller .se-btn-group button:hover:enabled{background-color:#e1e1e1;border-color:#d1d1d1;outline:0 none}.sun-editor .se-controller .se-btn-group button:active:enabled{background-color:#d1d1d1;border-color:#c1c1c1;-webkit-box-shadow:inset 0 3px 5px #c1c1c1;box-shadow:inset 0 3px 5px #c1c1c1}.sun-editor .se-controller .se-btn-group button span{display:block;padding:0;margin:0}.sun-editor .se-controller .se-btn-group button:enabled.active{color:#4592ff;outline:0 none}.sun-editor .se-controller .se-btn-group button:enabled.active:focus,.sun-editor .se-controller .se-btn-group button:enabled.active:hover{background-color:#e1e1e1;border-color:#d1d1d1;outline:0 none}.sun-editor .se-controller .se-btn-group button:enabled.active:active{background-color:#d1d1d1;border-color:#c1c1c1;-webkit-box-shadow:inset 0 3px 5px #c1c1c1;box-shadow:inset 0 3px 5px #c1c1c1}.sun-editor .se-controller .se-btn-group button:enabled.on{background-color:#e1e1e1;border-color:#d1d1d1;outline:0 none}.sun-editor .se-controller .se-btn-group button:enabled.on:focus,.sun-editor .se-controller .se-btn-group button:enabled.on:hover{background-color:#d1d1d1;border-color:#c1c1c1;outline:0 none}.sun-editor .se-controller .se-btn-group button:enabled.on:active{background-color:#c1c1c1;border-color:#b1b1b1;-webkit-box-shadow:inset 0 3px 5px #b1b1b1;box-shadow:inset 0 3px 5px #b1b1b1}.sun-editor .se-controller-resizing{margin-top:-50px!important;padding:0;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143}.sun-editor .se-controller-resizing .se-btn-group .se-btn-group-sub.se-resizing-align-list{left:57px}.sun-editor .se-resizing-container{position:absolute;display:none;z-index:4;border:1px solid #80bdff}.sun-editor .se-resizing-container .se-modal-resize{position:absolute;display:inline-block;background-color:#3f9dff;opacity:.3}.sun-editor .se-resizing-container .se-resize-dot{position:absolute;top:0;left:0;width:100%;height:100%}.sun-editor .se-resizing-container .se-resize-dot>span{position:absolute;width:7px;height:7px;background-color:#3f9dff;border:1px solid #4592ff}.sun-editor .se-resizing-container .se-resize-dot>span.tl{top:-5px;left:-5px;cursor:nw-resize}.sun-editor .se-resizing-container .se-resize-dot>span.tr{top:-5px;right:-5px;cursor:ne-resize}.sun-editor .se-resizing-container .se-resize-dot>span.bl{bottom:-5px;left:-5px;cursor:sw-resize}.sun-editor .se-resizing-container .se-resize-dot>span.br{right:-5px;bottom:-5px;cursor:se-resize}.sun-editor .se-resizing-container .se-resize-dot>span.lw{left:-7px;bottom:50%;cursor:w-resize}.sun-editor .se-resizing-container .se-resize-dot>span.th{left:50%;top:-7px;cursor:n-resize}.sun-editor .se-resizing-container .se-resize-dot>span.rw{right:-7px;bottom:50%;cursor:e-resize}.sun-editor .se-resizing-container .se-resize-dot>span.bh{right:50%;bottom:-7px;cursor:s-resize}.sun-editor .se-resizing-container .se-resize-display{position:absolute;right:0;bottom:0;padding:5px;margin:5px;font-size:12px;color:#fff;background-color:#333;border-radius:4px}.sun-editor .se-controller-table,.sun-editor .se-controller-table-cell{width:auto}.sun-editor .se-controller-link,.sun-editor .se-controller-table,.sun-editor .se-controller-table-cell{padding:0;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143}.sun-editor .se-controller-link:after,.sun-editor .se-controller-link:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.sun-editor .se-controller-link .link-content{padding:0;margin:0}.sun-editor .se-controller-link .link-content a{display:inline-block;color:#4592ff;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;margin-left:5px}.sun-editor .se-notice{position:relative;display:none;width:100%;height:auto;word-break:break-all;font-size:13px;color:#b94a48;background-color:#f2dede;padding:15px;margin:0;border:1px solid #eed3d7;user-select:text;-o-user-select:text;-moz-user-select:text;-khtml-user-select:text;-webkit-user-select:text;-ms-user-select:text}.sun-editor .se-notice button{float:right}.sun-editor .se-tooltip{position:relative;overflow:visible}.sun-editor .se-tooltip .se-tooltip-inner{visibility:hidden;position:absolute;display:block;width:auto;top:120%;left:50%;background:transparent;opacity:0;z-index:1;line-height:1.5;transition:opacity .5s;margin:0;padding:0;bottom:auto;float:none;pointer-events:none;backface-visibility:hidden;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden}.sun-editor .se-tooltip .se-tooltip-inner .se-tooltip-text{position:relative;display:inline-block;width:auto;left:-50%;font-size:.9em;margin:0;padding:4px 6px;border-radius:2px;background-color:#333;color:#fff;text-align:center;line-height:unset;white-space:nowrap;cursor:auto}.sun-editor .se-tooltip .se-tooltip-inner .se-tooltip-text:after{content:"";position:absolute;bottom:100%;left:50%;margin-left:-5px;border:5px solid transparent;border-bottom-color:#333}.sun-editor .se-tooltip:hover .se-tooltip-inner{visibility:visible;opacity:1}@keyframes blinker{50%{opacity:0}}@keyframes spinner{to{transform:rotate(1turn)}}.sun-editor-editable{font-family:Helvetica Neue,sans-serif;font-size:13px;line-height:1.5;color:#333;text-align:left;background-color:#fff;word-break:break-all;word-wrap:break-word;padding:16px;margin:0}.sun-editor-editable *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.sun-editor-editable audio,.sun-editor-editable figcaption,.sun-editor-editable figure,.sun-editor-editable iframe,.sun-editor-editable img,.sun-editor-editable td,.sun-editor-editable th,.sun-editor-editable video{position:relative}.sun-editor-editable .__se__float-left{float:left}.sun-editor-editable .__se__float-right{float:right}.sun-editor-editable .__se__float-center{float:center}.sun-editor-editable .__se__float-none{float:none}.sun-editor-editable span{display:inline;vertical-align:baseline;margin:0;padding:0}.sun-editor-editable a{color:#004cff;text-decoration:none}.sun-editor-editable span[style~="color:"] a{color:inherit}.sun-editor-editable a:focus,.sun-editor-editable a:hover{cursor:pointer;color:#0093ff;text-decoration:underline}.sun-editor-editable pre{display:block;padding:8px;margin:0 0 10px;line-height:1.45;color:#666;background-color:#f9f9f9;border:1px solid #e1e1e1;border-radius:2px;white-space:pre-wrap;word-wrap:break-word;overflow:visible}.sun-editor-editable ol{list-style-type:decimal}.sun-editor-editable ol,.sun-editor-editable ul{display:block;margin-block-start:1em;margin-block-end:1em;margin-inline-start:0;margin-inline-end:0;padding-inline-start:40px}.sun-editor-editable ul{list-style-type:disc}.sun-editor-editable li{display:list-item;text-align:-webkit-match-parent;margin-bottom:5px}.sun-editor-editable ol ol,.sun-editor-editable ol ul,.sun-editor-editable ul ol,.sun-editor-editable ul ul{margin:0}.sun-editor-editable ol ol,.sun-editor-editable ul ol{list-style-type:lower-alpha}.sun-editor-editable ol ol ol,.sun-editor-editable ul ol ol,.sun-editor-editable ul ul ol{list-style-type:upper-roman}.sun-editor-editable ol ul,.sun-editor-editable ul ul{list-style-type:circle}.sun-editor-editable ol ol ul,.sun-editor-editable ol ul ul,.sun-editor-editable ul ul ul{list-style-type:square}.sun-editor-editable sub,.sun-editor-editable sup{font-size:75%;line-height:0}.sun-editor-editable sub{vertical-align:sub}.sun-editor-editable sup{vertical-align:super}.sun-editor-editable p{display:block;margin:0 0 10px}.sun-editor-editable div{display:block;margin:0;padding:0}.sun-editor-editable blockquote{display:block;font-family:inherit;font-size:inherit;color:#999;margin-block-start:1em;margin-block-end:1em;margin-inline-start:0;margin-inline-end:0;padding:0 5px 0 20px;border:solid #b1b1b1;border-width:0 0 0 5px}.sun-editor-editable blockquote blockquote{border-color:#c1c1c1}.sun-editor-editable blockquote blockquote blockquote{border-color:#d1d1d1}.sun-editor-editable blockquote blockquote blockquote blockquote{border-color:#e1e1e1}.sun-editor-editable h1{font-size:2em;margin-block-start:.67em;margin-block-end:.67em}.sun-editor-editable h1,.sun-editor-editable h2{display:block;margin-inline-start:0;margin-inline-end:0;font-weight:700}.sun-editor-editable h2{font-size:1.5em;margin-block-start:.83em;margin-block-end:.83em}.sun-editor-editable h3{font-size:1.17em;margin-block-start:1em;margin-block-end:1em}.sun-editor-editable h3,.sun-editor-editable h4{display:block;margin-inline-start:0;margin-inline-end:0;font-weight:700}.sun-editor-editable h4{font-size:1em;margin-block-start:1.33em;margin-block-end:1.33em}.sun-editor-editable h5{font-size:.83em;margin-block-start:1.67em;margin-block-end:1.67em}.sun-editor-editable h5,.sun-editor-editable h6{display:block;margin-inline-start:0;margin-inline-end:0;font-weight:700}.sun-editor-editable h6{font-size:.67em;margin-block-start:2.33em;margin-block-end:2.33em}.sun-editor-editable hr{display:flex;border-width:1px 0 0;border-color:#000;border-image:initial;height:1px}.sun-editor-editable hr.__se__solid{border-style:solid none none}.sun-editor-editable hr.__se__dotted{border-style:dotted none none}.sun-editor-editable hr.__se__dashed{border-style:dashed none none}.sun-editor-editable table{display:table;table-layout:auto;border:1px solid #ccc;width:100%;max-width:100%;margin:0 0 10px;background-color:transparent;border-spacing:0;border-collapse:collapse}.sun-editor-editable table thead{border-bottom:2px solid #333}.sun-editor-editable table tr{border:1px solid #efefef}.sun-editor-editable table th{background-color:#f3f3f3}.sun-editor-editable table td,.sun-editor-editable table th{border:1px solid #e1e1e1;padding:.4em;background-clip:padding-box}.sun-editor-editable table td.se-table-selected-cell,.sun-editor-editable table th.se-table-selected-cell{border:1px double #4592ff;background-color:#f1f7ff}.sun-editor-editable.se-disabled *{user-select:none;-o-user-select:none;-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-ms-user-select:none}.sun-editor-editable .se-component{display:flex;padding:1px;margin:0 0 10px}.sun-editor-editable .se-component.__se__float-left{margin:0 20px 10px 0}.sun-editor-editable .se-component.__se__float-right{margin:0 0 10px 20px}.sun-editor-editable[contenteditable=true] .se-component{outline:1px dashed #e1e1e1}.sun-editor-editable audio,.sun-editor-editable iframe,.sun-editor-editable img,.sun-editor-editable video{display:block;margin:0;padding:0;width:auto;height:auto;max-width:100%}.sun-editor-editable[contenteditable=true] figure:after{position:absolute;content:"";z-index:1;top:0;left:0;right:0;bottom:0;cursor:default;display:block;background:transparent}.sun-editor-editable[contenteditable=true] figure a,.sun-editor-editable[contenteditable=true] figure iframe,.sun-editor-editable[contenteditable=true] figure img{z-index:0}.sun-editor-editable[contenteditable=true] figure figcaption{display:block;z-index:2}.sun-editor-editable .se-image-container,.sun-editor-editable .se-video-container{width:auto;height:auto;max-width:100%}.sun-editor-editable figure{display:block;outline:none;margin:0;padding:0}.sun-editor-editable figure figcaption{padding:1em .5em;margin:0;background-color:#f9f9f9;outline:none}.sun-editor-editable figure figcaption p{line-height:2;margin:0}.sun-editor-editable .se-image-container a img{padding:1px;margin:1px;outline:1px solid #4592ff}.sun-editor-editable .se-video-container iframe{outline:1px solid #9e9e9e;position:absolute;top:0;left:0;border:0;width:100%;height:100%}.sun-editor-editable .se-video-container figure{left:0;width:100%;max-width:100%}.sun-editor-editable.se-show-block div,.sun-editor-editable.se-show-block h1,.sun-editor-editable.se-show-block h2,.sun-editor-editable.se-show-block h3,.sun-editor-editable.se-show-block h4,.sun-editor-editable.se-show-block h5,.sun-editor-editable.se-show-block h6,.sun-editor-editable.se-show-block p{border:1px dashed #3f9dff!important;padding:10px 8px 8px!important}.se-show-block p{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAAPAQMAAAAF7dc0AAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAaSURBVAjXY/j/gwGCPvxg+F4BQiAGDP1HQQByxxw0gqOzIwAAAABJRU5ErkJggg==") no-repeat}.se-show-block div{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAPAQMAAAAxlBYoAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAmSURBVAjXY/j//wcDDH+8XsHwDYi/hwNx1A8w/nYLKH4XoQYJAwCXnSgcl2MOPgAAAABJRU5ErkJggg==") no-repeat}.se-show-block h1{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPAQMAAAA4f7ZSAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAfSURBVAjXY/j/v4EBhr+9B+LzEPrDeygfhI8j1CBhAEhmJGY4Rf6uAAAAAElFTkSuQmCC") no-repeat}.se-show-block h2{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPAQMAAAA4f7ZSAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAmSURBVAjXY/j/v4EBhr+dB+LtQPy9geEDEH97D8T3gbgdoQYJAwA51iPuD2haEAAAAABJRU5ErkJggg==") no-repeat}.se-show-block h3{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPAQMAAAA4f7ZSAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAiSURBVAjXY/j/v4EBhr+dB+LtQPy9geHDeQgN5p9HqEHCADeWI+69VG2MAAAAAElFTkSuQmCC") no-repeat}.se-show-block h4{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAPAQMAAADTSA1RAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAiSURBVAjXY/j//wADDH97DsTXIfjDdiDdDMTfIRhZHRQDAKJOJ6L+K3y7AAAAAElFTkSuQmCC") no-repeat}.se-show-block h5{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPAQMAAAA4f7ZSAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAlSURBVAjXY/j/v4EBhr+1A/F+IO5vYPiwHUh/B2IQfR6hBgkDABlWIy5uM+9GAAAAAElFTkSuQmCC") no-repeat}.se-show-block h6{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPAQMAAAA4f7ZSAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAiSURBVAjXY/j/v4EBhr+dB+LtQLy/geFDP5S9HSKOrA6KAR9GIza1ptJnAAAAAElFTkSuQmCC") no-repeat}.sun-editor-editable .__se__p-bordered,.sun-editor .__se__p-bordered{border-top:1px solid #b1b1b1;border-bottom:1px solid #b1b1b1;padding:4px 0}.sun-editor-editable .__se__p-spaced,.sun-editor .__se__p-spaced{letter-spacing:1px}.sun-editor-editable .__se__p-neon,.sun-editor .__se__p-neon{font-weight:200;font-style:italic;background:#000;color:#fff;padding:6px 4px;border:2px solid #fff;border-radius:6px;text-transform:uppercase;animation:neonFlicker 1.5s infinite alternate}@keyframes neonFlicker{0%,19%,21%,23%,25%,54%,56%,to{text-shadow:-.2rem -.2rem 1rem #fff,.2rem .2rem 1rem #fff,0 0 2px #f40,0 0 4px #f40,0 0 6px #f40,0 0 8px #f40,0 0 10px #f40;box-shadow:0 0 .5px #fff,inset 0 0 .5px #fff,0 0 2px #08f,inset 0 0 2px #08f,0 0 4px #08f,inset 0 0 4px #08f}20%,24%,55%{text-shadow:none;box-shadow:none}}.sun-editor-editable .__se__t-shadow,.sun-editor .__se__t-shadow{text-shadow:-.2rem -.2rem 1rem #fff,.2rem .2rem 1rem #fff,0 0 .2rem #999,0 0 .4rem #888,0 0 .6rem #777,0 0 .8rem #666,0 0 1rem #555} \ No newline at end of file +.sun-editor{width:auto;height:auto;box-sizing:border-box;font-family:Helvetica Neue,sans-serif;border:1px solid #dadada;text-align:left;background-color:#fff;color:#000;user-select:none;-o-user-select:none;-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-ms-user-select:none}.sun-editor *{box-sizing:border-box;-webkit-user-drag:none;overflow:visible}.sun-editor-common button,.sun-editor-common input,.sun-editor-common select,.sun-editor-common textarea{font-size:14px;line-height:1.5}.sun-editor-common blockquote,.sun-editor-common body,.sun-editor-common button,.sun-editor-common code,.sun-editor-common dd,.sun-editor-common div,.sun-editor-common dl,.sun-editor-common dt,.sun-editor-common fieldset,.sun-editor-common form,.sun-editor-common h1,.sun-editor-common h2,.sun-editor-common h3,.sun-editor-common h4,.sun-editor-common h5,.sun-editor-common h6,.sun-editor-common input,.sun-editor-common legend,.sun-editor-common li,.sun-editor-common ol,.sun-editor-common p,.sun-editor-common pre,.sun-editor-common select,.sun-editor-common td,.sun-editor-common textarea,.sun-editor-common th,.sun-editor-common ul{margin:0;padding:0;border:0}.sun-editor-common dl,.sun-editor-common li,.sun-editor-common menu,.sun-editor-common ol,.sun-editor-common ul{list-style:none!important}.sun-editor-common hr{margin:6px 0!important}.sun-editor textarea{resize:none!important;border:0!important}.sun-editor button{border:0;background-color:transparent;touch-action:manipulation;cursor:pointer;outline:none}.sun-editor button,.sun-editor input,.sun-editor select,.sun-editor textarea{vertical-align:middle}.sun-editor button span{display:block;margin:0;padding:0}.sun-editor button .txt{display:block;margin-top:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}@font-face{font-family:Suneditor-icon;src:url(../fonts/435801d088c67acdd4c667e00037f080.eot);src:url(../fonts/435801d088c67acdd4c667e00037f080.eot?#iefix) format("embedded-opentype"),url(../fonts/54469d382ec66ca4460d57a5f4a49b05.woff2) format("woff2"),url(../fonts/1d63e86b832ddfc4008baf6e69e7c39b.woff) format("woff"),url(../fonts/773c0f21a6a926b07f111a3892134dec.ttf) format("truetype"),url(../fonts/0b8f27509021ddc0f7d4ee103181bc05.svg#Suneditor-icon) format("svg");font-weight:400;font-style:normal}.sun-editor [class*=se-icon-]:before{-moz-osx-font-smoothing:grayscale;-webkit-font-smoothing:antialiased;font-family:Suneditor-icon;display:inline-block;font-style:normal;font-variant:normal;font-weight:400;text-rendering:auto;font-size:15px}.sun-editor button>svg{width:25px;height:25px;margin:5px}.sun-editor .se-toolbar button>i:before{line-height:2.1}.sun-editor .se-icon-align-justify:before{content:"A"}.sun-editor .se-icon-align-left:before{content:"B"}.sun-editor .se-icon-align-right:before{content:"C"}.sun-editor .se-icon-align-center:before{content:"D"}.sun-editor .se-icon-underline:before{content:"E"}.sun-editor .se-icon-bold:before{content:"F"}.sun-editor .se-icon-italic:before{content:"G"}.sun-editor .se-icon-strokethrough:before{content:"H"}.sun-editor .se-icon-subscript:before{content:"I"}.sun-editor .se-icon-superscript:before{content:"J"}.sun-editor .se-icon-redo:before{content:"K"}.sun-editor .se-icon-undo:before{content:"L"}.sun-editor .se-icon-erase:before{content:"M"}.sun-editor .se-icon-fontColor:before{content:"N"}.sun-editor .se-icon-hiliteColor:before{content:"O"}.sun-editor .se-icon-indent-left:before{content:"P"}.sun-editor .se-icon-indent-right:before{content:"Q"}.sun-editor .se-icon-list-bullets:before{content:"R"}.sun-editor .se-icon-list-number:before{content:"S"}.sun-editor .se-icon-grid:before{content:"T"}.sun-editor .se-icon-code-view:before{content:"U"}.sun-editor .se-icon-preview:before{content:"V"}.sun-editor .se-icon-showBlocks:before{content:"W"}.sun-editor .se-icon-expansion:before{content:"X"}.sun-editor .se-icon-reduction:before{content:"Y"}.sun-editor .se-icon-image:before{content:"Z"}.sun-editor .se-icon-link:before{content:"a"}.sun-editor .se-icon-auto-size:before{content:"b"}.sun-editor .se-icon-print:before{content:"c"}.sun-editor .se-icon-modify:before{content:"d"}.sun-editor .se-icon-revert:before{content:"e"}.sun-editor .se-icon-arrow-down:before{content:"f";font-size:10px}.sun-editor .se-icon-video:before{content:"g"}.sun-editor .se-icon-cancel:before{content:"h";font-size:10px}.sun-editor .se-icon-warning:before{content:"i"}.sun-editor .se-icon-insert-column-right:before{content:"j"}.sun-editor .se-icon-insert-row-below:before{content:"k"}.sun-editor .se-icon-insert-row-above:before{content:"l"}.sun-editor .se-icon-insert-column-left:before{content:"m"}.sun-editor .se-icon-delete-row:before{content:"n"}.sun-editor .se-icon-delete-column:before{content:"o"}.sun-editor .se-icon-unlink:before{content:"p"}.sun-editor .se-icon-empty-file:before{content:"q"}.sun-editor .se-icon-paragraph-style:before{content:"r"}.sun-editor .se-icon-delete:before{content:"s"}.sun-editor .se-icon-rotate-left:before{content:"t"}.sun-editor .se-icon-rotate-right:before{content:"u"}.sun-editor .se-icon-mirror-horizontal:before{content:"v"}.sun-editor .se-icon-mirror-vertical:before{content:"w"}.sun-editor .se-icon-save:before{content:"x"}.sun-editor .se-icon-hr:before{content:"y"}.sun-editor .se-icon-checked:before{content:"z"}.sun-editor .se-icon-table-header:before{content:"0"}.sun-editor .se-icon-merge-cell:before{content:"1"}.sun-editor .se-icon-split-cell:before{content:"2"}.sun-editor .se-icon-caption:before{content:"3"}.sun-editor .se-icon-edit:before{content:"4"}.sun-editor .se-icon-question:before{content:"5"}.sun-editor .se-icon-attachment:before{content:"6"}.sun-editor .se-icon-add:before{content:"7"}.sun-editor .se-icon-more-vertical:before{content:"8"}.sun-editor .se-icon-more-horizontal:before{content:"9"}.sun-editor .se-icon-map-pin:before{content:"!"}.sun-editor .se-icon-magic-stick:before{content:'"'}.sun-editor .se-icon-math:before{content:"#"}.sun-editor .se-icon-audio:before{content:"$"}.sun-editor .se-icon-emoji:before{content:"%"}.sun-editor .se-icon-template:before{content:"&"}.sun-editor .se-icon-line-height:before{content:"'"}.sun-editor .se-icon-text-style:before{content:"("}.sun-editor .se-arrow,.sun-editor .se-arrow:after{position:absolute;display:block;width:0;height:0;border:11px solid transparent}.sun-editor .se-arrow.se-arrow-up{top:-11px;left:20px;margin-left:-11px;border-top-width:0;border-bottom-color:rgba(0,0,0,.25)}.sun-editor .se-arrow.se-arrow-up:after{top:1px;margin-left:-11px;content:" ";border-top-width:0;border-bottom-color:#fff}.sun-editor .se-toolbar .se-arrow.se-arrow-up:after{border-bottom-color:#fafafa}.sun-editor .se-arrow.se-arrow-down{top:0;left:0;margin-left:-11px;border-bottom-width:0;border-top-color:rgba(0,0,0,.25)}.sun-editor .se-arrow.se-arrow-down:after{top:-12px;margin-left:-11px;content:" ";border-bottom-width:0;border-top-color:#fff}.sun-editor .se-toolbar .se-arrow.se-arrow-down:after{border-top-color:#fafafa}.sun-editor .se-container{position:relative;width:100%;height:100%}.sun-editor button{color:#000}.sun-editor .se-btn{float:left;width:35px;height:35px;border:0;border-radius:4px;margin:1px!important;padding:0;font-size:12px;line-height:27px}.sun-editor .se-btn:enabled:focus,.sun-editor .se-btn:enabled:hover{background-color:#e1e1e1;border-color:#d1d1d1;outline:0 none}.sun-editor .se-btn:enabled:active{background-color:#d1d1d1;border-color:#c1c1c1;-webkit-box-shadow:inset 0 3px 5px #c1c1c1;box-shadow:inset 0 3px 5px #c1c1c1}.sun-editor .se-btn-primary{color:#000;background-color:#c7deff;border:1px solid #80bdff;border-radius:4px}.sun-editor .se-btn-primary:focus,.sun-editor .se-btn-primary:hover{color:#000;background-color:#80bdff;border-color:#3f9dff;outline:0 none}.sun-editor .se-btn-primary:active{color:#fff;background-color:#3f9dff;border-color:#4592ff;-webkit-box-shadow:inset 0 3px 5px #4592ff;box-shadow:inset 0 3px 5px #4592ff}.sun-editor .se-btn:enabled.active{color:#4592ff;outline:0 none}.sun-editor .se-btn:enabled.active:focus,.sun-editor .se-btn:enabled.active:hover{background-color:#e1e1e1;border-color:#d1d1d1;outline:0 none}.sun-editor .se-btn:enabled.active:active{background-color:#d1d1d1;border-color:#c1c1c1;-webkit-box-shadow:inset 0 3px 5px #c1c1c1;box-shadow:inset 0 3px 5px #c1c1c1}.sun-editor .se-btn:enabled.on{background-color:#e1e1e1;border-color:#d1d1d1;outline:0 none}.sun-editor .se-btn:enabled.on:focus,.sun-editor .se-btn:enabled.on:hover{background-color:#d1d1d1;border-color:#c1c1c1;outline:0 none}.sun-editor .se-btn:enabled.on:active{background-color:#c1c1c1;border-color:#b1b1b1;-webkit-box-shadow:inset 0 3px 5px #b1b1b1;box-shadow:inset 0 3px 5px #b1b1b1}.sun-editor .se-btn-list:disabled,.sun-editor .se-btn:disabled,.sun-editor button:disabled{cursor:not-allowed;background-color:inherit;color:#bdbdbd}.sun-editor .se-loading-box{position:absolute;display:none;width:100%;height:100%;top:0;left:0;background-color:#fff;opacity:.7;filter:alpha(opacity=70);z-index:2147483647}.sun-editor .se-loading-box .se-loading-effect{position:absolute;display:block;top:50%;left:50%;height:25px;width:25px;border-top:2px solid #07d;border-right:2px solid transparent;border-radius:50%;animation:spinner .8s linear infinite;margin:-25px 0 0 -25px}.sun-editor .se-toolbar{display:block;position:relative;height:auto;width:100%;overflow:visible;padding:4px 3px 0;margin:0;background-color:#fafafa;outline:1px solid #dadada;z-index:5}.sun-editor .se-toolbar-cover{position:absolute;display:none;font-size:36px;width:100%;height:100%;top:0;left:0;background-color:#fefefe;opacity:.5;filter:alpha(opacity=50);cursor:not-allowed;z-index:4}.sun-editor .se-toolbar-separator-vertical{display:inline-block;height:0;width:0;margin:2px;vertical-align:top}.sun-editor .se-toolbar.se-toolbar-balloon,.sun-editor .se-toolbar.se-toolbar-inline{display:none;position:absolute;z-index:2147483647;box-shadow:0 3px 9px rgba(0,0,0,.5);-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5)}.sun-editor .se-toolbar.se-toolbar-balloon{width:auto}.sun-editor .se-toolbar.se-toolbar-sticky{position:fixed;top:0}.sun-editor .se-toolbar-sticky-dummy{display:none;position:static;z-index:-1}.sun-editor .se-btn-module{display:inline-block}.sun-editor .se-btn-module-border{border:1px solid #dadada;border-radius:4px}.sun-editor .se-btn-module-enter{display:block;width:100%;height:1px;margin-bottom:5px;background-color:transparent}.sun-editor .se-menu-list,.sun-editor .se-menu-list li{float:left;padding:0;margin:0}.sun-editor .se-menu-list li{position:relative}.sun-editor .se-btn-select{width:auto;display:flex;text-align:left;padding:4px 6px}.sun-editor .se-btn-select .txt{flex:5;float:left;text-align:left}.sun-editor .se-btn-select .se-icon-arrow-down{flex:1;float:right}.sun-editor .se-btn-select.se-btn-tool-font{width:100px}.sun-editor .se-btn-select.se-btn-tool-format,.sun-editor .se-btn-select.se-btn-tool-size{width:80px}.sun-editor .se-list-layer{display:none;position:absolute;top:37px;z-index:4;left:1px;border:1px solid #bababa;border-radius:4px;padding:6px 0;background-color:#fff;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5);outline:0 none}.sun-editor .se-list-layer .se-list-inner{padding:0;margin:0;overflow-x:initial;overflow-y:initial;overflow:visible}.sun-editor .se-list-layer button{margin:0;width:100%}.sun-editor .se-list-inner .se-list-basic{width:100%;padding:0}.sun-editor .se-list-inner .se-list-basic li{width:100%}.sun-editor .se-list-inner .se-list-basic li>button{min-width:100%;width:max-content}.sun-editor .se-list-inner .se-list-basic li button.active{background-color:#80bdff;border:1px solid #3f9dff;border-left:0;border-right:0}.sun-editor .se-list-inner .se-list-basic li button.active:active{background-color:#3f9dff;border:1px solid #4592ff;border-left:0;border-right:0;-webkit-box-shadow:inset 0 3px 5px #4592ff;box-shadow:inset 0 3px 5px #4592ff}.sun-editor .se-btn-list{width:100%;height:auto;min-height:32px;max-height:100px;padding:0 14px;cursor:pointer;font-size:12px;line-height:normal;text-indent:0;text-decoration:none;text-align:left}.sun-editor .se-btn-list.default_value{background-color:#f3f3f3;border-top:1px dotted #b1b1b1;border-bottom:1px dotted #b1b1b1}.sun-editor .se-btn-list:focus,.sun-editor .se-btn-list:hover{background-color:#e1e1e1;border-color:#d1d1d1;outline:0 none}.sun-editor .se-btn-list:active{background-color:#d1d1d1;border-color:#c1c1c1;-webkit-box-shadow:inset 0 3px 5px #c1c1c1;box-shadow:inset 0 3px 5px #c1c1c1}.sun-editor .se-list-layer .se-list-font-family{min-width:156px}.sun-editor .se-list-layer .se-list-font-family .default{border-bottom:1px solid #ccc}.sun-editor .se-list-layer .se-list-format{min-width:156px}.sun-editor .se-list-layer .se-list-format li{padding:0;width:100%}.sun-editor .se-list-layer .se-list-format .se-btn-list{line-height:100%}.sun-editor .se-list-layer .se-list-format .se-btn-list[data-value=h1]{height:40px}.sun-editor .se-list-layer .se-list-format .se-btn-list[data-value=h2]{height:34px}.sun-editor .se-list-layer .se-list-format div,.sun-editor .se-list-layer .se-list-format p{font-size:13px}.sun-editor .se-list-layer .se-list-format h1{font-size:2em;font-weight:700;color:#333}.sun-editor .se-list-layer .se-list-format h2{font-size:1.5em;font-weight:700;color:#333}.sun-editor .se-list-layer .se-list-format h3{font-size:1.17em;font-weight:700;color:#333}.sun-editor .se-list-layer .se-list-format h4{font-size:1em;font-weight:700;color:#333}.sun-editor .se-list-layer .se-list-format h5{font-size:.83em;font-weight:700;color:#333}.sun-editor .se-list-layer .se-list-format h6{font-size:.67em;font-weight:700;color:#333}.sun-editor .se-list-layer .se-list-format blockquote{font-size:13px;color:#999;height:22px;margin:0;background-color:transparent;line-height:1.5;border-color:#b1b1b1;padding:0 0 0 7px;border-left:5px #b1b1b1;border-style:solid}.sun-editor .se-list-layer .se-list-format pre{font-size:13px;color:#666;padding:4px 11px;margin:0;background-color:#f9f9f9;border:1px solid #e1e1e1;border-radius:4px}.sun-editor .se-list-layer .se-list-font-size{min-width:140px;max-height:300px;overflow-x:hidden;overflow-y:auto}.sun-editor .se-list-layer .se-list-line{width:125px}.sun-editor .se-list-layer .se-list-align{left:9px;width:125px}.sun-editor .se-list-layer .se-list-align .se-btn-align>span{display:inline-block;width:14px;height:32px;margin:-1px 10px 0 0;vertical-align:middle}.sun-editor .se-list-layer .se-list-format div{padding:4px 2px}.sun-editor .se-selector-table{display:none;position:absolute;top:34px;left:1px;z-index:4;padding:5px 0;float:left;margin:2px 0 0;font-size:14px;text-align:left;list-style:none;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid #ccc;border-radius:4px;-webkit-box-shadow:0 6px 12px rgba(0,0,0,.175);box-shadow:0 6px 12px rgba(0,0,0,.175)}.sun-editor .se-selector-table .se-table-size{font-size:18px;padding:0 5px}.sun-editor .se-selector-table .se-table-size-picker{position:absolute!important;z-index:3;font-size:18px;width:10em;height:10em;cursor:pointer}.sun-editor .se-selector-table .se-table-size-highlighted{position:absolute!important;z-index:2;font-size:18px;width:1em;height:1em;background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASCAYAAABWzo5XAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAAZdEVYdFNvZnR3YXJlAEFkb2JlIEltYWdlUmVhZHlxyWU8AAADJmlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDIgNzkuMTYwOTI0LCAyMDE3LzA3LzEzLTAxOjA2OjM5ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo4QTZCNzMzN0I3RUYxMUU4ODcwQ0QwMjM1NTgzRTJDNyIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo4QTZCNzMzNkI3RUYxMUU4ODcwQ0QwMjM1NTgzRTJDNyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ0MgMjAxOCAoV2luZG93cykiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDo0MzYyNEUxRUI3RUUxMUU4ODZGQzgwRjNBODgyNTdFOSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDo0MzYyNEUxRkI3RUUxMUU4ODZGQzgwRjNBODgyNTdFOSIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/Pl0yAuwAAABBSURBVDhPY/wPBAxUAGCDGvdBeWSAeicIDTfIXREiQArYeR9hEBOEohyMGkQYjBpEGAxjg6ib+yFMygCVvMbAAABj0hwMTNeKJwAAAABJRU5ErkJggg==") repeat}.sun-editor .se-selector-table .se-table-size-unhighlighted{position:relative!important;z-index:1;font-size:18px;width:5em;height:5em;background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAASAgMAAAAroGbEAAAACVBMVEUAAIj4+Pjp6ekKlAqjAAAAAXRSTlMAQObYZgAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfYAR0BKhmnaJzPAAAAG0lEQVQI12NgAAOtVatWMTCohoaGUY+EmIkEAEruEzK2J7tvAAAAAElFTkSuQmCC") repeat}.sun-editor .se-selector-table .se-table-size-display{padding-left:5px}.sun-editor .se-list-layer .se-selector-color{display:flex;width:max-content;max-width:270px;height:auto;padding:0;margin:auto}.sun-editor .se-list-layer .se-selector-color .se-color-pallet{width:100%;height:100%;padding:0}.sun-editor .se-list-layer .se-selector-color .se-color-pallet li{display:flex;float:left;position:relative;margin:0}.sun-editor .se-list-layer .se-selector-color .se-color-pallet button{display:block;cursor:default;width:30px;height:30px;text-indent:-9999px}.sun-editor .se-list-layer .se-selector-color .se-color-pallet button.active,.sun-editor .se-list-layer .se-selector-color .se-color-pallet button:focus,.sun-editor .se-list-layer .se-selector-color .se-color-pallet button:hover{border:3px solid #fff}.sun-editor .se-submenu-form-group{display:flex;width:100%;height:auto;padding:4px}.sun-editor .se-submenu-form-group input{flex:auto;display:inline-block;width:auto;height:33px;color:#555;font-size:12px;margin:1px 0;padding:0;border-radius:.25rem;border:1px solid #ccc}.sun-editor .se-submenu-form-group input:focus{border-color:#80bdff;outline:0;-webkit-box-shadow:0 0 0 .2rem #c7deff;box-shadow:0 0 0 .2rem #c7deff}.sun-editor .se-submenu-form-group button{float:right;width:35px;height:35px;margin:0 0 0 4px!important}.sun-editor .se-submenu-form-group button.se-btn{border:1px solid #ccc}.sun-editor .se-submenu-form-group>div{position:relative}.sun-editor .se-submenu-form-group .se-color-input{width:72px;text-transform:uppercase;border:none;border-bottom:2px solid #b1b1b1;outline:none}.sun-editor .se-submenu-form-group .se-color-input:focus{outline:none;border-bottom:3px solid #b1b1b1;-webkit-box-shadow:none;box-shadow:none}.sun-editor .se-wrapper{position:relative!important;width:100%;height:auto;overflow:hidden;z-index:1}.sun-editor .se-wrapper .se-wrapper-inner{width:100%;height:100%;min-height:65px;overflow-y:auto;overflow-x:auto;-webkit-overflow-scrolling:touch;user-select:text;-o-user-select:text;-moz-user-select:text;-khtml-user-select:text;-webkit-user-select:text;-ms-user-select:text}.sun-editor .se-wrapper .se-wrapper-inner:focus{outline:none}.sun-editor .se-wrapper .se-wrapper-code{background-color:#191919;color:#fff;font-size:13px;word-break:break-all;padding:0;margin:0}.sun-editor .se-wrapper .se-wrapper-wysiwyg{background-color:#fff}.sun-editor .se-wrapper .se-wrapper-code-mirror{font-size:13px}.sun-editor .se-wrapper .se-placeholder{position:absolute;display:none;white-space:nowrap;text-overflow:ellipsis;z-index:1;color:#b1b1b1;font-size:13px;line-height:1.5;top:0;left:0;right:0;overflow:hidden;margin-top:0;padding-top:16px;padding-left:16px;margin-left:0;padding-right:16px;margin-right:0;pointer-events:none;backface-visibility:hidden;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden}.sun-editor .se-resizing-bar{display:flex;width:auto;height:auto;min-height:16px;border-top:1px solid #dadada;padding:0 4px;background-color:#fafafa;cursor:ns-resize}.sun-editor .se-resizing-bar.se-resizing-none{cursor:default}.sun-editor .se-resizing-back{position:absolute;display:none;cursor:default;top:0;left:0;width:100%;height:100%;z-index:2147483647}.sun-editor .se-resizing-bar .se-navigation{flex:auto;position:relative;width:auto;height:auto;color:#666;margin:0;padding:0;font-size:10px;font-weight:700;line-height:1.5;background:transparent}.sun-editor .se-resizing-bar .se-char-counter-wrapper{flex:none;position:relative;display:block;width:auto;height:auto;margin:0;padding:0;font-size:10px;background:transparent}.sun-editor .se-resizing-bar .se-char-counter-wrapper span{color:#999;font-size:13px;font-family:Helvetica Neue,sans-serif}.sun-editor .se-resizing-bar .se-char-counter.se-blink{color:#b94a48;animation:blinker .2s linear infinite}.sun-editor .se-dialog{position:absolute;display:none;top:0;left:0;width:100%;height:100%;z-index:2147483647}.sun-editor .se-dialog button,.sun-editor .se-dialog input,.sun-editor .se-dialog label{font-size:14px;line-height:1.5;color:#111;margin:0}.sun-editor .se-dialog .se-dialog-back{background-color:#222;opacity:.5}.sun-editor .se-dialog .se-dialog-back,.sun-editor .se-dialog .se-dialog-inner{position:absolute;width:100%;height:100%;top:0;left:0}.sun-editor .se-dialog .se-dialog-inner .se-dialog-content{position:relative;width:auto;max-width:500px;margin:20px auto;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;border:1px solid rgba(0,0,0,.2);border-radius:4px;outline:0;-webkit-box-shadow:0 3px 9px rgba(0,0,0,.5);box-shadow:0 3px 9px rgba(0,0,0,.5)}@media screen and (max-width:509px){.sun-editor .se-dialog .se-dialog-inner .se-dialog-content{width:100%}}.sun-editor .se-dialog .se-dialog-inner .se-dialog-header{height:50px;padding:6px 15px;border-bottom:1px solid #e5e5e5}.sun-editor .se-dialog .se-dialog-inner .se-dialog-header .se-dialog-close{float:right;font-weight:700;text-shadow:0 1px 0 #fff;-webkit-appearance:none;filter:alpha(opacity=100);opacity:1}.sun-editor .se-dialog .se-dialog-inner .se-dialog-header .se-modal-title{font-size:14px;font-weight:700;margin:0;padding:0;line-height:2.5}.sun-editor .se-dialog .se-dialog-inner .se-dialog-body{position:relative;padding:15px}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form{margin-bottom:10px}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form-footer{margin-top:10px;margin-bottom:0}.sun-editor .se-dialog .se-dialog-inner input:disabled{background-color:#f3f3f3}.sun-editor .se-dialog .se-dialog-inner .se-dialog-size-text{width:100%}.sun-editor .se-dialog .se-dialog-inner .se-dialog-size-text .size-h,.sun-editor .se-dialog .se-dialog-inner .se-dialog-size-text .size-w{width:70px;text-align:center}.sun-editor .se-dialog .se-dialog-inner .se-dialog-size-x{margin:0 8px;width:25px;text-align:center}.sun-editor .se-dialog .se-dialog-inner .se-dialog-content label{display:inline-block;max-width:100%;margin-bottom:5px;font-weight:700}.sun-editor .se-dialog .se-dialog-inner .se-dialog-content .se-btn-primary{display:inline-block;padding:6px 12px;margin:0 0 10px!important;font-size:14px;font-weight:400;line-height:1.42857143;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation;border-radius:4px}.sun-editor .se-dialog .se-dialog-inner .se-dialog-footer{padding:10px 15px 0;text-align:right;border-top:1px solid #e5e5e5}.sun-editor .se-dialog .se-dialog-inner .se-dialog-footer>div{float:left}.sun-editor .se-dialog .se-dialog-inner .se-dialog-footer>div>label{margin-top:5px}.sun-editor .se-dialog .se-dialog-inner .se-dialog-btn-radio{margin-left:12px;margin-right:6px}.sun-editor .se-dialog .se-dialog-inner .se-dialog-btn-check{margin-left:12px;margin-right:4px}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form-footer .se-dialog-btn-check{margin-left:0;margin-right:4px}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-control,.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-select{display:inline-block;width:70px;height:34px;font-size:14px;text-align:center;line-height:1.42857143;color:#000;border:1px solid #ccc;border-radius:4px;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-form{display:block;width:100%;height:34px;font-size:14px;line-height:1.42857143;padding:0 4px;color:#000;border:1px solid #ccc;border-radius:4px;transition:border-color .15s ease-in-out,box-shadow .15s ease-in-out}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form input:focus,.sun-editor .se-dialog .se-dialog-inner .se-dialog-form select:focus,.sun-editor .se-dialog .se-dialog-inner .se-dialog-form textarea:focus{border-color:#80bdff;outline:0;-webkit-box-shadow:0 0 0 .2rem #c7deff;box-shadow:0 0 0 .2rem #c7deff}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-video-ratio{margin-left:4px}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form a{color:#004cff}.sun-editor .se-dialog .se-dialog-inner .se-dialog-btn-revert{border:1px solid #ccc}.sun-editor .se-dialog .se-dialog-inner .se-dialog-btn-revert:hover{background-color:#e1e1e1;border-color:#d1d1d1;outline:0 none}.sun-editor .se-dialog .se-dialog-inner .se-dialog-btn-revert:active{background-color:#d1d1d1;border-color:#c1c1c1;-webkit-box-shadow:inset 0 3px 5px #c1c1c1;box-shadow:inset 0 3px 5px #c1c1c1}.sun-editor .se-dialog-tabs{width:100%;height:25px;border-bottom:1px solid #e5e5e5}.sun-editor .se-dialog-tabs button{background-color:#e5e5e5;border-right:1px solid #e5e5e5;float:left;outline:none;padding:2px 13px;transition:.3s}.sun-editor .se-dialog-tabs button:hover{background-color:#fff}.sun-editor .se-dialog-tabs button.active{background-color:#fff;border-bottom:0}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-form.se-math-exp{resize:vertical!important;height:4rem;border:1px solid #ccc!important;font-size:13px}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-input-select.se-math-size{width:6em;height:28px;margin-left:1em}.sun-editor .se-dialog .se-dialog-inner .se-dialog-form .se-math-preview{font-size:13px}.sun-editor .se-controller .se-arrow.se-arrow-up{border-bottom-color:rgba(0,0,0,.25)}.sun-editor .se-controller{position:absolute;display:none;overflow:visible;z-index:4;border:1px solid rgba(0,0,0,.25);border-radius:4px;text-align:start;text-decoration:none;text-shadow:none;text-transform:none;letter-spacing:normal;word-break:normal;word-spacing:normal;word-wrap:normal;white-space:normal;background-color:#fff;-webkit-background-clip:padding-box;background-clip:padding-box;-webkit-box-shadow:0 5px 10px rgba(0,0,0,.2);box-shadow:0 5px 10px rgba(0,0,0,.2);line-break:auto}.sun-editor .se-controller .se-btn-group{position:relative;display:flex;vertical-align:middle;padding:2px 2px 2px 0;top:0;left:0}.sun-editor .se-controller .se-btn-group .se-btn-group-sub{left:50%;min-width:auto;width:max-content;display:none}.sun-editor .se-controller .se-btn-group .se-btn-group-sub button{margin:0;min-width:72px}.sun-editor .se-controller .se-btn-group button{position:relative;min-height:35px;height:auto;border:none;border-radius:4px;border-top-right-radius:0;border-bottom-right-radius:0;margin:0 0 0 2px;padding:5px 10px;font-size:12px;line-height:1.5;display:inline-block;font-weight:400;text-align:center;white-space:nowrap;vertical-align:middle;-ms-touch-action:manipulation;touch-action:manipulation}.sun-editor .se-controller .se-btn-group button:focus:enabled,.sun-editor .se-controller .se-btn-group button:hover:enabled{background-color:#e1e1e1;border-color:#d1d1d1;outline:0 none}.sun-editor .se-controller .se-btn-group button:active:enabled{background-color:#d1d1d1;border-color:#c1c1c1;-webkit-box-shadow:inset 0 3px 5px #c1c1c1;box-shadow:inset 0 3px 5px #c1c1c1}.sun-editor .se-controller .se-btn-group button span{display:block;padding:0;margin:0}.sun-editor .se-controller .se-btn-group button:enabled.active{color:#4592ff;outline:0 none}.sun-editor .se-controller .se-btn-group button:enabled.active:focus,.sun-editor .se-controller .se-btn-group button:enabled.active:hover{background-color:#e1e1e1;border-color:#d1d1d1;outline:0 none}.sun-editor .se-controller .se-btn-group button:enabled.active:active{background-color:#d1d1d1;border-color:#c1c1c1;-webkit-box-shadow:inset 0 3px 5px #c1c1c1;box-shadow:inset 0 3px 5px #c1c1c1}.sun-editor .se-controller .se-btn-group button:enabled.on{background-color:#e1e1e1;border-color:#d1d1d1;outline:0 none}.sun-editor .se-controller .se-btn-group button:enabled.on:focus,.sun-editor .se-controller .se-btn-group button:enabled.on:hover{background-color:#d1d1d1;border-color:#c1c1c1;outline:0 none}.sun-editor .se-controller .se-btn-group button:enabled.on:active{background-color:#c1c1c1;border-color:#b1b1b1;-webkit-box-shadow:inset 0 3px 5px #b1b1b1;box-shadow:inset 0 3px 5px #b1b1b1}.sun-editor .se-controller-resizing{margin-top:-50px!important;padding:0;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143}.sun-editor .se-controller-resizing .se-btn-group .se-btn-group-sub.se-resizing-align-list{left:57px}.sun-editor .se-resizing-container{position:absolute;display:none;z-index:4;border:1px solid #80bdff}.sun-editor .se-resizing-container .se-modal-resize{position:absolute;display:inline-block;background-color:#3f9dff;opacity:.3}.sun-editor .se-resizing-container .se-resize-dot{position:absolute;top:0;left:0;width:100%;height:100%}.sun-editor .se-resizing-container .se-resize-dot>span{position:absolute;width:7px;height:7px;background-color:#3f9dff;border:1px solid #4592ff}.sun-editor .se-resizing-container .se-resize-dot>span.tl{top:-5px;left:-5px;cursor:nw-resize}.sun-editor .se-resizing-container .se-resize-dot>span.tr{top:-5px;right:-5px;cursor:ne-resize}.sun-editor .se-resizing-container .se-resize-dot>span.bl{bottom:-5px;left:-5px;cursor:sw-resize}.sun-editor .se-resizing-container .se-resize-dot>span.br{right:-5px;bottom:-5px;cursor:se-resize}.sun-editor .se-resizing-container .se-resize-dot>span.lw{left:-7px;bottom:50%;cursor:w-resize}.sun-editor .se-resizing-container .se-resize-dot>span.th{left:50%;top:-7px;cursor:n-resize}.sun-editor .se-resizing-container .se-resize-dot>span.rw{right:-7px;bottom:50%;cursor:e-resize}.sun-editor .se-resizing-container .se-resize-dot>span.bh{right:50%;bottom:-7px;cursor:s-resize}.sun-editor .se-resizing-container .se-resize-display{position:absolute;right:0;bottom:0;padding:5px;margin:5px;font-size:12px;color:#fff;background-color:#333;border-radius:4px}.sun-editor .se-controller-table,.sun-editor .se-controller-table-cell{width:auto}.sun-editor .se-controller-link,.sun-editor .se-controller-table,.sun-editor .se-controller-table-cell{padding:0;font-size:14px;font-style:normal;font-weight:400;line-height:1.42857143}.sun-editor .se-controller-link:after,.sun-editor .se-controller-link:before{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.sun-editor .se-controller-link .link-content{padding:0;margin:0}.sun-editor .se-controller-link .link-content a{display:inline-block;color:#4592ff;max-width:200px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;vertical-align:middle;margin-left:5px}.sun-editor .se-notice{position:relative;display:none;width:100%;height:auto;word-break:break-all;font-size:13px;color:#b94a48;background-color:#f2dede;padding:15px;margin:0;border:1px solid #eed3d7;user-select:text;-o-user-select:text;-moz-user-select:text;-khtml-user-select:text;-webkit-user-select:text;-ms-user-select:text}.sun-editor .se-notice button{float:right}.sun-editor .se-tooltip{position:relative;overflow:visible}.sun-editor .se-tooltip .se-tooltip-inner{visibility:hidden;position:absolute;display:block;width:auto;top:120%;left:50%;background:transparent;opacity:0;z-index:1;line-height:1.5;transition:opacity .5s;margin:0;padding:0;bottom:auto;float:none;pointer-events:none;backface-visibility:hidden;-webkit-backface-visibility:hidden;-moz-backface-visibility:hidden}.sun-editor .se-tooltip .se-tooltip-inner .se-tooltip-text{position:relative;display:inline-block;width:auto;left:-50%;font-size:.9em;margin:0;padding:4px 6px;border-radius:2px;background-color:#333;color:#fff;text-align:center;line-height:unset;white-space:nowrap;cursor:auto}.sun-editor .se-tooltip .se-tooltip-inner .se-tooltip-text:after{content:"";position:absolute;bottom:100%;left:50%;margin-left:-5px;border:5px solid transparent;border-bottom-color:#333}.sun-editor .se-tooltip:hover .se-tooltip-inner{visibility:visible;opacity:1}@keyframes blinker{50%{opacity:0}}@keyframes spinner{to{transform:rotate(1turn)}}.sun-editor-editable{font-family:Helvetica Neue,sans-serif;font-size:13px;line-height:1.5;color:#333;text-align:left;background-color:#fff;word-break:break-all;word-wrap:break-word;padding:16px;margin:0}.sun-editor-editable *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.sun-editor-editable audio,.sun-editor-editable figcaption,.sun-editor-editable figure,.sun-editor-editable iframe,.sun-editor-editable img,.sun-editor-editable td,.sun-editor-editable th,.sun-editor-editable video{position:relative}.sun-editor-editable .__se__float-left{float:left}.sun-editor-editable .__se__float-right{float:right}.sun-editor-editable .__se__float-center{float:center}.sun-editor-editable .__se__float-none{float:none}.sun-editor-editable span{display:inline;vertical-align:baseline;margin:0;padding:0}.sun-editor-editable a{color:#004cff;text-decoration:none}.sun-editor-editable span[style~="color:"] a{color:inherit}.sun-editor-editable a:focus,.sun-editor-editable a:hover{cursor:pointer;color:#0093ff;text-decoration:underline}.sun-editor-editable pre{display:block;padding:8px;margin:0 0 10px;line-height:1.45;color:#666;background-color:#f9f9f9;border:1px solid #e1e1e1;border-radius:2px;white-space:pre-wrap;word-wrap:break-word;overflow:visible}.sun-editor-editable ol{list-style-type:decimal}.sun-editor-editable ol,.sun-editor-editable ul{display:block;margin-block-start:1em;margin-block-end:1em;margin-inline-start:0;margin-inline-end:0;padding-inline-start:40px}.sun-editor-editable ul{list-style-type:disc}.sun-editor-editable li{display:list-item;text-align:-webkit-match-parent;margin-bottom:5px}.sun-editor-editable ol ol,.sun-editor-editable ol ul,.sun-editor-editable ul ol,.sun-editor-editable ul ul{margin:0}.sun-editor-editable ol ol,.sun-editor-editable ul ol{list-style-type:lower-alpha}.sun-editor-editable ol ol ol,.sun-editor-editable ul ol ol,.sun-editor-editable ul ul ol{list-style-type:upper-roman}.sun-editor-editable ol ul,.sun-editor-editable ul ul{list-style-type:circle}.sun-editor-editable ol ol ul,.sun-editor-editable ol ul ul,.sun-editor-editable ul ul ul{list-style-type:square}.sun-editor-editable sub,.sun-editor-editable sup{font-size:75%;line-height:0}.sun-editor-editable sub{vertical-align:sub}.sun-editor-editable sup{vertical-align:super}.sun-editor-editable p{display:block;margin:0 0 10px}.sun-editor-editable div{display:block;margin:0;padding:0}.sun-editor-editable blockquote{display:block;font-family:inherit;font-size:inherit;color:#999;margin-block-start:1em;margin-block-end:1em;margin-inline-start:0;margin-inline-end:0;padding:0 5px 0 20px;border:solid #b1b1b1;border-width:0 0 0 5px}.sun-editor-editable blockquote blockquote{border-color:#c1c1c1}.sun-editor-editable blockquote blockquote blockquote{border-color:#d1d1d1}.sun-editor-editable blockquote blockquote blockquote blockquote{border-color:#e1e1e1}.sun-editor-editable h1{font-size:2em;margin-block-start:.67em;margin-block-end:.67em}.sun-editor-editable h1,.sun-editor-editable h2{display:block;margin-inline-start:0;margin-inline-end:0;font-weight:700}.sun-editor-editable h2{font-size:1.5em;margin-block-start:.83em;margin-block-end:.83em}.sun-editor-editable h3{font-size:1.17em;margin-block-start:1em;margin-block-end:1em}.sun-editor-editable h3,.sun-editor-editable h4{display:block;margin-inline-start:0;margin-inline-end:0;font-weight:700}.sun-editor-editable h4{font-size:1em;margin-block-start:1.33em;margin-block-end:1.33em}.sun-editor-editable h5{font-size:.83em;margin-block-start:1.67em;margin-block-end:1.67em}.sun-editor-editable h5,.sun-editor-editable h6{display:block;margin-inline-start:0;margin-inline-end:0;font-weight:700}.sun-editor-editable h6{font-size:.67em;margin-block-start:2.33em;margin-block-end:2.33em}.sun-editor-editable hr{display:flex;border-width:1px 0 0;border-color:#000;border-image:initial;height:1px}.sun-editor-editable hr.__se__solid{border-style:solid none none}.sun-editor-editable hr.__se__dotted{border-style:dotted none none}.sun-editor-editable hr.__se__dashed{border-style:dashed none none}.sun-editor-editable table{display:table;table-layout:auto;border:1px solid #ccc;width:100%;max-width:100%;margin:0 0 10px;background-color:transparent;border-spacing:0;border-collapse:collapse}.sun-editor-editable table thead{border-bottom:2px solid #333}.sun-editor-editable table tr{border:1px solid #efefef}.sun-editor-editable table th{background-color:#f3f3f3}.sun-editor-editable table td,.sun-editor-editable table th{border:1px solid #e1e1e1;padding:.4em;background-clip:padding-box}.sun-editor-editable table td.se-table-selected-cell,.sun-editor-editable table th.se-table-selected-cell{border:1px double #4592ff;background-color:#f1f7ff}.sun-editor-editable.se-disabled *{user-select:none;-o-user-select:none;-moz-user-select:none;-khtml-user-select:none;-webkit-user-select:none;-ms-user-select:none}.sun-editor-editable .se-component{display:flex;padding:1px;margin:0 0 10px}.sun-editor-editable .se-component.__se__float-left{margin:0 20px 10px 0}.sun-editor-editable .se-component.__se__float-right{margin:0 0 10px 20px}.sun-editor-editable[contenteditable=true] .se-component{outline:1px dashed #e1e1e1}.sun-editor-editable audio,.sun-editor-editable iframe,.sun-editor-editable img,.sun-editor-editable video{display:block;margin:0;padding:0;width:auto;height:auto;max-width:100%}.sun-editor-editable[contenteditable=true] figure:after{position:absolute;content:"";z-index:1;top:0;left:0;right:0;bottom:0;cursor:default;display:block;background:transparent}.sun-editor-editable[contenteditable=true] figure a,.sun-editor-editable[contenteditable=true] figure iframe,.sun-editor-editable[contenteditable=true] figure img{z-index:0}.sun-editor-editable[contenteditable=true] figure figcaption{display:block;z-index:2}.sun-editor-editable .se-image-container,.sun-editor-editable .se-video-container{width:auto;height:auto;max-width:100%}.sun-editor-editable figure{display:block;outline:none;margin:0;padding:0}.sun-editor-editable figure figcaption{padding:1em .5em;margin:0;background-color:#f9f9f9;outline:none}.sun-editor-editable figure figcaption p{line-height:2;margin:0}.sun-editor-editable .se-image-container a img{padding:1px;margin:1px;outline:1px solid #4592ff}.sun-editor-editable .se-video-container iframe{outline:1px solid #9e9e9e;position:absolute;top:0;left:0;border:0;width:100%;height:100%}.sun-editor-editable .se-video-container figure{left:0;width:100%;max-width:100%}.sun-editor-editable.se-show-block div,.sun-editor-editable.se-show-block h1,.sun-editor-editable.se-show-block h2,.sun-editor-editable.se-show-block h3,.sun-editor-editable.se-show-block h4,.sun-editor-editable.se-show-block h5,.sun-editor-editable.se-show-block h6,.sun-editor-editable.se-show-block li,.sun-editor-editable.se-show-block ol,.sun-editor-editable.se-show-block p,.sun-editor-editable.se-show-block ul{border:1px dashed #3f9dff!important;padding:10px 8px 8px!important}.se-show-block p{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA0AAAAPAQMAAAAF7dc0AAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAaSURBVAjXY/j/gwGCPvxg+F4BQiAGDP1HQQByxxw0gqOzIwAAAABJRU5ErkJggg==") no-repeat}.se-show-block div{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABUAAAAPAQMAAAAxlBYoAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAmSURBVAjXY/j//wcDDH+8XsHwDYi/hwNx1A8w/nYLKH4XoQYJAwCXnSgcl2MOPgAAAABJRU5ErkJggg==") no-repeat}.se-show-block h1{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPAQMAAAA4f7ZSAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAfSURBVAjXY/j/v4EBhr+9B+LzEPrDeygfhI8j1CBhAEhmJGY4Rf6uAAAAAElFTkSuQmCC") no-repeat}.se-show-block h2{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPAQMAAAA4f7ZSAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAmSURBVAjXY/j/v4EBhr+dB+LtQPy9geEDEH97D8T3gbgdoQYJAwA51iPuD2haEAAAAABJRU5ErkJggg==") no-repeat}.se-show-block h3{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPAQMAAAA4f7ZSAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAiSURBVAjXY/j/v4EBhr+dB+LtQPy9geHDeQgN5p9HqEHCADeWI+69VG2MAAAAAElFTkSuQmCC") no-repeat}.se-show-block h4{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABIAAAAPAQMAAADTSA1RAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAiSURBVAjXY/j//wADDH97DsTXIfjDdiDdDMTfIRhZHRQDAKJOJ6L+K3y7AAAAAElFTkSuQmCC") no-repeat}.se-show-block h5{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPAQMAAAA4f7ZSAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAlSURBVAjXY/j/v4EBhr+1A/F+IO5vYPiwHUh/B2IQfR6hBgkDABlWIy5uM+9GAAAAAElFTkSuQmCC") no-repeat}.se-show-block h6{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABEAAAAPAQMAAAA4f7ZSAAAABlBMVEWAgID////n1o2sAAAAAnRSTlP/AOW3MEoAAAAiSURBVAjXY/j/v4EBhr+dB+LtQLy/geFDP5S9HSKOrA6KAR9GIza1ptJnAAAAAElFTkSuQmCC") no-repeat}.se-show-block li{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAPCAYAAADkmO9VAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAA7SURBVDhPYxgFcNDQ0PAfykQBIHEYhgoRB/BpwCfHBKWpBkaggYxQGgOgBzyQD1aLLA4TGwWDGjAwAACR3RcEU9Ui+wAAAABJRU5ErkJggg==") no-repeat}.se-show-block ol{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABHSURBVDhPYxgFcNDQ0PAfhKFcFIBLHCdA1oBNM0kGEmMAPgOZoDTVANUNxAqQvURMECADRiiNAWCagDSGGhyW4DRrMAEGBgAu0SX6WpGgjAAAAABJRU5ErkJggg==") no-repeat}.se-show-block ul{background:url("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAMCAYAAABiDJ37AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAA1SURBVDhPYxgFDA0NDf+hTBSALI5LDQgwQWmqgVEDKQcsUBoF4ItFGEBXA+QzQpmDGjAwAAA8DQ4Lni6gdAAAAABJRU5ErkJggg==") no-repeat}.sun-editor-editable .__se__p-bordered,.sun-editor .__se__p-bordered{border-top:1px solid #b1b1b1;border-bottom:1px solid #b1b1b1;padding:4px 0}.sun-editor-editable .__se__p-spaced,.sun-editor .__se__p-spaced{letter-spacing:1px}.sun-editor-editable .__se__p-neon,.sun-editor .__se__p-neon{font-weight:200;font-style:italic;background:#000;color:#fff;padding:6px 4px;border:2px solid #fff;border-radius:6px;text-transform:uppercase;animation:neonFlicker 1.5s infinite alternate}@keyframes neonFlicker{0%,19%,21%,23%,25%,54%,56%,to{text-shadow:-.2rem -.2rem 1rem #fff,.2rem .2rem 1rem #fff,0 0 2px #f40,0 0 4px #f40,0 0 6px #f40,0 0 8px #f40,0 0 10px #f40;box-shadow:0 0 .5px #fff,inset 0 0 .5px #fff,0 0 2px #08f,inset 0 0 2px #08f,0 0 4px #08f,inset 0 0 4px #08f}20%,24%,55%{text-shadow:none;box-shadow:none}}.sun-editor-editable .__se__t-shadow,.sun-editor .__se__t-shadow{text-shadow:-.2rem -.2rem 1rem #fff,.2rem .2rem 1rem #fff,0 0 .2rem #999,0 0 .4rem #888,0 0 .6rem #777,0 0 .8rem #666,0 0 1rem #555} \ No newline at end of file diff --git a/dist/suneditor.min.js b/dist/suneditor.min.js index 3c886a3da..37b8a10dd 100644 --- a/dist/suneditor.min.js +++ b/dist/suneditor.min.js @@ -1 +1 @@ -!function(e){var t={};function i(n){if(t[n])return t[n].exports;var l=t[n]={i:n,l:!1,exports:{}};return e[n].call(l.exports,l,l.exports,i),l.l=!0,l.exports}i.m=e,i.c=t,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var l in e)i.d(n,l,function(t){return e[t]}.bind(null,l));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i(i.s="XJR1")}({"3FqI":function(e,t,i){},P6u4:function(e,t,i){"use strict";var n,l;n="undefined"!=typeof window?window:this,l=function(e,t){const i={toolbar:{default:"Default",save:"Save",font:"Font",formats:"Formats",fontSize:"Size",bold:"Bold",underline:"Underline",italic:"Italic",strike:"Strike",subscript:"Subscript",superscript:"Superscript",removeFormat:"Remove Format",fontColor:"Font Color",hiliteColor:"Highlight Color",indent:"Indent",outdent:"Outdent",align:"Align",alignLeft:"Align left",alignRight:"Align right",alignCenter:"Align center",alignJustify:"Align justify",list:"List",orderList:"Ordered list",unorderList:"Unordered list",horizontalRule:"Horizontal line",hr_solid:"Solid",hr_dotted:"Dotted",hr_dashed:"Dashed",table:"Table",link:"Link",math:"Math",image:"Image",video:"Video",fullScreen:"Full screen",showBlocks:"Show blocks",codeView:"Code view",undo:"Undo",redo:"Redo",preview:"Preview",print:"print",tag_p:"Paragraph",tag_div:"Normal (DIV)",tag_h:"Header",tag_blockquote:"Quote",tag_pre:"Code",template:"Template",lineHeight:"Line height",paragraphStyle:"Paragraph style",textStyle:"Text style"},dialogBox:{linkBox:{title:"Insert Link",url:"URL to link",text:"Text to display",newWindowCheck:"Open in new window"},mathBox:{title:"Math",inputLabel:"Mathematical Notation",fontSizeLabel:"Font Size",previewLabel:"Preview"},imageBox:{title:"Insert image",file:"Select from files",url:"Image URL",altText:"Alternative text"},videoBox:{title:"Insert Video",url:"Media embed URL, YouTube"},caption:"Insert description",close:"Close",submitButton:"Submit",revertButton:"Revert",proportion:"Constrain proportions",basic:"Basic",left:"Left",right:"Right",center:"Center",width:"Width",height:"Height",size:"Size",ratio:"Ratio"},controller:{edit:"Edit",unlink:"Unlink",remove:"Remove",insertRowAbove:"Insert row above",insertRowBelow:"Insert row below",deleteRow:"Delete row",insertColumnBefore:"Insert column before",insertColumnAfter:"Insert column after",deleteColumn:"Delete column",resize100:"Resize 100%",resize75:"Resize 75%",resize50:"Resize 50%",resize25:"Resize 25%",autoSize:"Auto size",mirrorHorizontal:"Mirror, Horizontal",mirrorVertical:"Mirror, Vertical",rotateLeft:"Rotate left",rotateRight:"Rotate right",maxSize:"Max size",minSize:"Min size",tableHeader:"Table header",mergeCells:"Merge cells",splitCells:"Split Cells",HorizontalSplit:"Horizontal split",VerticalSplit:"Vertical split"},menu:{spaced:"Spaced",bordered:"Bordered",neon:"Neon",translucent:"Translucent",shadow:"Shadow"}};return void 0===t&&(e.SUNEDITOR_LANG||(e.SUNEDITOR_LANG={}),e.SUNEDITOR_LANG.en=i),i},"object"==typeof e.exports?e.exports=n.document?l(n,!0):function(e){if(!e.document)throw new Error("SUNEDITOR_LANG a window with a document");return l(e)}:l(n)},WUQj:function(e,t,i){},XJR1:function(e,t,i){"use strict";i.r(t);i("3FqI"),i("WUQj");var n={name:"colorPicker",add:function(e){const t=e.context;t.colorPicker={colorListHTML:"",_colorInput:"",_defaultColor:"#000",_styleProperty:"color",_currentColor:"",_colorList:[]};let i=this.createColorList(e.context.option,e.lang,this._makeColorList);t.colorPicker.colorListHTML=i,i=null},createColorList:function(e,t,i){const n=e.colorList&&0!==e.colorList.length?e.colorList:["#ff0000","#ff5e00","#ffe400","#abf200","#00d8ff","#0055ff","#6600ff","#ff00dd","#000000","#ffd8d8","#fae0d4","#faf4c0","#e4f7ba","#d4f4fa","#d9e5ff","#e8d9ff","#ffd9fa","#f1f1f1","#ffa7a7","#ffc19e","#faed7d","#cef279","#b2ebf4","#b2ccff","#d1b2ff","#ffb2f5","#bdbdbd","#f15f5f","#f29661","#e5d85c","#bce55c","#5cd1e5","#6699ff","#a366ff","#f261df","#8c8c8c","#980000","#993800","#998a00","#6b9900","#008299","#003399","#3d0099","#990085","#353535","#670000","#662500","#665c00","#476600","#005766","#002266","#290066","#660058","#222222"];let l=[],s='
    ';for(let e,t=0,o=n.length;t0&&(s+='
    '+i(l)+"
    ",l=[]),"object"==typeof e&&(s+='
    '+i(e)+"
    ")));return s+='
    ",s},_makeColorList:function(e){let t="";t+='
      ';for(let i,n=0,l=e.length;n');return t+="
    ",t},init:function(e,t){const i=this.plugins.colorPicker;let n=t||(i.getColorInNode.call(this,e)||this.context.colorPicker._defaultColor);n=i.isHexColor(n)?n:i.rgb2hex(n)||n;const l=this.context.colorPicker._colorList;if(l)for(let e=0,t=l.length;e=3&&"#"+((1<<24)+(i[0]<<16)+(i[1]<<8)+i[2]).toString(16).substr(1)}},l={name:"dialog",add:function(e){const t=e.context;t.dialog={kind:"",updateModal:!1,_closeSignal:!1};let i=e.util.createElement("DIV");i.className="se-dialog sun-editor-common";let n=e.util.createElement("DIV");n.className="se-dialog-back",n.style.display="none";let l=e.util.createElement("DIV");l.className="se-dialog-inner",l.style.display="none",i.appendChild(n),i.appendChild(l),t.dialog.modalArea=i,t.dialog.back=n,t.dialog.modal=l,t.dialog.modal.addEventListener("mousedown",this.onMouseDown_dialog.bind(e)),t.dialog.modal.addEventListener("click",this.onClick_dialog.bind(e)),t.element.relative.appendChild(i),i=null,n=null,l=null},onMouseDown_dialog:function(e){/se-dialog-inner/.test(e.target.className)?this.context.dialog._closeSignal=!0:this.context.dialog._closeSignal=!1},onClick_dialog:function(e){e.stopPropagation(),(/close/.test(e.target.getAttribute("data-command"))||this.context.dialog._closeSignal)&&this.plugins.dialog.close.call(this)},open:function(e,t){if(this.modalForm)return!1;this.plugins.dialog._bindClose&&(this._d.removeEventListener("keydown",this.plugins.dialog._bindClose),this.plugins.dialog._bindClose=null),this.plugins.dialog._bindClose=function(e){/27/.test(e.keyCode)&&this.plugins.dialog.close.call(this)}.bind(this),this._d.addEventListener("keydown",this.plugins.dialog._bindClose),this.context.dialog.updateModal=t,"full"===this.context.option.popupDisplay?this.context.dialog.modalArea.style.position="fixed":this.context.dialog.modalArea.style.position="absolute",this.context.dialog.kind=e,this.modalForm=this.context[e].modal;const i=this.context[e].focusElement;"function"==typeof this.plugins[e].on&&this.plugins[e].on.call(this,t),this.context.dialog.modalArea.style.display="block",this.context.dialog.back.style.display="block",this.context.dialog.modal.style.display="block",this.modalForm.style.display="block",i&&i.focus()},_bindClose:null,close:function(){this.plugins.dialog._bindClose&&(this._d.removeEventListener("keydown",this.plugins.dialog._bindClose),this.plugins.dialog._bindClose=null);const e=this.context.dialog.kind;this.modalForm.style.display="none",this.context.dialog.back.style.display="none",this.context.dialog.modalArea.style.display="none",this.context.dialog.updateModal=!1,this.plugins[e].init.call(this),this.context.dialog.kind="",this.modalForm=null,this.focus()}},s={name:"resizing",add:function(e){const t=e.context;t.resizing={_resizeClientX:0,_resizeClientY:0,_resize_plugin:"",_resize_w:0,_resize_h:0,_origin_w:0,_origin_h:0,_rotateVertical:!1,_resize_direction:"",_move_path:null,_isChange:!1};let i=this.setController_resize.call(e);t.resizing.resizeContainer=i,t.resizing.resizeDiv=i.querySelector(".se-modal-resize"),t.resizing.resizeDot=i.querySelector(".se-resize-dot"),t.resizing.resizeDisplay=i.querySelector(".se-resize-display");let n=this.setController_button.call(e);t.resizing.resizeButton=n,n.addEventListener("mousedown",(function(e){e.stopPropagation()}),!1);let l=t.resizing.resizeHandles=t.resizing.resizeDot.querySelectorAll("span");t.resizing.resizeButtonGroup=n.querySelector("._se_resizing_btn_group"),t.resizing.rotationButtons=n.querySelectorAll("._se_resizing_btn_group ._se_rotation"),t.resizing.percentageButtons=n.querySelectorAll("._se_resizing_btn_group ._se_percentage"),t.resizing.alignMenu=n.querySelector(".se-resizing-align-list"),t.resizing.alignMenuList=t.resizing.alignMenu.querySelectorAll("button"),t.resizing.alignButton=n.querySelector("._se_resizing_align_button"),t.resizing.alignButtonIcon=t.resizing.alignButton.querySelector("i"),t.resizing.autoSizeButton=n.querySelector("._se_resizing_btn_group ._se_auto_size"),t.resizing.captionButton=n.querySelector("._se_resizing_caption_button"),l[0].addEventListener("mousedown",this.onMouseDown_resize_handle.bind(e)),l[1].addEventListener("mousedown",this.onMouseDown_resize_handle.bind(e)),l[2].addEventListener("mousedown",this.onMouseDown_resize_handle.bind(e)),l[3].addEventListener("mousedown",this.onMouseDown_resize_handle.bind(e)),l[4].addEventListener("mousedown",this.onMouseDown_resize_handle.bind(e)),l[5].addEventListener("mousedown",this.onMouseDown_resize_handle.bind(e)),l[6].addEventListener("mousedown",this.onMouseDown_resize_handle.bind(e)),l[7].addEventListener("mousedown",this.onMouseDown_resize_handle.bind(e)),n.addEventListener("click",this.onClick_resizeButton.bind(e)),t.element.relative.appendChild(i),t.element.relative.appendChild(n),i=null,n=null,l=null},setController_resize:function(){const e=this.util.createElement("DIV");return e.className="se-resizing-container",e.style.display="none",e.innerHTML='
    ',e},setController_button:function(){const e=this.lang,t=this.util.createElement("DIV");return t.className="se-controller se-controller-resizing",t.innerHTML='
    ",t},_module_getSizeX:function(e,t,i,n){return t||(t=e._element),i||(i=e._cover),n||(n=e._container),n&&i&&t?/%$/.test(t.style.width)?(this.util.getNumber(n.style.width,2)||100)+"%":t.style.width:""},_module_getSizeY:function(e,t,i,n){return t||(t=e._element),i||(i=e._cover),n||(n=e._container),n&&i&&t?this.util.getNumber(i.style.paddingBottom)>0&&!this.context.resizing._rotateVertical?i.style.height:/%$/.test(t.style.height)&&/%$/.test(t.style.width)?(this.util.getNumber(n.style.height,2)||100)+"%":t.style.height:""},_module_setModifyInputSize:function(e,t){const i=e._onlyPercentage&&this.context.resizing._rotateVertical;e.proportion.checked=e._proportionChecked="false"!==e._element.getAttribute("data-proportion");let n=i?"":this.plugins.resizing._module_getSizeX.call(this,e);if(n===e._defaultSizeX&&(n=""),e._onlyPercentage&&(n=this.util.getNumber(n,2)),e.inputX.value=n,t.setInputSize.call(this,"x"),!e._onlyPercentage){let t=i?"":this.plugins.resizing._module_getSizeY.call(this,e);t===e._defaultSizeY&&(t=""),e._onlyPercentage&&(t=this.util.getNumber(t,2)),e.inputY.value=t}e.inputX.disabled=!!i,e.inputY.disabled=!!i,e.proportion.disabled=!!i,t.setRatio.call(this)},_module_setInputSize:function(e,t){if(e._onlyPercentage)"x"===t&&e.inputX.value>100&&(e.inputX.value=100);else if(e.proportion.checked&&e._ratio&&/\d/.test(e.inputX.value)&&/\d/.test(e.inputY.value)){const i=e.inputX.value.replace(/\d+|\./g,"")||e.sizeUnit,n=e.inputY.value.replace(/\d+|\./g,"")||e.sizeUnit;if(i!==n)return;const l="%"===i?2:0;"x"===t?e.inputY.value=this.util.getNumber(e._ratioY*this.util.getNumber(e.inputX.value,l),l)+n:e.inputX.value=this.util.getNumber(e._ratioX*this.util.getNumber(e.inputY.value,l),l)+i}},_module_setRatio:function(e){const t=e.inputX.value,i=e.inputY.value;if(e.proportion.checked&&/\d+/.test(t)&&/\d+/.test(i)){if((t.replace(/\d+|\./g,"")||e.sizeUnit)!==(i.replace(/\d+|\./g,"")||e.sizeUnit))e._ratio=!1;else if(!e._ratio){const n=this.util.getNumber(t),l=this.util.getNumber(i);e._ratio=!0,e._ratioX=n/l,e._ratioY=l/n}}else e._ratio=!1},_module_sizeRevert:function(e){e._onlyPercentage?e.inputX.value=e._origin_w>100?100:e._origin_w:(e.inputX.value=e._origin_w,e.inputY.value=e._origin_h)},_module_saveCurrentSize:function(e){const t=this.plugins.resizing._module_getSizeX.call(this,e),i=this.plugins.resizing._module_getSizeY.call(this,e);e._element.setAttribute("data-size",t+","+i),e._videoRatio&&(e._videoRatio=i)},call_controller_resize:function(e,t){const i=this.context.resizing,n=this.context[t];i._resize_plugin=t;const l=i.resizeContainer,s=i.resizeDiv,o=this.util.getOffset(e,this.context.element.wysiwygFrame),a=i._rotateVertical=/^(90|270)$/.test(Math.abs(e.getAttribute("data-rotate")).toString()),r=a?e.offsetHeight:e.offsetWidth,c=a?e.offsetWidth:e.offsetHeight,d=o.top,u=o.left-this.context.element.wysiwygFrame.scrollLeft;l.style.top=d+"px",l.style.left=u+"px",l.style.width=r+"px",l.style.height=c+"px",s.style.top="0px",s.style.left="0px",s.style.width=r+"px",s.style.height=c+"px";let h=e.getAttribute("data-align")||"basic";h="none"===h?"basic":h;const p=this.util.getParentElement(e,this.util.isComponent),g=this.util.getParentElement(e,"FIGURE"),m=this.plugins.resizing._module_getSizeX.call(this,n,e,g,p)||"auto",f=n._onlyPercentage&&"image"===t?"":", "+(this.plugins.resizing._module_getSizeY.call(this,n,e,g,p)||"auto");this.util.changeTxt(i.resizeDisplay,this.lang.dialogBox[h]+" ("+m+f+")"),i.resizeButtonGroup.style.display=n._resizing?"":"none";const _=!n._resizing||n._resizeDotHide||n._onlyPercentage?"none":"flex",b=i.resizeHandles;for(let e=0,t=b.length;e",e},set_cover:function(e){const t=this.util.createElement("FIGURE");return t.appendChild(e),t},set_container:function(e,t){const i=this.util.createElement("DIV");return i.className="se-component "+t,i.setAttribute("contenteditable",!1),i.appendChild(e),i},onClick_resizeButton:function(e){e.stopPropagation();const t=e.target,i=t.getAttribute("data-command")||t.parentNode.getAttribute("data-command");if(!i)return;const n=t.getAttribute("data-value")||t.parentNode.getAttribute("data-value"),l=this.context.resizing._resize_plugin,s=this.context[l],o=s._element,a=this.plugins[l];if(e.preventDefault(),"function"!=typeof this.plugins.resizing._closeAlignMenu||(this.plugins.resizing._closeAlignMenu(),"onalign"!==i)){switch(i){case"auto":a.setAutoSize.call(this),a.onModifyMode.call(this,o,this.plugins.resizing.call_controller_resize.call(this,o,l));break;case"percent":let e=this.plugins.resizing._module_getSizeY.call(this,s);if(this.context.resizing._rotateVertical){const t=o.getAttribute("data-percentage");t&&(e=t.split(",")[1])}this.plugins.resizing.resetTransform.call(this,o),a.setPercentSize.call(this,100*n,e),a.onModifyMode.call(this,o,this.plugins.resizing.call_controller_resize.call(this,o,l));break;case"mirror":const t=o.getAttribute("data-rotate")||"0";let i=o.getAttribute("data-rotateX")||"",r=o.getAttribute("data-rotateY")||"";"h"===n&&!this.context.resizing._rotateVertical||"v"===n&&this.context.resizing._rotateVertical?r=r?"":"180":i=i?"":"180",o.setAttribute("data-rotateX",i),o.setAttribute("data-rotateY",r),this.plugins.resizing._setTransForm(o,t,i,r);break;case"rotate":const c=this.context.resizing,d=1*o.getAttribute("data-rotate")+1*n,u=this._w.Math.abs(d)>=360?0:d;o.setAttribute("data-rotate",u),c._rotateVertical=/^(90|270)$/.test(this._w.Math.abs(u).toString()),this.plugins.resizing.setTransformSize.call(this,o,null,null),a.onModifyMode.call(this,o,this.plugins.resizing.call_controller_resize.call(this,o,l));break;case"onalign":this.plugins.resizing.openAlignMenu.call(this);break;case"align":const h="basic"===n?"none":n;a.setAlign.call(this,h,null,null,null),a.onModifyMode.call(this,o,this.plugins.resizing.call_controller_resize.call(this,o,l));break;case"caption":const p=!s._captionChecked;if(a.openModify.call(this,!0),s._captionChecked=s.captionCheckEl.checked=p,"image"===l?a.update_image.call(this,!1,!1,!1):"video"===l&&(this.context.dialog.updateModal=!0,a.submitAction.call(this)),p){const e=this.util.getChildElement(s._caption,(function(e){return 3===e.nodeType}));e?this.setRange(e,0,e,e.textContent.length):s._caption.focus(),this.controllersOff()}else a.onModifyMode.call(this,o,this.plugins.resizing.call_controller_resize.call(this,o,l)),a.openModify.call(this,!0);break;case"revert":a.setOriginSize.call(this),a.onModifyMode.call(this,o,this.plugins.resizing.call_controller_resize.call(this,o,l));break;case"update":a.openModify.call(this),this.controllersOff();break;case"delete":a.destroy.call(this)}this.history.push(!1)}},resetTransform:function(e){const t=(e.getAttribute("data-size")||e.getAttribute("data-origin")||"").split(",");this.context.resizing._rotateVertical=!1,e.style.maxWidth="",e.style.transform="",e.style.transformOrigin="",e.setAttribute("data-rotate",""),e.setAttribute("data-rotateX",""),e.setAttribute("data-rotateY",""),this.plugins[this.context.resizing._resize_plugin].setSize.call(this,t[0]?t[0]:"auto",t[1]?t[1]:"",!0)},setTransformSize:function(e,t,i){let n=e.getAttribute("data-percentage");const l=this.context.resizing._rotateVertical,s=1*e.getAttribute("data-rotate");let o="";if(n&&!l)n=n.split(","),"auto"===n[0]&&"auto"===n[1]?this.plugins[this.context.resizing._resize_plugin].setAutoSize.call(this):this.plugins[this.context.resizing._resize_plugin].setPercentSize.call(this,n[0],n[1]);else{const n=this.util.getParentElement(e,"FIGURE"),a=t||e.offsetWidth,r=i||e.offsetHeight,c=(l?r:a)+"px",d=(l?a:r)+"px";if(this.plugins[this.context.resizing._resize_plugin].cancelPercentAttr.call(this),this.plugins[this.context.resizing._resize_plugin].setSize.call(this,a+"px",r+"px",!0),n.style.width=c,n.style.height=this.context[this.context.resizing._resize_plugin]._caption?"":d,l){let e=a/2+"px "+a/2+"px 0",t=r/2+"px "+r/2+"px 0";o=90===s||-270===s?t:e}}e.style.transformOrigin=o,this.plugins.resizing._setTransForm(e,s.toString(),e.getAttribute("data-rotateX")||"",e.getAttribute("data-rotateY")||""),e.style.maxWidth=l?"none":"",this.plugins.resizing.setCaptionPosition.call(this,e)},_setTransForm:function(e,t,i,n){let l=(e.offsetWidth-e.offsetHeight)*(/-/.test(t)?1:-1),s="";if(/[1-9]/.test(t)&&(i||n))switch(s=i?"Y":"X",t){case"90":s=i&&n?"X":n?s:"";break;case"270":l*=-1,s=i&&n?"Y":i?s:"";break;case"-90":s=i&&n?"Y":i?s:"";break;case"-270":l*=-1,s=i&&n?"X":n?s:"";break;default:s=""}t%180==0&&(e.style.maxWidth=""),e.style.transform="rotate("+t+"deg)"+(i?" rotateX("+i+"deg)":"")+(n?" rotateY("+n+"deg)":"")+(s?" translate"+s+"("+l+"px)":"")},setCaptionPosition:function(e){const t=this.util.getChildElement(this.util.getParentElement(e,"FIGURE"),"FIGCAPTION");t&&(t.style.marginTop=(this.context.resizing._rotateVertical?e.offsetWidth-e.offsetHeight:0)+"px")},onMouseDown_resize_handle:function(e){const t=this.context.resizing,i=t._resize_direction=e.target.classList[0];e.stopPropagation(),e.preventDefault();const n=this.context.resizing._resize_plugin,l=this.context[n]._element,s=this.plugins[n];t._resizeClientX=e.clientX,t._resizeClientY=e.clientY,this.context.element.resizeBackground.style.display="block",t.resizeButton.style.display="none",t.resizeDiv.style.float=/l/.test(i)?"right":/r/.test(i)?"left":"none";const o=function(e){if("keydown"===e.type&&27!==e.keyCode)return;const i=t._isChange;t._isChange=!1,this.removeDocEvent("mousemove",a),this.removeDocEvent("mouseup",o),this.removeDocEvent("keydown",o),"keydown"===e.type?(this.controllersOff(),this.context.element.resizeBackground.style.display="none",this.plugins[this.context.resizing._resize_plugin].init.call(this)):(this.plugins.resizing.cancel_controller_resize.call(this),i&&this.history.push(!1)),s.onModifyMode.call(this,l,this.plugins.resizing.call_controller_resize.call(this,l,t._resize_plugin))}.bind(this),a=this.plugins.resizing.resizing_element.bind(this,t,i,this.context[t._resize_plugin]);this.addDocEvent("mousemove",a),this.addDocEvent("mouseup",o),this.addDocEvent("keydown",o)},resizing_element:function(e,t,i,n){const l=n.clientX,s=n.clientY;let o=i._element_w,a=i._element_h;const r=i._element_w+(/r/.test(t)?l-e._resizeClientX:e._resizeClientX-l),c=i._element_h+(/b/.test(t)?s-e._resizeClientY:e._resizeClientY-s),d=i._element_h/i._element_w*r;/t/.test(t)&&(e.resizeDiv.style.top=i._element_h-(/h/.test(t)?c:d)+"px"),/l/.test(t)&&(e.resizeDiv.style.left=i._element_w-r+"px"),/r|l/.test(t)&&(e.resizeDiv.style.width=r+"px",o=r),/^(t|b)[^h]$/.test(t)?(e.resizeDiv.style.height=d+"px",a=d):/^(t|b)h$/.test(t)&&(e.resizeDiv.style.height=c+"px",a=c),e._resize_w=o,e._resize_h=a,this.util.changeTxt(e.resizeDisplay,this._w.Math.round(o)+" x "+this._w.Math.round(a)),e._isChange=!0},cancel_controller_resize:function(){const e=this.context.resizing._rotateVertical;this.controllersOff(),this.context.element.resizeBackground.style.display="none";let t=this._w.Math.round(e?this.context.resizing._resize_h:this.context.resizing._resize_w),i=this._w.Math.round(e?this.context.resizing._resize_w:this.context.resizing._resize_h);if(!e&&!/%$/.test(t)){const e=16,n=this.context.element.wysiwygFrame.clientWidth-2*e-2;this.util.getNumber(t)>n&&(i=this._w.Math.round(i/t*n),t=n)}this.plugins[this.context.resizing._resize_plugin].setSize.call(this,t,i,!1),this.plugins[this.context.resizing._resize_plugin].init.call(this)}},o={name:"notice",add:function(e){const t=e.context;t.notice={};let i=e.util.createElement("DIV"),n=e.util.createElement("SPAN"),l=e.util.createElement("BUTTON");i.className="se-notice",l.className="close",l.setAttribute("aria-label","Close"),l.setAttribute("title",e.lang.dialogBox.close),l.innerHTML='',i.appendChild(n),i.appendChild(l),t.notice.modal=i,t.notice.message=n,l.addEventListener("click",this.onClick_cancel.bind(e)),t.element.relative.insertBefore(i,t.element.editorArea),i=null},onClick_cancel:function(e){e.preventDefault(),e.stopPropagation(),this.plugins.notice.close.call(this)},open:function(e){this.context.notice.message.textContent=e,this.context.notice.modal.style.display="block"},close:function(){this.context.notice.modal.style.display="none"}},a={blockquote:{name:"blockquote",display:"command",add:function(e,t){e.context.blockquote={targetButton:t,tag:e.util.createElement("BLOCKQUOTE")}},active:function(e){if(e){if(/blockquote/i.test(e.nodeName))return this.util.addClass(this.context.blockquote.targetButton,"active"),!0}else this.util.removeClass(this.context.blockquote.targetButton,"active");return!1},action:function(){const e=this.util.getParentElement(this.getSelectionNode(),"blockquote");e?this.detachRangeFormatElement(e,null,null,!1,!1):this.applyRangeFormatElement(this.context.blockquote.tag.cloneNode(!1))}},align:{name:"align",display:"submenu",add:function(e,t){const i=e.context;i.align={targetIcon:t.querySelector("i"),_alignList:null,currentAlign:""};let n=this.setSubmenu.call(e),l=n.querySelector("ul");l.addEventListener("click",this.pickup.bind(e)),i.align._alignList=l.querySelectorAll("li button"),t.parentNode.appendChild(n),n=null,l=null},setSubmenu:function(){const e=this.lang,t=this.util.createElement("DIV");return t.className="se-list-layer",t.innerHTML='
    ",t},active:function(e){const t=this.context.align.targetIcon;if(e){if(this.util.isFormatElement(e)){const i=e.style.textAlign;return i&&(t.className="se-icon-align-"+i,t.setAttribute("data-focus",i)),!0}}else t.className="se-icon-align-left",t.removeAttribute("data-focus");return!1},on:function(){const e=this.context.align,t=e._alignList,i=e.targetIcon.getAttribute("data-focus")||"left";if(i!==e.currentAlign){for(let e=0,n=t.length;e('+t.toolbar.default+")";for(s=0,o=a.length;s";return r+="
    ",i.innerHTML=r,i},active:function(e){const t=this.context.font.targetText,i=this.context.font.targetTooltip;if(e){if(e.style&&e.style.fontFamily.length>0){const n=e.style.fontFamily.replace(/["']/g,"");return this.util.changeTxt(t,n),this.util.changeTxt(i,n),!0}}else{const e=this.lang.toolbar.font;this.util.changeTxt(t,e),this.util.changeTxt(i,e)}return!1},on:function(){const e=this.context.font,t=e._fontList,i=e.targetText.textContent;if(i!==e.currentFont){for(let e=0,n=t.length;e('+t.toolbar.default+")";for(let t,i=0,s=e.fontSizeUnit,o=n.length;i";return l+="
    ",i.innerHTML=l,i},active:function(e){if(e){if(e.style&&e.style.fontSize.length>0)return this.util.changeTxt(this.context.fontSize.targetText,e.style.fontSize),!0}else this.util.changeTxt(this.context.fontSize.targetText,this.lang.toolbar.fontSize);return!1},on:function(){const e=this.context.fontSize,t=e._sizeList,i=e.targetText.textContent;if(i!==e.currentSize){for(let e=0,n=t.length;e
  • ",t},appendHr:function(e){const t=this.util.createElement("HR");t.className=e,this.focus();let i=this.insertComponent(t,!1);this.setRange(i,0,i,0)},horizontalRulePick:function(e){e.preventDefault(),e.stopPropagation();let t=e.target,i=null;for(;!i&&!/UL/i.test(t.tagName);)i=t.getAttribute("data-value"),t=t.parentNode;i&&(this.plugins.horizontalRule.appendHr.call(this,"__se__"+i),this.submenuOff())}},list:{name:"list",display:"submenu",add:function(e,t){const i=e.context;i.list={targetButton:t,targetIcon:t.querySelector("i"),_list:null,currentList:""};let n=this.setSubmenu.call(e),l=n.querySelector("ul");l.addEventListener("click",this.pickup.bind(e)),i.list._list=l.querySelectorAll("li button"),t.parentNode.appendChild(n),n=null,l=null},setSubmenu:function(){const e=this.lang,t=this.util.createElement("DIV");return t.className="se-submenu se-list-layer",t.innerHTML='
    ",t},active:function(e){const t=this.context.list.targetButton,i=this.context.list.targetIcon,n=this.util;if(e){if(n.isList(e)){const l=e.nodeName;return t.setAttribute("data-focus",l),n.addClass(t,"active"),/UL/i.test(l)?(n.removeClass(i,"se-icon-list-number"),n.addClass(i,"se-icon-list-bullets")):(n.removeClass(i,"se-icon-list-bullets"),n.addClass(i,"se-icon-list-number")),!0}}else t.removeAttribute("data-focus"),n.removeClass(i,"se-icon-list-bullets"),n.addClass(i,"se-icon-list-number"),n.removeClass(t,"active");return!1},on:function(){const e=this.context.list,t=e._list,i=e.targetButton.getAttribute("data-focus")||"";if(i!==e.currentList){for(let e=0,n=t.length;e"),t.innerHTML+=i.outerHTML,e&&(t.innerHTML+="
    ")}else{const e=i.childNodes;for(;e[0];)t.appendChild(e[0])}c.appendChild(t),a||(p=c),a&&u===d&&!l.isRangeFormatElement(m)||(h||(h=c),s&&a&&u===d||a&&l.isList(d)&&d===r||c.parentNode!==u&&u.insertBefore(c,m)),l.removeItem(i),s&&null===g&&(g=c.children.length-1),a&&l.getRangeFormatElement(d,f)!==l.getRangeFormatElement(r,f)&&(c=l.createElement(e)),_&&0===_.children.length&&l.removeItem(_)}else l.removeItem(i);g&&(h=h.children[g]),r&&(m=c.children.length-1,c.innerHTML+=u.innerHTML,p=c.children[m],l.removeItem(u)),o=a=l.getEdgeChildNodes(h.firstChild,p.lastChild)}else{if(i)for(let e=0,t=n.length;e=0;i--)if(n[i].contains(n[e])){n.splice(e,1),e--,t--;break}const t=l.getRangeFormatElement(r),s=t&&t.tagName===e;let c,d,u;const h=function(e){return!this.isComponent(e)}.bind(l);s||(d=l.createElement(e));for(let t,r,p=0,g=n.length;p0){const e=l.cloneNode(!1),t=l.childNodes,s=this.util.getPositionIndex(n);for(;t[s];)e.appendChild(t[s]);i.appendChild(e)}0===l.children.length&&this.util.removeItem(l);const a=this.util.getEdgeChildNodes(t,i);return{cc:t.parentNode,sc:a.sc,ec:a.ec}},editInsideList:function(e,t){const i=(t=t||this.getSelectedElements().filter(function(e){return this.isListCell(e)}.bind(this.util))).length;if(0===i||!e&&!this.util.isListCell(t[0].previousElementSibling)&&!this.util.isListCell(t[i-1].nextElementSibling))return{sc:t[0],so:0,ec:t[i-1],eo:1};let n=t[0].parentNode,l=t[i-1],s=null;if(e){if(n!==l.parentNode&&this.util.isList(l.parentNode.parentNode)&&l.nextElementSibling)for(l=l.nextElementSibling;l;)t.push(l),l=l.nextElementSibling;s=this.plugins.list.editList.call(this,n.nodeName.toUpperCase(),t,!0)}else{s={sc:t[0],so:i>1||!this.getRange().collapsed?0:1,ec:l,eo:1};let e=this.util.createElement(n.nodeName),o=s.sc.previousElementSibling,a=s.sc.nextElementSibling;for(let l,s=0,r=i;s i"),i.table.resizeText=s.querySelector("._se_table_resize > span > span"),i.table.headerButton=s.querySelector("._se_table_header"),s.addEventListener("mousedown",(function(e){e.stopPropagation()}),!1);let o=this.setController_tableEditor.call(e);i.table.resizeDiv=o,i.table.splitMenu=o.querySelector(".se-btn-group-sub"),i.table.mergeButton=o.querySelector("._se_table_merge_button"),i.table.splitButton=o.querySelector("._se_table_split_button"),o.addEventListener("mousedown",(function(e){e.stopPropagation()}),!1),l.addEventListener("mousemove",this.onMouseMove_tablePicker.bind(e)),l.addEventListener("click",this.appendTable.bind(e)),o.addEventListener("click",this.onClick_tableController.bind(e)),s.addEventListener("click",this.onClick_tableController.bind(e)),t.parentNode.appendChild(n),i.element.relative.appendChild(o),i.element.relative.appendChild(s),n=null,l=null,o=null,s=null},setSubmenu:function(){const e=this.util.createElement("DIV");return e.className="se-submenu se-selector-table",e.innerHTML='
    1 x 1
    ',e},setController_table:function(){const e=this.lang,t=this.util.createElement("DIV");return t.className="se-controller se-controller-table",t.innerHTML='
    ",t},setController_tableEditor:function(){const e=this.lang,t=this.util.createElement("DIV");return t.className="se-controller se-controller-table-cell",t.innerHTML='
    • '+e.controller.VerticalSplit+'
    • '+e.controller.HorizontalSplit+"
    ",t},appendTable:function(){const e=this.util.createElement("TABLE"),t=this.plugins.table.createCells,i=this.context.table._tableXY[0];let n=this.context.table._tableXY[1],l="";for(;n>0;)l+=""+t.call(this,"td",i)+"",--n;l+="",e.innerHTML=l,this.insertComponent(e,!1);const s=e.querySelector("td div");this.setRange(s,0,s,0),this.plugins.table.reset_table_picker.call(this)},createCells:function(e,t,i){if(e=e.toLowerCase(),i){const t=this.util.createElement(e);return t.innerHTML="

    ",t}{let i="";for(;t>0;)i+="<"+e+">

    ",t--;return i}},onMouseMove_tablePicker:function(e){e.stopPropagation();let t=this._w.Math.ceil(e.offsetX/18),i=this._w.Math.ceil(e.offsetY/18);t=t<1?1:t,i=i<1?1:i,this.context.table.tableHighlight.style.width=t+"em",this.context.table.tableHighlight.style.height=i+"em";let n=t<5?5:t>9?10:t+1,l=i<5?5:i>9?10:i+1;this.context.table.tableUnHighlight.style.width=n+"em",this.context.table.tableUnHighlight.style.height=l+"em",this.util.changeTxt(this.context.table.tableDisplay,t+" x "+i),this.context.table._tableXY=[t,i]},reset_table_picker:function(){if(!this.context.table.tableHighlight)return;const e=this.context.table.tableHighlight.style,t=this.context.table.tableUnHighlight.style;e.width="1em",e.height="1em",t.width="5em",t.height="5em",this.util.changeTxt(this.context.table.tableDisplay,"1 x 1"),this.submenuOff()},init:function(){const e=this.context.table,t=this.plugins.table;if(t._removeEvents.call(this),t._selectedTable){const e=t._selectedTable.querySelectorAll(".se-table-selected-cell");for(let t=0,i=e.length;t0)for(let e,t=0;ts||(u>=e.index?(n+=e.cs,u+=e.cs,e.rs-=1,e.row=s+1,e.rs<1&&(r.splice(t,1),t--)):h===p-1&&(e.rs-=1,e.row=s+1,e.rs<1&&(r.splice(t,1),t--)));if(s===o&&h===l){i._logical_cellIndex=u;break}d>0&&a.push({index:u,cs:c+1,rs:d,row:-1}),n+=c}r=r.concat(a).sort((function(e,t){return e.index-t.index})),a=[]}a=null,r=null}},editTable:function(e,t){const i=this.plugins.table,n=this.context.table,l=n._element,s="row"===e;if(s){const e=n._trElement.parentNode;if(/^THEAD$/i.test(e.nodeName)){if("up"===t)return;if(!e.nextElementSibling||!/^TBODY$/i.test(e.nextElementSibling.nodeName))return void(l.innerHTML+=""+i.createCells.call(this,"td",n._logical_cellCnt,!1)+"")}}if(i._ref){const e=n._tdElement,l=i._selectedCells;if(s)if(t)i.setCellInfo.call(this,"up"===t?l[0]:l[l.length-1],!0),i.editRow.call(this,t,e);else{let e=l[0].parentNode;const n=[l[0]];for(let t,i=1,s=l.length;io&&o>t&&(e[l].rowSpan=i+a,c-=n)}if(n){const e=r[s+1];if(e){const t=[];let i=r[s].cells,n=0;for(let e,l,s=0,o=i.length;s1&&(e.rowSpan-=1,t.push({cell:e.cloneNode(!1),index:l}));if(t.length>0){let l=t.shift();i=e.cells,n=0;for(let s,o,a=0,r=i.length;a=l.index)||(a--,n--,n+=l.cell.colSpan-1,e.insertBefore(l.cell,s),l=t.shift(),l));a++);if(l){e.appendChild(l.cell);for(let i=0,n=t.length;i0){const e=!s[b+1];for(let t,i=0;i_||(g>=t.index?(f+=t.cs,g=b+f,t.rs-=1,t.row=_+1,t.rs<1&&(d.splice(i,1),i--)):e&&(t.rs-=1,t.row=_+1,t.rs<1&&(d.splice(i,1),i--)))}i>0&&c.push({rs:i,cs:r+1,index:g,row:-1}),g>=t&&g+r<=t+o?h.push(e):g<=t+o&&g+r>=t?e.colSpan-=n.getOverlapRangeAtIndex(a,a+o,g,g+r):i>0&&(gt+o)&&p.push({cell:e,i:_,rs:_+i}),f+=r}else{if(b>=t)break;if(r>0){if(u<1&&r+b>=t){e.colSpan+=1,t=null,u=i+1;break}t-=r}if(!m){for(let e,i=0;i0){u-=1;continue}null!==t&&s.length>0&&(g=this.plugins.table.createCells.call(this,s[0].nodeName,0,!0),g=e.insertBefore(g,s[t]))}}if(l){let e,t;for(let i,l=0,s=h.length;l1)c.colSpan=this._w.Math.floor(e/2),l.colSpan=e-c.colSpan,o.insertBefore(c,l.nextElementSibling);else{let t=[],i=[];for(let o,r,c=0,d=n._rowCnt;c0)for(let e,t=0;tc||(u>=e.index?(r+=e.cs,u+=e.cs,e.rs-=1,e.row=c+1,e.rs<1&&(i.splice(t,1),t--)):h===p-1&&(e.rs-=1,e.row=c+1,e.rs<1&&(i.splice(t,1),t--)));if(u<=a&&d>0&&t.push({index:u,cs:s+1,rs:d,row:-1}),n!==l&&u<=a&&u+s>=a+e-1){n.colSpan+=1;break}if(u>a)break;r+=s}i=i.concat(t).sort((function(e,t){return e.index-t.index})),t=[]}o.insertBefore(c,l.nextElementSibling)}}else{const e=l.rowSpan;if(c.colSpan=l.colSpan,e>1){c.rowSpan=this._w.Math.floor(e/2);const i=e-c.rowSpan,n=[],r=t.getArrayIndex(s,o)+i;for(let e,t,i=0;i=a));c++)l=e[c],s=l.rowSpan-1,s>0&&s+i>=r&&o=h.index&&(r+=h.cs,l+=h.cs,h=n.shift()),l>=a||s===o-1){d.insertBefore(c,e.nextElementSibling);break}r+=t}l.rowSpan=i}else{c.rowSpan=l.rowSpan;const e=t.createElement("TR");e.appendChild(c);for(let e,t=0;t=r&&(e[i].rowSpan+=1)}const i=n._physical_cellIndex,a=o.cells;for(let e=0,t=a.length;e0&&o+s>=n&&(e.rowSpan-=i.getOverlapRangeAtIndex(n,l,o,o+s));else s.push(e[o]);for(let e=0,t=s.length;e"+this.plugins.table.createCells.call(this,"th",this.context.table._logical_cellCnt,!1)+"",n.insertBefore(t,n.firstElementChild)}e.toggleClass(t,"active"),/TH/i.test(this.context.table._tdElement.nodeName)?this.controllersOff():this.plugins.table.setPositionControllerDiv.call(this,this.context.table._tdElement,!1)},resizeTable:function(){const e=this.context.table,t=e.resizeIcon,i=e.resizeText;let n="se-icon-expansion",l="se-icon-reduction",s=e.minText,o="100%";e._maxWidth||(n="se-icon-reduction",l="se-icon-expansion",s=e.maxText,o="auto"),this.util.removeClass(t,n),this.util.addClass(t,l),this.util.changeTxt(i,s),e._element.style.width=o},setActiveButton:function(e,t){const i=this.context.table;t&&e!==t?(i.splitButton.setAttribute("disabled",!0),i.mergeButton.removeAttribute("disabled")):(i.splitButton.removeAttribute("disabled"),i.mergeButton.setAttribute("disabled",!0))},_bindOnSelect:null,_bindOffSelect:null,_bindOffShift:null,_selectedCells:null,_shift:!1,_fixedCell:null,_fixedCellName:null,_selectedCell:null,_selectedTable:null,_ref:null,_toggleEditor:function(e){this.context.element.wysiwyg.setAttribute("contenteditable",e),e?this.util.removeClass(this.context.element.wysiwyg,"se-disabled"):this.util.addClass(this.context.element.wysiwyg,"se-disabled")},_offCellMultiSelect:function(e){e.stopPropagation();const t=this.plugins.table;t._shift?t._initBind&&(this._wd.removeEventListener("touchmove",t._initBind),t._initBind=null):(t._removeEvents.call(this),t._toggleEditor.call(this,!0)),t._fixedCell&&t._selectedTable&&(t.setActiveButton.call(this,t._fixedCell,t._selectedCell),t.call_controller_tableEdit.call(this,t._selectedCell||t._fixedCell),t._selectedCells=t._selectedTable.querySelectorAll(".se-table-selected-cell"),t._selectedCell&&t._fixedCell&&this.focusEdge(t._selectedCell),t._shift||(t._fixedCell=null,t._selectedCell=null,t._fixedCellName=null))},_onCellMultiSelect:function(e){const t=this.plugins.table,i=this.util.getParentElement(e.target,this.util.isCell);if(t._shift)i===t._fixedCell?t._toggleEditor.call(this,!0):t._toggleEditor.call(this,!1);else if(!t._ref){if(i===t._fixedCell)return;t._toggleEditor.call(this,!1)}i&&i!==t._selectedCell&&t._fixedCellName===i.nodeName&&t._selectedTable===this.util.getParentElement(i,"TABLE")&&(t._selectedCell=i,t._setMultiCells.call(this,t._fixedCell,i))},_setMultiCells:function(e,t){const i=this.plugins.table,n=i._selectedTable.rows,l=this.util,s=i._selectedTable.querySelectorAll(".se-table-selected-cell");for(let e=0,t=s.length;e0)for(let e,t=0;td||(u>=e.index?(s+=e.cs,u+=e.cs,e.rs-=1,e.row=d+1,e.rs<1&&(a.splice(t,1),t--)):g===m-1&&(e.rs-=1,e.row=d+1,e.rs<1&&(a.splice(t,1),t--)));if(o){if(n!==e&&n!==t||(c.cs=null!==c.cs&&c.csu+h?c.ce:u+h,c.rs=null!==c.rs&&c.rsd+p?c.re:d+p,c._i+=1),2===c._i){o=!1,a=[],r=[],d=-1;break}}else if(l.getOverlapRangeAtIndex(c.cs,c.ce,u,u+h)&&l.getOverlapRangeAtIndex(c.rs,c.re,d,d+p)){const e=c.csu+h?c.ce:u+h,i=c.rsd+p?c.re:d+p;if(c.cs!==e||c.ce!==t||c.rs!==i||c.re!==s){c.cs=e,c.ce=t,c.rs=i,c.re=s,d=-1,a=[],r=[];break}l.addClass(n,"se-table-selected-cell")}p>0&&r.push({index:u,cs:h+1,rs:p,row:-1}),s+=n.colSpan-1}a=a.concat(r).sort((function(e,t){return e.index-t.index})),r=[]}},_removeEvents:function(){const e=this.plugins.table;e._initBind&&(this._wd.removeEventListener("touchmove",e._initBind),e._initBind=null),e._bindOnSelect&&(this._wd.removeEventListener("mousedown",e._bindOnSelect),this._wd.removeEventListener("mousemove",e._bindOnSelect),e._bindOnSelect=null),e._bindOffSelect&&(this._wd.removeEventListener("mouseup",e._bindOffSelect),e._bindOffSelect=null),e._bindOffShift&&(this._wd.removeEventListener("keyup",e._bindOffShift),e._bindOffShift=null)},_initBind:null,onTableCellMultiSelect:function(e,t){const i=this.plugins.table;i._removeEvents.call(this),this.controllersOff(),i._shift=t,i._fixedCell=e,i._fixedCellName=e.nodeName,i._selectedTable=this.util.getParentElement(e,"TABLE");const n=i._selectedTable.querySelectorAll(".se-table-selected-cell");for(let e=0,t=n.length;e-1?(i=e.toLowerCase(),o="blockquote"===i?"range":"pre"===i?"free":"replace",r=/^h/.test(i)?i.match(/\d+/)[0]:"",a=t["tag_"+(r?"h":i)]+r,d="",c=""):(i=e.tag.toLowerCase(),o=e.command,a=e.name||i,d=e.class,c=d?' class="'+d+'"':""),s+='
  • ";return s+="
    ",i.innerHTML=s,i},active:function(e){let t=this.lang.toolbar.formats;const i=this.context.formatBlock.targetText,n=this.context.formatBlock.targetTooltip;if(e){if(this.util.isFormatElement(e)){const l=this.context.formatBlock._formatList,s=e.nodeName.toLowerCase(),o=(e.className.match(/(\s|^)__se__format__[^\s]+/)||[""])[0].trim();for(let e,i=0,n=l.length;i=0;u--)if(n=g[u],n!==(g[u+1]?g[u+1].parentNode:null)){if(d=a.isComponent(n),s=d?"":n.innerHTML.replace(/(?!>)\s+(?=<)|\n/g," "),o=a.getParentElement(n,(function(e){return e.parentNode===t})),(t!==n.parentNode||d)&&(a.isFormatElement(t)?(t.parentNode.insertBefore(i,t.nextSibling),t=t.parentNode):(t.insertBefore(i,o?o.nextSibling:null),t=n.parentNode),r=i.nextSibling,r&&i.nodeName===r.nodeName&&a.isSameAttributes(i,r)&&(i.innerHTML+="
    "+r.innerHTML,a.removeItem(r)),i=l.cloneNode(!1),h=!0),c=i.innerHTML,i.innerHTML=(h||!s||!c||/
    $/i.test(s)?s:s+"
    ")+c,0===u){t.insertBefore(i,n),r=n.nextSibling,r&&i.nodeName===r.nodeName&&a.isSameAttributes(i,r)&&(i.innerHTML+="
    "+r.innerHTML,a.removeItem(r));const e=i.previousSibling;e&&i.nodeName===e.nodeName&&a.isSameAttributes(i,e)&&(e.innerHTML+="
    "+i.innerHTML,a.removeItem(i))}d||a.removeItem(n),s&&(h=!1)}this.setRange(n,0,n,0)}else{for(let e,t,i=0,o=g.length;i('+t.toolbar.default+")";for(let e,t=0,i=n.length;t";return l+="
    ",i.innerHTML=l,i},on:function(){const e=this.context.lineHeight,t=e._sizeList,i=this.util.getFormatElement(this.getSelectionNode()).style.lineHeight+"";if(i!==e.currentSize){for(let e=0,n=t.length;e";return i+="
    ",t.innerHTML=i,t},pickup:function(e){if(!/^BUTTON$/i.test(e.target.tagName))return!1;e.preventDefault(),e.stopPropagation();const t=this.context.option.templates[e.target.getAttribute("data-value")];if(!t.html)throw this.submenuOff(),Error('[SUNEDITOR.template.fail] cause : "templates[i].html not found"');this.setContents(t.html),this.submenuOff()}},paragraphStyle:{name:"paragraphStyle",display:"submenu",add:function(e,t){const i=e.context;i.paragraphStyle={_classList:null};let n=this.setSubmenu.call(e);n.querySelector("ul").addEventListener("click",this.pickUp.bind(e)),i.paragraphStyle._classList=n.querySelectorAll("li button"),t.parentNode.appendChild(n),n=null},setSubmenu:function(){const e=this.context.option,t=this.util.createElement("DIV");t.className="se-submenu se-list-layer";const i=this.lang.menu,n={spaced:{name:i.spaced,class:"__se__p-spaced",_class:""},bordered:{name:i.bordered,class:"__se__p-bordered",_class:""},neon:{name:i.neon,class:"__se__p-neon",_class:""}},l=e.paragraphStyles&&0!==e.paragraphStyles.length?e.paragraphStyles:["spaced","bordered","neon"];let s='
      ';for(let e,t,i,o,a=0,r=l.length;a
    "}return s+="
    ",t.innerHTML=s,t},on:function(){const e=this.context.paragraphStyle._classList,t=this.util.getFormatElement(this.getSelectionNode());for(let i=0,n=e.length;i"}return l+="
    ",t.innerHTML=l,t},on:function(){const e=this.util,t=this.context.textStyle._styleList,i=this.getSelectionNode();for(let n,l,s,o=0,a=t.length;o'+e.dialogBox.linkBox.title+'
    ",t},setController_LinkButton:function(){const e=this.lang,t=this.util.createElement("DIV");return t.className="se-controller se-controller-link",t.innerHTML='
    ",t},open:function(){this.plugins.dialog.open.call(this,"link","link"===this.currentControllerName)},submit:function(e){this.showLoading(),e.preventDefault(),e.stopPropagation();const t=function(){if(0===this.context.link.focusElement.value.trim().length)return!1;const e=this.context.link,t=e.focusElement.value,i=e.linkAnchorText,n=0===i.value.length?t:i.value;if(this.context.dialog.updateModal)e._linkAnchor.href=t,e._linkAnchor.textContent=n,e._linkAnchor.target=e.linkNewWindowCheck.checked?"_blank":"",this.setRange(e._linkAnchor.childNodes[0],0,e._linkAnchor.childNodes[0],e._linkAnchor.textContent.length);else{const i=this.util.createElement("A");i.href=t,i.textContent=n,i.target=e.linkNewWindowCheck.checked?"_blank":"";const l=this.getSelectedElements();if(l.length>1){const e=this.util.createElement(l[0].nodeName);e.appendChild(i),this.insertNode(e)}else this.insertNode(i);this.setRange(i.childNodes[0],0,i.childNodes[0],i.textContent.length)}this.history.push(!1),e.focusElement.value="",e.linkAnchorText.value=""}.bind(this);try{t()}finally{this.plugins.dialog.close.call(this),this.closeLoading(),this.focus()}return!1},active:function(e){if(e){if(this.util.isAnchor(e)&&null===e.getAttribute("data-image-link"))return this.controllerArray[0]!==this.context.link.linkBtn&&this.plugins.link.call_controller_linkButton.call(this,e),!0}else this.controllerArray[0]===this.context.link.linkBtn&&this.controllersOff();return!1},on:function(e){e||(this.context.link.linkAnchorText.value=this.getSelection().toString()),this.context.link._linkAnchor&&(this.context.dialog.updateModal=!0,this.context.link.focusElement.value=this.context.link._linkAnchor.href,this.context.link.linkAnchorText.value=this.context.link._linkAnchor.textContent,this.context.link.linkNewWindowCheck.checked=!!/_blank/i.test(this.context.link._linkAnchor.target))},call_controller_linkButton:function(e){this.editLink=this.context.link._linkAnchor=e;const t=this.context.link.linkBtn,i=t.querySelector("a");i.href=e.href,i.title=e.textContent,i.textContent=e.textContent;const n=this.util.getOffset(e,this.context.element.wysiwygFrame);t.style.top=n.top+e.offsetHeight+10+"px",t.style.left=n.left-this.context.element.wysiwygFrame.scrollLeft+"px",t.style.display="block";const l=this.context.element.wysiwygFrame.offsetWidth-(t.offsetLeft+t.offsetWidth);l<0?(t.style.left=t.offsetLeft+l+"px",t.firstElementChild.style.left=20-l+"px"):t.firstElementChild.style.left="20px",this.controllersOn(t,this.plugins.link.init.bind(this),"link")},onClick_linkBtn:function(e){e.stopPropagation();const t=e.target.getAttribute("data-command")||e.target.parentNode.getAttribute("data-command");if(t){if(e.preventDefault(),/update/.test(t))this.context.link.focusElement.value=this.context.link._linkAnchor.href,this.context.link.linkAnchorText.value=this.context.link._linkAnchor.textContent,this.context.link.linkNewWindowCheck.checked=!!/_blank/i.test(this.context.link._linkAnchor.target),this.plugins.dialog.open.call(this,"link",!0);else if(/unlink/.test(t)){const e=this.util.getChildElement(this.context.link._linkAnchor,(function(e){return 0===e.childNodes.length||3===e.nodeType}),!1),t=this.util.getChildElement(this.context.link._linkAnchor,(function(e){return 0===e.childNodes.length||3===e.nodeType}),!0);this.setRange(e,0,t,t.textContent.length),this.nodeChange(null,null,["A"],!1)}else this.util.removeItem(this.context.link._linkAnchor),this.context.link._linkAnchor=null,this.focus(),this.history.push(!1);this.controllersOff()}},init:function(){if(!/link/i.test(this.context.dialog.kind)){const e=this.context.link;e.linkBtn.style.display="none",e._linkAnchor=null,e.focusElement.value="",e.linkAnchorText.value="",e.linkNewWindowCheck.checked=!1}}},image:{name:"image",display:"dialog",add:function(e){e.addModule([l,s,o]);const t=e.context;t.image={sizeUnit:t.option._imageSizeUnit,_linkElement:null,_container:null,_cover:null,_element:null,_element_w:1,_element_h:1,_element_l:0,_element_t:0,_defaultSizeX:"auto",_defaultSizeY:"auto",_origin_w:"auto"===t.option.imageWidth?"":t.option.imageWidth,_origin_h:"",_altText:"",_caption:null,captionCheckEl:null,_linkValue:"",_align:"none",_captionChecked:!1,_proportionChecked:!0,_floatClassRegExp:"__se__float\\-[a-z]+",_xmlHttp:null,_captionShow:!0,_resizing:t.option.imageResizing,_rotation:t.option.imageRotation,_resizeDotHide:!t.option.imageHeightShow,_uploadFileLength:0,_onlyPercentage:t.option.imageSizeOnlyPercentage,_ratio:!1,_ratioX:1,_ratioY:1};let i=this.setDialog.call(e);t.image.modal=i,t.image.imgUrlFile=i.querySelector("._se_image_url"),t.image.imgInputFile=t.image.focusElement=i.querySelector("._se_image_file")||i.querySelector("._se_image_url"),t.image.altText=i.querySelector("._se_image_alt"),t.image.imgLink=i.querySelector("._se_image_link"),t.image.imgLinkNewWindowCheck=i.querySelector("._se_image_link_check"),t.image.captionCheckEl=i.querySelector("._se_image_check_caption"),t.image.modal.querySelector(".se-dialog-tabs").addEventListener("click",this.openTab.bind(e)),t.image.modal.querySelector(".se-btn-primary").addEventListener("click",this.submit.bind(e)),t.image.proportion={},t.image.inputX={},t.image.inputY={},t.option.imageResizing&&(t.image.proportion=i.querySelector("._se_image_check_proportion"),t.image.inputX=i.querySelector("._se_image_size_x"),t.image.inputY=i.querySelector("._se_image_size_y"),t.image.inputX.value=t.option.imageWidth,t.image.inputX.addEventListener("keyup",this.setInputSize.bind(e,"x")),t.image.inputY.addEventListener("keyup",this.setInputSize.bind(e,"y")),t.image.inputX.addEventListener("change",this.setRatio.bind(e)),t.image.inputY.addEventListener("change",this.setRatio.bind(e)),t.image.proportion.addEventListener("change",this.setRatio.bind(e)),i.querySelector(".se-dialog-btn-revert").addEventListener("click",this.sizeRevert.bind(e))),t.dialog.modal.appendChild(i),i=null},setDialog:function(){const e=this.context.option,t=this.lang,i=this.util.createElement("DIV");i.className="se-dialog-content",i.style.display="none";let n='
    '+t.dialogBox.imageBox.title+'
    ';if(e.imageFileInput&&(n+='
    '),e.imageUrlInput&&(n+='
    '),n+='
    ',e.imageResizing){const i=e.imageSizeOnlyPercentage,l=i?' style="display: none !important;"':"",s=e.imageHeightShow?"":' style="display: none !important;"';n+='
    ',i||!e.imageHeightShow?n+='
    ":n+='
    ",n+=' '+t.dialogBox.proportion+'
    '}return n+='
    ",i.innerHTML=n,i},open:function(){this.plugins.dialog.open.call(this,"image","image"===this.currentControllerName)},openTab:function(e){const t=this.context.image.modal,i="init"===e?t.querySelector("._se_tab_link"):e.target;if(!/^BUTTON$/i.test(i.tagName))return!1;const n=i.getAttribute("data-tab-link");let l,s,o;for(s=t.getElementsByClassName("_se_tab_content"),l=0;l0){let t=0;const i=[];for(let n=0,l=e.length;n0){let e=0;const i=this._variable._imagesInfo;for(let t=0,n=i.length;tn){const i="[SUNEDITOR.imageUpload.fail] Size of uploadable total images: "+n/1e3+"KB";return this._imageUploadError(i,{limitSize:n,currentSize:e,uploadSize:t})&&o.open.call(this,i),void this.closeLoading()}}this.context.image._uploadFileLength=i.length;const l=this.context.option.imageUploadUrl,s=this.context.option.imageUploadHeader,a=this.context.dialog.updateModal?1:i.length,r={linkValue:this.context.image._linkValue,linkNewWindow:this.context.image.imgLinkNewWindowCheck.checked,inputWidth:this.context.image.inputX.value,inputHeight:this.context.image.inputY.value,align:this.context.image._align,isUpdate:this.context.dialog.updateModal,currentImage:this.context.image._element};if(!this._imageUploadBefore(i,r))return;if("string"==typeof l&&l.length>0){const e=new FormData;for(let t=0;t0)for(let e in s)this.context.image._xmlHttp.setRequestHeader(e,s[e]);this.context.image._xmlHttp.send(e)}else for(let e=0;e0){const n=this.util.createElement("A");return n.href=/^https?:\/\//.test(t)?t:"http://"+t,n.target=i?"_blank":"",n.setAttribute("data-image-link","image"),e.setAttribute("data-image-link",t),n.appendChild(e),n}return e},setInputSize:function(e,t){t&&32===t.keyCode?t.preventDefault():this.plugins.resizing._module_setInputSize.call(this,this.context.image,e)},setRatio:function(){this.plugins.resizing._module_setRatio.call(this,this.context.image)},submit:function(e){const t=this.context.image,i=this.plugins.image;this.showLoading(),e.preventDefault(),e.stopPropagation(),t._linkValue=t.imgLink.value,t._altText=t.altText.value,t._align=t.modal.querySelector('input[name="suneditor_image_radio"]:checked').value,t._captionChecked=t.captionCheckEl.checked,t._resizing&&(t._proportionChecked=t.proportion.checked);try{this.context.dialog.updateModal&&i.update_image.call(this,!1,!1,!1),t.imgInputFile&&t.imgInputFile.files.length>0?i.onRender_imgInput.call(this):t.imgUrlFile&&t.imgUrlFile.value.trim().length>0?i.onRender_imgUrl.call(this):this.closeLoading()}catch(e){throw this.closeLoading(),Error('[SUNEDITOR.image.submit.fail] cause : "'+e.message+'"')}finally{this.plugins.dialog.close.call(this)}return!1},setImagesInfo:function(e,t){const i=this._variable._imagesInfo;let n=e.getAttribute("data-index"),l=null,s="";if(!n||this._imagesInfoInit)s="create",n=this._variable._imageIndex,this._variable._imageIndex++,e.setAttribute("data-index",n),e.setAttribute("data-file-name",t.name),e.setAttribute("data-file-size",t.size),l={src:e.src,index:1*n,name:t.name,size:t.size},i.push(l);else{s="update",n*=1;for(let e=0,t=i.length;e-1||(i.splice(t,1),this._imageUpload(null,e,"delete",null,0),t--);this.context.resizing._resize_plugin=""},_onload_image:function(e,t){t&&(this.plugins.image.setImagesInfo.call(this,e,t),this.history.push(!0))},create_image:function(e,t,i,n,l,s,o){const a=this.context.image;this.context.resizing._resize_plugin="image";let r=this.util.createElement("IMG");r.addEventListener("load",this.plugins.image._onload_image.bind(this,r,o)),r.src=e,r.alt=a._altText,r=this.plugins.image.onRender_link.call(this,r,t,i),r.setAttribute("data-rotate","0"),a._resizing&&r.setAttribute("data-proportion",a._proportionChecked);const c=this.plugins.resizing.set_cover.call(this,r),d=this.plugins.resizing.set_container.call(this,c,"se-image-container");a._captionChecked&&(a._caption=this.plugins.resizing.create_caption.call(this),a._caption.setAttribute("contenteditable",!1),c.appendChild(a._caption)),a._element=r,a._cover=c,a._container=d,this.plugins.image.applySize.call(this),this.plugins.image.setAlign.call(this,s,r,c,d),this.insertComponent(d,!0),this.context.resizing._resize_plugin=""},update_image:function(e,t,i){const n=this.context.image,l=n._linkValue;let s,o=n._element,a=n._cover,r=n._container,c=!1;null===a&&(c=!0,o=n._element.cloneNode(!0),a=this.plugins.resizing.set_cover.call(this,o)),null===r&&(a=a.cloneNode(!0),c=!0,r=this.plugins.resizing.set_container.call(this,a,"se-image-container")),c&&(r.innerHTML="",r.appendChild(a));const d=this.util.isNumber(n.inputX.value)?n.inputX.value+n.sizeUnit:n.inputX.value,u=this.util.isNumber(n.inputY.value)?n.inputY.value+n.sizeUnit:n.inputY.value;if(s=/%$/.test(o.style.width)?d!==r.style.width||u!==r.style.height:d!==o.style.width||u!==o.style.height,o.alt=n._altText,n._captionChecked?n._caption||(n._caption=this.plugins.resizing.create_caption.call(this),a.appendChild(n._caption)):n._caption&&(this.util.removeItem(n._caption),n._caption=null),l.trim().length>0)if(null!==n._linkElement)n._linkElement.href=l,n._linkElement.target=n.imgLinkNewWindowCheck.checked?"_blank":"",o.setAttribute("data-image-link",l);else{let e=this.plugins.image.onRender_link.call(this,o,l,this.context.image.imgLinkNewWindowCheck.checked);a.insertBefore(e,n._caption)}else if(null!==n._linkElement){const e=o;e.setAttribute("data-image-link","");let t=e.cloneNode(!0);a.removeChild(n._linkElement),a.insertBefore(t,n._caption),o=t}if(c){const e=this.util.isRangeFormatElement(n._element.parentNode)||this.util.isWysiwygDiv(n._element.parentNode)?n._element:/^A$/i.test(n._element.parentNode.nodeName)?n._element.parentNode:this.util.getFormatElement(n._element)||n._element;e.parentNode.replaceChild(r,e),o=r.querySelector("img"),n._element=o,n._cover=a,n._container=r}!n._onlyPercentage&&s&&!e&&(/\d+/.test(o.style.height)||this.context.resizing._rotateVertical&&n._captionChecked)&&(/%$/.test(n.inputX.value)||/%$/.test(n.inputY.value)?this.plugins.resizing.resetTransform.call(this,o):this.plugins.resizing.setTransformSize.call(this,o,this.util.getNumber(n.inputX.value,0),this.util.getNumber(n.inputY.value,0)));if(n._resizing&&(o.setAttribute("data-proportion",n._proportionChecked),s&&this.plugins.image.applySize.call(this)),this.plugins.image.setAlign.call(this,null,o,null,null),e&&this.plugins.image.setImagesInfo.call(this,o,{name:o.getAttribute("data-file-name")||o.src.split("/").pop(),size:o.getAttribute("data-file-size")||0}),t){this.plugins.image.init.call(this);const e=this.plugins.resizing.call_controller_resize.call(this,o,"image");this.plugins.image.onModifyMode.call(this,o,e)}i||this.history.push(!1)},update_src:function(e,t,i){t.src=e,this._w.setTimeout(this.plugins.image.setImagesInfo.bind(this,t,i))},onModifyMode:function(e,t){if(!e)return;const i=this.context.image;i._linkElement=/^A$/i.test(e.parentNode.nodeName)?e.parentNode:null,i._element=e,i._cover=this.util.getParentElement(e,"FIGURE"),i._container=this.util.getParentElement(e,this.util.isMediaComponent),i._caption=this.util.getChildElement(i._cover,"FIGCAPTION"),i._align=e.getAttribute("data-align")||"none",t&&(i._element_w=t.w,i._element_h=t.h,i._element_t=t.t,i._element_l=t.l);let n=i._element.getAttribute("data-size")||i._element.getAttribute("data-origin");n?(n=n.split(","),i._origin_w=n[0],i._origin_h=n[1]):t&&(i._origin_w=t.w,i._origin_h=t.h)},openModify:function(e){const t=this.context.image;t.imgUrlFile.value=t._element.src,t._altText=t.altText.value=t._element.alt,t._linkValue=t.imgLink.value=null===t._linkElement?"":t._linkElement.href,t.imgLinkNewWindowCheck.checked=t._linkElement&&"_blank"===t._linkElement.target,t.modal.querySelector('input[name="suneditor_image_radio"][value="'+t._align+'"]').checked=!0,t._align=t.modal.querySelector('input[name="suneditor_image_radio"]:checked').value,t._captionChecked=t.captionCheckEl.checked=!!t._caption,t._resizing&&this.plugins.resizing._module_setModifyInputSize.call(this,t,this.plugins.image),e||this.plugins.dialog.open.call(this,"image",!0)},on:function(e){if(!e){const e=this.context.image;e.inputX.value=e._origin_w=this.context.option.imageWidth===e._defaultSizeX?"":this.context.option.imageWidth,e.inputY.value=e._origin_h="",e.inputY.disabled=!0,e.proportion.disabled=!0}},sizeRevert:function(){this.plugins.resizing._module_sizeRevert.call(this,this.context.image)},applySize:function(e,t){const i=this.context.image;return e||(e=i.inputX.value),t||(t=i.inputY.value),i._onlyPercentage&&e||/%$/.test(e)?(this.plugins.image.setPercentSize.call(this,e,t),!0):(e&&"auto"!==e||t&&"auto"!==t?this.plugins.image.setSize.call(this,e,t,!1):this.plugins.image.setAutoSize.call(this),!1)},setSize:function(e,t,i){const n=this.context.image;this.plugins.image.cancelPercentAttr.call(this),n._element.style.width=this.util.isNumber(e)?e+n.sizeUnit:e,n._element.style.height=this.util.isNumber(t)?t+n.sizeUnit:/%$/.test(t)?"":t,"center"===n._align&&this.plugins.image.setAlign.call(this,null,null,null,null),i||n._element.removeAttribute("data-percentage"),this.plugins.resizing._module_saveCurrentSize.call(this,n)},setAutoSize:function(){const e=this.context.image;this.plugins.resizing.resetTransform.call(this,e._element),this.plugins.image.cancelPercentAttr.call(this),e._element.style.maxWidth="",e._element.style.width="",e._element.style.height="",e._cover.style.width="",e._cover.style.height="",this.plugins.image.setAlign.call(this,null,null,null,null),e._element.setAttribute("data-percentage","auto,auto"),this.plugins.resizing._module_saveCurrentSize.call(this,e)},setOriginSize:function(){const e=this.context.image;e._element.removeAttribute("data-percentage"),this.plugins.resizing.resetTransform.call(this,e._element),this.plugins.image.cancelPercentAttr.call(this);const t=(e._element.getAttribute("data-origin")||"").split(","),i=t[0],n=t[1];t&&(e._onlyPercentage||/%$/.test(i)&&(/%$/.test(n)||!/\d/.test(n))?this.plugins.image.setPercentSize.call(this,i,n):this.plugins.image.setSize.call(this,i,n),this.plugins.resizing._module_saveCurrentSize.call(this,e))},setPercentSize:function(e,t){const i=this.context.image;t=!t||/%$/.test(t)||this.util.getNumber(t,0)?this.util.isNumber(t)?t+i.sizeUnit:t||"":this.util.isNumber(t)?t+"%":t;const n=/%$/.test(t);i._container.style.width=this.util.isNumber(e)?e+"%":e,i._container.style.height="",i._cover.style.width="100%",i._cover.style.height=n?t:"",i._element.style.width="100%",i._element.style.height=n?"":t,i._element.style.maxWidth="","center"===i._align&&this.plugins.image.setAlign.call(this,null,null,null,null),i._element.setAttribute("data-percentage",e+","+t),this.plugins.resizing.setCaptionPosition.call(this,i._element),this.plugins.resizing._module_saveCurrentSize.call(this,i)},cancelPercentAttr:function(){const e=this.context.image;e._cover.style.width="",e._cover.style.height="",e._container.style.width="",e._container.style.height="",this.util.removeClass(e._container,this.context.image._floatClassRegExp),this.util.addClass(e._container,"__se__float-"+e._align),"center"===e._align&&this.plugins.image.setAlign.call(this,null,null,null,null)},setAlign:function(e,t,i,n){const l=this.context.image;e||(e=l._align),t||(t=l._element),i||(i=l._cover),n||(n=l._container),i.style.margin=e&&"none"!==e?"auto":"0",/%$/.test(t.style.width)&&"center"===e?(n.style.minWidth="100%",i.style.width=n.style.width):(n.style.minWidth="",i.style.width=this.context.resizing._rotateVertical?t.style.height||t.offsetHeight:t.style.width&&"auto"!==t.style.width?t.style.width||"100%":""),this.util.hasClass(n,"__se__float-"+e)||(this.util.removeClass(n,l._floatClassRegExp),this.util.addClass(n,"__se__float-"+e)),t.setAttribute("data-align",e)},resetAlign:function(){const e=this.context.image;e._element.setAttribute("data-align",""),e._align="none",e._cover.style.margin="0",this.util.removeClass(e._container,e._floatClassRegExp)},destroy:function(e){const t=e||this.context.image._element,i=this.util.getParentElement(t,this.util.isMediaComponent)||t,n=1*t.getAttribute("data-index");let l=i.previousElementSibling||i.nextElementSibling;if(this.util.removeItem(i),this.plugins.image.init.call(this),this.controllersOff(),this.focusEdge(l),n>=0){const e=this._variable._imagesInfo;for(let t=0,i=e.length;t'+t.dialogBox.videoBox.title+'
    ';if(e.videoResizing){const i=e.videoRatioList||[{name:"16:9",value:.5625},{name:"4:3",value:.75},{name:"21:9",value:.4285}],l=e.videoRatio,s=e.videoSizeOnlyPercentage,o=s?' style="display: none !important;"':"",a=e.videoHeightShow?"":' style="display: none !important;"',r=e.videoRatioShow?"":' style="display: none !important;"',c=s||e.videoHeightShow||e.videoRatioShow?"":' style="display: none !important;"';n+='
    "}return n+='
    ",i.innerHTML=n,i},open:function(){this.plugins.dialog.open.call(this,"video","video"===this.currentControllerName)},setVideoRatio:function(e){const t=this.context.video,i=e.target.options[e.target.selectedIndex].value;t._defaultSizeY=t._videoRatio=i?100*i+"%":t._defaultSizeY,t.inputY.placeholder=i?100*i+"%":"",t.inputY.value=""},setInputSize:function(e,t){if(t&&32===t.keyCode)return void t.preventDefault();const i=this.context.video;this.plugins.resizing._module_setInputSize.call(this,i,e),"y"===e&&this.plugins.video.setVideoRatioSelect.call(this,t.target.value||i._videoRatio)},setRatio:function(){this.plugins.resizing._module_setRatio.call(this,this.context.video)},_onload_video:function(e){this.plugins.video.setVideosInfo.call(this,e)},submitAction:function(){if(0===this.context.video.focusElement.value.trim().length)return!1;this.context.resizing._resize_plugin="video";const e=this.context.video;let t=null,i=null,n=null,l=e.focusElement.value.trim();if(e._align=e.modal.querySelector('input[name="suneditor_video_radio"]:checked').value,/^$/.test(l))t=(new this._w.DOMParser).parseFromString(l,"text/html").querySelector("iframe");else{if(t=this.util.createElement("IFRAME"),/youtu\.?be/.test(l)&&(/^http/.test(l)||(l="https://"+l),l=l.replace("watch?v=",""),/^\/\/.+\/embed\//.test(l)||(l=l.replace(l.match(/\/\/.+\//)[0],"//www.youtube.com/embed/").replace("&","?&")),e._youtubeQuery.length>0))if(/\?/.test(l)){const t=l.split("?");l=t[0]+"?"+e._youtubeQuery+"&"+t[1]}else l+="?"+e._youtubeQuery;t.src=l}this.context.dialog.updateModal?(e._element.src!==t.src&&(e._element.src=t.src),n=e._container,i=this.util.getParentElement(e._element,"FIGURE"),t=e._element):(t.frameBorder="0",t.allowFullscreen=!0,t.addEventListener("load",this.plugins.video._onload_video.bind(this,t)),e._element=t,i=this.plugins.resizing.set_cover.call(this,t),n=this.plugins.resizing.set_container.call(this,i,"se-video-container"),this._variable._videosCnt++),e._cover=i,e._container=n;const s=this.plugins.resizing._module_getSizeX.call(this,e)!==(e.inputX.value||e._defaultSizeX)||this.plugins.resizing._module_getSizeY.call(this,e)!==(e.inputY.value||e._videoRatio),o=!this.context.dialog.updateModal||s;e._resizing&&(this.context.video._proportionChecked=e.proportion.checked,t.setAttribute("data-proportion",e._proportionChecked));let a=!1;o&&(a=this.plugins.video.applySize.call(this)),a&&"center"===e._align||this.plugins.video.setAlign.call(this,null,t,i,n),this.context.dialog.updateModal?e._resizing&&this.context.resizing._rotateVertical&&o&&this.plugins.resizing.setTransformSize.call(this,t,null,null):this.insertComponent(n,!1),this.context.resizing._resize_plugin="",this.context.dialog.updateModal&&this.history.push(!1)},setVideosInfo:function(e){if(!e.getAttribute("data-origin")){const t=this.util.getParentElement(e,this.util.isMediaComponent),i=this.util.getParentElement(e,"FIGURE"),n=this.plugins.resizing._module_getSizeX.call(this,this.context.video,e,i,t),l=this.plugins.resizing._module_getSizeY.call(this,this.context.video,e,i,t);e.setAttribute("data-origin",n+","+l),e.setAttribute("data-size",n+","+l)}},submit:function(e){this.showLoading(),e.preventDefault(),e.stopPropagation();try{this.plugins.video.submitAction.call(this)}finally{this.plugins.dialog.close.call(this),this.closeLoading()}return this.focus(),!1},_update_videoCover:function(e){if(!e)return;const t=this.context.video;e.frameBorder="0",e.allowFullscreen=!0,e.onload=e.addEventListener("load",this.plugins.video._onload_video.bind(this,e));const i=this.util.getParentElement(e,this.util.isMediaComponent)||this.util.getParentElement(e,function(e){return this.isWysiwygDiv(e.parentNode)}.bind(this.util));t._element=e=e.cloneNode(!1);const n=t._cover=this.plugins.resizing.set_cover.call(this,e),l=t._container=this.plugins.resizing.set_container.call(this,n,"se-video-container"),s=i.querySelector("figcaption");let o=null;s&&(o=this.util.createElement("DIV"),o.innerHTML=s.innerHTML,this.util.removeItem(s));const a=(e.getAttribute("data-size")||e.getAttribute("data-origin")||"").split(",");this.plugins.video.applySize.call(this,a[0]||this.context.option.videoWidth,a[1]||""),i.parentNode.replaceChild(l,i),o&&i.parentNode.insertBefore(o,l.nextElementSibling)},onModifyMode:function(e,t){const i=this.context.video;i._element=e,i._cover=this.util.getParentElement(e,"FIGURE"),i._container=this.util.getParentElement(e,this.util.isMediaComponent),i._align=e.getAttribute("data-align")||"none",i._element_w=t.w,i._element_h=t.h,i._element_t=t.t,i._element_l=t.l;let n=i._element.getAttribute("data-size")||i._element.getAttribute("data-origin");n?(n=n.split(","),i._origin_w=n[0],i._origin_h=n[1]):(i._origin_w=t.w,i._origin_h=t.h)},openModify:function(e){const t=this.context.video;if(t.focusElement.value=t._element.src,t.modal.querySelector('input[name="suneditor_video_radio"][value="'+t._align+'"]').checked=!0,t._resizing){this.plugins.resizing._module_setModifyInputSize.call(this,t,this.plugins.video);const e=t._videoRatio=this.plugins.resizing._module_getSizeY.call(this,t);this.plugins.video.setVideoRatioSelect.call(this,e)||(t.inputY.value=t._onlyPercentage?this.util.getNumber(e,2):e)}e||this.plugins.dialog.open.call(this,"video",!0)},on:function(e){if(!e){const e=this.context.video;e.inputX.value=e._origin_w=this.context.option.videoWidth===e._defaultSizeX?"":this.context.option.videoWidth,e.inputY.value=e._origin_h="",e.proportion.disabled=!0}},setVideoRatioSelect:function(e){let t=!1;const i=this.context.video,n=i.videoRatioOption.options;/%$/.test(e)||i._onlyPercentage?e=this.util.getNumber(e,2)/100+"":(!this.util.isNumber(e)||1*e>=1)&&(e=""),i.inputY.placeholder="";for(let l=0,s=n.length;l0||!i.style.width)&&t._update_videoCover.call(this,i);this.context.resizing._resize_plugin=""},sizeRevert:function(){this.plugins.resizing._module_sizeRevert.call(this,this.context.video)},applySize:function(e,t){const i=this.context.video;return e||(e=i.inputX.value),t||(t=i.inputY.value),i._onlyPercentage||/%$/.test(e)||!e?(this.plugins.video.setPercentSize.call(this,e||"100%",t||i._videoRatio),!0):(e&&"auto"!==e||t&&"auto"!==t?this.plugins.video.setSize.call(this,e,t||i._defaultRatio,!1):this.plugins.video.setAutoSize.call(this),!1)},setSize:function(e,t,i){const n=this.context.video;e=this.util.getNumber(e,0),t=this.util.isNumber(t)?t+n.sizeUnit:t||"",n._element.style.width=e?e+n.sizeUnit:"",n._cover.style.paddingBottom=n._cover.style.height=t,/%$/.test(t)?n._element.style.height="":n._element.style.height=t,i||n._element.removeAttribute("data-percentage"),this.plugins.resizing._module_saveCurrentSize.call(this,n)},setAutoSize:function(){this.plugins.video.setPercentSize.call(this,100,this.context.video._defaultRatio)},setOriginSize:function(e){const t=this.context.video;t._element.removeAttribute("data-percentage"),this.plugins.resizing.resetTransform.call(this,t._element),this.plugins.video.cancelPercentAttr.call(this);const i=((e?t._element.getAttribute("data-size"):"")||t._element.getAttribute("data-origin")||"").split(",");if(i){const e=i[0],n=i[1];t._onlyPercentage||/%$/.test(e)&&(/%$/.test(n)||!/\d/.test(n))?this.plugins.video.setPercentSize.call(this,e,n):this.plugins.video.setSize.call(this,e,n),this.plugins.resizing._module_saveCurrentSize.call(this,t)}},setPercentSize:function(e,t){const i=this.context.video;t=!t||/%$/.test(t)||this.util.getNumber(t,0)?this.util.isNumber(t)?t+i.sizeUnit:t||i._videoRatio:this.util.isNumber(t)?t+"%":t,i._container.style.width=this.util.isNumber(e)?e+"%":e,i._container.style.height="",i._cover.style.width="100%",i._cover.style.height=t,i._cover.style.paddingBottom=t,i._element.style.width="100%",i._element.style.height="100%",i._element.style.maxWidth="","center"===i._align&&this.plugins.video.setAlign.call(this,null,null,null,null),i._element.setAttribute("data-percentage",e+","+t),this.plugins.resizing._module_saveCurrentSize.call(this,i)},cancelPercentAttr:function(){const e=this.context.video;e._cover.style.width="",e._cover.style.height="",e._cover.style.paddingBottom="",e._container.style.width="",e._container.style.height="",this.util.removeClass(e._container,this.context.video._floatClassRegExp),this.util.addClass(e._container,"__se__float-"+e._align),"center"===e._align&&this.plugins.video.setAlign.call(this,null,null,null,null)},setAlign:function(e,t,i,n){const l=this.context.video;e||(e=l._align),t||(t=l._element),i||(i=l._cover),n||(n=l._container),i.style.margin=e&&"none"!==e?"auto":"0",/%$/.test(t.style.width)&&"center"===e?(n.style.minWidth="100%",i.style.width=n.style.width,i.style.height=i.style.paddingBottom,i.style.paddingBottom=this.util.getNumber(this.util.getNumber(i.style.paddingBottom,2)/100*this.util.getNumber(i.style.width,2),2)+"%"):(n.style.minWidth="",i.style.width=this.context.resizing._rotateVertical?t.style.height||t.offsetHeight:t.style.width||"100%",i.style.paddingBottom=i.style.height),this.util.hasClass(n,"__se__float-"+e)||(this.util.removeClass(n,l._floatClassRegExp),this.util.addClass(n,"__se__float-"+e)),t.setAttribute("data-align",e)},resetAlign:function(){const e=this.context.video;e._element.setAttribute("data-align",""),e._align="none",e._cover.style.margin="0",this.util.removeClass(e._container,e._floatClassRegExp)},destroy:function(){this._variable._videosCnt--;const e=this.context.video._container;let t=e.previousElementSibling||e.nextElementSibling;this.util.removeItem(e),this.plugins.video.init.call(this),this.controllersOff(),this.focusEdge(t),this.history.push(!1)},init:function(){const e=this.context.video;e.focusElement.value="",e._origin_w=this.context.option.videoWidth,e._origin_h="",e.modal.querySelector('input[name="suneditor_video_radio"][value="none"]').checked=!0,e._resizing&&(e.inputX.value=this.context.option.videoWidth===e._defaultSizeX?"":this.context.option.videoWidth,e.inputY.value="",e.proportion.checked=!0,e.proportion.disabled=!0,this.plugins.video.setVideoRatioSelect.call(this,e._defaultRatio))}},math:{name:"math",display:"dialog",add:function(e){e.addModule([l]);const t=e.context;t.math={focusElement:null,previewElement:null,fontSizeElement:null,_mathExp:null,_renderer:null};let i=this.setDialog.call(e);t.math.modal=i,t.math.focusElement=i.querySelector(".se-math-exp"),t.math.previewElement=i.querySelector(".se-math-preview"),t.math.fontSizeElement=i.querySelector(".se-math-size"),t.math._renderer=function(e){return this.src.renderToString(e,this.options)}.bind(e.context.option.katex),t.math.focusElement.addEventListener("keyup",this._renderMathExp.bind(t.math),!1),t.math.focusElement.addEventListener("change",this._renderMathExp.bind(t.math),!1),t.math.fontSizeElement.addEventListener("change",function(e){this.fontSize=e.target.value}.bind(t.math.previewElement.style),!1);let n=this.setController_MathButton.call(e);t.math.mathBtn=n,t.math._mathExp=null,n.addEventListener("mousedown",(function(e){e.stopPropagation()}),!1),i.querySelector(".se-btn-primary").addEventListener("click",this.submit.bind(e),!1),n.addEventListener("click",this.onClick_mathBtn.bind(e)),t.dialog.modal.appendChild(i),t.element.relative.appendChild(n),i=null,n=null},setDialog:function(){const e=this.lang,t=this.util.createElement("DIV");return t.className="se-dialog-content",t.style.display="none",t.innerHTML='
    '+e.dialogBox.mathBox.title+'

    ",t},setController_MathButton:function(){const e=this.lang,t=this.util.createElement("DIV");return t.className="se-controller se-controller-link",t.innerHTML='
    ",t},open:function(){this.plugins.dialog.open.call(this,"math","math"===this.currentControllerName)},_renderMathExp:function(e){this.previewElement.innerHTML=this._renderer(e.target.value)},submit:function(e){this.showLoading(),e.preventDefault(),e.stopPropagation();const t=function(){if(0===this.context.math.focusElement.value.trim().length)return!1;const e=this.context.math,t=e.focusElement.value,i=e.previewElement.querySelector(".katex");if(!i)return!1;if(i.setAttribute("contenteditable",!1),i.setAttribute("data-exp",t),i.setAttribute("data-font-size",e.fontSizeElement.value),i.style.fontSize=e.fontSizeElement.value,this.context.dialog.updateModal){const t=function(e,i){if(e.classList.contains(i))return e;const n=e.parentNode;return n!==document.body?n.classList.contains(i)?n:void t(n,i):void 0},n=t(e._mathExp,"katex");n.parentNode.replaceChild(i,n),this.setRange(i,0,i,1)}else{const e=this.getSelectedElements();if(e.length>1){const t=this.util.createElement(e[0].nodeName);t.appendChild(i),this.insertNode(t)}else this.insertNode(i);const t=this.util.createTextNode(this.util.zeroWidthSpace);i.parentNode.insertBefore(t,i.nextSibling),this.setRange(i,0,i,1)}return e.focusElement.value="",e.fontSizeElement.value="1em",e.previewElement.style.fontSize="1em",e.previewElement.innerHTML="",!0}.bind(this);try{t()&&(this.plugins.dialog.close.call(this),this.history.push(!1))}catch(e){this.plugins.dialog.close.call(this)}finally{this.closeLoading()}return!1},active:function(e){if(e){if(e.getAttribute("data-exp"))return this.controllerArray[0]!==this.context.math.mathBtn&&(this.setRange(e,0,e,1),this.plugins.math.call_controller_mathButton.call(this,e)),!0}else this.controllerArray[0]===this.context.math.mathBtn&&this.controllersOff();return!1},on:function(e){const t=this.context.math;if(t._mathExp&&e){const e=t._mathExp.getAttribute("data-exp"),i=t._mathExp.getAttribute("data-font-size")||"1em";this.context.dialog.updateModal=!0,t.focusElement.value=e,t.fontSizeElement.value=i,t.previewElement.innerHTML=t._renderer(e),t.previewElement.style.fontSize=i}},call_controller_mathButton:function(e){this.context.math._mathExp=e;const t=this.context.math.mathBtn,i=this.util.getOffset(e,this.context.element.wysiwygFrame);t.style.top=i.top+e.offsetHeight+10+"px",t.style.left=i.left-this.context.element.wysiwygFrame.scrollLeft+"px",t.style.display="block";const n=this.context.element.wysiwygFrame.offsetWidth-(t.offsetLeft+t.offsetWidth);n<0?(t.style.left=t.offsetLeft+n+"px",t.firstElementChild.style.left=20-n+"px"):t.firstElementChild.style.left="20px",this.controllersOn(t,this.plugins.math.init.bind(this),"math")},onClick_mathBtn:function(e){e.stopPropagation();const t=e.target.getAttribute("data-command")||e.target.parentNode.getAttribute("data-command");t&&(e.preventDefault(),/update/.test(t)?(this.context.math.focusElement.value=this.context.math._mathExp.getAttribute("data-exp"),this.plugins.dialog.open.call(this,"math",!0)):(this.util.removeItem(this.context.math._mathExp),this.context.math._mathExp=null,this.focus(),this.history.push(!1)),this.controllersOff())},init:function(){if(!/math/i.test(this.context.dialog.kind)){const e=this.context.math;e.mathBtn.style.display="none",e._mathExp=null,e.focusElement.value="",e.previewElement.innerHTML=""}}}},r=i("P6u4"),c=i.n(r);const d={_d:document,_w:window,_tagConvertor:function(e){const t={b:"strong",i:"em",u:"ins",strike:"del",s:"del"};return e.replace(/(<\/?)(b|strong|i|em|u|ins|s|strike|del)\b\s*(?:[^>^<]+)?\s*(?=>)/gi,(function(e,i,n){return i+("string"==typeof t[n]?t[n]:n)}))},_HTMLConvertor:function(e){const t={"&":"&"," ":" ","'":""","<":"<",">":">"};return e.replace(/&|\u00A0|'|<|>/g,(function(e){return"string"==typeof t[e]?t[e]:e}))},zeroWidthSpace:"​",zeroWidthRegExp:new RegExp(String.fromCharCode(8203),"g"),onlyZeroWidthRegExp:new RegExp("^"+String.fromCharCode(8203)+"+$"),onlyZeroWidthSpace:function(e){return"string"!=typeof e&&(e=e.textContent),""===e||this.onlyZeroWidthRegExp.test(e)},getXMLHttpRequest:function(){if(!this._w.ActiveXObject)return this._w.XMLHttpRequest?new XMLHttpRequest:null;try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(e){try{return new ActiveXObject("Microsoft.XMLHTTP")}catch(e){return null}}},createElement:function(e){return this._d.createElement(e)},createTextNode:function(e){return this._d.createTextNode(e||"")},getIncludePath:function(e,t){let i="";const n=[],l="js"===t?"script":"link",s="js"===t?"src":"href";let o="(?:";for(let t=0,i=e.length;t0?n[0][s]:""),-1===i.indexOf(":/")&&"//"!==i.slice(0,2)&&(i=0===i.indexOf("/")?location.href.match(/^.*?:\/\/[^\/]*/)[0]+i:location.href.match(/^[^\?]*\/(?:)/)[0]+i),!i)throw"[SUNEDITOR.util.getIncludePath.fail] The SUNEDITOR installation path could not be automatically detected. (name: +"+name+", extension: "+t+")";return i},getPageStyle:function(e){let t="";const i=(e?this.getIframeDocument(e):this._d).styleSheets;for(let e,n=0,l=i.length;n-1||(n+=i[e].name+'="'+i[e].value+'" ');return n},isWysiwygDiv:function(e){return!(!e||1!==e.nodeType||!this.hasClass(e,"se-wrapper-wysiwyg")&&!/^BODY$/i.test(e.nodeName))},isFormatElement:function(e){return!(!e||1!==e.nodeType||!/^(P|DIV|H[1-6]|PRE|LI)$/i.test(e.nodeName)&&!this.hasClass(e,"(\\s|^)__se__format__replace_.+(\\s|$)|(\\s|^)__se__format__free_.+(\\s|$)")||this.isComponent(e)||this.isWysiwygDiv(e))},isRangeFormatElement:function(e){return!(!e||1!==e.nodeType||!/^(BLOCKQUOTE|OL|UL|FIGCAPTION|TABLE|THEAD|TBODY|TR|TH|TD)$/i.test(e.nodeName)&&!this.hasClass(e,"(\\s|^)__se__format__range_.+(\\s|$)"))},isFreeFormatElement:function(e){return!(!e||1!==e.nodeType||!/^PRE$/i.test(e.nodeName)&&!this.hasClass(e,"(\\s|^)__se__format__free_.+(\\s|$)")||this.isComponent(e)||this.isWysiwygDiv(e))},isComponent:function(e){return e&&(/se-component/.test(e.className)||/^(TABLE|HR)$/.test(e.nodeName))},isMediaComponent:function(e){return e&&/se-component/.test(e.className)},getFormatElement:function(e,t){if(!e)return null;for(t||(t=function(){return!0});e;){if(this.isWysiwygDiv(e))return null;if(this.isRangeFormatElement(e)&&e.firstElementChild,this.isFormatElement(e)&&t(e))return e;e=e.parentNode}return null},getRangeFormatElement:function(e,t){if(!e)return null;for(t||(t=function(){return!0});e;){if(this.isWysiwygDiv(e))return null;if(this.isRangeFormatElement(e)&&!/^(THEAD|TBODY|TR)$/i.test(e.nodeName)&&t(e))return e;e=e.parentNode}return null},getFreeFormatElement:function(e,t){if(!e)return null;for(t||(t=function(){return!0});e;){if(this.isWysiwygDiv(e))return null;if(this.isFreeFormatElement(e)&&t(e))return e;e=e.parentNode}return null},copyTagAttributes:function(e,t){t.style.cssText&&(e.style.cssText+=t.style.cssText);const i=t.classList;for(let t=0,n=i.length;t0&&!this.isBreak(e);)e=e.firstChild;for(;t&&1===t.nodeType&&t.childNodes.length>0&&!this.isBreak(t);)t=t.lastChild;return{sc:e,ec:t||e}}},getOffset:function(e,t){let i=0,n=0,l=3===e.nodeType?e.parentElement:e;const s=this.getParentElement(e,this.isWysiwygDiv.bind(this));for(;l&&!this.hasClass(l,"se-container")&&l!==s;)i+=l.offsetLeft,n+=l.offsetTop,l=l.offsetParent;const o=t&&/iframe/i.test(t.nodeName);return{left:i+(o?t.parentElement.offsetLeft:0),top:n-s.scrollTop+(o?t.parentElement.offsetTop:0)}},getOverlapRangeAtIndex:function(e,t,i,n){if(e<=n?ti)return 0;const l=(e>i?e:i)-(t0?" ":"")+t)},removeClass:function(e,t){if(!e)return;const i=new this._w.RegExp("(\\s|^)"+t+"(\\s|$)");e.className=e.className.replace(i," ").trim(),e.className.trim()||e.removeAttribute("class")},toggleClass:function(e,t){if(!e)return;const i=new this._w.RegExp("(\\s|^)"+t+"(\\s|$)");i.test(e.className)?e.className=e.className.replace(i," ").trim():e.className+=" "+t,e.className.trim()||e.removeAttribute("class")},removeItem:function(e){if(e)try{e.remove()}catch(t){e.parentNode.removeChild(e)}},removeItemAllParents:function(e,t,i){if(!e)return null;let n=null;return t||(t=function(e){if(e===i||this.isComponent(e))return!1;const t=e.textContent.trim();return 0===t.length||/^(\n|\u200B)+$/.test(t)}.bind(this)),function e(i){if(!d.isWysiwygDiv(i)){const l=i.parentNode;l&&t(i)&&(n={sc:i.previousElementSibling,ec:i.nextElementSibling},d.removeItem(i),e(l))}}(e),n},detachNestedList:function(e,t){const i=this.__deleteNestedList(e);let n,l,s;if(i){n=i.cloneNode(!1),l=i.childNodes;const t=this.getPositionIndex(e);for(;l[t];)n.appendChild(l[t])}else n=e;if(t)s=this.getListChildren(n,function(e){return this.isListCell(e)&&!e.previousElementSibling}.bind(this));else{const t=this.getElementDepth(e)+2;s=this.getListChildren(e,function(e){return this.isListCell(e)&&!e.previousElementSibling&&this.getElementDepth(e)===t}.bind(this))}for(let e=0,t=s.length;e=0){e.splitText(t);const i=this.getNodeFromPath([a+1],n);this.onlyZeroWidthSpace(i)&&(i.data=this.zeroWidthSpace)}}else 1===e.nodeType&&(e.previousSibling?e=e.previousSibling:this.getElementDepth(e)===i&&(r=!1));let c=e;for(;this.getElementDepth(c)>i;)for(a=this.getPositionIndex(c)+1,c=c.parentNode,o=l,l=c.cloneNode(!1),s=c.childNodes,o&&(this.isListCell(l)&&this.isList(o)&&o.firstElementChild&&(l.innerHTML=o.firstElementChild.innerHTML,d.removeItem(o.firstElementChild),o.children.length>0&&l.appendChild(o)),l.appendChild(o));s[a];)l.appendChild(s[a]);const u=c.parentNode;return r&&(c=c.nextSibling),l?(this.mergeSameTags(l,null,null,!1),this.mergeNestedTags(l,function(e){return this.isList(e)}.bind(this)),l.childNodes.length>0?u.insertBefore(l,c):l=c,0===n.childNodes.length&&this.removeItem(n),l):c},mergeSameTags:function(e,t,i,n){const l=this,s={a:0,b:0};return function e(o,a,r,c,d){const u=o.childNodes;for(let h,p,g=0,m=u.length;g0&&n++;const o=h.lastChild,u=p.firstChild;if(o&&u){const e=3===o.nodeType&&3===u.nodeType;let l=o.textContent.length,h=o.previousSibling;for(;h&&3===h.nodeType;)l+=h.textContent.length,h=h.previousSibling;n>0&&3===o.nodeType&&3===u.nodeType&&(o.textContent.length>0||u.textContent.length>0)&&n--,c&&t&&t[a]>g&&(a>0&&t[a-1]!==r?c=!1:(t[a]-=1,t[a+1]>=0&&t[a]===g&&(t[a+1]+=n,e&&o&&3===o.nodeType&&u&&3===u.nodeType&&(s.a+=l)))),d&&i&&i[a]>g&&(a>0&&i[a-1]!==r?d=!1:(i[a]-=1,i[a+1]>=0&&i[a]===g&&(i[a+1]+=n,e&&o&&3===o.nodeType&&u&&3===u.nodeType&&(s.b+=l))))}3===h.nodeType?h.textContent+=p.textContent:h.innerHTML+=p.innerHTML,l.removeItem(p),g--}else 1===h.nodeType&&e(h,a+1,g,c,d)}}(e,0,0,!0,!0),s},mergeNestedTags:function(e,t){"string"==typeof t?t=function(e){return this.test(e.tagName)}.bind(new this._w.RegExp("^("+(t||".+")+")$","i")):"function"!=typeof t&&(t=function(){return!0}),function e(i){let n=i.children;if(1===n.length&&n[0].nodeName===i.nodeName&&t(i)){const e=n[0];for(n=e.children;n[0];)i.appendChild(n[0]);i.removeChild(e)}for(let t=0,n=i.children.length;t")},sortByDepth:function(e,t){const i=t?1:-1,n=-1*i;e.sort(function(e,t){return this.isListCell(e)&&this.isListCell(t)?(e=this.getElementDepth(e))>(t=this.getElementDepth(t))?i:e'}return i}()+("auto"===e.height?"":"");l.allowFullscreen=!0,l.frameBorder=0,l.addEventListener("load",(function(){this.setAttribute("scrolling","auto"),this.contentDocument.head.innerHTML=''+t,this.contentDocument.body.className="sun-editor-editable",this.contentDocument.body.setAttribute("contenteditable",!0)}))}else l.setAttribute("contenteditable",!0),l.setAttribute("scrolling","auto"),l.className+=" sun-editor-editable";l.style.height=e.height,l.style.minHeight=e.minHeight,l.style.maxHeight=e.maxHeight;const s=document.createElement("TEXTAREA");s.className="se-wrapper-inner se-wrapper-code",s.style.display="none",s.style.height=e.height,s.style.minHeight=e.minHeight,s.style.maxHeight=e.maxHeight,"auto"===e.height&&(s.style.overflow="hidden");let o=null,a=null,r=null;if(e.resizingBar&&(o=document.createElement("DIV"),o.className="se-resizing-bar sun-editor-common",a=document.createElement("DIV"),a.className="se-navigation sun-editor-common",o.appendChild(a),e.charCounter)){const t=document.createElement("DIV");if(t.className="se-char-counter-wrapper",r=document.createElement("SPAN"),r.className="se-char-counter",r.textContent="0",t.appendChild(r),e.maxCharCount>0){const i=document.createElement("SPAN");i.textContent=" / "+e.maxCharCount,t.appendChild(i)}o.appendChild(t)}let c=null;return e.placeholder&&(c=document.createElement("SPAN"),c.className="se-placeholder",c.innerText=e.placeholder),{bottomBar:{resizingBar:o,navigation:a,charCounter:r},wysiwygFrame:l,codeView:s,placeholder:c}},_initOptions:function(e,t){t.lang=t.lang||c.a,t._defaultTagsWhitelist="string"==typeof t._defaultTagsWhitelist?t._defaultTagsWhitelist:"br|p|div|pre|blockquote|h[1-6]|ol|ul|li|hr|figure|figcaption|img|iframe|audio|video|table|thead|tbody|tr|th|td|a|b|strong|var|i|em|u|ins|s|span|strike|del|sub|sup",t._editorTagsWhitelist=t._defaultTagsWhitelist+("string"==typeof t.addTagsWhitelist&&t.addTagsWhitelist.length>0?"|"+t.addTagsWhitelist:""),t.pasteTagsWhitelist="string"==typeof t.pasteTagsWhitelist?t.pasteTagsWhitelist:t._editorTagsWhitelist,t.attributesWhitelist=t.attributesWhitelist&&"object"==typeof t.attributesWhitelist?t.attributesWhitelist:null,t.mode=t.mode||"classic",t.toolbarWidth=t.toolbarWidth?u.isNumber(t.toolbarWidth)?t.toolbarWidth+"px":t.toolbarWidth:"auto",t.stickyToolbar=/balloon/i.test(t.mode)?-1:void 0===t.stickyToolbar?0:/^\d+/.test(t.stickyToolbar)?u.getNumber(t.stickyToolbar,0):-1,t.iframe=t.fullPage||t.iframe,t.iframeCSSFileName=t.iframe?"string"==typeof t.iframeCSSFileName?[t.iframeCSSFileName]:t.iframeCSSFileName||["suneditor"]:null,t.codeMirror=t.codeMirror?t.codeMirror.src?t.codeMirror:{src:t.codeMirror}:null,t.display=t.display||("none"!==e.style.display&&e.style.display?e.style.display:"block"),t.popupDisplay=t.popupDisplay||"full",t.resizingBar=void 0===t.resizingBar?!/inline|balloon/i.test(t.mode):t.resizingBar,t.showPathLabel=!!t.resizingBar&&("boolean"!=typeof t.showPathLabel||t.showPathLabel),t.charCounter=t.maxCharCount>0||"boolean"==typeof t.charCounter&&t.charCounter,t.maxCharCount=u.isNumber(t.maxCharCount)&&t.maxCharCount>-1?1*t.maxCharCount:null,t.width=t.width?u.isNumber(t.width)?t.width+"px":t.width:e.clientWidth?e.clientWidth+"px":"100%",t.minWidth=(u.isNumber(t.minWidth)?t.minWidth+"px":t.minWidth)||"",t.maxWidth=(u.isNumber(t.maxWidth)?t.maxWidth+"px":t.maxWidth)||"",t.height=t.height?u.isNumber(t.height)?t.height+"px":t.height:e.clientHeight?e.clientHeight+"px":"auto",t.minHeight=(u.isNumber(t.minHeight)?t.minHeight+"px":t.minHeight)||"",t.maxHeight=(u.isNumber(t.maxHeight)?t.maxHeight+"px":t.maxHeight)||"",t.font=t.font?t.font:null,t.fontSize=t.fontSize?t.fontSize:null,t.formats=t.formats?t.formats:null,t.colorList=t.colorList?t.colorList:null,t.lineHeights=t.lineHeights?t.lineHeights:null,t.paragraphStyles=t.paragraphStyles?t.paragraphStyles:null,t.textStyles=t.textStyles?t.textStyles:null,t.fontSizeUnit="string"==typeof t.fontSizeUnit&&t.fontSizeUnit.trim()||"px",t.imageResizing=void 0===t.imageResizing||t.imageResizing,t.imageHeightShow=void 0===t.imageHeightShow||!!t.imageHeightShow,t.imageWidth=t.imageWidth?u.isNumber(t.imageWidth)?t.imageWidth+"px":t.imageWidth:"auto",t.imageSizeOnlyPercentage=!!t.imageSizeOnlyPercentage,t._imageSizeUnit=t.imageSizeOnlyPercentage?"%":"px",t.imageRotation=void 0!==t.imageRotation?t.imageRotation:!(t.imageSizeOnlyPercentage||!t.imageHeightShow),t.imageFileInput=void 0===t.imageFileInput||t.imageFileInput,t.imageUrlInput=void 0===t.imageUrlInput||!t.imageFileInput||t.imageUrlInput,t.imageUploadHeader=t.imageUploadHeader||null,t.imageUploadUrl=t.imageUploadUrl||null,t.imageUploadSizeLimit=/\d+/.test(t.imageUploadSizeLimit)?u.getNumber(t.imageUploadSizeLimit,0):null,t.videoResizing=void 0===t.videoResizing||t.videoResizing,t.videoHeightShow=void 0===t.videoHeightShow||!!t.videoHeightShow,t.videoRatioShow=void 0===t.videoRatioShow||!!t.videoRatioShow,t.videoWidth=t.videoWidth&&u.getNumber(t.videoWidth)?u.isNumber(t.videoWidth)?t.videoWidth+"px":t.videoWidth:"100%",t.videoSizeOnlyPercentage=!!t.videoSizeOnlyPercentage,t._videoSizeUnit=t.videoSizeOnlyPercentage?"%":"px",t.videoRotation=void 0!==t.videoRotation?t.videoRotation:!(t.videoSizeOnlyPercentage||!t.videoHeightShow),t.videoRatio=u.getNumber(t.videoRatio,4)||.5625,t.videoRatioList=t.videoRatioList?t.videoRatioList:null,t.youtubeQuery=(t.youtubeQuery||"").replace("?",""),t.callBackSave=t.callBackSave?t.callBackSave:null,t.templates=t.templates?t.templates:null,t.placeholder="string"==typeof t.placeholder?t.placeholder:null,t.katex=t.katex?t.katex.src?t.katex:{src:t.katex}:null,t.buttonList=t.buttonList||[["undo","redo"],["bold","underline","italic","strike","subscript","superscript"],["removeFormat"],["outdent","indent"],["fullScreen","showBlocks","codeView"],["preview","print"]]},_defaultButtons:function(e){return{bold:["_se_command_bold",e.toolbar.bold+" (CTRL+B)","STRONG","",''],underline:["_se_command_underline",e.toolbar.underline+" (CTRL+U)","INS","",''],italic:["_se_command_italic",e.toolbar.italic+" (CTRL+I)","EM","",''],strike:["_se_command_strike",e.toolbar.strike+" (CTRL+SHIFT+S)","DEL","",''],subscript:["_se_command_subscript",e.toolbar.subscript,"SUB","",''],superscript:["_se_command_superscript",e.toolbar.superscript,"SUP","",''],removeFormat:["",e.toolbar.removeFormat,"removeFormat","",''],indent:["_se_command_indent",e.toolbar.indent+" (CTRL+])","indent","",''],outdent:["_se_command_outdent",e.toolbar.outdent+" (CTRL+[)","outdent","",'',!0],fullScreen:["code-view-enabled",e.toolbar.fullScreen,"fullScreen","",''],showBlocks:["",e.toolbar.showBlocks,"showBlocks","",''],codeView:["code-view-enabled",e.toolbar.codeView,"codeView","",''],undo:["_se_command_undo",e.toolbar.undo+" (CTRL+Z)","undo","",'',!0],redo:["_se_command_redo",e.toolbar.redo+" (CTRL+Y / CTRL+SHIFT+Z)","redo","",'',!0],preview:["",e.toolbar.preview,"preview","",''],print:["",e.toolbar.print,"print","",''],save:["_se_command_save",e.toolbar.save,"save","",'',!0],blockquote:["",e.toolbar.tag_blockquote,"blockquote","command",''],font:["se-btn-select se-btn-tool-font",e.toolbar.font,"font","submenu",''+e.toolbar.font+''],formatBlock:["se-btn-select se-btn-tool-format",e.toolbar.formats,"formatBlock","submenu",''+e.toolbar.formats+''],fontSize:["se-btn-select se-btn-tool-size",e.toolbar.fontSize,"fontSize","submenu",''+e.toolbar.fontSize+''],fontColor:["",e.toolbar.fontColor,"fontColor","submenu",''],hiliteColor:["",e.toolbar.hiliteColor,"hiliteColor","submenu",''],align:["se-btn-align",e.toolbar.align,"align","submenu",''],list:["",e.toolbar.list,"list","submenu",''],horizontalRule:["btn_line",e.toolbar.horizontalRule,"horizontalRule","submenu",''],table:["",e.toolbar.table,"table","submenu",''],lineHeight:["",e.toolbar.lineHeight,"lineHeight","submenu",''],template:["",e.toolbar.template,"template","submenu",''],paragraphStyle:["",e.toolbar.paragraphStyle,"paragraphStyle","submenu",''],textStyle:["",e.toolbar.textStyle,"textStyle","submenu",''],link:["",e.toolbar.link,"link","dialog",''],image:["",e.toolbar.image,"image","dialog",''],video:["",e.toolbar.video,"video","dialog",''],math:["",e.toolbar.math,"math","dialog",'']}},_createModuleGroup:function(e){const t=u.createElement("DIV");t.className="se-btn-module"+(e?"":" se-btn-module-border");const i=u.createElement("UL");return i.className="se-menu-list",t.appendChild(i),{div:t,ul:i}},_createButton:function(e,t,i,n,l,s){const o=u.createElement("LI"),a=u.createElement("BUTTON");return a.setAttribute("type","button"),a.setAttribute("class","se-btn"+(e?" "+e:"")+" se-tooltip"),a.setAttribute("data-command",i),a.setAttribute("data-display",n),l+=''+t+"",s&&a.setAttribute("disabled",!0),a.innerHTML=l,o.appendChild(a),{li:o,button:a}},_createToolBar:function(e,t,i,n){const l=e.createElement("DIV");l.className="se-toolbar-separator-vertical";const s=e.createElement("DIV");s.className="se-toolbar sun-editor-common";const o=this._defaultButtons(n),a={},r={};if(i){const e=i.length?i:Object.keys(i).map((function(e){return i[e]}));for(let t,i=0,n=e.length;i0){for(let e=0;e":i),this.history.push(!0)},_nativeFocus:function(){const t=r.getParentElement(this.getSelectionNode(),"figcaption");t?t.focus():e.element.wysiwyg.focus(),this._editorRange()},focus:function(){if("none"!==e.element.wysiwygFrame.style.display){if(l.iframe)this._nativeFocus();else try{const e=this.getRange();this.setRange(e.startContainer,e.startOffset,e.endContainer,e.endOffset)}catch(e){this._nativeFocus()}d._applyTagEffects(),c._isBalloon&&d._toggleToolbarBalloon()}},focusEdge:function(e){if(r.isComponent(e)){const t=e.querySelector("IMG"),i=e.querySelector("IFRAME");t?this.selectComponent(t,"image"):i&&this.selectComponent(i,"video")}else e=r.getChildElement(e,(function(e){return 0===e.childNodes.length||3===e.nodeType}),!0),this.setRange(e,e.textContent.length,e,e.textContent.length)},setRange:function(e,t,i,n){if(!e||!i)return;t>e.textContent.length&&(t=e.textContent.length),n>i.textContent.length&&(n=i.textContent.length);const l=this._wd.createRange();l.setStart(e,t),l.setEnd(i,n);const s=this.getSelection();s.removeAllRanges&&s.removeAllRanges(),s.addRange(l),this._editorRange()},removeRange:function(){this.getSelection().removeAllRanges();const e=this.commandMap;r.removeClass(e.STRONG,"active"),r.removeClass(e.INS,"active"),r.removeClass(e.EM,"active"),r.removeClass(e.DEL,"active"),r.removeClass(e.SUB,"active"),r.removeClass(e.SUP,"active"),e.OUTDENT&&e.OUTDENT.setAttribute("disabled",!0),e.INDENT&&e.INDENT.removeAttribute("disabled")},getRange:function(){return this._variable._range||this._createDefaultRange()},getSelection:function(){return this._ww.getSelection()},getSelectionNode:function(){return this._variable._selectionNode&&!r.isWysiwygDiv(this._variable._selectionNode)||this._editorRange(),this._variable._selectionNode||e.element.wysiwyg.firstChild},_editorRange:function(){const e=this.getSelection();let t=null,i=null;t=e.rangeCount>0?e.getRangeAt(0):this._createDefaultRange(),this._variable._range=t,i=t.collapsed?t.commonAncestorContainer:e.extentNode||e.anchorNode,this._variable._selectionNode=i},_createDefaultRange:function(){e.element.wysiwyg.focus();const t=this._wd.createRange();return e.element.wysiwyg.firstChild||this.execCommand("formatBlock",!1,"P"),t.setStart(e.element.wysiwyg.firstChild,0),t.setEnd(e.element.wysiwyg.firstChild,0),t},_resetRangeToTextNode:function(){const t=this.getRange();let i,n,l,s=t.startContainer,o=t.startOffset,a=t.endContainer,c=t.endOffset;if(i=r.isWysiwygDiv(s)?e.element.wysiwyg.firstChild:s,n=o,r.isBreak(i)||1===i.nodeType&&i.childNodes.length>0){const e=r.isBreak(i);if(!e){for(;i&&!r.isBreak(i)&&1===i.nodeType;)i=i.childNodes[n]||i.nextElementSibling||i.nextSibling,n=0;let e=r.getFormatElement(i);e===r.getRangeFormatElement(e)&&(e=r.createElement(r.isCell(i)?"DIV":"P"),i.parentNode.insertBefore(e,i),e.appendChild(i))}if(r.isBreak(i)){const t=r.createTextNode(r.zeroWidthSpace);i.parentNode.insertBefore(t,i),i=t,e&&(s===a&&(a=i,c=1),r.removeItem(s))}}if(s=i,o=n,i=r.isWysiwygDiv(a)?e.element.wysiwyg.lastChild:a,n=c,r.isBreak(i)||1===i.nodeType&&i.childNodes.length>0){const e=r.isBreak(i);if(!e){for(;i&&!r.isBreak(i)&&1===i.nodeType&&(l=i.childNodes,0!==l.length);)i=l[n>0?n-1:n]||!/FIGURE/i.test(l[0].nodeName)?l[0]:i.previousElementSibling||i.previousSibling||s,n=n>0?i.textContent.length:n;let e=r.getFormatElement(i);e===r.getRangeFormatElement(e)&&(e=r.createElement(r.isCell(e)?"DIV":"P"),i.parentNode.insertBefore(e,i),e.appendChild(i))}if(r.isBreak(i)){const t=r.createTextNode(r.zeroWidthSpace);i.parentNode.insertBefore(t,i),i=t,n=1,e&&r.removeItem(a)}}a=i,c=n,this.setRange(s,o,a,c)},getSelectedElements:function(t){this._resetRangeToTextNode();let i=this.getRange();if(r.isWysiwygDiv(i.startContainer)){const t=e.element.wysiwyg.children;if(0===t.length)return null;this.setRange(t[0],0,t[t.length-1],t[t.length-1].textContent.trim().length),i=this.getRange()}const n=i.startContainer,l=i.endContainer,s=i.commonAncestorContainer,o=r.getListChildren(s,(function(e){return t?t(e):r.isFormatElement(e)}));if(r.isWysiwygDiv(s)||r.isRangeFormatElement(s)||o.unshift(r.getFormatElement(s)),n===l||1===o.length)return o;let a=r.getFormatElement(n),c=r.getFormatElement(l),d=null,u=null;const h=function(e){return!r.isTable(e)||/^TABLE$/i.test(e.nodeName)};let p=r.getRangeFormatElement(a,h),g=r.getRangeFormatElement(c,h);r.isTable(p)&&r.isListCell(p.parentNode)&&(p=p.parentNode),r.isTable(g)&&r.isListCell(g.parentNode)&&(g=g.parentNode);const m=p===g;for(let e,t=0,i=o.length;t=0;i--)if(n[i].contains(n[e])){n.splice(e,1),e--,t--;break}return n},isEdgePoint:function(e,t){return 0===t||!e.nodeValue&&1===t||t===e.nodeValue.length},showLoading:function(){e.element.loading.style.display="block"},closeLoading:function(){e.element.loading.style.display="none"},appendFormatTag:function(e,t){const i=r.getFormatElement(this.getSelectionNode()),n=t?"string"==typeof t?t:t.nodeName:r.isFormatElement(i)?i.nodeName:"P",l=r.createElement(n);return l.innerHTML="
    ",(t&&"string"!=typeof t||!t&&r.isFormatElement(i))&&r.copyTagAttributes(l,t||i),r.isCell(e)?e.insertBefore(l,e.nextElementSibling):e.parentNode.insertBefore(l,e.nextElementSibling),l},insertComponent:function(e,t){const i=this.removeNode();let n=null,l=this.getSelectionNode(),s=r.getFormatElement(l);if(r.isListCell(s))if(/^HR$/i.test(e.nodeName)){const t=r.createElement("LI"),i=r.createTextNode(r.zeroWidthSpace);t.appendChild(e),t.appendChild(i),s.parentNode.insertBefore(t,s.nextElementSibling),this.setRange(i,1,i,1)}else this.insertNode(e,l===s?null:i.container.nextSibling),e.nextSibling||e.parentNode.appendChild(r.createElement("BR")),n=r.createElement("LI"),s.parentNode.insertBefore(n,s.nextElementSibling);else{if(this.getRange().collapsed&&3===i.container.nodeType){const e=r.getParentElement(i.container,function(e){return this.isRangeFormatElement(e)}.bind(r));n=r.splitElement(i.container,i.offset,e?r.getElementDepth(e)+1:0),s=n.previousSibling}this.insertNode(e,s),n||(n=this.appendFormatTag(e,r.isFormatElement(s)?s:null))}return t||this.history.push(!1),n},selectComponent:function(e,t){if("image"===t){if(!c.plugins.image)return;c.removeRange(),c.callPlugin("image",(function(){const t=c.plugins.resizing.call_controller_resize.call(c,e,"image");c.plugins.image.onModifyMode.call(c,e,t),r.getParentElement(e,".se-image-container")||(c.plugins.image.openModify.call(c,!0),c.plugins.image.update_image.call(c,!0,!0,!0))}))}else if("video"===t){if(!c.plugins.video)return;c.removeRange(),c.callPlugin("video",(function(){const t=c.plugins.resizing.call_controller_resize.call(c,e,"video");c.plugins.video.onModifyMode.call(c,e,t)}))}},insertNode:function(e,t){const i=this.getRange();let n=null;if(t)n=t.parentNode,t=t.nextSibling;else{const e=i.startContainer,l=i.startOffset,s=i.endContainer,o=i.endOffset,a=i.commonAncestorContainer;if(n=e,3===e.nodeType&&(n=e.parentNode),i.collapsed)if(3===a.nodeType)t=a.textContent.length>o?a.splitText(o):a.nextSibling;else if(r.isBreak(n))t=n,n=n.parentNode;else{const e=n.childNodes[l];e?e.nextSibling?t=r.isBreak(e)?e.nextSibling:e:(n.removeChild(e),t=null):t=null}else{if(e===s){t=this.isEdgePoint(s,o)?s.nextSibling:s.splitText(o);let i=e;this.isEdgePoint(e,l)||(i=e.splitText(l)),n.removeChild(i)}else for(this.removeNode(),n=a,t=s;t.parentNode!==a;)t=t.parentNode}}try{if(r.isFormatElement(e)||r.isRangeFormatElement(e)||!r.isListCell(n)&&r.isComponent(e))if(r.isList(t))n=t,t=null;else if(!t){const e=this.removeNode(),i=3===e.container.nodeType?r.isListCell(r.getFormatElement(e.container))?e.container:r.getFormatElement(e.container)||e.container.parentNode:e.container;n=i.parentNode,t=i.nextSibling}n.insertBefore(e,t)}catch(t){n.appendChild(e)}finally{if(3===e.nodeType){const t=e.previousSibling,i=e.nextSibling,n=!t||3!==t.nodeType||r.onlyZeroWidthSpace(t)?"":t.textContent,l=!i||3!==i.nodeType||r.onlyZeroWidthSpace(i)?"":i.textContent;return t&&n.length>0&&(e.textContent=n+e.textContent,r.removeItem(t)),i&&i.length>0&&(e.textContent+=l,r.removeItem(i)),{startOffset:n.length,endOffset:e.textContent.length-l.length}}this.setRange(e,1,e,1),this.history.push(!0)}},removeNode:function(){const e=this.getRange();let t,i=0,n=e.startContainer,l=e.endContainer;const s=e.startOffset,o=e.endOffset,a=e.commonAncestorContainer;let c=null,d=null;const u=r.getListChildNodes(a);let h=r.getArrayIndex(u,n),p=r.getArrayIndex(u,l);if(u.length>0&&h>-1&&p>-1){for(let e=h+1,t=n;e>=0;e--)u[e]===t.parentNode&&u[e].firstChild===t&&0===s&&(h=e,t=t.parentNode);for(let e=p-1,t=l;e>h;e--)u[e]===t.parentNode&&1===u[e].nodeType&&(u.splice(e,1),t=t.parentNode,--p)}else{if(0===u.length)u.push(a),n=l=a;else if(n=l=u[0],r.isBreak(n))return{container:n,offset:0};h=p=0}function g(e){const t=r.getFormatElement(e);if(r.removeItem(e),r.isListCell(t)){const e=r.getArrayItem(t.children,r.isList,!1);if(e){const i=e.firstElementChild,n=i.childNodes;for(;n[0];)t.insertBefore(n[0],e);r.removeItemAllParents(i)}}}for(let e=h;e<=p;e++){const t=u[e];if(0===t.length||3===t.nodeType&&void 0===t.data)g(t);else if(t!==n)t!==l?g(t):(d=1===l.nodeType?r.createTextNode(l.textContent):r.createTextNode(l.substringData(o,l.length-o)),d.length>0?l.data=d.data:g(l));else if(1===n.nodeType?c=r.createTextNode(n.textContent):t===l?(c=r.createTextNode(n.substringData(0,s)+l.substringData(o,l.length-o)),i=s):c=r.createTextNode(n.substringData(0,s)),c.length>0?n.data=c.data:g(n),t===l)break}return t=l&&l.parentNode?l:n&&n.parentNode?n:e.endContainer||e.startContainer,this.setRange(t,i,t,i),this.history.push(!0),{container:t,offset:i}},applyRangeFormatElement:function(e){const t=this.getSelectedElementsAndComponents(!1);if(!t||0===t.length)return;e:for(let e,i,n,l,s,o,a=0,c=t.length;a-1&&(l=i.lastElementChild,t.indexOf(l)>-1)){let e=null;for(;e=l.lastElementChild;)if(r.isList(e)){if(!(t.indexOf(e.lastElementChild)>-1))continue e;l=e.lastElementChild}n=i.firstElementChild,s=t.indexOf(n),o=t.indexOf(l),t.splice(s,o-s+1),c=t.length}else;let i,n,l,s=t[t.length-1];i=r.isRangeFormatElement(s)||r.isFormatElement(s)?s:r.getRangeFormatElement(s)||r.getFormatElement(s),r.isCell(i)?(n=null,l=i):(n=i.nextSibling,l=i.parentNode);let o=r.getElementDepth(i),a=null;const d=[],u=function(e,t,i){let n=null;if(e!==t&&!r.isTable(t)){if(t&&r.getElementDepth(e)===r.getElementDepth(t))return i;n=r.removeItemAllParents(t,null,e)}return n?n.ec:i};for(let i,s,c,h,p,g,m,f=0,_=t.length;f<_;f++)if(i=t[f],s=i.parentNode,s&&!e.contains(s))if(c=r.getElementDepth(i),r.isList(s)){if(null===a&&(g?(a=g,m=!0,g=null):a=s.cloneNode(!1)),d.push(i),p=t[f+1],f===_-1||p&&p.parentNode!==s){p&&i.contains(p.parentNode)&&(g=p.parentNode.cloneNode(!1));let t,f=s.parentNode;for(;r.isList(f);)t=r.createElement(f.nodeName),t.appendChild(a),a=t,f=f.parentNode;const _=this.detachRangeFormatElement(s,d,null,!0,!0);o>=c?(o=c,l=_.cc,n=u(l,s,_.ec),n&&(l=n.parentNode)):l===_.cc&&(n=_.ec),l!==_.cc&&(h=u(l,_.cc,h),n=void 0!==h?h:_.cc);for(let e=0,t=_.removeArray.length;e=c&&(o=c,l=s,n=i.nextSibling),e.appendChild(i),l!==s&&(h=u(l,s),void 0!==h&&(n=h));if(c._lastEffectNode=null,r.mergeSameTags(e,null,null,!1),r.mergeNestedTags(e,function(e){return this.isList(e)}.bind(r)),n&&r.getElementDepth(n)>0&&(r.isList(n.parentNode)||r.isList(n.parentNode.parentNode))){const t=r.getParentElement(n,function(e){return this.isRangeFormatElement(e)&&!this.isList(e)}.bind(r)),i=r.splitElement(n,null,t?r.getElementDepth(t)+1:0);i.parentNode.insertBefore(e,i)}else l.insertBefore(e,n),u(e,n);const h=r.getEdgeChildNodes(e.firstElementChild,e.lastElementChild);t.length>1?this.setRange(h.sc,0,h.ec,h.ec.textContent.length):this.setRange(h.ec,h.ec.textContent.length,h.ec,h.ec.textContent.length),this.history.push(!1)},detachRangeFormatElement:function(e,t,i,n,l){const s=this.getRange(),o=s.startOffset,a=s.endOffset;let u=r.getListChildNodes(e,(function(t){return t.parentNode===e})),h=e.parentNode,p=null,g=null,m=e.cloneNode(!1);const f=[],_=r.isList(i);let b=!1,y=!1,v=!1;function x(t,i,n,l){if(r.onlyZeroWidthSpace(i)&&(i.innerHTML=r.zeroWidthSpace),3===i.nodeType)return t.insertBefore(i,n),i;const s=(v?i:l).childNodes;let o=i.cloneNode(!1),a=null,c=null;for(;s[0];)c=s[0],!r._notTextNode(c)||r.isBreak(c)||r.isListCell(o)?o.appendChild(c):(o.childNodes.length>0&&(a||(a=o),t.insertBefore(o,n),o=i.cloneNode(!1)),t.insertBefore(c,n),a||(a=c));if(o.childNodes.length>0){if(r.isListCell(t)&&r.isListCell(o)&&r.isList(n))if(_){for(a=n;n;)o.appendChild(n),n=n.nextSibling;t.parentNode.insertBefore(o,t.nextElementSibling)}else{const t=l.nextElementSibling,i=r.detachNestedList(l,!1);e===i&&t===l.nextElementSibling||(e=i,y=!0)}else t.insertBefore(o,n);a||(a=o)}return a}for(let l,s,o,a=0,c=u.length;a0&&(h.insertBefore(m,e),m=null),!_&&r.isListCell(l))if(r.getElementDepth(l)!==r.getElementDepth(o)&&(r.isListCell(h)||r.getArrayItem(l.children,r.isList,!1))){const t=l.nextElementSibling,i=r.detachNestedList(l,!1);e===i&&t===l.nextElementSibling||(e=i,y=!0)}else{const t=l;l=r.createElement(n?t.nodeName:r.isList(e.parentNode)||r.isListCell(e.parentNode)?"LI":r.isCell(e.parentNode)?"DIV":"P");const i=t.childNodes;for(;i[0];)l.appendChild(i[0]);r.copyFormatAttributes(l,t),v=!0}else l=l.cloneNode(!1);if(y){y=v=!1,u=r.getListChildNodes(e,(function(t){return t.parentNode===e})),m=e.cloneNode(!1),h=e.parentNode,a=-1,c=u.length;continue}n?(f.push(l),r.removeItem(u[a])):(i?(b||(h.insertBefore(i,e),b=!0),l=x(i,l,null,u[a])):l=x(h,l,e,u[a]),t?(g=l,p||(p=l)):p||(p=g=l))}const C=e.parentNode;let w=e.nextSibling;m&&m.children.length>0&&C.insertBefore(m,w),i?p=i.previousSibling:p||(p=e.previousSibling),w=e.nextSibling,r.removeItem(e);let N=null;if(n)N={cc:C,sc:p,ec:w,removeArray:f};else{const e=r.getEdgeChildNodes(p,g&&g.parentNode?g:p);N={cc:(e.sc||e.ec).parentNode,sc:e.sc,ec:e.ec}}if(c._lastEffectNode=null,l)return N;!n&&N&&(t?this.setRange(N.sc,o,N.ec,a):this.setRange(N.sc,0,N.sc,0)),this.history.push(!1),d._applyTagEffects()},detachList:function(e,t){let i={},n=!1,l=!1,s=null,o=null;const a=function(e){return!this.isComponent(e)}.bind(r);for(let c,d,u,h,p=0,g=e.length;p0)&&t,i=!!(i&&i.length>0)&&i;const s=!e,o=s&&!i&&!t;let c=l.startContainer,d=l.startOffset,u=l.endContainer,h=l.endOffset;if(o&&l.collapsed&&r.isFormatElement(c.parentNode)&&r.isFormatElement(u.parentNode)||c===u&&1===c.nodeType&&"false"===c.getAttribute("contenteditable"))return;if(l.collapsed&&1===c.nodeType&&!r.isBreak(c)){let e=null;const t=c.childNodes[d];t&&(t.nextSibling?e=r.isBreak(t)?t.nextSibling:t:(c.removeChild(t),e=null));const i=r.createTextNode(r.zeroWidthSpace);c.insertBefore(i,e),this.setRange(i,1,i,1),l=this.getRange(),c=l.startContainer,d=l.startOffset,u=l.endContainer,h=l.endOffset}s&&(e=r.createElement("DIV"));const p=e.nodeName;if(!o&&c===u&&!i&&e){let t=c,i=0;const n=[],l=e.style;for(let e=0,t=l.length;e0){for(;!r.isFormatElement(t)&&!r.isWysiwygDiv(t);){for(let l=0;l=n.length)return}}let g,m={},f={},_="",b="",y="";if(t){for(let e,i=0,n=t.length;i0&&(c=l.replace(_,"").trim(),c!==l&&(v.v=!0));const d=t.className;let u="";return b&&d.length>0&&(u=d.replace(b,"").trim(),u!==d&&(v.v=!0)),(!s||!b&&d||!_&&l||c||u||!i)&&(c||u||t.nodeName!==p||a.Boolean(_)!==a.Boolean(l)||a.Boolean(b)!==a.Boolean(d))?(_&&l.length>0&&(t.style.cssText=c),t.style.cssText||t.removeAttribute("style"),b&&d.length>0&&(t.className=u.trim()),t.className.trim()||t.removeAttribute("class"),t.style.cssText||t.className||t.nodeName!==p&&!i?t:(v.v=!0,null)):(v.v=!0,null)},C=this.getSelectedElements();r.getFormatElement(c)||(c=r.getChildElement(C[0],(function(e){return 3===e.nodeType})),d=0),r.getFormatElement(u)||(u=r.getChildElement(C[C.length-1],(function(e){return 3===e.nodeType})),h=u.textContent.length);const w=r.getFormatElement(c)===r.getFormatElement(u),N=C.length-(w?0:1);g=e.cloneNode(!1);const E=o||s&&function(e,t){for(let i=0,n=e.length;i0&&(g=e.cloneNode(!1),f=this._nodeChange_endLine(C[N],g,x,u,h,o,s,v,S,k));for(let t=N-1;t>0;t--)g=e.cloneNode(!1),this._nodeChange_middleLine(C[t],g,x,o,s,v);g=e.cloneNode(!1),m=this._nodeChange_startLine(C[0],g,x,c,d,o,s,v,S,k),N<=0&&(f=m)}this.controllersOff(),this.setRange(m.container,m.offset,f.container,f.offset),this.history.push(!1)},_stripRemoveNode:function(e){const t=e.parentNode;if(!e||3===e.nodeType||!t)return;const i=e.childNodes;for(;i[0];)t.insertBefore(i[0],e);t.removeChild(e)},_util_getMaintainedNode:function(e,t){return t&&!e?this.getParentElement(t,function(e){return this._isMaintainedNode(e)}.bind(this)):null},_util_isMaintainedNode:function(e,t){return t&&!e&&3!==t.nodeType&&this._isMaintainedNode(t)},_nodeChange_oneLine:function(e,t,i,n,l,s,o,c,d,u,h,p,g){let m=n.parentNode;for(;!(m.nextSibling||m.previousSibling||r.isFormatElement(m.parentNode)||r.isWysiwygDiv(m.parentNode))&&m.nodeName!==t.nodeName;)m=m.parentNode;if(!d&&m===s.parentNode&&m.nodeName===t.nodeName&&r.onlyZeroWidthSpace(n.textContent.slice(0,l))&&r.onlyZeroWidthSpace(s.textContent.slice(o))){const e=m.childNodes;let i=!0;for(let t,l,o,a,c=0,d=e.length;c0&&(i=t.test(e.style.cssText)),!i}if(function e(n,l){const s=n.childNodes;for(let n,o=0,a=s.length;o=S?T-S:E.data.length-S));if(N){const t=p(l);if(t&&t.parentNode!==e){let i=t,n=null;for(;i.parentNode!==e;){for(l=n=i.parentNode.cloneNode(!1);i.childNodes[0];)n.appendChild(i.childNodes[0]);i.appendChild(n),i=i.parentNode}i.parentNode.appendChild(t)}N=N.cloneNode(!1)}r.onlyZeroWidthSpace(s)||l.appendChild(s);const a=p(l);for(a&&(N=a),N&&(e=N),x=d,v=[],w="";x!==e&&x!==f&&null!==x;)n=g(x)?null:i(x),n&&1===x.nodeType&&A(x)&&(v.push(n),w+=x.style.cssText.substr(0,x.style.cssText.indexOf(":"))+"|"),x=x.parentNode;const c=v.pop()||o;for(C=x=c;v.length>0;)x=v.pop(),C.appendChild(x),C=x;if(t.appendChild(c),e.appendChild(t),N&&!p(k)&&(t=t.cloneNode(!1),b.appendChild(t),_.push(t)),E=o,S=0,z=!0,x!==o&&x.appendChild(E),!y)continue}if(L||d!==k){if(z){if(1===d.nodeType&&!r.isBreak(d)){r._isIgnoreNodeChange(d)?(b.appendChild(d),o--,a--,u||(t=t.cloneNode(!1),b.appendChild(t),_.push(t))):e(d,d);continue}x=d,v=[],w="";const s=[];for(;null!==x.parentNode&&x!==f&&x!==t;)n=L?x.cloneNode(!1):i(x),1===x.nodeType&&!r.isBreak(d)&&n&&A(x)&&(n&&(g(n)?N||s.push(n):v.push(n)),w+=x.style.cssText.substr(0,x.style.cssText.indexOf(":"))+"|"),x=x.parentNode;v=v.concat(s);const c=v.pop()||d;for(C=x=c;v.length>0;)x=v.pop(),C.appendChild(x),C=x;if(g(t.parentNode)&&!g(c)&&(t=t.cloneNode(!1),b.appendChild(t),_.push(t)),L||N||!g(c))c===d?l=L?b:t:L?(b.appendChild(c),l=x):(t.appendChild(c),l=x);else{t=t.cloneNode(!1);const e=c.childNodes;for(let i=0,n=e.length;i0?x:t}if(N&&3===d.nodeType)if(p(d)){const e=r.getParentElement(l,function(e){return this._isMaintainedNode(e.parentNode)||e.parentNode===b}.bind(r));N.appendChild(e),t=e.cloneNode(!1),_.push(t),b.appendChild(t)}else N=null}h=d.cloneNode(!1),l.appendChild(h),1!==d.nodeType||r.isBreak(d)||(m=h),e(d,m)}else{N=p(d);const e=r.createTextNode(1===k.nodeType?"":k.substringData(T,k.length-T)),l=r.createTextNode(y||1===k.nodeType?"":k.substringData(0,T));if(N?N=N.cloneNode(!1):g(t.parentNode)&&!N&&(t=t.cloneNode(!1),b.appendChild(t),_.push(t)),!r.onlyZeroWidthSpace(e)){x=d,w="",v=[];const t=[];for(;x!==b&&x!==f&&null!==x;)1===x.nodeType&&A(x)&&(g(x)?t.push(x.cloneNode(!1)):v.push(x.cloneNode(!1)),w+=x.style.cssText.substr(0,x.style.cssText.indexOf(":"))+"|"),x=x.parentNode;for(v=v.concat(t),h=C=x=v.pop()||e;v.length>0;)x=v.pop(),C.appendChild(x),C=x;b.appendChild(h),x.textContent=e.data}if(N&&h){const e=p(h);e&&(N=e)}for(x=d,v=[],w="";x!==b&&x!==f&&null!==x;)n=g(x)?null:i(x),n&&1===x.nodeType&&A(x)&&(v.push(n),w+=x.style.cssText.substr(0,x.style.cssText.indexOf(":"))+"|"),x=x.parentNode;const s=v.pop()||l;for(C=x=s;v.length>0;)x=v.pop(),C.appendChild(x),C=x;N?((t=t.cloneNode(!1)).appendChild(s),N.insertBefore(t,N.firstChild),b.appendChild(N),_.push(t),N=null):t.appendChild(s),k=l,T=l.data.length,L=!0,!c&&u&&(t=l,l.textContent=r.zeroWidthSpace),x!==l&&x.appendChild(k)}}}(e,b),d&&!c&&!h.v)return{startContainer:n,startOffset:l,endContainer:s,endOffset:o};if(c=c&&d)for(let e=0;e<_.length;e++){let t=_[e],i=r.createTextNode(u?r.zeroWidthSpace:t.textContent);b.replaceChild(i,t),0===e&&(E=k=i)}else{if(d)for(let e=0;e<_.length;e++)this._stripRemoveNode(_[e]);u&&(E=k=t)}r.removeEmptyNode(b,t),u&&(S=E.textContent.length,T=k.textContent.length);const B=c||0===k.textContent.length;0===k.textContent.length&&(r.removeItem(k),k=E),T=B?k.textContent.length:T;const I={s:0,e:0},R=r.getNodePath(E,b,I),D=!k.parentNode;D&&(k=E);const M={s:0,e:0},O=r.getNodePath(k,b,D||B?null:M);S+=I.s,T=u?S:D?E.textContent.length:B?T+I.s:T+M.s;const P=r.mergeSameTags(b,R,O,!0);return e.parentNode.replaceChild(b,e),E=r.getNodeFromPath(R,b),k=r.getNodeFromPath(O,b),{startContainer:E,startOffset:S+P.a,endContainer:k,endOffset:T+P.b}},_nodeChange_startLine:function(e,t,i,n,l,s,o,a,c,d){let u=n.parentNode;for(;!(u.nextSibling||u.previousSibling||r.isFormatElement(u.parentNode)||r.isWysiwygDiv(u.parentNode))&&u.nodeName!==t.nodeName;)u=u.parentNode;if(!o&&u.nodeName===t.nodeName&&!r.isFormatElement(u)&&!u.nextSibling&&r.onlyZeroWidthSpace(n.textContent.slice(0,l))){let e=!0,i=n.previousSibling;for(;i;){if(!r.onlyZeroWidthSpace(i)){e=!1;break}i=i.previousSibling}if(e)return r.copyTagAttributes(u,t),{container:n,offset:l}}a.v=!1;const h=e,p=[t],g=e.cloneNode(!1);let m,f,_,b,y=n,v=l,x=!1;if(function e(n,l){const s=n.childNodes;for(let n,o=0,a=s.length;o0,v=m.pop()||u;for(_=f=v;m.length>0;)f=m.pop(),_.appendChild(f),_=f;if(d(t.parentNode)&&!d(v)&&(t=t.cloneNode(!1),g.appendChild(t),p.push(t)),!b&&d(v)){t=t.cloneNode(!1);const e=v.childNodes;for(let i=0,n=e.length;i0;)f=m.pop(),_.appendChild(f),_=f;d!==l?(t.appendChild(d),l=f):l=t,r.isBreak(u)&&t.appendChild(u.cloneNode(!1)),e.appendChild(t),y=o,v=0,x=!0,l.appendChild(y)}}}(e,g),o&&!s&&!a.v)return{container:n,offset:l};if(s=s&&o)for(let e=0;e0&&c===d)return void(e.innerHTML=i.innerHTML)}s.v=!1;const o=e.cloneNode(!1),a=[t];let c=!0;if(function e(n,l){const s=n.childNodes;for(let n,d=0,u=s.length;d0&&(o.appendChild(t),t=t.cloneNode(!1)),o.appendChild(h),o.appendChild(t),a.push(t),l=t,d--,u--)}}(e,t),!c&&(!l||n||s.v)){if(o.appendChild(t),n&&l)for(let e=0;e0,y=m.pop()||a;for(_=f=y;m.length>0;)f=m.pop(),_.appendChild(f),_=f;if(d(t.parentNode)&&!d(y)&&(t=t.cloneNode(!1),g.insertBefore(t,g.firstChild),p.push(t)),!b&&d(y)){t=t.cloneNode(!1);const e=y.childNodes;for(let i=0,n=e.length;i0?f:t}else u?(t.insertBefore(y,t.firstChild),l=f):l=t;if(b&&3===a.nodeType)if(c(a)){const e=r.getParentElement(l,function(e){return this._isMaintainedNode(e.parentNode)||e.parentNode===g}.bind(r));b.appendChild(e),t=e.cloneNode(!1),p.push(t),g.insertBefore(t,g.firstChild)}else b=null}if(x||a!==y)n=x?i(a):a.cloneNode(!1),n&&(l.insertBefore(n,l.firstChild),1!==a.nodeType||r.isBreak(a)||(u=n)),e(a,u);else{b=c(a);const e=r.createTextNode(1===y.nodeType?"":y.substringData(v,y.length-v)),s=r.createTextNode(1===y.nodeType?"":y.substringData(0,v));if(b){b=b.cloneNode(!1);const e=c(l);if(e&&e.parentNode!==g){let t=e,i=null;for(;t.parentNode!==g;){for(l=i=t.parentNode.cloneNode(!1);t.childNodes[0];)i.appendChild(t.childNodes[0]);t.appendChild(i),t=t.parentNode}t.parentNode.insertBefore(e,t.parentNode.firstChild)}b=b.cloneNode(!1)}else d(t.parentNode)&&!b&&(t=t.cloneNode(!1),g.appendChild(t),p.push(t));for(r.onlyZeroWidthSpace(e)||l.insertBefore(e,l.firstChild),f=l,m=[];f!==g&&null!==f;)n=d(f)?null:i(f),n&&1===f.nodeType&&m.push(n),f=f.parentNode;const o=m.pop()||l;for(_=f=o;m.length>0;)f=m.pop(),_.appendChild(f),_=f;o!==l?(t.insertBefore(o,t.firstChild),l=f):l=t,r.isBreak(a)&&t.appendChild(a.cloneNode(!1)),b?(b.insertBefore(t,b.firstChild),g.insertBefore(b,g.firstChild),b=null):g.insertBefore(t,g.firstChild),y=s,v=s.data.length,x=!0,l.insertBefore(y,l.firstChild)}}}(e,g),o&&!s&&!a.v)return{container:n,offset:l};if(s=s&&o)for(let e=0;e0&&c.plugins.list.editInsideList.call(c,n,i),this._lastEffectNode=null,d._applyTagEffects(),this.history.push(!1)},toggleDisplayBlocks:function(){r.toggleClass(e.element.wysiwyg,"se-show-block"),this._resourcesStateChange()},toggleCodeView:function(){const t=this._variable.isCodeView,i=this.codeViewDisabledButtons;for(let e=0,n=i.length;e0?e.element.code.scrollHeight+"px":"auto"),l.codeMirrorEditor&&l.codeMirrorEditor.refresh(),this._variable.isCodeView=!0,this._variable.isFullScreen||(this._notHideToolbar=!0,this._isBalloon&&(e.element._arrow.style.display="none",e.element.toolbar.style.left="",this._isInline=!0,this._isBalloon=!1,d._showToolbarInline())),this._variable._range=null,e.element.code.focus()),this._checkPlaceholder()},_setCodeDataToEditor:function(){const t=this._getCodeView();if(l.fullPage){const e=(new this._w.DOMParser).parseFromString(t,"text/html"),i=e.head.children;for(let t=0,n=i.length;t0?this.convertContentsForEditor(t):"


    "},_setEditorDataToCodeView:function(){const t=this.convertHTMLForCodeView(e.element.wysiwyg);let i="";if(l.fullPage){const e=r.getAttributesToString(this._wd.body,null);i="\n\n"+this._wd.head.outerHTML.replace(/>(?!\n)/g,">\n")+"\n"+t+"\n"}else i=t;e.element.code.style.display="block",e.element.wysiwygFrame.style.display="none",this._setCodeView(i)},toggleFullScreen:function(t){const i=e.element.topArea,n=e.element.toolbar,o=e.element.editorArea,c=e.element.wysiwygFrame,u=e.element.code,h=this._variable;h.isFullScreen?(h.isFullScreen=!1,c.style.cssText=h._wysiwygOriginCssText,u.style.cssText=h._codeOriginCssText,n.style.cssText="",o.style.cssText=h._editorAreaOriginCssText,i.style.cssText=h._originCssText,s.body.style.overflow=h._bodyOverflow,l.stickyToolbar>-1&&r.removeClass(n,"se-toolbar-sticky"),h._fullScreenAttrs.sticky&&(h._fullScreenAttrs.sticky=!1,e.element._stickyDummy.style.display="block",r.addClass(n,"se-toolbar-sticky")),this._isInline=h._fullScreenAttrs.inline,this._isBalloon=h._fullScreenAttrs.balloon,this._isInline&&d._showToolbarInline(),d.onScroll_window(),r.removeClass(t.firstElementChild,"se-icon-reduction"),r.addClass(t.firstElementChild,"se-icon-expansion")):(h.isFullScreen=!0,h._fullScreenAttrs.inline=this._isInline,h._fullScreenAttrs.balloon=this._isBalloon,(this._isInline||this._isBalloon)&&(this._isInline=!1,this._isBalloon=!1),i.style.position="fixed",i.style.top="0",i.style.left="0",i.style.width="100%",i.style.height="100%",i.style.zIndex="2147483647",""!==e.element._stickyDummy.style.display&&(h._fullScreenAttrs.sticky=!0,e.element._stickyDummy.style.display="none",r.removeClass(n,"se-toolbar-sticky")),h._bodyOverflow=s.body.style.overflow,s.body.style.overflow="hidden",h._editorAreaOriginCssText=o.style.cssText,h._wysiwygOriginCssText=c.style.cssText,h._codeOriginCssText=u.style.cssText,o.style.cssText=n.style.cssText="",c.style.cssText=(c.style.cssText.match(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/)||[""])[0],u.style.cssText=(u.style.cssText.match(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/)||[""])[0],n.style.width=c.style.height=u.style.height="100%",n.style.position="relative",n.style.display="block",h.innerHeight_fullScreen=a.innerHeight-n.offsetHeight,o.style.height=h.innerHeight_fullScreen+"px",r.removeClass(t.firstElementChild,"se-icon-expansion"),r.addClass(t.firstElementChild,"se-icon-reduction"),l.iframe&&"auto"===l.height&&(o.style.overflow="auto",this._iframeAutoHeight()))},print:function(){const t=r.createElement("IFRAME");t.style.display="none",s.body.appendChild(t);const i=r.getIframeDocument(t),n=this.getContents(!0);if(l.iframe){const t=r.getIframeDocument(e.element.wysiwygFrame),s=l.fullPage?r.getAttributesToString(t.body,["contenteditable"]):'class="sun-editor-editable"';i.write(""+t.head.innerHTML+""+n+"")}else{const e=r.createElement("DIV"),t=r.createElement("STYLE");t.innerHTML=r.getPageStyle(),e.className="sun-editor-editable",e.innerHTML=n,i.head.appendChild(t),i.body.appendChild(e)}try{if(t.focus(),-1!==a.navigator.userAgent.indexOf("MSIE")||s.documentMode||a.StyleMedia)try{t.contentWindow.document.execCommand("print",!1,null)}catch(e){t.contentWindow.print()}else t.contentWindow.print()}catch(e){throw Error("[SUNEDITOR.core.print.fail] error: "+e)}finally{r.removeItem(t)}},preview:function(){const t=this.getContents(!0),i=a.open("","_blank");if(i.mimeType="text/html",l.iframe){const n=r.getIframeDocument(e.element.wysiwygFrame),s=l.fullPage?r.getAttributesToString(n.body,["contenteditable"]):'class="sun-editor-editable"';i.document.write(""+n.head.innerHTML+""+t+"")}else i.document.write(''+n.toolbar.preview+"'+t+"")},setContents:function(t){const i=this.convertContentsForEditor(t);if(this._resetComponents(),c._variable.isCodeView){const e=this.convertHTMLForCodeView(i);c._setCodeView(e)}else e.element.wysiwyg.innerHTML=i,c.history.push(!1)},getContents:function(t){const i=e.element.wysiwyg.innerHTML,n=r.createElement("DIV");n.innerHTML=i;const s=r.getListChildren(n,(function(e){return/FIGCAPTION/i.test(e.nodeName)}));for(let e=0,t=s.length;e"+this._wd.head.outerHTML+""+n.innerHTML+""}return n.innerHTML},cleanHTML:function(e,t){const i=new this._w.RegExp("^(meta|script|link|style|[a-z]+:[a-z]+)$","i"),n=this._d.createRange().createContextualFragment(e).childNodes;let l="";for(let e=0,t=n.length;e(\n|.)*<\/(script|style)>/g,"").replace(/(<[a-zA-Z0-9]+)[^>]*(?=>)/g,function(e,t){let i=null;const n=this._attributesTagsWhitelist[t.match(/(?!<)[a-zA-Z]+/)[0].toLowerCase()];if(i=n?e.match(n):e.match(this._attributesWhitelistRegExp),i)for(let e=0,n=i.length;e^<]*)>/g,""),r._tagConvertor(l?t?l.replace("string"==typeof t?r.createTagsWhitelist(t):t,""):l:e)},addDocEvent:function(e,t,i){s.addEventListener(e,t,i),l.iframe&&this._wd.addEventListener(e,t)},removeDocEvent:function(e,t){s.removeEventListener(e,t),l.iframe&&this._wd.removeEventListener(e,t)},convertContentsForEditor:function(e){let t="",i=this._d.createRange().createContextualFragment(e).childNodes;for(let e,n=0,l=i.length;n0&&(t+="

    "+n+"

    ")}else t+=e.replace(/<(?!span|font|b|strong|var|i|em|u|ins|s|strike|del|sub|sup|mark|a|label)[^>^<]+>\s+(?=<)/g,(function(e){return e.trim()}));return 0===t.length&&(t="

    "+((e=r._HTMLConvertor(e)).length>0?e:"
    ")+"

    "),r._tagConvertor(t.replace(this.editorTagsWhitelistRegExp,""))},convertHTMLForCodeView:function(e){let t="";const i=this._w.RegExp,n=new i("^(BLOCKQUOTE|PRE|TABLE|THEAD|TBODY|TR|TH|TD|OL|UL|IMG|IFRAME|VIDEO|AUDIO|FIGURE|FIGCAPTION|HR|BR|CANVAS|SELECT)$","i"),l=r.isFormatElement.bind(r),s="string"==typeof e?this._d.createRange().createContextualFragment(e):e;let o=1*this._variable.codeIndent;return o=o>0?new this._w.Array(o+1).join(" "):"",function e(s,a,c){const d=s.childNodes,u=n.test(s.nodeName),h=u?a:"";for(let p,g,m,f=0,_=d.length;f<_;f++){if(p=d[f],m=n.test(p.nodeName),g=m?"\n":"",c=!l(p)||u||/^(TH|TD)$/i.test(s.nodeName)?"":"\n",3===p.nodeType){t+=r._HTMLConvertor(/^\n+$/.test(p.data)?"":p.data);continue}if(0===p.childNodes.length){t+=(/^(HR)$/i.test(p.nodeName)?"\n":"")+h+p.outerHTML+g;continue}p.innerHTML=p.innerHTML;const _=p.nodeName.toLowerCase();t+=(c||(u?"":g))+(h||m?a:"")+p.outerHTML.match(i("<"+_+"[^>]*>","i"))[0]+g,e(p,a+o,""),t+=(m?a:"")+""+(c||g||u?"\n":/^(TH|TD)$/i.test(p.nodeName)?"\n":"")}}(s,"","\n"),t.trim()+"\n"},_charCount:function(t,i){const n=e.element.charCounter;if(!n)return!0;(!t||t<0)&&(t=0);const s=l.maxCharCount;if(a.setTimeout((function(){n.textContent=e.element.wysiwyg.textContent.length})),s>0){let l=!1;const o=e.element.wysiwyg.textContent.length;if(o>s){c._editorRange();const e=c.getRange(),t=e.endOffset-1,i=c.getSelectionNode().textContent;c.getSelectionNode().textContent=i.slice(0,e.endOffset-1)+i.slice(e.endOffset,i.length),c.setRange(e.endContainer,t,e.endContainer,t),l=!0}else o+t>s&&(l=!0);if(l)return i&&!r.hasClass(n,"se-blink")&&(r.addClass(n,"se-blink"),a.setTimeout((function(){r.removeClass(n,"se-blink")}),600)),!1}return!0},_checkComponents:function(){this.plugins.image&&(this.initPlugins.image?this.plugins.image.checkImagesInfo.call(this):this.callPlugin("image",this.plugins.image.checkImagesInfo.bind(this))),this.plugins.video&&(this.initPlugins.video?this.plugins.video.checkVideosInfo.call(this):this.callPlugin("video",this.plugins.video.checkVideosInfo.bind(this)))},_resetComponents:function(){this._variable._imagesInfo=[],this._variable._imageIndex=0,this._variable._videosCnt=0},_setCodeView:function(t){l.codeMirrorEditor?l.codeMirrorEditor.getDoc().setValue(t):e.element.code.value=t},_getCodeView:function(){return l.codeMirrorEditor?l.codeMirrorEditor.getDoc().getValue():e.element.code.value},_init:function(n,o){this._ww=l.iframe?e.element.wysiwygFrame.contentWindow:a,this._wd=s,a.setTimeout(function(){if(this._checkComponents(),this._imagesInfoInit=!1,this._imagesInfoReset=!1,this.history.reset(!0),l.iframe&&(this._wd=e.element.wysiwygFrame.contentDocument,e.element.wysiwyg=this._wd.body,"auto"===l.height&&(this._iframeAuto=this._wd.body),this._iframeAutoHeight()),"function"==typeof g.onload)return g.onload(c,n)}.bind(this)),this.editorTagsWhitelistRegExp=r.createTagsWhitelist(l._editorTagsWhitelist),this.pasteTagsWhitelistRegExp=r.createTagsWhitelist(l.pasteTagsWhitelist);const u=l.attributesWhitelist,h={};let p,m,f="";if(u){const e=a.Object.keys(u);for(let t,i=0,n=e.length;ir&&(c=c.slice(0,r),o&&o.setAttribute("disabled",!0)),c[r]={contents:i,s:{path:l.getNodePath(n.startContainer,null),offset:n.startOffset},e:{path:l.getNodePath(n.endContainer,null),offset:n.endOffset}},1===r&&s&&s.removeAttribute("disabled"),e._checkComponents(),e._charCount(0,!1),t()}return{stack:c,push:function(t){i.setTimeout(e._resourcesStateChange),t&&!a||(i.clearTimeout(a),t)?a=i.setTimeout((function(){i.clearTimeout(a),a=null,u()}),350):u()},undo:function(){r>0&&(r--,d())},redo:function(){c.length-1>r&&(r++,d())},go:function(e){r=e<0?c.length-1:e,d()},reset:function(i){s&&s.setAttribute("disabled",!0),o&&o.setAttribute("disabled",!0),e.context.tool.save&&e.context.tool.save.setAttribute("disabled",!0),c.splice(0),r=0,c[r]={contents:e.getContents(!0),s:{path:[0,0],offset:0},e:{path:[0,0],offset:0}},i||t()},_destroy:function(){a&&i.clearTimeout(a),c=null}}}(this,d._onChange_historyStack)},_resourcesStateChange:function(){c._iframeAutoHeight(),c._checkPlaceholder()},_iframeAutoHeight:function(){this._iframeAuto&&(e.element.wysiwygFrame.style.height=this._iframeAuto.offsetHeight+"px")},_checkPlaceholder:function(){if(this._placeholder){if(this._variable.isCodeView)return void(this._placeholder.style.display="none");const t=e.element.wysiwyg;!r.onlyZeroWidthSpace(t.textContent)||t.querySelector(".se-component, pre, blockquote, hr, li, table, img, iframe, video")||(t.innerText.match(/\n/g)||"").length>1?this._placeholder.style.display="none":this._placeholder.style.display="block"}}},d={_directionKeyCode:new a.RegExp("^(8|13|3[2-9]|40|46)$"),_nonTextKeyCode:new a.RegExp("^(8|13|1[6-9]|20|27|3[3-9]|40|45|46|11[2-9]|12[0-3]|144|145)$"),_historyIgnoreKeyCode:new a.RegExp("^(1[6-9]|20|27|3[3-9]|40|45|11[2-9]|12[0-3]|144|145)$"),_onButtonsCheck:new a.RegExp("^(STRONG|INS|EM|DEL|SUB|SUP)$"),_frontZeroWidthReg:new a.RegExp(r.zeroWidthSpace+"+",""),_keyCodeShortcut:{65:"A",66:"B",83:"S",85:"U",73:"I",89:"Y",90:"Z",219:"[",221:"]"},_shortcutCommand:function(e,t){let i=null;switch(d._keyCodeShortcut[e]){case"A":i="selectAll";break;case"B":i="STRONG";break;case"S":t&&(i="DEL");break;case"U":i="INS";break;case"I":i="EM";break;case"Z":i=t?"redo":"undo";break;case"Y":i="redo";break;case"[":i="outdent";break;case"]":i="indent"}return!!i&&(c.commandHandler(c.commandMap[i],i),!0)},_applyTagEffects:function(){let t=c.getSelectionNode();if(t===c._lastEffectNode)return;c._lastEffectNode=t;const n=c.commandMap,s=this._onButtonsCheck,o=[],a=[],d=c.activePlugins,u=d.length;let h="";for(;t.firstChild;)t=t.firstChild;for(let e=t;!r.isWysiwygDiv(e)&&e;e=e.parentNode)if(1===e.nodeType&&!r.isBreak(e)){h=e.nodeName.toUpperCase(),a.push(h);for(let t,n=0;n0)&&(o.push("OUTDENT"),n.OUTDENT.removeAttribute("disabled")),-1===o.indexOf("INDENT")&&n.INDENT&&r.isListCell(e)&&!e.previousElementSibling&&(o.push("INDENT"),n.INDENT.setAttribute("disabled",!0))):s.test(h)&&(o.push(h),r.addClass(n[h],"active"))}for(let e in n)o.indexOf(e)>-1||(d.indexOf(e)>-1?i[e].active.call(c,null):n.OUTDENT&&/^OUTDENT$/i.test(e)?n.OUTDENT.setAttribute("disabled",!0):n.INDENT&&/^INDENT$/i.test(e)?n.INDENT.removeAttribute("disabled"):r.removeClass(n[e],"active"));c._variable.currentNodes=a.reverse(),l.showPathLabel&&(e.element.navigation.textContent=c._variable.currentNodes.join(" > "))},_cancelCaptionEdit:function(){this.setAttribute("contenteditable",!1),this.removeEventListener("blur",d._cancelCaptionEdit)},onMouseDown_toolbar:function(e){let t=e.target;if(r.getParentElement(t,".se-submenu"))e.stopPropagation(),c._notHideToolbar=!0;else{e.preventDefault();let i=t.getAttribute("data-command"),n=t.className;for(;!i&&!/se-menu-list/.test(n)&&!/se-toolbar/.test(n);)t=t.parentNode,i=t.getAttribute("data-command"),n=t.className;i!==c._submenuName&&i!==c._containerName||e.stopPropagation()}},onClick_toolbar:function(e){e.preventDefault(),e.stopPropagation();let t=e.target,i=t.getAttribute("data-display"),n=t.getAttribute("data-command"),l=t.className;for(;!n&&!/se-menu-list/.test(l)&&!/se-toolbar/.test(l);)t=t.parentNode,n=t.getAttribute("data-command"),i=t.getAttribute("data-display"),l=t.className;(n||i)&&(t.disabled||(c.hasFocus||c.focus(),c._editorRange(),c.actionCall(n,i,t)))},onMouseDown_wysiwyg:function(t){if("false"===e.element.wysiwyg.getAttribute("contenteditable"))return;const i=r.getParentElement(t.target,r.isCell);if(i){const e=c.plugins.table;e&&i!==e._fixedCell&&!e._shift&&c.callPlugin("table",(function(){e.onTableCellMultiSelect.call(c,i,!1)}))}c._isBalloon&&d._hideToolbar(),g.onMouseDown&&g.onMouseDown(t,c)},onClick_wysiwyg:function(t){const i=t.target;if("false"===e.element.wysiwyg.getAttribute("contenteditable"))return;if(t.stopPropagation(),/^FIGURE$/i.test(i.nodeName)){const e=i.querySelector("IMG"),n=i.querySelector("IFRAME");if(e)return t.preventDefault(),void c.selectComponent(e,"image");if(n)return t.preventDefault(),void c.selectComponent(n,"video")}const n=r.getParentElement(i,"FIGCAPTION");if(n&&(!n.getAttribute("contenteditable")||"false"===n.getAttribute("contenteditable"))&&(t.preventDefault(),n.setAttribute("contenteditable",!0),n.focus(),c._isInline&&!c._inlineToolbarAttr.isShow)){d._showToolbarInline();const e=function(){d._hideToolbar(),n.removeEventListener("blur",e)};n.addEventListener("blur",e)}c._editorRange(),a.setTimeout(c._editorRange.bind(c));const l=c.getSelectionNode(),s=r.getFormatElement(l),o=r.getRangeFormatElement(l);if(!c.getRange().collapsed||s&&s!==o||"false"===i.getAttribute("contenteditable"))d._applyTagEffects();else{if(r.isList(o)){const e=r.createElement("LI"),t=l.nextElementSibling;e.appendChild(l),o.insertBefore(e,t)}else c.execCommand("formatBlock",!1,r.isRangeFormatElement(o)?"DIV":"P");t.preventDefault(),c.focus()}c._isBalloon&&a.setTimeout(d._toggleToolbarBalloon),g.onClick&&g.onClick(t,c)},_balloonDelay:null,_showToolbarBalloonDelay:function(){d._balloonDelay&&a.clearTimeout(d._balloonDelay),d._balloonDelay=a.setTimeout(function(){a.clearTimeout(this._balloonDelay),this._balloonDelay=null,this._showToolbarBalloon()}.bind(d),350)},_toggleToolbarBalloon:function(){c._editorRange();const e=c.getRange();"table"===c.currentControllerName||!c._isBalloonAlways&&e.collapsed?d._hideToolbar():d._showToolbarBalloon(e)},_showToolbarBalloon:function(t){if(!c._isBalloon)return;const i=t||c.getRange(),n=e.element.toolbar,l=c.getSelection();let s;if(l.focusNode===l.anchorNode)s=l.focusOffsetn.offsetWidth?n.offsetWidth-u:b",!o.nextElementSibling){const e=o.attributes;for(;e[0];)o.removeAttribute(e[0].name);c.execCommand("formatBlock",!1,"P")}return!1}}const i=u.commonAncestorContainer;if(m=r.getFormatElement(u.startContainer),f=r.getRangeFormatElement(m),f&&m&&!r.isCell(f)&&!/^FIGCAPTION$/i.test(f.nodeName)){if(r.isListCell(m)&&r.isList(f)&&(r.isListCell(f.parentNode)||m.previousElementSibling)&&(o===m||3===o.nodeType&&(!o.previousSibling||r.isList(o.previousSibling)))&&(r.getFormatElement(u.startContainer)!==r.getFormatElement(u.endContainer)?f.contains(u.startContainer):0===u.startOffset&&u.collapsed)){if(u.startContainer!==u.endContainer)t.preventDefault(),c.removeNode(),3===u.startContainer.nodeType&&c.setRange(u.startContainer,u.startContainer.textContent.length,u.startContainer,u.startContainer.textContent.length),c.history.push(!0);else{let e=m.previousElementSibling||f.parentNode;if(r.isListCell(e)){t.preventDefault();const i=e.lastElementChild;r.isList(i)&&(e=i.lastElementChild);let n=e===f.parentNode?f.previousSibling:e.lastChild;n||(n=r.createTextNode(r.zeroWidthSpace),f.parentNode.insertBefore(n,f.parentNode.firstChild));const l=3===n.nodeType?n.textContent.length:1,s=m.childNodes;let o=n,a=s[0];for(;a=s[0];)e.insertBefore(a,o.nextSibling),o=a;r.removeItem(m),0===f.children.length&&r.removeItem(f),c.setRange(n,l,n,l),c.history.push(!0)}}break}if(!h&&0===u.startOffset){let e=!0,n=i;for(;n&&n!==f&&!r.isWysiwygDiv(n);){if(n.previousSibling){e=!1;break}n=n.parentNode}if(e&&f.parentNode){t.preventDefault(),c.detachRangeFormatElement(f,r.isListCell(m)?[m]:null,null,!1,!1),c.history.push(!0);break}}}if(!h&&0===u.startOffset&&(r.isComponent(i.previousSibling)||3===i.nodeType&&!i.previousSibling&&0===u.startOffset&&0===u.endOffset&&r.isComponent(m.previousSibling))){const e=m.previousSibling;r.removeItem(e)}break;case 46:if(p){t.preventDefault(),t.stopPropagation(),c.plugins[p].destroy.call(c);break}if((r.isFormatElement(o)||null===o.nextSibling)&&u.startOffset===o.textContent.length){let e=m.nextElementSibling;if(r.isComponent(e)){t.preventDefault(),r.onlyZeroWidthSpace(m)&&r.removeItem(m),(r.hasClass(e,"se-component")||/^IMG$/i.test(e.nodeName))&&(t.stopPropagation(),r.hasClass(e,"se-image-container")||/^IMG$/i.test(e.nodeName)?(e=/^IMG$/i.test(e.nodeName)?e:e.querySelector("img"),c.selectComponent(e,"image")):r.hasClass(e,"se-video-container")&&c.selectComponent(e.querySelector("iframe"),"video"));break}}if(m=r.getFormatElement(u.startContainer),f=r.getRangeFormatElement(m),r.isListCell(m)&&r.isList(f)&&(o===m||3===o.nodeType&&(!o.nextSibling||r.isList(o.nextSibling))&&(r.getFormatElement(u.startContainer)!==r.getFormatElement(u.endContainer)?f.contains(u.endContainer):u.endOffset===o.textContent.length&&u.collapsed))){u.startContainer!==u.endContainer&&c.removeNode();let e=r.getArrayItem(m.children,r.isList,!1);if(e=e||m.nextElementSibling||f.parentNode.nextElementSibling,e&&(r.isList(e)||r.getArrayItem(e.children,r.isList,!1))){let i,n;if(t.preventDefault(),r.isList(e)){const t=e.firstElementChild;for(n=t.childNodes,i=n[0];n[0];)m.insertBefore(n[0],e);r.removeItem(t)}else{for(i=e.firstChild,n=e.childNodes;n[0];)m.appendChild(n[0]);r.removeItem(e)}c.setRange(i,0,i,0),c.history.push(!0)}break}break;case 9:if(t.preventDefault(),l||s||r.isWysiwygDiv(o))break;c.controllersOff();const g=!u.collapsed||c.isEdgePoint(u.startContainer,u.startOffset),_=c.getSelectedElements(),b=[];let y=[],v=r.isListCell(_[0]),x=r.isListCell(_[_.length-1]),C={sc:null,so:null,ec:null,eo:null};for(let e,t=0,i=_.length;t0&&g&&c.plugins.list){const e=c.plugins.list.editInsideList.call(c,n,b);v&&(C.sc=e.sc,C.so=e.so),x&&(C.ec=e.ec,C.eo=e.eo)}else{const e=r.getParentElement(o,r.isCell);if(e&&g){const t=r.getParentElement(e,"table"),i=r.getListChildren(t,r.isCell);let l=n?r.prevIdx(i,e):r.nextIdx(i,e);l!==i.length||n||(l=0),-1===l&&n&&(l=i.length-1);const s=i[l];if(!s)return!1;c.setRange(s,0,s,0);break}y=y.concat(b),v=x=null}if(y.length>0)if(n){const e=y.length-1;for(let t,i=0;i<=e;i++)t=y[i].firstChild,t&&(/^\s{1,4}$/.test(t.textContent)?r.removeItem(t):/^\s{1,4}/.test(t.textContent)&&(t.textContent=t.textContent.replace(/^\s{1,4}/,"")));const t=r.getChildElement(y[0],"text",!1),i=r.getChildElement(y[e],"text",!0);!v&&t&&(C.sc=t,C.so=0),!x&&i&&(C.ec=i,C.eo=i.textContent.length)}else{const e=r.createTextNode(new a.Array(c._variable.tabSize+1).join(" "));if(1===y.length){const t=c.insertNode(e);v||(C.sc=e,C.so=t.endOffset),x||(C.ec=e,C.eo=t.endOffset)}else{const t=y.length-1;for(let i,n=0;n<=t;n++)i=y[n].firstChild,i&&(r.isBreak(i)?y[n].insertBefore(e.cloneNode(!1),i):i.textContent=e.textContent+i.textContent);const i=r.getChildElement(y[0],"text",!1),n=r.getChildElement(y[t],"text",!0);!v&&i&&(C.sc=i,C.so=0),!x&&n&&(C.ec=n,C.eo=n.textContent.length)}}c.setRange(C.sc,C.so,C.ec,C.eo),c.history.push(!1);break;case 13:const w=r.getFreeFormatElement(o);if(!n&&w){t.preventDefault();const e=o===w,i=c.getSelection(),n=o.childNodes,l=i.focusOffset,s=o.previousElementSibling,a=o.nextSibling;if(e&&u.collapsed&&n.length-1<=l+1&&r.isBreak(n[l])&&(!n[l+1]||(!n[l+2]||r.onlyZeroWidthSpace(n[l+2].textContent))&&3===n[l+1].nodeType&&r.onlyZeroWidthSpace(n[l+1].textContent))&&l>0&&r.isBreak(n[l-1])||!e&&r.onlyZeroWidthSpace(o.textContent)&&r.isBreak(s)&&(r.isBreak(s.previousSibling)||!r.onlyZeroWidthSpace(s.previousSibling.textContent))&&(!a||!r.isBreak(a)&&r.onlyZeroWidthSpace(a.textContent))){e?r.removeItem(n[l-1]):r.removeItem(o);const t=c.appendFormatTag(w,r.isFormatElement(w.nextElementSibling)?w.nextElementSibling:null);r.copyFormatAttributes(t,w),c.setRange(t,1,t,1);break}if(e){c.execCommand("insertHTML",!1,"

    ");let e=i.focusNode;const t=i.focusOffset;e=w===e?e.childNodes[t-l>1?t-1:t]:e.previousSibling,c.setRange(e,1,e,1)}else{const e=i.focusNode.nextSibling,t=r.createElement("BR");c.insertNode(t);const n=t.previousSibling,l=t.nextSibling;r.isBreak(e)||r.isBreak(n)||l&&!r.onlyZeroWidthSpace(l)?c.setRange(l,0,l,0):(t.parentNode.insertBefore(t.cloneNode(!1),t),c.setRange(t,1,t,1))}d._onShortcutKey=!0;break}if(h)break;if(f&&m&&!r.isCell(f)&&!/^FIGCAPTION$/i.test(f.nodeName)){const e=c.getRange();if((3!==e.commonAncestorContainer.nodeType||!e.commonAncestorContainer.nextElementSibling)&&r.onlyZeroWidthSpace(m.innerText.trim())){t.preventDefault();let e=null;if(r.isListCell(f.parentNode)){f=m.parentNode.parentNode.parentNode;const t=r.splitElement(m,null,r.getElementDepth(m)-2);e=r.createElement("LI"),f.insertBefore(e,t)}else{const t=r.isCell(f.parentNode)?"DIV":r.isList(f.parentNode)?"LI":r.isFormatElement(f.nextElementSibling)?f.nextElementSibling.nodeName:r.isFormatElement(f.previousElementSibling)?f.previousElementSibling.nodeName:"P";e=r.createElement(t);const i=c.detachRangeFormatElement(f,[m],null,!0,!0);i.cc.insertBefore(e,i.ec)}e.innerHTML="
    ",r.copyFormatAttributes(e,m),r.removeItemAllParents(m,null),c.setRange(e,1,e,1);break}}if(f&&r.getParentElement(f,"FIGCAPTION")&&r.getParentElement(f,r.isList)&&(t.preventDefault(),m=c.appendFormatTag(m,null),c.setRange(m,0,m,0)),p){t.preventDefault(),t.stopPropagation();const i=e[p],n=i._container,l=n.previousElementSibling||n.nextElementSibling;let s=null;r.isListCell(n.parentNode)?s=r.createElement("BR"):(s=r.createElement(r.isFormatElement(l)?l.nodeName:"P"),s.innerHTML="
    "),n.parentNode.insertBefore(s,n),c.callPlugin(p,(function(){const e=c.plugins.resizing.call_controller_resize.call(c,i._element,p);c.plugins[p].onModifyMode.call(c,i._element,e)}))}}if(n&&/16/.test(i)){t.preventDefault(),t.stopPropagation();const e=c.plugins.table;if(e&&!e._shift&&!e._ref){const t=r.getParentElement(m,r.isCell);if(t)return void e.onTableCellMultiSelect.call(c,t,!0)}}const _=!(l||s||h||d._nonTextKeyCode.test(i));if(!c._charCount(1,_)&&_)return t.preventDefault(),t.stopPropagation(),!1;g.onKeyDown&&g.onKeyDown(t,c)},onKeyUp_wysiwyg:function(e){if(d._onShortcutKey)return;c._editorRange();const t=c.getRange(),i=e.keyCode,n=e.ctrlKey||e.metaKey||91===i||92===i,l=e.altKey;let s=c.getSelectionNode();if(c._isBalloon&&(c._isBalloonAlways&&27!==i||!t.collapsed)){if(!c._isBalloonAlways)return void d._showToolbarBalloon();d._showToolbarBalloonDelay()}if(8===i&&r.isWysiwygDiv(s)&&""===s.textContent){e.preventDefault(),e.stopPropagation(),s.innerHTML="";const t=r.createElement(r.isFormatElement(c._variable.currentNodes[0])?c._variable.currentNodes[0]:"P");return t.innerHTML="
    ",s.appendChild(t),c.setRange(t,0,t,0),d._applyTagEffects(),c._checkComponents(),void c.history.push(!1)}const o=r.getFormatElement(s),a=r.getRangeFormatElement(s);(!o&&t.collapsed||o===a)&&(c.execCommand("formatBlock",!1,r.isRangeFormatElement(a)?"DIV":"P"),c.focus(),s=c.getSelectionNode()),d._directionKeyCode.test(i)&&d._applyTagEffects(),c._checkComponents();const u=!n&&!l&&!d._nonTextKeyCode.test(i);if(u&&3===s.nodeType&&r.zeroWidthRegExp.test(s.textContent)){let e=t.startOffset,i=t.endOffset;const n=(s.textContent.substring(0,i).match(d._frontZeroWidthReg)||"").length;e=t.startOffset-n,i=t.endOffset-n,s.textContent=s.textContent.replace(r.zeroWidthRegExp,""),c.setRange(s,e<0?0:e,s,i<0?0:i)}if(!c._charCount(1,u)&&1===e.key.length)return e.preventDefault(),e.stopPropagation(),!1;!n&&!l&&!d._historyIgnoreKeyCode.test(i)&&c.history.push(!0),g.onKeyUp&&g.onKeyUp(e,c)},onScroll_wysiwyg:function(e){c.controllersOff(),c._isBalloon&&d._hideToolbar(),g.onScroll&&g.onScroll(e,c)},onFocus_wysiwyg:function(e){c.hasFocus=!0,c._isInline&&d._showToolbarInline(),g.onFocus&&g.onFocus(e,c)},onBlur_wysiwyg:function(e){c.hasFocus=!1,(c._isInline||c._isBalloon)&&d._hideToolbar(),g.onBlur&&g.onBlur(e,c)},onMouseDown_resizingBar:function(t){t.stopPropagation(),c._variable.resizeClientY=t.clientY,e.element.resizeBackground.style.display="block",s.addEventListener("mousemove",d._resize_editor),s.addEventListener("mouseup",(function t(){e.element.resizeBackground.style.display="none",s.removeEventListener("mousemove",d._resize_editor),s.removeEventListener("mouseup",t)}))},_resize_editor:function(t){const i=e.element.editorArea.offsetHeight+(t.clientY-c._variable.resizeClientY);e.element.wysiwygFrame.style.height=e.element.code.style.height=(i=i+o?(c._sticky||d._onStickyToolbar(),t.toolbar.style.top=i+o+l.stickyToolbar-n-c._variable.minResizingSize+"px"):n>=o&&d._onStickyToolbar()},_getStickyOffsetTop:function(){let t=e.element.topArea,i=0;for(;t;)i+=t.offsetTop,t=t.offsetParent;return i},_onStickyToolbar:function(){const t=e.element;c._isInline||(t._stickyDummy.style.height=t.toolbar.offsetHeight+"px",t._stickyDummy.style.display="block"),t.toolbar.style.top=l.stickyToolbar+"px",t.toolbar.style.width=c._isInline?c._inlineToolbarAttr.width:t.toolbar.offsetWidth+"px",r.addClass(t.toolbar,"se-toolbar-sticky"),c._sticky=!0},_offStickyToolbar:function(){const t=e.element;t._stickyDummy.style.display="none",t.toolbar.style.top=c._isInline?c._inlineToolbarAttr.top:"",t.toolbar.style.width=c._isInline?c._inlineToolbarAttr.width:"",t.editorArea.style.marginTop="",r.removeClass(t.toolbar,"se-toolbar-sticky"),c._sticky=!1},_codeViewAutoHeight:function(){e.element.code.style.height=e.element.code.scrollHeight+"px"},onPaste_wysiwyg:function(e){const t=e.clipboardData;if(!t)return!0;const i=c._charCount(t.getData("text/plain").length,!0),n=c.cleanHTML(t.getData("text/html"),c.pasteTagsWhitelistRegExp);return("function"!=typeof g.onPaste||g.onPaste(e,n,i,c))&&i?void(n?(e.stopPropagation(),e.preventDefault(),c.execCommand("insertHTML",!1,n)):c.history.push(!0)):(e.preventDefault(),e.stopPropagation(),!1)},onCut_wysiwyg:function(){a.setTimeout((function(){c._resourcesStateChange(),c._charCount(0,!1),c.history.push(!1)}))},onDragOver_wysiwyg:function(e){e.preventDefault()},onDrop_wysiwyg:function(t){const i=t.dataTransfer;if(!i)return!0;const n=i.files;if(n.length>0&&c.plugins.image)d._setDropLocationSelection(t),c.callPlugin("image",(function(){e.image.imgInputFile.files=n,c.plugins.image.onRender_imgInput.call(c),e.image.imgInputFile.files=null}));else{if(!c._charCount(i.getData("text/plain").length,!0))return t.preventDefault(),t.stopPropagation(),!1;{const e=c.cleanHTML(i.getData("text/html"),c.pasteTagsWhitelistRegExp);e&&(d._setDropLocationSelection(t),c.execCommand("insertHTML",!1,e))}}g.onDrop&&g.onDrop(t,c)},_setDropLocationSelection:function(e){e.stopPropagation(),e.preventDefault();const t=c.getRange();c.setRange(t.startContainer,t.startOffset,t.endContainer,t.endOffset)},_onChange_historyStack:function(){d._applyTagEffects(),e.tool.save&&e.tool.save.removeAttribute("disabled"),g.onChange&&g.onChange(c.getContents(!0),c)},_addEvent:function(){const t=l.iframe?c._ww:e.element.wysiwyg;e.element.toolbar.addEventListener("mousedown",d.onMouseDown_toolbar,!1),e.element.toolbar.addEventListener("click",d.onClick_toolbar,!1),t.addEventListener("mousedown",d.onMouseDown_wysiwyg,!1),t.addEventListener("click",d.onClick_wysiwyg,!1),t.addEventListener("keydown",d.onKeyDown_wysiwyg,!1),t.addEventListener("keyup",d.onKeyUp_wysiwyg,!1),t.addEventListener("paste",d.onPaste_wysiwyg,!1),t.addEventListener("cut",d.onCut_wysiwyg,!1),t.addEventListener("dragover",d.onDragOver_wysiwyg,!1),t.addEventListener("drop",d.onDrop_wysiwyg,!1),t.addEventListener("scroll",d.onScroll_wysiwyg,!1),t.addEventListener("focus",d.onFocus_wysiwyg,!1),t.addEventListener("blur",d.onBlur_wysiwyg,!1),c.plugins.table&&t.addEventListener("touchstart",d.onMouseDown_wysiwyg,{passive:!0,useCapture:!1}),"auto"!==l.height||l.codeMirrorEditor||(e.element.code.addEventListener("keydown",d._codeViewAutoHeight,!1),e.element.code.addEventListener("keyup",d._codeViewAutoHeight,!1),e.element.code.addEventListener("paste",d._codeViewAutoHeight,!1)),e.element.resizingBar&&(/\d+/.test(l.height)?e.element.resizingBar.addEventListener("mousedown",d.onMouseDown_resizingBar,!1):r.addClass(e.element.resizingBar,"se-resizing-none")),a.removeEventListener("resize",d.onResize_window),a.removeEventListener("scroll",d.onScroll_window),a.addEventListener("resize",d.onResize_window,!1),l.stickyToolbar>-1&&a.addEventListener("scroll",d.onScroll_window,!1)},_removeEvent:function(){const t=l.iframe?c._ww:e.element.wysiwyg;e.element.toolbar.removeEventListener("mousedown",d.onMouseDown_toolbar),e.element.toolbar.removeEventListener("click",d.onClick_toolbar),t.removeEventListener("click",d.onClick_wysiwyg),t.removeEventListener("keydown",d.onKeyDown_wysiwyg),t.removeEventListener("keyup",d.onKeyUp_wysiwyg),t.removeEventListener("paste",d.onPaste_wysiwyg),t.removeEventListener("cut",d.onCut_wysiwyg),t.removeEventListener("dragover",d.onDragOver_wysiwyg),t.removeEventListener("drop",d.onDrop_wysiwyg),t.removeEventListener("scroll",d.onScroll_wysiwyg),t.removeEventListener("mousedown",d.onMouseDown_wysiwyg),t.removeEventListener("touchstart",d.onMouseDown_wysiwyg,{passive:!0,useCapture:!1}),t.removeEventListener("focus",d.onFocus_wysiwyg),t.removeEventListener("blur",d.onBlur_wysiwyg),e.element.code.removeEventListener("keydown",d._codeViewAutoHeight),e.element.code.removeEventListener("keyup",d._codeViewAutoHeight),e.element.code.removeEventListener("paste",d._codeViewAutoHeight),e.element.resizingBar&&e.element.resizingBar.removeEventListener("mousedown",d.onMouseDown_resizingBar),a.removeEventListener("resize",d.onResize_window),a.removeEventListener("scroll",d.onScroll_window)}},g={core:c,util:r,onload:null,onScroll:null,onMouseDown:null,onClick:null,onKeyDown:null,onKeyUp:null,onDrop:null,onChange:null,onPaste:null,onFocus:null,onBlur:null,showInline:null,imageUploadHandler:null,onImageUploadBefore:null,onImageUpload:null,onImageUploadError:null,setOptions:function(s){d._removeEvent(),c.plugins=s.plugins||c.plugins;const o=[s,s].reduce((function(e,t){for(let i in t)if("plugins"===i&&t[i]&&e[i]){let n=e[i],l=t[i];n=n.length?n:a.Object.keys(n).map((function(e){return n[e]})),l=l.length?l:a.Object.keys(l).map((function(e){return l[e]})),e[i]=l.filter((function(e){return-1===n.indexOf(e)})).concat(n)}else e[i]=t[i];return e}),{}),r=h._setOptions(o,e,c.plugins,s);r.callButtons&&(t=r.callButtons,c.initPlugins={}),r.plugins&&(c.plugins=i=r.plugins);const u=e.element.wysiwyg.innerHTML,g=e.element,m={_top:g.topArea,_relative:g.relative,_toolBar:g.toolbar,_editorArea:g.editorArea,_wysiwygArea:g.wysiwygFrame,_codeArea:g.code,_placeholder:g.placeholder,_resizingBar:g.resizingBar,_navigation:g.navigation,_charCounter:g.charCounter,_loading:g.loading,_resizeBack:g.resizeBackground,_stickyDummy:g._stickyDummy,_arrow:g._arrow};l=o,c.lang=n=l.lang,c.context=e=p(e.element.originElement,m,l),c._imagesInfoReset=!0,c._init(!0,u),d._addEvent(),c._charCount(0,!1),d._offStickyToolbar(),d.onResize_window(),c.focus()},noticeOpen:function(e){c.addModule([o]),o.open.call(c,e)},noticeClose:function(){c.addModule([o]),o.close.call(c)},save:function(){e.element.originElement.value=c.getContents(!1)},getContext:function(){return e},getContents:function(e){return c.getContents(e)},getImagesInfo:function(){return c._variable._imagesInfo},insertImage:function(e){c.plugins.image&&e&&(c.initPlugins.image?c.plugins.image.submitAction.call(c,e):c.callPlugin("image",c.plugins.image.submitAction.bind(c,e)),c.focus())},insertHTML:function(e){if(!e.nodeType||1!==e.nodeType){const t=r.createElement("DIV");t.innerHTML=e,e=t.firstChild||t.content.firstChild}let t=null;(r.isFormatElement(e)||/^(IMG|IFRAME)$/i.test(e.nodeName))&&(t=r.getFormatElement(c.getSelectionNode())),r.isComponent(e)?c.insertComponent(e,!1):c.insertNode(e,t),c.focus()},setContents:function(e){c.setContents(e)},appendContents:function(t){const i=c.convertContentsForEditor(t);if(c._variable.isCodeView)c._setCodeView(c._getCodeView()+"\n"+c.convertHTMLForCodeView(i));else{const t=r.createElement("DIV");t.innerHTML=i;const n=e.element.wysiwyg,l=t.children;for(let e=0,t=l.length;e';for(let e,t=0,o=n.length;t0&&(s+='
    '+i(l)+"
    ",l=[]),"object"==typeof e&&(s+='
    '+i(e)+"
    ")));return s+='
    ",s},_makeColorList:function(e){let t="";t+='
      ';for(let i,n=0,l=e.length;n');return t+="
    ",t},init:function(e,t){const i=this.plugins.colorPicker;let n=t||(i.getColorInNode.call(this,e)||this.context.colorPicker._defaultColor);n=i.isHexColor(n)?n:i.rgb2hex(n)||n;const l=this.context.colorPicker._colorList;if(l)for(let e=0,t=l.length;e=3&&"#"+((1<<24)+(i[0]<<16)+(i[1]<<8)+i[2]).toString(16).substr(1)}},l={name:"dialog",add:function(e){const t=e.context;t.dialog={kind:"",updateModal:!1,_closeSignal:!1};let i=e.util.createElement("DIV");i.className="se-dialog sun-editor-common";let n=e.util.createElement("DIV");n.className="se-dialog-back",n.style.display="none";let l=e.util.createElement("DIV");l.className="se-dialog-inner",l.style.display="none",i.appendChild(n),i.appendChild(l),t.dialog.modalArea=i,t.dialog.back=n,t.dialog.modal=l,t.dialog.modal.addEventListener("mousedown",this.onMouseDown_dialog.bind(e)),t.dialog.modal.addEventListener("click",this.onClick_dialog.bind(e)),t.element.relative.appendChild(i),i=null,n=null,l=null},onMouseDown_dialog:function(e){/se-dialog-inner/.test(e.target.className)?this.context.dialog._closeSignal=!0:this.context.dialog._closeSignal=!1},onClick_dialog:function(e){e.stopPropagation(),(/close/.test(e.target.getAttribute("data-command"))||this.context.dialog._closeSignal)&&this.plugins.dialog.close.call(this)},open:function(e,t){if(this.modalForm)return!1;this.plugins.dialog._bindClose&&(this._d.removeEventListener("keydown",this.plugins.dialog._bindClose),this.plugins.dialog._bindClose=null),this.plugins.dialog._bindClose=function(e){/27/.test(e.keyCode)&&this.plugins.dialog.close.call(this)}.bind(this),this._d.addEventListener("keydown",this.plugins.dialog._bindClose),this.context.dialog.updateModal=t,"full"===this.context.option.popupDisplay?this.context.dialog.modalArea.style.position="fixed":this.context.dialog.modalArea.style.position="absolute",this.context.dialog.kind=e,this.modalForm=this.context[e].modal;const i=this.context[e].focusElement;"function"==typeof this.plugins[e].on&&this.plugins[e].on.call(this,t),this.context.dialog.modalArea.style.display="block",this.context.dialog.back.style.display="block",this.context.dialog.modal.style.display="block",this.modalForm.style.display="block",i&&i.focus()},_bindClose:null,close:function(){this.plugins.dialog._bindClose&&(this._d.removeEventListener("keydown",this.plugins.dialog._bindClose),this.plugins.dialog._bindClose=null);const e=this.context.dialog.kind;this.modalForm.style.display="none",this.context.dialog.back.style.display="none",this.context.dialog.modalArea.style.display="none",this.context.dialog.updateModal=!1,this.plugins[e].init.call(this),this.context.dialog.kind="",this.modalForm=null,this.focus()}},s={name:"resizing",add:function(e){const t=e.context;t.resizing={_resizeClientX:0,_resizeClientY:0,_resize_plugin:"",_resize_w:0,_resize_h:0,_origin_w:0,_origin_h:0,_rotateVertical:!1,_resize_direction:"",_move_path:null,_isChange:!1};let i=this.setController_resize.call(e);t.resizing.resizeContainer=i,t.resizing.resizeDiv=i.querySelector(".se-modal-resize"),t.resizing.resizeDot=i.querySelector(".se-resize-dot"),t.resizing.resizeDisplay=i.querySelector(".se-resize-display");let n=this.setController_button.call(e);t.resizing.resizeButton=n,n.addEventListener("mousedown",(function(e){e.stopPropagation()}),!1);let l=t.resizing.resizeHandles=t.resizing.resizeDot.querySelectorAll("span");t.resizing.resizeButtonGroup=n.querySelector("._se_resizing_btn_group"),t.resizing.rotationButtons=n.querySelectorAll("._se_resizing_btn_group ._se_rotation"),t.resizing.percentageButtons=n.querySelectorAll("._se_resizing_btn_group ._se_percentage"),t.resizing.alignMenu=n.querySelector(".se-resizing-align-list"),t.resizing.alignMenuList=t.resizing.alignMenu.querySelectorAll("button"),t.resizing.alignButton=n.querySelector("._se_resizing_align_button"),t.resizing.alignButtonIcon=t.resizing.alignButton.querySelector("i"),t.resizing.autoSizeButton=n.querySelector("._se_resizing_btn_group ._se_auto_size"),t.resizing.captionButton=n.querySelector("._se_resizing_caption_button"),l[0].addEventListener("mousedown",this.onMouseDown_resize_handle.bind(e)),l[1].addEventListener("mousedown",this.onMouseDown_resize_handle.bind(e)),l[2].addEventListener("mousedown",this.onMouseDown_resize_handle.bind(e)),l[3].addEventListener("mousedown",this.onMouseDown_resize_handle.bind(e)),l[4].addEventListener("mousedown",this.onMouseDown_resize_handle.bind(e)),l[5].addEventListener("mousedown",this.onMouseDown_resize_handle.bind(e)),l[6].addEventListener("mousedown",this.onMouseDown_resize_handle.bind(e)),l[7].addEventListener("mousedown",this.onMouseDown_resize_handle.bind(e)),n.addEventListener("click",this.onClick_resizeButton.bind(e)),t.element.relative.appendChild(i),t.element.relative.appendChild(n),i=null,n=null,l=null},setController_resize:function(){const e=this.util.createElement("DIV");return e.className="se-resizing-container",e.style.display="none",e.innerHTML='
    ',e},setController_button:function(){const e=this.lang,t=this.util.createElement("DIV");return t.className="se-controller se-controller-resizing",t.innerHTML='
    ",t},_module_getSizeX:function(e,t,i,n){return t||(t=e._element),i||(i=e._cover),n||(n=e._container),n&&i&&t?/%$/.test(t.style.width)?(this.util.getNumber(n.style.width,2)||100)+"%":t.style.width:""},_module_getSizeY:function(e,t,i,n){return t||(t=e._element),i||(i=e._cover),n||(n=e._container),n&&i&&t?this.util.getNumber(i.style.paddingBottom)>0&&!this.context.resizing._rotateVertical?i.style.height:/%$/.test(t.style.height)&&/%$/.test(t.style.width)?(this.util.getNumber(n.style.height,2)||100)+"%":t.style.height:""},_module_setModifyInputSize:function(e,t){const i=e._onlyPercentage&&this.context.resizing._rotateVertical;e.proportion.checked=e._proportionChecked="false"!==e._element.getAttribute("data-proportion");let n=i?"":this.plugins.resizing._module_getSizeX.call(this,e);if(n===e._defaultSizeX&&(n=""),e._onlyPercentage&&(n=this.util.getNumber(n,2)),e.inputX.value=n,t.setInputSize.call(this,"x"),!e._onlyPercentage){let t=i?"":this.plugins.resizing._module_getSizeY.call(this,e);t===e._defaultSizeY&&(t=""),e._onlyPercentage&&(t=this.util.getNumber(t,2)),e.inputY.value=t}e.inputX.disabled=!!i,e.inputY.disabled=!!i,e.proportion.disabled=!!i,t.setRatio.call(this)},_module_setInputSize:function(e,t){if(e._onlyPercentage)"x"===t&&e.inputX.value>100&&(e.inputX.value=100);else if(e.proportion.checked&&e._ratio&&/\d/.test(e.inputX.value)&&/\d/.test(e.inputY.value)){const i=e.inputX.value.replace(/\d+|\./g,"")||e.sizeUnit,n=e.inputY.value.replace(/\d+|\./g,"")||e.sizeUnit;if(i!==n)return;const l="%"===i?2:0;"x"===t?e.inputY.value=this.util.getNumber(e._ratioY*this.util.getNumber(e.inputX.value,l),l)+n:e.inputX.value=this.util.getNumber(e._ratioX*this.util.getNumber(e.inputY.value,l),l)+i}},_module_setRatio:function(e){const t=e.inputX.value,i=e.inputY.value;if(e.proportion.checked&&/\d+/.test(t)&&/\d+/.test(i)){if((t.replace(/\d+|\./g,"")||e.sizeUnit)!==(i.replace(/\d+|\./g,"")||e.sizeUnit))e._ratio=!1;else if(!e._ratio){const n=this.util.getNumber(t),l=this.util.getNumber(i);e._ratio=!0,e._ratioX=n/l,e._ratioY=l/n}}else e._ratio=!1},_module_sizeRevert:function(e){e._onlyPercentage?e.inputX.value=e._origin_w>100?100:e._origin_w:(e.inputX.value=e._origin_w,e.inputY.value=e._origin_h)},_module_saveCurrentSize:function(e){const t=this.plugins.resizing._module_getSizeX.call(this,e),i=this.plugins.resizing._module_getSizeY.call(this,e);e._element.setAttribute("data-size",t+","+i),e._videoRatio&&(e._videoRatio=i)},call_controller_resize:function(e,t){const i=this.context.resizing,n=this.context[t];i._resize_plugin=t;const l=i.resizeContainer,s=i.resizeDiv,o=this.util.getOffset(e,this.context.element.wysiwygFrame),a=i._rotateVertical=/^(90|270)$/.test(Math.abs(e.getAttribute("data-rotate")).toString()),r=a?e.offsetHeight:e.offsetWidth,c=a?e.offsetWidth:e.offsetHeight,d=o.top,u=o.left-this.context.element.wysiwygFrame.scrollLeft;l.style.top=d+"px",l.style.left=u+"px",l.style.width=r+"px",l.style.height=c+"px",s.style.top="0px",s.style.left="0px",s.style.width=r+"px",s.style.height=c+"px";let h=e.getAttribute("data-align")||"basic";h="none"===h?"basic":h;const p=this.util.getParentElement(e,this.util.isComponent),g=this.util.getParentElement(e,"FIGURE"),m=this.plugins.resizing._module_getSizeX.call(this,n,e,g,p)||"auto",f=n._onlyPercentage&&"image"===t?"":", "+(this.plugins.resizing._module_getSizeY.call(this,n,e,g,p)||"auto");this.util.changeTxt(i.resizeDisplay,this.lang.dialogBox[h]+" ("+m+f+")"),i.resizeButtonGroup.style.display=n._resizing?"":"none";const _=!n._resizing||n._resizeDotHide||n._onlyPercentage?"none":"flex",b=i.resizeHandles;for(let e=0,t=b.length;e",e},set_cover:function(e){const t=this.util.createElement("FIGURE");return t.appendChild(e),t},set_container:function(e,t){const i=this.util.createElement("DIV");return i.className="se-component "+t,i.setAttribute("contenteditable",!1),i.appendChild(e),i},onClick_resizeButton:function(e){e.stopPropagation();const t=e.target,i=t.getAttribute("data-command")||t.parentNode.getAttribute("data-command");if(!i)return;const n=t.getAttribute("data-value")||t.parentNode.getAttribute("data-value"),l=this.context.resizing._resize_plugin,s=this.context[l],o=s._element,a=this.plugins[l];if(e.preventDefault(),"function"!=typeof this.plugins.resizing._closeAlignMenu||(this.plugins.resizing._closeAlignMenu(),"onalign"!==i)){switch(i){case"auto":a.setAutoSize.call(this),a.onModifyMode.call(this,o,this.plugins.resizing.call_controller_resize.call(this,o,l));break;case"percent":let e=this.plugins.resizing._module_getSizeY.call(this,s);if(this.context.resizing._rotateVertical){const t=o.getAttribute("data-percentage");t&&(e=t.split(",")[1])}this.plugins.resizing.resetTransform.call(this,o),a.setPercentSize.call(this,100*n,e),a.onModifyMode.call(this,o,this.plugins.resizing.call_controller_resize.call(this,o,l));break;case"mirror":const t=o.getAttribute("data-rotate")||"0";let i=o.getAttribute("data-rotateX")||"",r=o.getAttribute("data-rotateY")||"";"h"===n&&!this.context.resizing._rotateVertical||"v"===n&&this.context.resizing._rotateVertical?r=r?"":"180":i=i?"":"180",o.setAttribute("data-rotateX",i),o.setAttribute("data-rotateY",r),this.plugins.resizing._setTransForm(o,t,i,r);break;case"rotate":const c=this.context.resizing,d=1*o.getAttribute("data-rotate")+1*n,u=this._w.Math.abs(d)>=360?0:d;o.setAttribute("data-rotate",u),c._rotateVertical=/^(90|270)$/.test(this._w.Math.abs(u).toString()),this.plugins.resizing.setTransformSize.call(this,o,null,null),a.onModifyMode.call(this,o,this.plugins.resizing.call_controller_resize.call(this,o,l));break;case"onalign":this.plugins.resizing.openAlignMenu.call(this);break;case"align":const h="basic"===n?"none":n;a.setAlign.call(this,h,null,null,null),a.onModifyMode.call(this,o,this.plugins.resizing.call_controller_resize.call(this,o,l));break;case"caption":const p=!s._captionChecked;if(a.openModify.call(this,!0),s._captionChecked=s.captionCheckEl.checked=p,"image"===l?a.update_image.call(this,!1,!1,!1):"video"===l&&(this.context.dialog.updateModal=!0,a.submitAction.call(this)),p){const e=this.util.getChildElement(s._caption,(function(e){return 3===e.nodeType}));e?this.setRange(e,0,e,e.textContent.length):s._caption.focus(),this.controllersOff()}else a.onModifyMode.call(this,o,this.plugins.resizing.call_controller_resize.call(this,o,l)),a.openModify.call(this,!0);break;case"revert":a.setOriginSize.call(this),a.onModifyMode.call(this,o,this.plugins.resizing.call_controller_resize.call(this,o,l));break;case"update":a.openModify.call(this),this.controllersOff();break;case"delete":a.destroy.call(this)}this.history.push(!1)}},resetTransform:function(e){const t=(e.getAttribute("data-size")||e.getAttribute("data-origin")||"").split(",");this.context.resizing._rotateVertical=!1,e.style.maxWidth="",e.style.transform="",e.style.transformOrigin="",e.setAttribute("data-rotate",""),e.setAttribute("data-rotateX",""),e.setAttribute("data-rotateY",""),this.plugins[this.context.resizing._resize_plugin].setSize.call(this,t[0]?t[0]:"auto",t[1]?t[1]:"",!0)},setTransformSize:function(e,t,i){let n=e.getAttribute("data-percentage");const l=this.context.resizing._rotateVertical,s=1*e.getAttribute("data-rotate");let o="";if(n&&!l)n=n.split(","),"auto"===n[0]&&"auto"===n[1]?this.plugins[this.context.resizing._resize_plugin].setAutoSize.call(this):this.plugins[this.context.resizing._resize_plugin].setPercentSize.call(this,n[0],n[1]);else{const n=this.util.getParentElement(e,"FIGURE"),a=t||e.offsetWidth,r=i||e.offsetHeight,c=(l?r:a)+"px",d=(l?a:r)+"px";if(this.plugins[this.context.resizing._resize_plugin].cancelPercentAttr.call(this),this.plugins[this.context.resizing._resize_plugin].setSize.call(this,a+"px",r+"px",!0),n.style.width=c,n.style.height=this.context[this.context.resizing._resize_plugin]._caption?"":d,l){let e=a/2+"px "+a/2+"px 0",t=r/2+"px "+r/2+"px 0";o=90===s||-270===s?t:e}}e.style.transformOrigin=o,this.plugins.resizing._setTransForm(e,s.toString(),e.getAttribute("data-rotateX")||"",e.getAttribute("data-rotateY")||""),e.style.maxWidth=l?"none":"",this.plugins.resizing.setCaptionPosition.call(this,e)},_setTransForm:function(e,t,i,n){let l=(e.offsetWidth-e.offsetHeight)*(/-/.test(t)?1:-1),s="";if(/[1-9]/.test(t)&&(i||n))switch(s=i?"Y":"X",t){case"90":s=i&&n?"X":n?s:"";break;case"270":l*=-1,s=i&&n?"Y":i?s:"";break;case"-90":s=i&&n?"Y":i?s:"";break;case"-270":l*=-1,s=i&&n?"X":n?s:"";break;default:s=""}t%180==0&&(e.style.maxWidth=""),e.style.transform="rotate("+t+"deg)"+(i?" rotateX("+i+"deg)":"")+(n?" rotateY("+n+"deg)":"")+(s?" translate"+s+"("+l+"px)":"")},setCaptionPosition:function(e){const t=this.util.getChildElement(this.util.getParentElement(e,"FIGURE"),"FIGCAPTION");t&&(t.style.marginTop=(this.context.resizing._rotateVertical?e.offsetWidth-e.offsetHeight:0)+"px")},onMouseDown_resize_handle:function(e){const t=this.context.resizing,i=t._resize_direction=e.target.classList[0];e.stopPropagation(),e.preventDefault();const n=this.context.resizing._resize_plugin,l=this.context[n]._element,s=this.plugins[n];t._resizeClientX=e.clientX,t._resizeClientY=e.clientY,this.context.element.resizeBackground.style.display="block",t.resizeButton.style.display="none",t.resizeDiv.style.float=/l/.test(i)?"right":/r/.test(i)?"left":"none";const o=function(e){if("keydown"===e.type&&27!==e.keyCode)return;const i=t._isChange;t._isChange=!1,this.removeDocEvent("mousemove",a),this.removeDocEvent("mouseup",o),this.removeDocEvent("keydown",o),"keydown"===e.type?(this.controllersOff(),this.context.element.resizeBackground.style.display="none",this.plugins[this.context.resizing._resize_plugin].init.call(this)):(this.plugins.resizing.cancel_controller_resize.call(this),i&&this.history.push(!1)),s.onModifyMode.call(this,l,this.plugins.resizing.call_controller_resize.call(this,l,t._resize_plugin))}.bind(this),a=this.plugins.resizing.resizing_element.bind(this,t,i,this.context[t._resize_plugin]);this.addDocEvent("mousemove",a),this.addDocEvent("mouseup",o),this.addDocEvent("keydown",o)},resizing_element:function(e,t,i,n){const l=n.clientX,s=n.clientY;let o=i._element_w,a=i._element_h;const r=i._element_w+(/r/.test(t)?l-e._resizeClientX:e._resizeClientX-l),c=i._element_h+(/b/.test(t)?s-e._resizeClientY:e._resizeClientY-s),d=i._element_h/i._element_w*r;/t/.test(t)&&(e.resizeDiv.style.top=i._element_h-(/h/.test(t)?c:d)+"px"),/l/.test(t)&&(e.resizeDiv.style.left=i._element_w-r+"px"),/r|l/.test(t)&&(e.resizeDiv.style.width=r+"px",o=r),/^(t|b)[^h]$/.test(t)?(e.resizeDiv.style.height=d+"px",a=d):/^(t|b)h$/.test(t)&&(e.resizeDiv.style.height=c+"px",a=c),e._resize_w=o,e._resize_h=a,this.util.changeTxt(e.resizeDisplay,this._w.Math.round(o)+" x "+this._w.Math.round(a)),e._isChange=!0},cancel_controller_resize:function(){const e=this.context.resizing._rotateVertical;this.controllersOff(),this.context.element.resizeBackground.style.display="none";let t=this._w.Math.round(e?this.context.resizing._resize_h:this.context.resizing._resize_w),i=this._w.Math.round(e?this.context.resizing._resize_w:this.context.resizing._resize_h);if(!e&&!/%$/.test(t)){const e=16,n=this.context.element.wysiwygFrame.clientWidth-2*e-2;this.util.getNumber(t)>n&&(i=this._w.Math.round(i/t*n),t=n)}this.plugins[this.context.resizing._resize_plugin].setSize.call(this,t,i,!1),this.plugins[this.context.resizing._resize_plugin].init.call(this)}},o={name:"notice",add:function(e){const t=e.context;t.notice={};let i=e.util.createElement("DIV"),n=e.util.createElement("SPAN"),l=e.util.createElement("BUTTON");i.className="se-notice",l.className="close",l.setAttribute("aria-label","Close"),l.setAttribute("title",e.lang.dialogBox.close),l.innerHTML='',i.appendChild(n),i.appendChild(l),t.notice.modal=i,t.notice.message=n,l.addEventListener("click",this.onClick_cancel.bind(e)),t.element.relative.insertBefore(i,t.element.editorArea),i=null},onClick_cancel:function(e){e.preventDefault(),e.stopPropagation(),this.plugins.notice.close.call(this)},open:function(e){this.context.notice.message.textContent=e,this.context.notice.modal.style.display="block"},close:function(){this.context.notice.modal.style.display="none"}},a={blockquote:{name:"blockquote",display:"command",add:function(e,t){e.context.blockquote={targetButton:t,tag:e.util.createElement("BLOCKQUOTE")}},active:function(e){if(e){if(/blockquote/i.test(e.nodeName))return this.util.addClass(this.context.blockquote.targetButton,"active"),!0}else this.util.removeClass(this.context.blockquote.targetButton,"active");return!1},action:function(){const e=this.util.getParentElement(this.getSelectionNode(),"blockquote");e?this.detachRangeFormatElement(e,null,null,!1,!1):this.applyRangeFormatElement(this.context.blockquote.tag.cloneNode(!1))}},align:{name:"align",display:"submenu",add:function(e,t){const i=e.context;i.align={targetIcon:t.querySelector("i"),_alignList:null,currentAlign:""};let n=this.setSubmenu.call(e),l=n.querySelector("ul");l.addEventListener("click",this.pickup.bind(e)),i.align._alignList=l.querySelectorAll("li button"),t.parentNode.appendChild(n),n=null,l=null},setSubmenu:function(){const e=this.lang,t=this.util.createElement("DIV");return t.className="se-list-layer",t.innerHTML='
    ",t},active:function(e){const t=this.context.align.targetIcon;if(e){if(this.util.isFormatElement(e)){const i=e.style.textAlign;return i&&(t.className="se-icon-align-"+i,t.setAttribute("data-focus",i)),!0}}else t.className="se-icon-align-left",t.removeAttribute("data-focus");return!1},on:function(){const e=this.context.align,t=e._alignList,i=e.targetIcon.getAttribute("data-focus")||"left";if(i!==e.currentAlign){for(let e=0,n=t.length;e('+t.toolbar.default+")";for(s=0,o=a.length;s";return r+="",i.innerHTML=r,i},active:function(e){const t=this.context.font.targetText,i=this.context.font.targetTooltip;if(e){if(e.style&&e.style.fontFamily.length>0){const n=e.style.fontFamily.replace(/["']/g,"");return this.util.changeTxt(t,n),this.util.changeTxt(i,n),!0}}else{const e=this.lang.toolbar.font;this.util.changeTxt(t,e),this.util.changeTxt(i,e)}return!1},on:function(){const e=this.context.font,t=e._fontList,i=e.targetText.textContent;if(i!==e.currentFont){for(let e=0,n=t.length;e('+t.toolbar.default+")";for(let t,i=0,s=e.fontSizeUnit,o=n.length;i";return l+="",i.innerHTML=l,i},active:function(e){if(e){if(e.style&&e.style.fontSize.length>0)return this.util.changeTxt(this.context.fontSize.targetText,e.style.fontSize),!0}else this.util.changeTxt(this.context.fontSize.targetText,this.lang.toolbar.fontSize);return!1},on:function(){const e=this.context.fontSize,t=e._sizeList,i=e.targetText.textContent;if(i!==e.currentSize){for(let e=0,n=t.length;e
  • ",t},appendHr:function(e){const t=this.util.createElement("HR");t.className=e,this.focus();let i=this.insertComponent(t,!1);this.setRange(i,0,i,0)},horizontalRulePick:function(e){e.preventDefault(),e.stopPropagation();let t=e.target,i=null;for(;!i&&!/UL/i.test(t.tagName);)i=t.getAttribute("data-value"),t=t.parentNode;i&&(this.plugins.horizontalRule.appendHr.call(this,"__se__"+i),this.submenuOff())}},list:{name:"list",display:"submenu",add:function(e,t){const i=e.context;i.list={targetButton:t,targetIcon:t.querySelector("i"),_list:null,currentList:""};let n=this.setSubmenu.call(e),l=n.querySelector("ul");l.addEventListener("click",this.pickup.bind(e)),i.list._list=l.querySelectorAll("li button"),t.parentNode.appendChild(n),n=null,l=null},setSubmenu:function(){const e=this.lang,t=this.util.createElement("DIV");return t.className="se-submenu se-list-layer",t.innerHTML='
    ",t},active:function(e){const t=this.context.list.targetButton,i=this.context.list.targetIcon,n=this.util;if(e){if(n.isList(e)){const l=e.nodeName;return t.setAttribute("data-focus",l),n.addClass(t,"active"),/UL/i.test(l)?(n.removeClass(i,"se-icon-list-number"),n.addClass(i,"se-icon-list-bullets")):(n.removeClass(i,"se-icon-list-bullets"),n.addClass(i,"se-icon-list-number")),!0}}else t.removeAttribute("data-focus"),n.removeClass(i,"se-icon-list-bullets"),n.addClass(i,"se-icon-list-number"),n.removeClass(t,"active");return!1},on:function(){const e=this.context.list,t=e._list,i=e.targetButton.getAttribute("data-focus")||"";if(i!==e.currentList){for(let e=0,n=t.length;e"),t.innerHTML+=i.outerHTML,e&&(t.innerHTML+="
    ")}else{const e=i.childNodes;for(;e[0];)t.appendChild(e[0])}c.appendChild(t),a||(p=c),a&&u===d&&!l.isRangeFormatElement(m)||(h||(h=c),s&&a&&u===d||a&&l.isList(d)&&d===r||c.parentNode!==u&&u.insertBefore(c,m)),l.removeItem(i),s&&null===g&&(g=c.children.length-1),a&&l.getRangeFormatElement(d,f)!==l.getRangeFormatElement(r,f)&&(c=l.createElement(e)),_&&0===_.children.length&&l.removeItem(_)}else l.removeItem(i);g&&(h=h.children[g]),r&&(m=c.children.length-1,c.innerHTML+=u.innerHTML,p=c.children[m],l.removeItem(u)),o=a=l.getEdgeChildNodes(h.firstChild,p.lastChild)}else{if(i)for(let e=0,t=n.length;e=0;i--)if(n[i].contains(n[e])){n.splice(e,1),e--,t--;break}const t=l.getRangeFormatElement(r),s=t&&t.tagName===e;let c,d,u;const h=function(e){return!this.isComponent(e)}.bind(l);s||(d=l.createElement(e));for(let t,r,p=0,g=n.length;p0){const e=l.cloneNode(!1),t=l.childNodes,s=this.util.getPositionIndex(n);for(;t[s];)e.appendChild(t[s]);i.appendChild(e)}0===l.children.length&&this.util.removeItem(l);const a=this.util.getEdgeChildNodes(t,i);return{cc:t.parentNode,sc:a.sc,ec:a.ec}},editInsideList:function(e,t){const i=(t=t||this.getSelectedElements().filter(function(e){return this.isListCell(e)}.bind(this.util))).length;if(0===i||!e&&!this.util.isListCell(t[0].previousElementSibling)&&!this.util.isListCell(t[i-1].nextElementSibling))return{sc:t[0],so:0,ec:t[i-1],eo:1};let n=t[0].parentNode,l=t[i-1],s=null;if(e){if(n!==l.parentNode&&this.util.isList(l.parentNode.parentNode)&&l.nextElementSibling)for(l=l.nextElementSibling;l;)t.push(l),l=l.nextElementSibling;s=this.plugins.list.editList.call(this,n.nodeName.toUpperCase(),t,!0)}else{s={sc:t[0],so:i>1||!this.getRange().collapsed?0:1,ec:l,eo:1};let e=this.util.createElement(n.nodeName),o=s.sc.previousElementSibling,a=s.sc.nextElementSibling;for(let l,s=0,r=i;s i"),i.table.resizeText=s.querySelector("._se_table_resize > span > span"),i.table.headerButton=s.querySelector("._se_table_header"),s.addEventListener("mousedown",(function(e){e.stopPropagation()}),!1);let o=this.setController_tableEditor.call(e);i.table.resizeDiv=o,i.table.splitMenu=o.querySelector(".se-btn-group-sub"),i.table.mergeButton=o.querySelector("._se_table_merge_button"),i.table.splitButton=o.querySelector("._se_table_split_button"),o.addEventListener("mousedown",(function(e){e.stopPropagation()}),!1),l.addEventListener("mousemove",this.onMouseMove_tablePicker.bind(e)),l.addEventListener("click",this.appendTable.bind(e)),o.addEventListener("click",this.onClick_tableController.bind(e)),s.addEventListener("click",this.onClick_tableController.bind(e)),t.parentNode.appendChild(n),i.element.relative.appendChild(o),i.element.relative.appendChild(s),n=null,l=null,o=null,s=null},setSubmenu:function(){const e=this.util.createElement("DIV");return e.className="se-submenu se-selector-table",e.innerHTML='
    1 x 1
    ',e},setController_table:function(){const e=this.lang,t=this.util.createElement("DIV");return t.className="se-controller se-controller-table",t.innerHTML='
    ",t},setController_tableEditor:function(){const e=this.lang,t=this.util.createElement("DIV");return t.className="se-controller se-controller-table-cell",t.innerHTML='
    • '+e.controller.VerticalSplit+'
    • '+e.controller.HorizontalSplit+"
    ",t},appendTable:function(){const e=this.util.createElement("TABLE"),t=this.plugins.table.createCells,i=this.context.table._tableXY[0];let n=this.context.table._tableXY[1],l="";for(;n>0;)l+=""+t.call(this,"td",i)+"",--n;l+="",e.innerHTML=l,this.insertComponent(e,!1);const s=e.querySelector("td div");this.setRange(s,0,s,0),this.plugins.table.reset_table_picker.call(this)},createCells:function(e,t,i){if(e=e.toLowerCase(),i){const t=this.util.createElement(e);return t.innerHTML="

    ",t}{let i="";for(;t>0;)i+="<"+e+">

    ",t--;return i}},onMouseMove_tablePicker:function(e){e.stopPropagation();let t=this._w.Math.ceil(e.offsetX/18),i=this._w.Math.ceil(e.offsetY/18);t=t<1?1:t,i=i<1?1:i,this.context.table.tableHighlight.style.width=t+"em",this.context.table.tableHighlight.style.height=i+"em";let n=t<5?5:t>9?10:t+1,l=i<5?5:i>9?10:i+1;this.context.table.tableUnHighlight.style.width=n+"em",this.context.table.tableUnHighlight.style.height=l+"em",this.util.changeTxt(this.context.table.tableDisplay,t+" x "+i),this.context.table._tableXY=[t,i]},reset_table_picker:function(){if(!this.context.table.tableHighlight)return;const e=this.context.table.tableHighlight.style,t=this.context.table.tableUnHighlight.style;e.width="1em",e.height="1em",t.width="5em",t.height="5em",this.util.changeTxt(this.context.table.tableDisplay,"1 x 1"),this.submenuOff()},init:function(){const e=this.context.table,t=this.plugins.table;if(t._removeEvents.call(this),t._selectedTable){const e=t._selectedTable.querySelectorAll(".se-table-selected-cell");for(let t=0,i=e.length;t0)for(let e,t=0;ts||(u>=e.index?(n+=e.cs,u+=e.cs,e.rs-=1,e.row=s+1,e.rs<1&&(r.splice(t,1),t--)):h===p-1&&(e.rs-=1,e.row=s+1,e.rs<1&&(r.splice(t,1),t--)));if(s===o&&h===l){i._logical_cellIndex=u;break}d>0&&a.push({index:u,cs:c+1,rs:d,row:-1}),n+=c}r=r.concat(a).sort((function(e,t){return e.index-t.index})),a=[]}a=null,r=null}},editTable:function(e,t){const i=this.plugins.table,n=this.context.table,l=n._element,s="row"===e;if(s){const e=n._trElement.parentNode;if(/^THEAD$/i.test(e.nodeName)){if("up"===t)return;if(!e.nextElementSibling||!/^TBODY$/i.test(e.nextElementSibling.nodeName))return void(l.innerHTML+=""+i.createCells.call(this,"td",n._logical_cellCnt,!1)+"")}}if(i._ref){const e=n._tdElement,l=i._selectedCells;if(s)if(t)i.setCellInfo.call(this,"up"===t?l[0]:l[l.length-1],!0),i.editRow.call(this,t,e);else{let e=l[0].parentNode;const n=[l[0]];for(let t,i=1,s=l.length;io&&o>t&&(e[l].rowSpan=i+a,c-=n)}if(n){const e=r[s+1];if(e){const t=[];let i=r[s].cells,n=0;for(let e,l,s=0,o=i.length;s1&&(e.rowSpan-=1,t.push({cell:e.cloneNode(!1),index:l}));if(t.length>0){let l=t.shift();i=e.cells,n=0;for(let s,o,a=0,r=i.length;a=l.index)||(a--,n--,n+=l.cell.colSpan-1,e.insertBefore(l.cell,s),l=t.shift(),l));a++);if(l){e.appendChild(l.cell);for(let i=0,n=t.length;i0){const e=!s[b+1];for(let t,i=0;i_||(g>=t.index?(f+=t.cs,g=b+f,t.rs-=1,t.row=_+1,t.rs<1&&(d.splice(i,1),i--)):e&&(t.rs-=1,t.row=_+1,t.rs<1&&(d.splice(i,1),i--)))}i>0&&c.push({rs:i,cs:r+1,index:g,row:-1}),g>=t&&g+r<=t+o?h.push(e):g<=t+o&&g+r>=t?e.colSpan-=n.getOverlapRangeAtIndex(a,a+o,g,g+r):i>0&&(gt+o)&&p.push({cell:e,i:_,rs:_+i}),f+=r}else{if(b>=t)break;if(r>0){if(u<1&&r+b>=t){e.colSpan+=1,t=null,u=i+1;break}t-=r}if(!m){for(let e,i=0;i0){u-=1;continue}null!==t&&s.length>0&&(g=this.plugins.table.createCells.call(this,s[0].nodeName,0,!0),g=e.insertBefore(g,s[t]))}}if(l){let e,t;for(let i,l=0,s=h.length;l1)c.colSpan=this._w.Math.floor(e/2),l.colSpan=e-c.colSpan,o.insertBefore(c,l.nextElementSibling);else{let t=[],i=[];for(let o,r,c=0,d=n._rowCnt;c0)for(let e,t=0;tc||(u>=e.index?(r+=e.cs,u+=e.cs,e.rs-=1,e.row=c+1,e.rs<1&&(i.splice(t,1),t--)):h===p-1&&(e.rs-=1,e.row=c+1,e.rs<1&&(i.splice(t,1),t--)));if(u<=a&&d>0&&t.push({index:u,cs:s+1,rs:d,row:-1}),n!==l&&u<=a&&u+s>=a+e-1){n.colSpan+=1;break}if(u>a)break;r+=s}i=i.concat(t).sort((function(e,t){return e.index-t.index})),t=[]}o.insertBefore(c,l.nextElementSibling)}}else{const e=l.rowSpan;if(c.colSpan=l.colSpan,e>1){c.rowSpan=this._w.Math.floor(e/2);const i=e-c.rowSpan,n=[],r=t.getArrayIndex(s,o)+i;for(let e,t,i=0;i=a));c++)l=e[c],s=l.rowSpan-1,s>0&&s+i>=r&&o=h.index&&(r+=h.cs,l+=h.cs,h=n.shift()),l>=a||s===o-1){d.insertBefore(c,e.nextElementSibling);break}r+=t}l.rowSpan=i}else{c.rowSpan=l.rowSpan;const e=t.createElement("TR");e.appendChild(c);for(let e,t=0;t=r&&(e[i].rowSpan+=1)}const i=n._physical_cellIndex,a=o.cells;for(let e=0,t=a.length;e0&&o+s>=n&&(e.rowSpan-=i.getOverlapRangeAtIndex(n,l,o,o+s));else s.push(e[o]);for(let e=0,t=s.length;e"+this.plugins.table.createCells.call(this,"th",this.context.table._logical_cellCnt,!1)+"",n.insertBefore(t,n.firstElementChild)}e.toggleClass(t,"active"),/TH/i.test(this.context.table._tdElement.nodeName)?this.controllersOff():this.plugins.table.setPositionControllerDiv.call(this,this.context.table._tdElement,!1)},resizeTable:function(){const e=this.context.table,t=e.resizeIcon,i=e.resizeText;let n="se-icon-expansion",l="se-icon-reduction",s=e.minText,o="100%";e._maxWidth||(n="se-icon-reduction",l="se-icon-expansion",s=e.maxText,o="auto"),this.util.removeClass(t,n),this.util.addClass(t,l),this.util.changeTxt(i,s),e._element.style.width=o},setActiveButton:function(e,t){const i=this.context.table;t&&e!==t?(i.splitButton.setAttribute("disabled",!0),i.mergeButton.removeAttribute("disabled")):(i.splitButton.removeAttribute("disabled"),i.mergeButton.setAttribute("disabled",!0))},_bindOnSelect:null,_bindOffSelect:null,_bindOffShift:null,_selectedCells:null,_shift:!1,_fixedCell:null,_fixedCellName:null,_selectedCell:null,_selectedTable:null,_ref:null,_toggleEditor:function(e){this.context.element.wysiwyg.setAttribute("contenteditable",e),e?this.util.removeClass(this.context.element.wysiwyg,"se-disabled"):this.util.addClass(this.context.element.wysiwyg,"se-disabled")},_offCellMultiSelect:function(e){e.stopPropagation();const t=this.plugins.table;t._shift?t._initBind&&(this._wd.removeEventListener("touchmove",t._initBind),t._initBind=null):(t._removeEvents.call(this),t._toggleEditor.call(this,!0)),t._fixedCell&&t._selectedTable&&(t.setActiveButton.call(this,t._fixedCell,t._selectedCell),t.call_controller_tableEdit.call(this,t._selectedCell||t._fixedCell),t._selectedCells=t._selectedTable.querySelectorAll(".se-table-selected-cell"),t._selectedCell&&t._fixedCell&&this.focusEdge(t._selectedCell),t._shift||(t._fixedCell=null,t._selectedCell=null,t._fixedCellName=null))},_onCellMultiSelect:function(e){const t=this.plugins.table,i=this.util.getParentElement(e.target,this.util.isCell);if(t._shift)i===t._fixedCell?t._toggleEditor.call(this,!0):t._toggleEditor.call(this,!1);else if(!t._ref){if(i===t._fixedCell)return;t._toggleEditor.call(this,!1)}i&&i!==t._selectedCell&&t._fixedCellName===i.nodeName&&t._selectedTable===this.util.getParentElement(i,"TABLE")&&(t._selectedCell=i,t._setMultiCells.call(this,t._fixedCell,i))},_setMultiCells:function(e,t){const i=this.plugins.table,n=i._selectedTable.rows,l=this.util,s=i._selectedTable.querySelectorAll(".se-table-selected-cell");for(let e=0,t=s.length;e0)for(let e,t=0;td||(u>=e.index?(s+=e.cs,u+=e.cs,e.rs-=1,e.row=d+1,e.rs<1&&(a.splice(t,1),t--)):g===m-1&&(e.rs-=1,e.row=d+1,e.rs<1&&(a.splice(t,1),t--)));if(o){if(n!==e&&n!==t||(c.cs=null!==c.cs&&c.csu+h?c.ce:u+h,c.rs=null!==c.rs&&c.rsd+p?c.re:d+p,c._i+=1),2===c._i){o=!1,a=[],r=[],d=-1;break}}else if(l.getOverlapRangeAtIndex(c.cs,c.ce,u,u+h)&&l.getOverlapRangeAtIndex(c.rs,c.re,d,d+p)){const e=c.csu+h?c.ce:u+h,i=c.rsd+p?c.re:d+p;if(c.cs!==e||c.ce!==t||c.rs!==i||c.re!==s){c.cs=e,c.ce=t,c.rs=i,c.re=s,d=-1,a=[],r=[];break}l.addClass(n,"se-table-selected-cell")}p>0&&r.push({index:u,cs:h+1,rs:p,row:-1}),s+=n.colSpan-1}a=a.concat(r).sort((function(e,t){return e.index-t.index})),r=[]}},_removeEvents:function(){const e=this.plugins.table;e._initBind&&(this._wd.removeEventListener("touchmove",e._initBind),e._initBind=null),e._bindOnSelect&&(this._wd.removeEventListener("mousedown",e._bindOnSelect),this._wd.removeEventListener("mousemove",e._bindOnSelect),e._bindOnSelect=null),e._bindOffSelect&&(this._wd.removeEventListener("mouseup",e._bindOffSelect),e._bindOffSelect=null),e._bindOffShift&&(this._wd.removeEventListener("keyup",e._bindOffShift),e._bindOffShift=null)},_initBind:null,onTableCellMultiSelect:function(e,t){const i=this.plugins.table;i._removeEvents.call(this),this.controllersOff(),i._shift=t,i._fixedCell=e,i._fixedCellName=e.nodeName,i._selectedTable=this.util.getParentElement(e,"TABLE");const n=i._selectedTable.querySelectorAll(".se-table-selected-cell");for(let e=0,t=n.length;e-1?(i=e.toLowerCase(),o="blockquote"===i?"range":"pre"===i?"free":"replace",r=/^h/.test(i)?i.match(/\d+/)[0]:"",a=t["tag_"+(r?"h":i)]+r,d="",c=""):(i=e.tag.toLowerCase(),o=e.command,a=e.name||i,d=e.class,c=d?' class="'+d+'"':""),s+='
  • ";return s+="",i.innerHTML=s,i},active:function(e){let t=this.lang.toolbar.formats;const i=this.context.formatBlock.targetText,n=this.context.formatBlock.targetTooltip;if(e){if(this.util.isFormatElement(e)){const l=this.context.formatBlock._formatList,s=e.nodeName.toLowerCase(),o=(e.className.match(/(\s|^)__se__format__[^\s]+/)||[""])[0].trim();for(let e,i=0,n=l.length;i=0;u--)if(n=g[u],n!==(g[u+1]?g[u+1].parentNode:null)){if(d=a.isComponent(n),s=d?"":n.innerHTML.replace(/(?!>)\s+(?=<)|\n/g," "),o=a.getParentElement(n,(function(e){return e.parentNode===t})),(t!==n.parentNode||d)&&(a.isFormatElement(t)?(t.parentNode.insertBefore(i,t.nextSibling),t=t.parentNode):(t.insertBefore(i,o?o.nextSibling:null),t=n.parentNode),r=i.nextSibling,r&&i.nodeName===r.nodeName&&a.isSameAttributes(i,r)&&(i.innerHTML+="
    "+r.innerHTML,a.removeItem(r)),i=l.cloneNode(!1),h=!0),c=i.innerHTML,i.innerHTML=(h||!s||!c||/
    $/i.test(s)?s:s+"
    ")+c,0===u){t.insertBefore(i,n),r=n.nextSibling,r&&i.nodeName===r.nodeName&&a.isSameAttributes(i,r)&&(i.innerHTML+="
    "+r.innerHTML,a.removeItem(r));const e=i.previousSibling;e&&i.nodeName===e.nodeName&&a.isSameAttributes(i,e)&&(e.innerHTML+="
    "+i.innerHTML,a.removeItem(i))}d||a.removeItem(n),s&&(h=!1)}this.setRange(n,0,n,0)}else{for(let e,t,i=0,o=g.length;i('+t.toolbar.default+")";for(let e,t=0,i=n.length;t";return l+="",i.innerHTML=l,i},on:function(){const e=this.context.lineHeight,t=e._sizeList,i=this.util.getFormatElement(this.getSelectionNode()).style.lineHeight+"";if(i!==e.currentSize){for(let e=0,n=t.length;e";return i+="",t.innerHTML=i,t},pickup:function(e){if(!/^BUTTON$/i.test(e.target.tagName))return!1;e.preventDefault(),e.stopPropagation();const t=this.context.option.templates[e.target.getAttribute("data-value")];if(!t.html)throw this.submenuOff(),Error('[SUNEDITOR.template.fail] cause : "templates[i].html not found"');this.setContents(t.html),this.submenuOff()}},paragraphStyle:{name:"paragraphStyle",display:"submenu",add:function(e,t){const i=e.context;i.paragraphStyle={_classList:null};let n=this.setSubmenu.call(e);n.querySelector("ul").addEventListener("click",this.pickUp.bind(e)),i.paragraphStyle._classList=n.querySelectorAll("li button"),t.parentNode.appendChild(n),n=null},setSubmenu:function(){const e=this.context.option,t=this.util.createElement("DIV");t.className="se-submenu se-list-layer";const i=this.lang.menu,n={spaced:{name:i.spaced,class:"__se__p-spaced",_class:""},bordered:{name:i.bordered,class:"__se__p-bordered",_class:""},neon:{name:i.neon,class:"__se__p-neon",_class:""}},l=e.paragraphStyles&&0!==e.paragraphStyles.length?e.paragraphStyles:["spaced","bordered","neon"];let s='
      ';for(let e,t,i,o,a=0,r=l.length;a
    "}return s+="",t.innerHTML=s,t},on:function(){const e=this.context.paragraphStyle._classList,t=this.util.getFormatElement(this.getSelectionNode());for(let i=0,n=e.length;i"}return l+="",t.innerHTML=l,t},on:function(){const e=this.util,t=this.context.textStyle._styleList,i=this.getSelectionNode();for(let n,l,s,o=0,a=t.length;o'+e.dialogBox.linkBox.title+'
    ",t},setController_LinkButton:function(){const e=this.lang,t=this.util.createElement("DIV");return t.className="se-controller se-controller-link",t.innerHTML='
    ",t},open:function(){this.plugins.dialog.open.call(this,"link","link"===this.currentControllerName)},submit:function(e){this.showLoading(),e.preventDefault(),e.stopPropagation();const t=function(){if(0===this.context.link.focusElement.value.trim().length)return!1;const e=this.context.link,t=e.focusElement.value,i=e.linkAnchorText,n=0===i.value.length?t:i.value;if(this.context.dialog.updateModal)e._linkAnchor.href=t,e._linkAnchor.textContent=n,e._linkAnchor.target=e.linkNewWindowCheck.checked?"_blank":"",this.setRange(e._linkAnchor.childNodes[0],0,e._linkAnchor.childNodes[0],e._linkAnchor.textContent.length);else{const i=this.util.createElement("A");i.href=t,i.textContent=n,i.target=e.linkNewWindowCheck.checked?"_blank":"";const l=this.getSelectedElements();if(l.length>1){const e=this.util.createElement(l[0].nodeName);e.appendChild(i),this.insertNode(e)}else this.insertNode(i);this.setRange(i.childNodes[0],0,i.childNodes[0],i.textContent.length)}this.history.push(!1),e.focusElement.value="",e.linkAnchorText.value=""}.bind(this);try{t()}finally{this.plugins.dialog.close.call(this),this.closeLoading(),this.focus()}return!1},active:function(e){if(e){if(this.util.isAnchor(e)&&null===e.getAttribute("data-image-link"))return this.controllerArray[0]!==this.context.link.linkBtn&&this.plugins.link.call_controller_linkButton.call(this,e),!0}else this.controllerArray[0]===this.context.link.linkBtn&&this.controllersOff();return!1},on:function(e){e||(this.context.link.linkAnchorText.value=this.getSelection().toString()),this.context.link._linkAnchor&&(this.context.dialog.updateModal=!0,this.context.link.focusElement.value=this.context.link._linkAnchor.href,this.context.link.linkAnchorText.value=this.context.link._linkAnchor.textContent,this.context.link.linkNewWindowCheck.checked=!!/_blank/i.test(this.context.link._linkAnchor.target))},call_controller_linkButton:function(e){this.editLink=this.context.link._linkAnchor=e;const t=this.context.link.linkBtn,i=t.querySelector("a");i.href=e.href,i.title=e.textContent,i.textContent=e.textContent;const n=this.util.getOffset(e,this.context.element.wysiwygFrame);t.style.top=n.top+e.offsetHeight+10+"px",t.style.left=n.left-this.context.element.wysiwygFrame.scrollLeft+"px",t.style.display="block";const l=this.context.element.wysiwygFrame.offsetWidth-(t.offsetLeft+t.offsetWidth);l<0?(t.style.left=t.offsetLeft+l+"px",t.firstElementChild.style.left=20-l+"px"):t.firstElementChild.style.left="20px",this.controllersOn(t,this.plugins.link.init.bind(this),"link")},onClick_linkBtn:function(e){e.stopPropagation();const t=e.target.getAttribute("data-command")||e.target.parentNode.getAttribute("data-command");if(t){if(e.preventDefault(),/update/.test(t))this.context.link.focusElement.value=this.context.link._linkAnchor.href,this.context.link.linkAnchorText.value=this.context.link._linkAnchor.textContent,this.context.link.linkNewWindowCheck.checked=!!/_blank/i.test(this.context.link._linkAnchor.target),this.plugins.dialog.open.call(this,"link",!0);else if(/unlink/.test(t)){const e=this.util.getChildElement(this.context.link._linkAnchor,(function(e){return 0===e.childNodes.length||3===e.nodeType}),!1),t=this.util.getChildElement(this.context.link._linkAnchor,(function(e){return 0===e.childNodes.length||3===e.nodeType}),!0);this.setRange(e,0,t,t.textContent.length),this.nodeChange(null,null,["A"],!1)}else this.util.removeItem(this.context.link._linkAnchor),this.context.link._linkAnchor=null,this.focus(),this.history.push(!1);this.controllersOff()}},init:function(){if(!/link/i.test(this.context.dialog.kind)){const e=this.context.link;e.linkBtn.style.display="none",e._linkAnchor=null,e.focusElement.value="",e.linkAnchorText.value="",e.linkNewWindowCheck.checked=!1}}},image:{name:"image",display:"dialog",add:function(e){e.addModule([l,s,o]);const t=e.context;t.image={sizeUnit:t.option._imageSizeUnit,_linkElement:null,_container:null,_cover:null,_element:null,_element_w:1,_element_h:1,_element_l:0,_element_t:0,_defaultSizeX:"auto",_defaultSizeY:"auto",_origin_w:"auto"===t.option.imageWidth?"":t.option.imageWidth,_origin_h:"",_altText:"",_caption:null,captionCheckEl:null,_linkValue:"",_align:"none",_captionChecked:!1,_proportionChecked:!0,_floatClassRegExp:"__se__float\\-[a-z]+",_xmlHttp:null,_captionShow:!0,_resizing:t.option.imageResizing,_rotation:t.option.imageRotation,_resizeDotHide:!t.option.imageHeightShow,_uploadFileLength:0,_onlyPercentage:t.option.imageSizeOnlyPercentage,_ratio:!1,_ratioX:1,_ratioY:1};let i=this.setDialog.call(e);t.image.modal=i,t.image.imgUrlFile=i.querySelector("._se_image_url"),t.image.imgInputFile=t.image.focusElement=i.querySelector("._se_image_file")||i.querySelector("._se_image_url"),t.image.altText=i.querySelector("._se_image_alt"),t.image.imgLink=i.querySelector("._se_image_link"),t.image.imgLinkNewWindowCheck=i.querySelector("._se_image_link_check"),t.image.captionCheckEl=i.querySelector("._se_image_check_caption"),t.image.modal.querySelector(".se-dialog-tabs").addEventListener("click",this.openTab.bind(e)),t.image.modal.querySelector(".se-btn-primary").addEventListener("click",this.submit.bind(e)),t.image.proportion={},t.image.inputX={},t.image.inputY={},t.option.imageResizing&&(t.image.proportion=i.querySelector("._se_image_check_proportion"),t.image.inputX=i.querySelector("._se_image_size_x"),t.image.inputY=i.querySelector("._se_image_size_y"),t.image.inputX.value=t.option.imageWidth,t.image.inputX.addEventListener("keyup",this.setInputSize.bind(e,"x")),t.image.inputY.addEventListener("keyup",this.setInputSize.bind(e,"y")),t.image.inputX.addEventListener("change",this.setRatio.bind(e)),t.image.inputY.addEventListener("change",this.setRatio.bind(e)),t.image.proportion.addEventListener("change",this.setRatio.bind(e)),i.querySelector(".se-dialog-btn-revert").addEventListener("click",this.sizeRevert.bind(e))),t.dialog.modal.appendChild(i),i=null},setDialog:function(){const e=this.context.option,t=this.lang,i=this.util.createElement("DIV");i.className="se-dialog-content",i.style.display="none";let n='
    '+t.dialogBox.imageBox.title+'
    ';if(e.imageFileInput&&(n+='
    '),e.imageUrlInput&&(n+='
    '),n+='
    ',e.imageResizing){const i=e.imageSizeOnlyPercentage,l=i?' style="display: none !important;"':"",s=e.imageHeightShow?"":' style="display: none !important;"';n+='
    ',i||!e.imageHeightShow?n+='
    ":n+='
    ",n+=' '+t.dialogBox.proportion+'
    '}return n+='
    ",i.innerHTML=n,i},open:function(){this.plugins.dialog.open.call(this,"image","image"===this.currentControllerName)},openTab:function(e){const t=this.context.image.modal,i="init"===e?t.querySelector("._se_tab_link"):e.target;if(!/^BUTTON$/i.test(i.tagName))return!1;const n=i.getAttribute("data-tab-link");let l,s,o;for(s=t.getElementsByClassName("_se_tab_content"),l=0;l0){let t=0;const i=[];for(let n=0,l=e.length;n0){let e=0;const i=this._variable._imagesInfo;for(let t=0,n=i.length;tn){const i="[SUNEDITOR.imageUpload.fail] Size of uploadable total images: "+n/1e3+"KB";return this._imageUploadError(i,{limitSize:n,currentSize:e,uploadSize:t})&&o.open.call(this,i),void this.closeLoading()}}this.context.image._uploadFileLength=i.length;const l=this.context.option.imageUploadUrl,s=this.context.option.imageUploadHeader,a=this.context.dialog.updateModal?1:i.length,r={linkValue:this.context.image._linkValue,linkNewWindow:this.context.image.imgLinkNewWindowCheck.checked,inputWidth:this.context.image.inputX.value,inputHeight:this.context.image.inputY.value,align:this.context.image._align,isUpdate:this.context.dialog.updateModal,currentImage:this.context.image._element};if(!this._imageUploadBefore(i,r))return;if("string"==typeof l&&l.length>0){const e=new FormData;for(let t=0;t0)for(let e in s)this.context.image._xmlHttp.setRequestHeader(e,s[e]);this.context.image._xmlHttp.send(e)}else for(let e=0;e0){const n=this.util.createElement("A");return n.href=/^https?:\/\//.test(t)?t:"http://"+t,n.target=i?"_blank":"",n.setAttribute("data-image-link","image"),e.setAttribute("data-image-link",t),n.appendChild(e),n}return e},setInputSize:function(e,t){t&&32===t.keyCode?t.preventDefault():this.plugins.resizing._module_setInputSize.call(this,this.context.image,e)},setRatio:function(){this.plugins.resizing._module_setRatio.call(this,this.context.image)},submit:function(e){const t=this.context.image,i=this.plugins.image;this.showLoading(),e.preventDefault(),e.stopPropagation(),t._linkValue=t.imgLink.value,t._altText=t.altText.value,t._align=t.modal.querySelector('input[name="suneditor_image_radio"]:checked').value,t._captionChecked=t.captionCheckEl.checked,t._resizing&&(t._proportionChecked=t.proportion.checked);try{this.context.dialog.updateModal&&i.update_image.call(this,!1,!1,!1),t.imgInputFile&&t.imgInputFile.files.length>0?i.onRender_imgInput.call(this):t.imgUrlFile&&t.imgUrlFile.value.trim().length>0?i.onRender_imgUrl.call(this):this.closeLoading()}catch(e){throw this.closeLoading(),Error('[SUNEDITOR.image.submit.fail] cause : "'+e.message+'"')}finally{this.plugins.dialog.close.call(this)}return!1},setImagesInfo:function(e,t){const i=this._variable._imagesInfo;let n=e.getAttribute("data-index"),l=null,s="";if(!n||this._imagesInfoInit)s="create",n=this._variable._imageIndex,this._variable._imageIndex++,e.setAttribute("data-index",n),e.setAttribute("data-file-name",t.name),e.setAttribute("data-file-size",t.size),l={src:e.src,index:1*n,name:t.name,size:t.size},i.push(l);else{s="update",n*=1;for(let e=0,t=i.length;e-1||(i.splice(t,1),this._imageUpload(null,e,"delete",null,0),t--);this.context.resizing._resize_plugin=""},_onload_image:function(e,t){t&&(this.plugins.image.setImagesInfo.call(this,e,t),this.history.push(!0))},create_image:function(e,t,i,n,l,s,o){const a=this.context.image;this.context.resizing._resize_plugin="image";let r=this.util.createElement("IMG");r.addEventListener("load",this.plugins.image._onload_image.bind(this,r,o)),r.src=e,r.alt=a._altText,r=this.plugins.image.onRender_link.call(this,r,t,i),r.setAttribute("data-rotate","0"),a._resizing&&r.setAttribute("data-proportion",a._proportionChecked);const c=this.plugins.resizing.set_cover.call(this,r),d=this.plugins.resizing.set_container.call(this,c,"se-image-container");a._captionChecked&&(a._caption=this.plugins.resizing.create_caption.call(this),a._caption.setAttribute("contenteditable",!1),c.appendChild(a._caption)),a._element=r,a._cover=c,a._container=d,this.plugins.image.applySize.call(this,n,l),this.plugins.image.setAlign.call(this,s,r,c,d),this.insertComponent(d,!0),this.context.resizing._resize_plugin=""},update_image:function(e,t,i){const n=this.context.image,l=n._linkValue;let s,o=n._element,a=n._cover,r=n._container,c=!1;null===a&&(c=!0,o=n._element.cloneNode(!0),a=this.plugins.resizing.set_cover.call(this,o)),null===r&&(a=a.cloneNode(!0),c=!0,r=this.plugins.resizing.set_container.call(this,a,"se-image-container")),c&&(r.innerHTML="",r.appendChild(a));const d=this.util.isNumber(n.inputX.value)?n.inputX.value+n.sizeUnit:n.inputX.value,u=this.util.isNumber(n.inputY.value)?n.inputY.value+n.sizeUnit:n.inputY.value;if(s=/%$/.test(o.style.width)?d!==r.style.width||u!==r.style.height:d!==o.style.width||u!==o.style.height,o.alt=n._altText,n._captionChecked?n._caption||(n._caption=this.plugins.resizing.create_caption.call(this),a.appendChild(n._caption)):n._caption&&(this.util.removeItem(n._caption),n._caption=null),l.trim().length>0)if(null!==n._linkElement)n._linkElement.href=l,n._linkElement.target=n.imgLinkNewWindowCheck.checked?"_blank":"",o.setAttribute("data-image-link",l);else{let e=this.plugins.image.onRender_link.call(this,o,l,this.context.image.imgLinkNewWindowCheck.checked);a.insertBefore(e,n._caption)}else if(null!==n._linkElement){const e=o;e.setAttribute("data-image-link","");let t=e.cloneNode(!0);a.removeChild(n._linkElement),a.insertBefore(t,n._caption),o=t}if(c){const e=this.util.isRangeFormatElement(n._element.parentNode)||this.util.isWysiwygDiv(n._element.parentNode)?n._element:/^A$/i.test(n._element.parentNode.nodeName)?n._element.parentNode:this.util.getFormatElement(n._element)||n._element;e.parentNode.replaceChild(r,e),o=r.querySelector("img"),n._element=o,n._cover=a,n._container=r}!n._onlyPercentage&&s&&!e&&(/\d+/.test(o.style.height)||this.context.resizing._rotateVertical&&n._captionChecked)&&(/%$/.test(n.inputX.value)||/%$/.test(n.inputY.value)?this.plugins.resizing.resetTransform.call(this,o):this.plugins.resizing.setTransformSize.call(this,o,this.util.getNumber(n.inputX.value,0),this.util.getNumber(n.inputY.value,0)));if(n._resizing&&(o.setAttribute("data-proportion",n._proportionChecked),s&&this.plugins.image.applySize.call(this)),this.plugins.image.setAlign.call(this,null,o,null,null),e&&this.plugins.image.setImagesInfo.call(this,o,{name:o.getAttribute("data-file-name")||o.src.split("/").pop(),size:o.getAttribute("data-file-size")||0}),t){this.plugins.image.init.call(this);const e=this.plugins.resizing.call_controller_resize.call(this,o,"image");this.plugins.image.onModifyMode.call(this,o,e)}i||this.history.push(!1)},update_src:function(e,t,i){t.src=e,this._w.setTimeout(this.plugins.image.setImagesInfo.bind(this,t,i))},onModifyMode:function(e,t){if(!e)return;const i=this.context.image;i._linkElement=/^A$/i.test(e.parentNode.nodeName)?e.parentNode:null,i._element=e,i._cover=this.util.getParentElement(e,"FIGURE"),i._container=this.util.getParentElement(e,this.util.isMediaComponent),i._caption=this.util.getChildElement(i._cover,"FIGCAPTION"),i._align=e.getAttribute("data-align")||"none",t&&(i._element_w=t.w,i._element_h=t.h,i._element_t=t.t,i._element_l=t.l);let n=i._element.getAttribute("data-size")||i._element.getAttribute("data-origin");n?(n=n.split(","),i._origin_w=n[0],i._origin_h=n[1]):t&&(i._origin_w=t.w,i._origin_h=t.h)},openModify:function(e){const t=this.context.image;t.imgUrlFile.value=t._element.src,t._altText=t.altText.value=t._element.alt,t._linkValue=t.imgLink.value=null===t._linkElement?"":t._linkElement.href,t.imgLinkNewWindowCheck.checked=t._linkElement&&"_blank"===t._linkElement.target,t.modal.querySelector('input[name="suneditor_image_radio"][value="'+t._align+'"]').checked=!0,t._align=t.modal.querySelector('input[name="suneditor_image_radio"]:checked').value,t._captionChecked=t.captionCheckEl.checked=!!t._caption,t._resizing&&this.plugins.resizing._module_setModifyInputSize.call(this,t,this.plugins.image),e||this.plugins.dialog.open.call(this,"image",!0)},on:function(e){if(!e){const e=this.context.image;e.inputX.value=e._origin_w=this.context.option.imageWidth===e._defaultSizeX?"":this.context.option.imageWidth,e.inputY.value=e._origin_h="",e.inputY.disabled=!0,e.proportion.disabled=!0}},sizeRevert:function(){this.plugins.resizing._module_sizeRevert.call(this,this.context.image)},applySize:function(e,t){const i=this.context.image;return e||(e=i.inputX.value),t||(t=i.inputY.value),i._onlyPercentage&&e||/%$/.test(e)?(this.plugins.image.setPercentSize.call(this,e,t),!0):(e&&"auto"!==e||t&&"auto"!==t?this.plugins.image.setSize.call(this,e,t,!1):this.plugins.image.setAutoSize.call(this),!1)},setSize:function(e,t,i){const n=this.context.image;this.plugins.image.cancelPercentAttr.call(this),n._element.style.width=this.util.isNumber(e)?e+n.sizeUnit:e,n._element.style.height=this.util.isNumber(t)?t+n.sizeUnit:/%$/.test(t)?"":t,"center"===n._align&&this.plugins.image.setAlign.call(this,null,null,null,null),i||n._element.removeAttribute("data-percentage"),this.plugins.resizing._module_saveCurrentSize.call(this,n)},setAutoSize:function(){const e=this.context.image;this.plugins.resizing.resetTransform.call(this,e._element),this.plugins.image.cancelPercentAttr.call(this),e._element.style.maxWidth="",e._element.style.width="",e._element.style.height="",e._cover.style.width="",e._cover.style.height="",this.plugins.image.setAlign.call(this,null,null,null,null),e._element.setAttribute("data-percentage","auto,auto"),this.plugins.resizing._module_saveCurrentSize.call(this,e)},setOriginSize:function(){const e=this.context.image;e._element.removeAttribute("data-percentage"),this.plugins.resizing.resetTransform.call(this,e._element),this.plugins.image.cancelPercentAttr.call(this);const t=(e._element.getAttribute("data-origin")||"").split(","),i=t[0],n=t[1];t&&(e._onlyPercentage||/%$/.test(i)&&(/%$/.test(n)||!/\d/.test(n))?this.plugins.image.setPercentSize.call(this,i,n):this.plugins.image.setSize.call(this,i,n),this.plugins.resizing._module_saveCurrentSize.call(this,e))},setPercentSize:function(e,t){const i=this.context.image;t=!t||/%$/.test(t)||this.util.getNumber(t,0)?this.util.isNumber(t)?t+i.sizeUnit:t||"":this.util.isNumber(t)?t+"%":t;const n=/%$/.test(t);i._container.style.width=this.util.isNumber(e)?e+"%":e,i._container.style.height="",i._cover.style.width="100%",i._cover.style.height=n?t:"",i._element.style.width="100%",i._element.style.height=n?"":t,i._element.style.maxWidth="","center"===i._align&&this.plugins.image.setAlign.call(this,null,null,null,null),i._element.setAttribute("data-percentage",e+","+t),this.plugins.resizing.setCaptionPosition.call(this,i._element),this.plugins.resizing._module_saveCurrentSize.call(this,i)},cancelPercentAttr:function(){const e=this.context.image;e._cover.style.width="",e._cover.style.height="",e._container.style.width="",e._container.style.height="",this.util.removeClass(e._container,this.context.image._floatClassRegExp),this.util.addClass(e._container,"__se__float-"+e._align),"center"===e._align&&this.plugins.image.setAlign.call(this,null,null,null,null)},setAlign:function(e,t,i,n){const l=this.context.image;e||(e=l._align),t||(t=l._element),i||(i=l._cover),n||(n=l._container),i.style.margin=e&&"none"!==e?"auto":"0",/%$/.test(t.style.width)&&"center"===e?(n.style.minWidth="100%",i.style.width=n.style.width):(n.style.minWidth="",i.style.width=this.context.resizing._rotateVertical?t.style.height||t.offsetHeight:t.style.width&&"auto"!==t.style.width?t.style.width||"100%":""),this.util.hasClass(n,"__se__float-"+e)||(this.util.removeClass(n,l._floatClassRegExp),this.util.addClass(n,"__se__float-"+e)),t.setAttribute("data-align",e)},resetAlign:function(){const e=this.context.image;e._element.setAttribute("data-align",""),e._align="none",e._cover.style.margin="0",this.util.removeClass(e._container,e._floatClassRegExp)},destroy:function(e){const t=e||this.context.image._element,i=this.util.getParentElement(t,this.util.isMediaComponent)||t,n=1*t.getAttribute("data-index");let l=i.previousElementSibling||i.nextElementSibling;if(this.util.removeItem(i),this.plugins.image.init.call(this),this.controllersOff(),this.focusEdge(l),n>=0){const e=this._variable._imagesInfo;for(let t=0,i=e.length;t'+t.dialogBox.videoBox.title+'
    ';if(e.videoResizing){const i=e.videoRatioList||[{name:"16:9",value:.5625},{name:"4:3",value:.75},{name:"21:9",value:.4285}],l=e.videoRatio,s=e.videoSizeOnlyPercentage,o=s?' style="display: none !important;"':"",a=e.videoHeightShow?"":' style="display: none !important;"',r=e.videoRatioShow?"":' style="display: none !important;"',c=s||e.videoHeightShow||e.videoRatioShow?"":' style="display: none !important;"';n+='
    "}return n+='
    ",i.innerHTML=n,i},open:function(){this.plugins.dialog.open.call(this,"video","video"===this.currentControllerName)},setVideoRatio:function(e){const t=this.context.video,i=e.target.options[e.target.selectedIndex].value;t._defaultSizeY=t._videoRatio=i?100*i+"%":t._defaultSizeY,t.inputY.placeholder=i?100*i+"%":"",t.inputY.value=""},setInputSize:function(e,t){if(t&&32===t.keyCode)return void t.preventDefault();const i=this.context.video;this.plugins.resizing._module_setInputSize.call(this,i,e),"y"===e&&this.plugins.video.setVideoRatioSelect.call(this,t.target.value||i._videoRatio)},setRatio:function(){this.plugins.resizing._module_setRatio.call(this,this.context.video)},_onload_video:function(e){this.plugins.video.setVideosInfo.call(this,e)},submitAction:function(){if(0===this.context.video.focusElement.value.trim().length)return!1;this.context.resizing._resize_plugin="video";const e=this.context.video;let t=null,i=null,n=null,l=e.focusElement.value.trim();if(e._align=e.modal.querySelector('input[name="suneditor_video_radio"]:checked').value,/^$/.test(l))t=(new this._w.DOMParser).parseFromString(l,"text/html").querySelector("iframe");else{if(t=this.util.createElement("IFRAME"),/youtu\.?be/.test(l)&&(/^http/.test(l)||(l="https://"+l),l=l.replace("watch?v=",""),/^\/\/.+\/embed\//.test(l)||(l=l.replace(l.match(/\/\/.+\//)[0],"//www.youtube.com/embed/").replace("&","?&")),e._youtubeQuery.length>0))if(/\?/.test(l)){const t=l.split("?");l=t[0]+"?"+e._youtubeQuery+"&"+t[1]}else l+="?"+e._youtubeQuery;t.src=l}this.context.dialog.updateModal?(e._element.src!==t.src&&(e._element.src=t.src),n=e._container,i=this.util.getParentElement(e._element,"FIGURE"),t=e._element):(t.frameBorder="0",t.allowFullscreen=!0,t.addEventListener("load",this.plugins.video._onload_video.bind(this,t)),e._element=t,i=this.plugins.resizing.set_cover.call(this,t),n=this.plugins.resizing.set_container.call(this,i,"se-video-container"),this._variable._videosCnt++),e._cover=i,e._container=n;const s=this.plugins.resizing._module_getSizeX.call(this,e)!==(e.inputX.value||e._defaultSizeX)||this.plugins.resizing._module_getSizeY.call(this,e)!==(e.inputY.value||e._videoRatio),o=!this.context.dialog.updateModal||s;e._resizing&&(this.context.video._proportionChecked=e.proportion.checked,t.setAttribute("data-proportion",e._proportionChecked));let a=!1;o&&(a=this.plugins.video.applySize.call(this)),a&&"center"===e._align||this.plugins.video.setAlign.call(this,null,t,i,n),this.context.dialog.updateModal?e._resizing&&this.context.resizing._rotateVertical&&o&&this.plugins.resizing.setTransformSize.call(this,t,null,null):this.insertComponent(n,!1),this.context.resizing._resize_plugin="",this.context.dialog.updateModal&&this.history.push(!1)},setVideosInfo:function(e){if(!e.getAttribute("data-origin")){const t=this.util.getParentElement(e,this.util.isMediaComponent),i=this.util.getParentElement(e,"FIGURE"),n=this.plugins.resizing._module_getSizeX.call(this,this.context.video,e,i,t),l=this.plugins.resizing._module_getSizeY.call(this,this.context.video,e,i,t);e.setAttribute("data-origin",n+","+l),e.setAttribute("data-size",n+","+l)}},submit:function(e){this.showLoading(),e.preventDefault(),e.stopPropagation();try{this.plugins.video.submitAction.call(this)}finally{this.plugins.dialog.close.call(this),this.closeLoading()}return this.focus(),!1},_update_videoCover:function(e){if(!e)return;const t=this.context.video;e.frameBorder="0",e.allowFullscreen=!0,e.onload=e.addEventListener("load",this.plugins.video._onload_video.bind(this,e));const i=this.util.getParentElement(e,this.util.isMediaComponent)||this.util.getParentElement(e,function(e){return this.isWysiwygDiv(e.parentNode)}.bind(this.util));t._element=e=e.cloneNode(!1);const n=t._cover=this.plugins.resizing.set_cover.call(this,e),l=t._container=this.plugins.resizing.set_container.call(this,n,"se-video-container"),s=i.querySelector("figcaption");let o=null;s&&(o=this.util.createElement("DIV"),o.innerHTML=s.innerHTML,this.util.removeItem(s));const a=(e.getAttribute("data-size")||e.getAttribute("data-origin")||"").split(",");this.plugins.video.applySize.call(this,a[0]||this.context.option.videoWidth,a[1]||""),i.parentNode.replaceChild(l,i),o&&i.parentNode.insertBefore(o,l.nextElementSibling)},onModifyMode:function(e,t){const i=this.context.video;i._element=e,i._cover=this.util.getParentElement(e,"FIGURE"),i._container=this.util.getParentElement(e,this.util.isMediaComponent),i._align=e.getAttribute("data-align")||"none",i._element_w=t.w,i._element_h=t.h,i._element_t=t.t,i._element_l=t.l;let n=i._element.getAttribute("data-size")||i._element.getAttribute("data-origin");n?(n=n.split(","),i._origin_w=n[0],i._origin_h=n[1]):(i._origin_w=t.w,i._origin_h=t.h)},openModify:function(e){const t=this.context.video;if(t.focusElement.value=t._element.src,t.modal.querySelector('input[name="suneditor_video_radio"][value="'+t._align+'"]').checked=!0,t._resizing){this.plugins.resizing._module_setModifyInputSize.call(this,t,this.plugins.video);const e=t._videoRatio=this.plugins.resizing._module_getSizeY.call(this,t);this.plugins.video.setVideoRatioSelect.call(this,e)||(t.inputY.value=t._onlyPercentage?this.util.getNumber(e,2):e)}e||this.plugins.dialog.open.call(this,"video",!0)},on:function(e){if(!e){const e=this.context.video;e.inputX.value=e._origin_w=this.context.option.videoWidth===e._defaultSizeX?"":this.context.option.videoWidth,e.inputY.value=e._origin_h="",e.proportion.disabled=!0}},setVideoRatioSelect:function(e){let t=!1;const i=this.context.video,n=i.videoRatioOption.options;/%$/.test(e)||i._onlyPercentage?e=this.util.getNumber(e,2)/100+"":(!this.util.isNumber(e)||1*e>=1)&&(e=""),i.inputY.placeholder="";for(let l=0,s=n.length;l0||!i.style.width)&&t._update_videoCover.call(this,i);this.context.resizing._resize_plugin=""},sizeRevert:function(){this.plugins.resizing._module_sizeRevert.call(this,this.context.video)},applySize:function(e,t){const i=this.context.video;return e||(e=i.inputX.value),t||(t=i.inputY.value),i._onlyPercentage||/%$/.test(e)||!e?(this.plugins.video.setPercentSize.call(this,e||"100%",t||i._videoRatio),!0):(e&&"auto"!==e||t&&"auto"!==t?this.plugins.video.setSize.call(this,e,t||i._defaultRatio,!1):this.plugins.video.setAutoSize.call(this),!1)},setSize:function(e,t,i){const n=this.context.video;e=this.util.getNumber(e,0),t=this.util.isNumber(t)?t+n.sizeUnit:t||"",n._element.style.width=e?e+n.sizeUnit:"",n._cover.style.paddingBottom=n._cover.style.height=t,/%$/.test(t)?n._element.style.height="":n._element.style.height=t,i||n._element.removeAttribute("data-percentage"),this.plugins.resizing._module_saveCurrentSize.call(this,n)},setAutoSize:function(){this.plugins.video.setPercentSize.call(this,100,this.context.video._defaultRatio)},setOriginSize:function(e){const t=this.context.video;t._element.removeAttribute("data-percentage"),this.plugins.resizing.resetTransform.call(this,t._element),this.plugins.video.cancelPercentAttr.call(this);const i=((e?t._element.getAttribute("data-size"):"")||t._element.getAttribute("data-origin")||"").split(",");if(i){const e=i[0],n=i[1];t._onlyPercentage||/%$/.test(e)&&(/%$/.test(n)||!/\d/.test(n))?this.plugins.video.setPercentSize.call(this,e,n):this.plugins.video.setSize.call(this,e,n),this.plugins.resizing._module_saveCurrentSize.call(this,t)}},setPercentSize:function(e,t){const i=this.context.video;t=!t||/%$/.test(t)||this.util.getNumber(t,0)?this.util.isNumber(t)?t+i.sizeUnit:t||i._videoRatio:this.util.isNumber(t)?t+"%":t,i._container.style.width=this.util.isNumber(e)?e+"%":e,i._container.style.height="",i._cover.style.width="100%",i._cover.style.height=t,i._cover.style.paddingBottom=t,i._element.style.width="100%",i._element.style.height="100%",i._element.style.maxWidth="","center"===i._align&&this.plugins.video.setAlign.call(this,null,null,null,null),i._element.setAttribute("data-percentage",e+","+t),this.plugins.resizing._module_saveCurrentSize.call(this,i)},cancelPercentAttr:function(){const e=this.context.video;e._cover.style.width="",e._cover.style.height="",e._cover.style.paddingBottom="",e._container.style.width="",e._container.style.height="",this.util.removeClass(e._container,this.context.video._floatClassRegExp),this.util.addClass(e._container,"__se__float-"+e._align),"center"===e._align&&this.plugins.video.setAlign.call(this,null,null,null,null)},setAlign:function(e,t,i,n){const l=this.context.video;e||(e=l._align),t||(t=l._element),i||(i=l._cover),n||(n=l._container),i.style.margin=e&&"none"!==e?"auto":"0",/%$/.test(t.style.width)&&"center"===e?(n.style.minWidth="100%",i.style.width=n.style.width,i.style.height=i.style.paddingBottom,i.style.paddingBottom=this.util.getNumber(this.util.getNumber(i.style.paddingBottom,2)/100*this.util.getNumber(i.style.width,2),2)+"%"):(n.style.minWidth="",i.style.width=this.context.resizing._rotateVertical?t.style.height||t.offsetHeight:t.style.width||"100%",i.style.paddingBottom=i.style.height),this.util.hasClass(n,"__se__float-"+e)||(this.util.removeClass(n,l._floatClassRegExp),this.util.addClass(n,"__se__float-"+e)),t.setAttribute("data-align",e)},resetAlign:function(){const e=this.context.video;e._element.setAttribute("data-align",""),e._align="none",e._cover.style.margin="0",this.util.removeClass(e._container,e._floatClassRegExp)},destroy:function(){this._variable._videosCnt--;const e=this.context.video._container;let t=e.previousElementSibling||e.nextElementSibling;this.util.removeItem(e),this.plugins.video.init.call(this),this.controllersOff(),this.focusEdge(t),this.history.push(!1)},init:function(){const e=this.context.video;e.focusElement.value="",e._origin_w=this.context.option.videoWidth,e._origin_h="",e.modal.querySelector('input[name="suneditor_video_radio"][value="none"]').checked=!0,e._resizing&&(e.inputX.value=this.context.option.videoWidth===e._defaultSizeX?"":this.context.option.videoWidth,e.inputY.value="",e.proportion.checked=!0,e.proportion.disabled=!0,this.plugins.video.setVideoRatioSelect.call(this,e._defaultRatio))}},math:{name:"math",display:"dialog",add:function(e){e.addModule([l]);const t=e.context;t.math={focusElement:null,previewElement:null,fontSizeElement:null,_mathExp:null,_renderer:null};let i=this.setDialog.call(e);t.math.modal=i,t.math.focusElement=i.querySelector(".se-math-exp"),t.math.previewElement=i.querySelector(".se-math-preview"),t.math.fontSizeElement=i.querySelector(".se-math-size"),t.math._renderer=function(e){return this.src.renderToString(e,this.options)}.bind(e.context.option.katex),t.math.focusElement.addEventListener("keyup",this._renderMathExp.bind(t.math),!1),t.math.focusElement.addEventListener("change",this._renderMathExp.bind(t.math),!1),t.math.fontSizeElement.addEventListener("change",function(e){this.fontSize=e.target.value}.bind(t.math.previewElement.style),!1);let n=this.setController_MathButton.call(e);t.math.mathBtn=n,t.math._mathExp=null,n.addEventListener("mousedown",(function(e){e.stopPropagation()}),!1),i.querySelector(".se-btn-primary").addEventListener("click",this.submit.bind(e),!1),n.addEventListener("click",this.onClick_mathBtn.bind(e)),t.dialog.modal.appendChild(i),t.element.relative.appendChild(n),i=null,n=null},setDialog:function(){const e=this.lang,t=this.util.createElement("DIV");return t.className="se-dialog-content",t.style.display="none",t.innerHTML='
    '+e.dialogBox.mathBox.title+'

    ",t},setController_MathButton:function(){const e=this.lang,t=this.util.createElement("DIV");return t.className="se-controller se-controller-link",t.innerHTML='
    ",t},open:function(){this.plugins.dialog.open.call(this,"math","math"===this.currentControllerName)},_renderMathExp:function(e){this.previewElement.innerHTML=this._renderer(e.target.value)},submit:function(e){this.showLoading(),e.preventDefault(),e.stopPropagation();const t=function(){if(0===this.context.math.focusElement.value.trim().length)return!1;const e=this.context.math,t=e.focusElement.value,i=e.previewElement.querySelector(".katex");if(!i)return!1;if(i.setAttribute("contenteditable",!1),i.setAttribute("data-exp",t),i.setAttribute("data-font-size",e.fontSizeElement.value),i.style.fontSize=e.fontSizeElement.value,this.context.dialog.updateModal){const t=function(e,i){if(e.classList.contains(i))return e;const n=e.parentNode;return n!==document.body?n.classList.contains(i)?n:void t(n,i):void 0},n=t(e._mathExp,"katex");n.parentNode.replaceChild(i,n),this.setRange(i,0,i,1)}else{const e=this.getSelectedElements();if(e.length>1){const t=this.util.createElement(e[0].nodeName);t.appendChild(i),this.insertNode(t)}else this.insertNode(i);const t=this.util.createTextNode(this.util.zeroWidthSpace);i.parentNode.insertBefore(t,i.nextSibling),this.setRange(i,0,i,1)}return e.focusElement.value="",e.fontSizeElement.value="1em",e.previewElement.style.fontSize="1em",e.previewElement.innerHTML="",!0}.bind(this);try{t()&&(this.plugins.dialog.close.call(this),this.history.push(!1))}catch(e){this.plugins.dialog.close.call(this)}finally{this.closeLoading()}return!1},active:function(e){if(e){if(e.getAttribute("data-exp"))return this.controllerArray[0]!==this.context.math.mathBtn&&(this.setRange(e,0,e,1),this.plugins.math.call_controller_mathButton.call(this,e)),!0}else this.controllerArray[0]===this.context.math.mathBtn&&this.controllersOff();return!1},on:function(e){const t=this.context.math;if(t._mathExp&&e){const e=t._mathExp.getAttribute("data-exp"),i=t._mathExp.getAttribute("data-font-size")||"1em";this.context.dialog.updateModal=!0,t.focusElement.value=e,t.fontSizeElement.value=i,t.previewElement.innerHTML=t._renderer(e),t.previewElement.style.fontSize=i}},call_controller_mathButton:function(e){this.context.math._mathExp=e;const t=this.context.math.mathBtn,i=this.util.getOffset(e,this.context.element.wysiwygFrame);t.style.top=i.top+e.offsetHeight+10+"px",t.style.left=i.left-this.context.element.wysiwygFrame.scrollLeft+"px",t.style.display="block";const n=this.context.element.wysiwygFrame.offsetWidth-(t.offsetLeft+t.offsetWidth);n<0?(t.style.left=t.offsetLeft+n+"px",t.firstElementChild.style.left=20-n+"px"):t.firstElementChild.style.left="20px",this.controllersOn(t,this.plugins.math.init.bind(this),"math")},onClick_mathBtn:function(e){e.stopPropagation();const t=e.target.getAttribute("data-command")||e.target.parentNode.getAttribute("data-command");t&&(e.preventDefault(),/update/.test(t)?(this.context.math.focusElement.value=this.context.math._mathExp.getAttribute("data-exp"),this.plugins.dialog.open.call(this,"math",!0)):(this.util.removeItem(this.context.math._mathExp),this.context.math._mathExp=null,this.focus(),this.history.push(!1)),this.controllersOff())},init:function(){if(!/math/i.test(this.context.dialog.kind)){const e=this.context.math;e.mathBtn.style.display="none",e._mathExp=null,e.focusElement.value="",e.previewElement.innerHTML=""}}}},r=i("P6u4"),c=i.n(r);const d={_d:document,_w:window,_tagConvertor:function(e){const t={b:"strong",i:"em",u:"ins",strike:"del",s:"del"};return e.replace(/(<\/?)(b|strong|i|em|u|ins|s|strike|del)\b\s*(?:[^>^<]+)?\s*(?=>)/gi,(function(e,i,n){return i+("string"==typeof t[n]?t[n]:n)}))},_HTMLConvertor:function(e){const t={"&":"&"," ":" ","'":""","<":"<",">":">"};return e.replace(/&|\u00A0|'|<|>/g,(function(e){return"string"==typeof t[e]?t[e]:e}))},zeroWidthSpace:"​",zeroWidthRegExp:new RegExp(String.fromCharCode(8203),"g"),onlyZeroWidthRegExp:new RegExp("^"+String.fromCharCode(8203)+"+$"),onlyZeroWidthSpace:function(e){return"string"!=typeof e&&(e=e.textContent),""===e||this.onlyZeroWidthRegExp.test(e)},getXMLHttpRequest:function(){if(!this._w.ActiveXObject)return this._w.XMLHttpRequest?new XMLHttpRequest:null;try{return new ActiveXObject("Msxml2.XMLHTTP")}catch(e){try{return new ActiveXObject("Microsoft.XMLHTTP")}catch(e){return null}}},createElement:function(e){return this._d.createElement(e)},createTextNode:function(e){return this._d.createTextNode(e||"")},getIncludePath:function(e,t){let i="";const n=[],l="js"===t?"script":"link",s="js"===t?"src":"href";let o="(?:";for(let t=0,i=e.length;t0?n[0][s]:""),-1===i.indexOf(":/")&&"//"!==i.slice(0,2)&&(i=0===i.indexOf("/")?location.href.match(/^.*?:\/\/[^\/]*/)[0]+i:location.href.match(/^[^\?]*\/(?:)/)[0]+i),!i)throw"[SUNEDITOR.util.getIncludePath.fail] The SUNEDITOR installation path could not be automatically detected. (name: +"+name+", extension: "+t+")";return i},getPageStyle:function(e){let t="";const i=(e?this.getIframeDocument(e):this._d).styleSheets;for(let e,n=0,l=i.length;n-1||(n+=i[e].name+'="'+i[e].value+'" ');return n},isWysiwygDiv:function(e){return!(!e||1!==e.nodeType||!this.hasClass(e,"se-wrapper-wysiwyg")&&!/^BODY$/i.test(e.nodeName))},isFormatElement:function(e){return!(!e||1!==e.nodeType||!/^(P|DIV|H[1-6]|PRE|LI)$/i.test(e.nodeName)&&!this.hasClass(e,"(\\s|^)__se__format__replace_.+(\\s|$)|(\\s|^)__se__format__free_.+(\\s|$)")||this.isComponent(e)||this.isWysiwygDiv(e))},isRangeFormatElement:function(e){return!(!e||1!==e.nodeType||!/^(BLOCKQUOTE|OL|UL|FIGCAPTION|TABLE|THEAD|TBODY|TR|TH|TD)$/i.test(e.nodeName)&&!this.hasClass(e,"(\\s|^)__se__format__range_.+(\\s|$)"))},isFreeFormatElement:function(e){return!(!e||1!==e.nodeType||!/^PRE$/i.test(e.nodeName)&&!this.hasClass(e,"(\\s|^)__se__format__free_.+(\\s|$)")||this.isComponent(e)||this.isWysiwygDiv(e))},isComponent:function(e){return e&&(/se-component/.test(e.className)||/^(TABLE|HR)$/.test(e.nodeName))},isMediaComponent:function(e){return e&&/se-component/.test(e.className)},getFormatElement:function(e,t){if(!e)return null;for(t||(t=function(){return!0});e;){if(this.isWysiwygDiv(e))return null;if(this.isRangeFormatElement(e)&&e.firstElementChild,this.isFormatElement(e)&&t(e))return e;e=e.parentNode}return null},getRangeFormatElement:function(e,t){if(!e)return null;for(t||(t=function(){return!0});e;){if(this.isWysiwygDiv(e))return null;if(this.isRangeFormatElement(e)&&!/^(THEAD|TBODY|TR)$/i.test(e.nodeName)&&t(e))return e;e=e.parentNode}return null},getFreeFormatElement:function(e,t){if(!e)return null;for(t||(t=function(){return!0});e;){if(this.isWysiwygDiv(e))return null;if(this.isFreeFormatElement(e)&&t(e))return e;e=e.parentNode}return null},copyTagAttributes:function(e,t){t.style.cssText&&(e.style.cssText+=t.style.cssText);const i=t.classList;for(let t=0,n=i.length;t0&&!this.isBreak(e);)e=e.firstChild;for(;t&&1===t.nodeType&&t.childNodes.length>0&&!this.isBreak(t);)t=t.lastChild;return{sc:e,ec:t||e}}},getOffset:function(e,t){let i=0,n=0,l=3===e.nodeType?e.parentElement:e;const s=this.getParentElement(e,this.isWysiwygDiv.bind(this));for(;l&&!this.hasClass(l,"se-container")&&l!==s;)i+=l.offsetLeft,n+=l.offsetTop,l=l.offsetParent;const o=t&&/iframe/i.test(t.nodeName);return{left:i+(o?t.parentElement.offsetLeft:0),top:n-s.scrollTop+(o?t.parentElement.offsetTop:0)}},getOverlapRangeAtIndex:function(e,t,i,n){if(e<=n?ti)return 0;const l=(e>i?e:i)-(t0?" ":"")+t)},removeClass:function(e,t){if(!e)return;const i=new this._w.RegExp("(\\s|^)"+t+"(\\s|$)");e.className=e.className.replace(i," ").trim(),e.className.trim()||e.removeAttribute("class")},toggleClass:function(e,t){if(!e)return;const i=new this._w.RegExp("(\\s|^)"+t+"(\\s|$)");i.test(e.className)?e.className=e.className.replace(i," ").trim():e.className+=" "+t,e.className.trim()||e.removeAttribute("class")},removeItem:function(e){if(e)try{e.remove()}catch(t){e.parentNode.removeChild(e)}},removeItemAllParents:function(e,t,i){if(!e)return null;let n=null;return t||(t=function(e){if(e===i||this.isComponent(e))return!1;const t=e.textContent.trim();return 0===t.length||/^(\n|\u200B)+$/.test(t)}.bind(this)),function e(i){if(!d.isWysiwygDiv(i)){const l=i.parentNode;l&&t(i)&&(n={sc:i.previousElementSibling,ec:i.nextElementSibling},d.removeItem(i),e(l))}}(e),n},detachNestedList:function(e,t){const i=this.__deleteNestedList(e);let n,l,s;if(i){n=i.cloneNode(!1),l=i.childNodes;const t=this.getPositionIndex(e);for(;l[t];)n.appendChild(l[t])}else n=e;if(t)s=this.getListChildren(n,function(e){return this.isListCell(e)&&!e.previousElementSibling}.bind(this));else{const t=this.getElementDepth(e)+2;s=this.getListChildren(e,function(e){return this.isListCell(e)&&!e.previousElementSibling&&this.getElementDepth(e)===t}.bind(this))}for(let e=0,t=s.length;e=0){e.splitText(t);const i=this.getNodeFromPath([a+1],n);this.onlyZeroWidthSpace(i)&&(i.data=this.zeroWidthSpace)}}else 1===e.nodeType&&(e.previousSibling?e=e.previousSibling:this.getElementDepth(e)===i&&(r=!1));let c=e;for(;this.getElementDepth(c)>i;)for(a=this.getPositionIndex(c)+1,c=c.parentNode,o=l,l=c.cloneNode(!1),s=c.childNodes,o&&(this.isListCell(l)&&this.isList(o)&&o.firstElementChild&&(l.innerHTML=o.firstElementChild.innerHTML,d.removeItem(o.firstElementChild),o.children.length>0&&l.appendChild(o)),l.appendChild(o));s[a];)l.appendChild(s[a]);const u=c.parentNode;return r&&(c=c.nextSibling),l?(this.mergeSameTags(l,null,null,!1),this.mergeNestedTags(l,function(e){return this.isList(e)}.bind(this)),l.childNodes.length>0?u.insertBefore(l,c):l=c,0===n.childNodes.length&&this.removeItem(n),l):c},mergeSameTags:function(e,t,i,n){const l=this,s={a:0,b:0};return function e(o,a,r,c,d){const u=o.childNodes;for(let h,p,g=0,m=u.length;g0&&n++;const o=h.lastChild,u=p.firstChild;if(o&&u){const e=3===o.nodeType&&3===u.nodeType;let l=o.textContent.length,h=o.previousSibling;for(;h&&3===h.nodeType;)l+=h.textContent.length,h=h.previousSibling;n>0&&3===o.nodeType&&3===u.nodeType&&(o.textContent.length>0||u.textContent.length>0)&&n--,c&&t&&t[a]>g&&(a>0&&t[a-1]!==r?c=!1:(t[a]-=1,t[a+1]>=0&&t[a]===g&&(t[a+1]+=n,e&&o&&3===o.nodeType&&u&&3===u.nodeType&&(s.a+=l)))),d&&i&&i[a]>g&&(a>0&&i[a-1]!==r?d=!1:(i[a]-=1,i[a+1]>=0&&i[a]===g&&(i[a+1]+=n,e&&o&&3===o.nodeType&&u&&3===u.nodeType&&(s.b+=l))))}3===h.nodeType?h.textContent+=p.textContent:h.innerHTML+=p.innerHTML,l.removeItem(p),g--}else 1===h.nodeType&&e(h,a+1,g,c,d)}}(e,0,0,!0,!0),s},mergeNestedTags:function(e,t){"string"==typeof t?t=function(e){return this.test(e.tagName)}.bind(new this._w.RegExp("^("+(t||".+")+")$","i")):"function"!=typeof t&&(t=function(){return!0}),function e(i){let n=i.children;if(1===n.length&&n[0].nodeName===i.nodeName&&t(i)){const e=n[0];for(n=e.children;n[0];)i.appendChild(n[0]);i.removeChild(e)}for(let t=0,n=i.children.length;t")},sortByDepth:function(e,t){const i=t?1:-1,n=-1*i;e.sort(function(e,t){return this.isListCell(e)&&this.isListCell(t)?(e=this.getElementDepth(e))>(t=this.getElementDepth(t))?i:e'}return i}()+("auto"===e.height?"":"");l.allowFullscreen=!0,l.frameBorder=0,l.addEventListener("load",(function(){this.setAttribute("scrolling","auto"),this.contentDocument.head.innerHTML=''+t,this.contentDocument.body.className="sun-editor-editable",this.contentDocument.body.setAttribute("contenteditable",!0)}))}else l.setAttribute("contenteditable",!0),l.setAttribute("scrolling","auto"),l.className+=" sun-editor-editable";l.style.height=e.height,l.style.minHeight=e.minHeight,l.style.maxHeight=e.maxHeight;const s=document.createElement("TEXTAREA");s.className="se-wrapper-inner se-wrapper-code",s.style.display="none",s.style.height=e.height,s.style.minHeight=e.minHeight,s.style.maxHeight=e.maxHeight,"auto"===e.height&&(s.style.overflow="hidden");let o=null,a=null,r=null;if(e.resizingBar&&(o=document.createElement("DIV"),o.className="se-resizing-bar sun-editor-common",a=document.createElement("DIV"),a.className="se-navigation sun-editor-common",o.appendChild(a),e.charCounter)){const t=document.createElement("DIV");if(t.className="se-char-counter-wrapper",r=document.createElement("SPAN"),r.className="se-char-counter",r.textContent="0",t.appendChild(r),e.maxCharCount>0){const i=document.createElement("SPAN");i.textContent=" / "+e.maxCharCount,t.appendChild(i)}o.appendChild(t)}let c=null;return e.placeholder&&(c=document.createElement("SPAN"),c.className="se-placeholder",c.innerText=e.placeholder),{bottomBar:{resizingBar:o,navigation:a,charCounter:r},wysiwygFrame:l,codeView:s,placeholder:c}},_initOptions:function(e,t){t.lang=t.lang||c.a,t._defaultTagsWhitelist="string"==typeof t._defaultTagsWhitelist?t._defaultTagsWhitelist:"br|p|div|pre|blockquote|h[1-6]|ol|ul|li|hr|figure|figcaption|img|iframe|audio|video|table|thead|tbody|tr|th|td|a|b|strong|var|i|em|u|ins|s|span|strike|del|sub|sup",t._editorTagsWhitelist=t._defaultTagsWhitelist+("string"==typeof t.addTagsWhitelist&&t.addTagsWhitelist.length>0?"|"+t.addTagsWhitelist:""),t.pasteTagsWhitelist="string"==typeof t.pasteTagsWhitelist?t.pasteTagsWhitelist:t._editorTagsWhitelist,t.attributesWhitelist=t.attributesWhitelist&&"object"==typeof t.attributesWhitelist?t.attributesWhitelist:null,t.mode=t.mode||"classic",t.toolbarWidth=t.toolbarWidth?u.isNumber(t.toolbarWidth)?t.toolbarWidth+"px":t.toolbarWidth:"auto",t.stickyToolbar=/balloon/i.test(t.mode)?-1:void 0===t.stickyToolbar?0:/^\d+/.test(t.stickyToolbar)?u.getNumber(t.stickyToolbar,0):-1,t.iframe=t.fullPage||t.iframe,t.iframeCSSFileName=t.iframe?"string"==typeof t.iframeCSSFileName?[t.iframeCSSFileName]:t.iframeCSSFileName||["suneditor"]:null,t.codeMirror=t.codeMirror?t.codeMirror.src?t.codeMirror:{src:t.codeMirror}:null,t.display=t.display||("none"!==e.style.display&&e.style.display?e.style.display:"block"),t.popupDisplay=t.popupDisplay||"full",t.resizingBar=void 0===t.resizingBar?!/inline|balloon/i.test(t.mode):t.resizingBar,t.showPathLabel=!!t.resizingBar&&("boolean"!=typeof t.showPathLabel||t.showPathLabel),t.charCounter=t.maxCharCount>0||"boolean"==typeof t.charCounter&&t.charCounter,t.maxCharCount=u.isNumber(t.maxCharCount)&&t.maxCharCount>-1?1*t.maxCharCount:null,t.width=t.width?u.isNumber(t.width)?t.width+"px":t.width:e.clientWidth?e.clientWidth+"px":"100%",t.minWidth=(u.isNumber(t.minWidth)?t.minWidth+"px":t.minWidth)||"",t.maxWidth=(u.isNumber(t.maxWidth)?t.maxWidth+"px":t.maxWidth)||"",t.height=t.height?u.isNumber(t.height)?t.height+"px":t.height:e.clientHeight?e.clientHeight+"px":"auto",t.minHeight=(u.isNumber(t.minHeight)?t.minHeight+"px":t.minHeight)||"",t.maxHeight=(u.isNumber(t.maxHeight)?t.maxHeight+"px":t.maxHeight)||"",t.font=t.font?t.font:null,t.fontSize=t.fontSize?t.fontSize:null,t.formats=t.formats?t.formats:null,t.colorList=t.colorList?t.colorList:null,t.lineHeights=t.lineHeights?t.lineHeights:null,t.paragraphStyles=t.paragraphStyles?t.paragraphStyles:null,t.textStyles=t.textStyles?t.textStyles:null,t.fontSizeUnit="string"==typeof t.fontSizeUnit&&t.fontSizeUnit.trim()||"px",t.imageResizing=void 0===t.imageResizing||t.imageResizing,t.imageHeightShow=void 0===t.imageHeightShow||!!t.imageHeightShow,t.imageWidth=t.imageWidth?u.isNumber(t.imageWidth)?t.imageWidth+"px":t.imageWidth:"auto",t.imageSizeOnlyPercentage=!!t.imageSizeOnlyPercentage,t._imageSizeUnit=t.imageSizeOnlyPercentage?"%":"px",t.imageRotation=void 0!==t.imageRotation?t.imageRotation:!(t.imageSizeOnlyPercentage||!t.imageHeightShow),t.imageFileInput=void 0===t.imageFileInput||t.imageFileInput,t.imageUrlInput=void 0===t.imageUrlInput||!t.imageFileInput||t.imageUrlInput,t.imageUploadHeader=t.imageUploadHeader||null,t.imageUploadUrl=t.imageUploadUrl||null,t.imageUploadSizeLimit=/\d+/.test(t.imageUploadSizeLimit)?u.getNumber(t.imageUploadSizeLimit,0):null,t.videoResizing=void 0===t.videoResizing||t.videoResizing,t.videoHeightShow=void 0===t.videoHeightShow||!!t.videoHeightShow,t.videoRatioShow=void 0===t.videoRatioShow||!!t.videoRatioShow,t.videoWidth=t.videoWidth&&u.getNumber(t.videoWidth)?u.isNumber(t.videoWidth)?t.videoWidth+"px":t.videoWidth:"100%",t.videoSizeOnlyPercentage=!!t.videoSizeOnlyPercentage,t._videoSizeUnit=t.videoSizeOnlyPercentage?"%":"px",t.videoRotation=void 0!==t.videoRotation?t.videoRotation:!(t.videoSizeOnlyPercentage||!t.videoHeightShow),t.videoRatio=u.getNumber(t.videoRatio,4)||.5625,t.videoRatioList=t.videoRatioList?t.videoRatioList:null,t.youtubeQuery=(t.youtubeQuery||"").replace("?",""),t.callBackSave=t.callBackSave?t.callBackSave:null,t.templates=t.templates?t.templates:null,t.placeholder="string"==typeof t.placeholder?t.placeholder:null,t.katex=t.katex?t.katex.src?t.katex:{src:t.katex}:null,t.buttonList=t.buttonList||[["undo","redo"],["bold","underline","italic","strike","subscript","superscript"],["removeFormat"],["outdent","indent"],["fullScreen","showBlocks","codeView"],["preview","print"]]},_defaultButtons:function(e){return{bold:["_se_command_bold",e.toolbar.bold+" (CTRL+B)","STRONG","",''],underline:["_se_command_underline",e.toolbar.underline+" (CTRL+U)","INS","",''],italic:["_se_command_italic",e.toolbar.italic+" (CTRL+I)","EM","",''],strike:["_se_command_strike",e.toolbar.strike+" (CTRL+SHIFT+S)","DEL","",''],subscript:["_se_command_subscript",e.toolbar.subscript,"SUB","",''],superscript:["_se_command_superscript",e.toolbar.superscript,"SUP","",''],removeFormat:["",e.toolbar.removeFormat,"removeFormat","",''],indent:["_se_command_indent",e.toolbar.indent+" (CTRL+])","indent","",''],outdent:["_se_command_outdent",e.toolbar.outdent+" (CTRL+[)","outdent","",'',!0],fullScreen:["code-view-enabled",e.toolbar.fullScreen,"fullScreen","",''],showBlocks:["",e.toolbar.showBlocks,"showBlocks","",''],codeView:["code-view-enabled",e.toolbar.codeView,"codeView","",''],undo:["_se_command_undo",e.toolbar.undo+" (CTRL+Z)","undo","",'',!0],redo:["_se_command_redo",e.toolbar.redo+" (CTRL+Y / CTRL+SHIFT+Z)","redo","",'',!0],preview:["",e.toolbar.preview,"preview","",''],print:["",e.toolbar.print,"print","",''],save:["_se_command_save",e.toolbar.save,"save","",'',!0],blockquote:["",e.toolbar.tag_blockquote,"blockquote","command",''],font:["se-btn-select se-btn-tool-font",e.toolbar.font,"font","submenu",''+e.toolbar.font+''],formatBlock:["se-btn-select se-btn-tool-format",e.toolbar.formats,"formatBlock","submenu",''+e.toolbar.formats+''],fontSize:["se-btn-select se-btn-tool-size",e.toolbar.fontSize,"fontSize","submenu",''+e.toolbar.fontSize+''],fontColor:["",e.toolbar.fontColor,"fontColor","submenu",''],hiliteColor:["",e.toolbar.hiliteColor,"hiliteColor","submenu",''],align:["se-btn-align",e.toolbar.align,"align","submenu",''],list:["",e.toolbar.list,"list","submenu",''],horizontalRule:["btn_line",e.toolbar.horizontalRule,"horizontalRule","submenu",''],table:["",e.toolbar.table,"table","submenu",''],lineHeight:["",e.toolbar.lineHeight,"lineHeight","submenu",''],template:["",e.toolbar.template,"template","submenu",''],paragraphStyle:["",e.toolbar.paragraphStyle,"paragraphStyle","submenu",''],textStyle:["",e.toolbar.textStyle,"textStyle","submenu",''],link:["",e.toolbar.link,"link","dialog",''],image:["",e.toolbar.image,"image","dialog",''],video:["",e.toolbar.video,"video","dialog",''],math:["",e.toolbar.math,"math","dialog",'']}},_createModuleGroup:function(e){const t=u.createElement("DIV");t.className="se-btn-module"+(e?"":" se-btn-module-border");const i=u.createElement("UL");return i.className="se-menu-list",t.appendChild(i),{div:t,ul:i}},_createButton:function(e,t,i,n,l,s){const o=u.createElement("LI"),a=u.createElement("BUTTON");return a.setAttribute("type","button"),a.setAttribute("class","se-btn"+(e?" "+e:"")+" se-tooltip"),a.setAttribute("data-command",i),a.setAttribute("data-display",n),l+=''+t+"",s&&a.setAttribute("disabled",!0),a.innerHTML=l,o.appendChild(a),{li:o,button:a}},_createToolBar:function(e,t,i,n){const l=e.createElement("DIV");l.className="se-toolbar-separator-vertical";const s=e.createElement("DIV");s.className="se-toolbar sun-editor-common";const o=this._defaultButtons(n),a={},r={};if(i){const e=i.length?i:Object.keys(i).map((function(e){return i[e]}));for(let t,i=0,n=e.length;i0){for(let e=0;e":i),this.history.push(!0)},_nativeFocus:function(){const t=r.getParentElement(this.getSelectionNode(),"figcaption");t?t.focus():e.element.wysiwyg.focus(),this._editorRange()},focus:function(){if("none"!==e.element.wysiwygFrame.style.display){if(l.iframe)this._nativeFocus();else try{const e=this.getRange();this.setRange(e.startContainer,e.startOffset,e.endContainer,e.endOffset)}catch(e){this._nativeFocus()}d._applyTagEffects(),c._isBalloon&&d._toggleToolbarBalloon()}},focusEdge:function(e){if(r.isComponent(e)){const t=e.querySelector("IMG"),i=e.querySelector("IFRAME");t?this.selectComponent(t,"image"):i&&this.selectComponent(i,"video")}else e=r.getChildElement(e,(function(e){return 0===e.childNodes.length||3===e.nodeType}),!0),this.setRange(e,e.textContent.length,e,e.textContent.length)},setRange:function(e,t,i,n){if(!e||!i)return;t>e.textContent.length&&(t=e.textContent.length),n>i.textContent.length&&(n=i.textContent.length);const l=this._wd.createRange();l.setStart(e,t),l.setEnd(i,n);const s=this.getSelection();s.removeAllRanges&&s.removeAllRanges(),s.addRange(l),this._editorRange()},removeRange:function(){this.getSelection().removeAllRanges();const e=this.commandMap;r.removeClass(e.STRONG,"active"),r.removeClass(e.INS,"active"),r.removeClass(e.EM,"active"),r.removeClass(e.DEL,"active"),r.removeClass(e.SUB,"active"),r.removeClass(e.SUP,"active"),e.OUTDENT&&e.OUTDENT.setAttribute("disabled",!0),e.INDENT&&e.INDENT.removeAttribute("disabled")},getRange:function(){return this._variable._range||this._createDefaultRange()},getSelection:function(){return this._ww.getSelection()},getSelectionNode:function(){return this._variable._selectionNode&&!r.isWysiwygDiv(this._variable._selectionNode)||this._editorRange(),this._variable._selectionNode||e.element.wysiwyg.firstChild},_editorRange:function(){const e=this.getSelection();let t=null,i=null;t=e.rangeCount>0?e.getRangeAt(0):this._createDefaultRange(),this._variable._range=t,i=t.collapsed?t.commonAncestorContainer:e.extentNode||e.anchorNode,this._variable._selectionNode=i},_createDefaultRange:function(){e.element.wysiwyg.focus();const t=this._wd.createRange();return e.element.wysiwyg.firstChild||this.execCommand("formatBlock",!1,"P"),t.setStart(e.element.wysiwyg.firstChild,0),t.setEnd(e.element.wysiwyg.firstChild,0),t},_resetRangeToTextNode:function(){const t=this.getRange();let i,n,l,s=t.startContainer,o=t.startOffset,a=t.endContainer,c=t.endOffset;if(i=r.isWysiwygDiv(s)?e.element.wysiwyg.firstChild:s,n=o,r.isBreak(i)||1===i.nodeType&&i.childNodes.length>0){const e=r.isBreak(i);if(!e){for(;i&&!r.isBreak(i)&&1===i.nodeType;)i=i.childNodes[n]||i.nextElementSibling||i.nextSibling,n=0;let e=r.getFormatElement(i);e===r.getRangeFormatElement(e)&&(e=r.createElement(r.isCell(i)?"DIV":"P"),i.parentNode.insertBefore(e,i),e.appendChild(i))}if(r.isBreak(i)){const t=r.createTextNode(r.zeroWidthSpace);i.parentNode.insertBefore(t,i),i=t,e&&(s===a&&(a=i,c=1),r.removeItem(s))}}if(s=i,o=n,i=r.isWysiwygDiv(a)?e.element.wysiwyg.lastChild:a,n=c,r.isBreak(i)||1===i.nodeType&&i.childNodes.length>0){const e=r.isBreak(i);if(!e){for(;i&&!r.isBreak(i)&&1===i.nodeType&&(l=i.childNodes,0!==l.length);)i=l[n>0?n-1:n]||!/FIGURE/i.test(l[0].nodeName)?l[0]:i.previousElementSibling||i.previousSibling||s,n=n>0?i.textContent.length:n;let e=r.getFormatElement(i);e===r.getRangeFormatElement(e)&&(e=r.createElement(r.isCell(e)?"DIV":"P"),i.parentNode.insertBefore(e,i),e.appendChild(i))}if(r.isBreak(i)){const t=r.createTextNode(r.zeroWidthSpace);i.parentNode.insertBefore(t,i),i=t,n=1,e&&r.removeItem(a)}}a=i,c=n,this.setRange(s,o,a,c)},getSelectedElements:function(t){this._resetRangeToTextNode();let i=this.getRange();if(r.isWysiwygDiv(i.startContainer)){const t=e.element.wysiwyg.children;if(0===t.length)return null;this.setRange(t[0],0,t[t.length-1],t[t.length-1].textContent.trim().length),i=this.getRange()}const n=i.startContainer,l=i.endContainer,s=i.commonAncestorContainer,o=r.getListChildren(s,(function(e){return t?t(e):r.isFormatElement(e)}));if(r.isWysiwygDiv(s)||r.isRangeFormatElement(s)||o.unshift(r.getFormatElement(s)),n===l||1===o.length)return o;let a=r.getFormatElement(n),c=r.getFormatElement(l),d=null,u=null;const h=function(e){return!r.isTable(e)||/^TABLE$/i.test(e.nodeName)};let p=r.getRangeFormatElement(a,h),g=r.getRangeFormatElement(c,h);r.isTable(p)&&r.isListCell(p.parentNode)&&(p=p.parentNode),r.isTable(g)&&r.isListCell(g.parentNode)&&(g=g.parentNode);const m=p===g;for(let e,t=0,i=o.length;t=0;i--)if(n[i].contains(n[e])){n.splice(e,1),e--,t--;break}return n},isEdgePoint:function(e,t){return 0===t||!e.nodeValue&&1===t||t===e.nodeValue.length},showLoading:function(){e.element.loading.style.display="block"},closeLoading:function(){e.element.loading.style.display="none"},appendFormatTag:function(e,t){const i=r.getFormatElement(this.getSelectionNode()),n=t?"string"==typeof t?t:t.nodeName:r.isFormatElement(i)?i.nodeName:"P",l=r.createElement(n);return l.innerHTML="
    ",(t&&"string"!=typeof t||!t&&r.isFormatElement(i))&&r.copyTagAttributes(l,t||i),r.isCell(e)?e.insertBefore(l,e.nextElementSibling):e.parentNode.insertBefore(l,e.nextElementSibling),l},insertComponent:function(e,t){const i=this.removeNode();let n=null,l=this.getSelectionNode(),s=r.getFormatElement(l);if(r.isListCell(s))if(/^HR$/i.test(e.nodeName)){const t=r.createElement("LI"),i=r.createTextNode(r.zeroWidthSpace);t.appendChild(e),t.appendChild(i),s.parentNode.insertBefore(t,s.nextElementSibling),this.setRange(i,1,i,1)}else this.insertNode(e,l===s?null:i.container.nextSibling),e.nextSibling||e.parentNode.appendChild(r.createElement("BR")),n=r.createElement("LI"),s.parentNode.insertBefore(n,s.nextElementSibling);else{if(this.getRange().collapsed&&(3===i.container.nodeType||r.isBreak(i.container))){const e=r.getParentElement(i.container,function(e){return this.isRangeFormatElement(e)}.bind(r));n=r.splitElement(i.container,i.offset,e?r.getElementDepth(e)+1:0),n&&(s=n.previousSibling)}this.insertNode(e,s),n||(n=this.appendFormatTag(e,r.isFormatElement(s)?s:null))}return this.setRange(n,0,n,0),t||this.history.push(!1),n},selectComponent:function(e,t){if("image"===t){if(!c.plugins.image)return;c.removeRange(),c.callPlugin("image",(function(){const t=c.plugins.resizing.call_controller_resize.call(c,e,"image");c.plugins.image.onModifyMode.call(c,e,t),r.getParentElement(e,".se-image-container")||(c.plugins.image.openModify.call(c,!0),c.plugins.image.update_image.call(c,!0,!0,!0))}))}else if("video"===t){if(!c.plugins.video)return;c.removeRange(),c.callPlugin("video",(function(){const t=c.plugins.resizing.call_controller_resize.call(c,e,"video");c.plugins.video.onModifyMode.call(c,e,t)}))}},insertNode:function(e,t){const i=this.getRange();let n=null,l=null;if(t)n=t.parentNode,t=t.nextSibling,l=!0;else{const e=i.startContainer,l=i.startOffset,s=i.endContainer,o=i.endOffset,a=i.commonAncestorContainer;if(n=e,3===e.nodeType&&(n=e.parentNode),i.collapsed)if(3===a.nodeType)t=a.textContent.length>o?a.splitText(o):a.nextSibling;else if(r.isBreak(n))t=n,n=n.parentNode;else{const e=n.childNodes[l];e?e.nextSibling?t=r.isBreak(e)?e:e.nextSibling:(n.removeChild(e),t=null):t=null}else{if(e===s){t=this.isEdgePoint(s,o)?s.nextSibling:s.splitText(o);let i=e;this.isEdgePoint(e,l)||(i=e.splitText(l)),n.removeChild(i)}else for(this.removeNode(),n=a,t=s;t.parentNode!==a;)t=t.parentNode}}try{if(r.isFormatElement(e)||r.isRangeFormatElement(e)||!r.isListCell(n)&&r.isComponent(e))if(r.isList(t))n=t,t=null;else if(!l&&!t){const e=this.removeNode(),i=3===e.container.nodeType?r.isListCell(r.getFormatElement(e.container))?e.container:r.getFormatElement(e.container)||e.container.parentNode:e.container;n=i.parentNode,t=i.nextSibling}n.insertBefore(e,t)}catch(t){n.appendChild(e)}finally{if(3===e.nodeType){const t=e.previousSibling,i=e.nextSibling,n=!t||3!==t.nodeType||r.onlyZeroWidthSpace(t)?"":t.textContent,l=!i||3!==i.nodeType||r.onlyZeroWidthSpace(i)?"":i.textContent;return t&&n.length>0&&(e.textContent=n+e.textContent,r.removeItem(t)),i&&i.length>0&&(e.textContent+=l,r.removeItem(i)),{startOffset:n.length,endOffset:e.textContent.length-l.length}}this.setRange(e,1,e,1),this.history.push(!0)}},removeNode:function(){const e=this.getRange();let t,i=0,n=e.startContainer,l=e.endContainer;const s=e.startOffset,o=e.endOffset,a=e.commonAncestorContainer;let c=null,d=null;const u=r.getListChildNodes(a);let h=r.getArrayIndex(u,n),p=r.getArrayIndex(u,l);if(u.length>0&&h>-1&&p>-1){for(let e=h+1,t=n;e>=0;e--)u[e]===t.parentNode&&u[e].firstChild===t&&0===s&&(h=e,t=t.parentNode);for(let e=p-1,t=l;e>h;e--)u[e]===t.parentNode&&1===u[e].nodeType&&(u.splice(e,1),t=t.parentNode,--p)}else{if(0===u.length)u.push(a),n=l=a;else if(n=l=u[0],r.isBreak(n))return{container:n,offset:0};h=p=0}function g(e){const t=r.getFormatElement(e);if(r.removeItem(e),r.isListCell(t)){const e=r.getArrayItem(t.children,r.isList,!1);if(e){const i=e.firstElementChild,n=i.childNodes;for(;n[0];)t.insertBefore(n[0],e);r.removeItemAllParents(i)}}}for(let e=h;e<=p;e++){const t=u[e];if(0===t.length||3===t.nodeType&&void 0===t.data)g(t);else if(t!==n)t!==l?g(t):(d=1===l.nodeType?r.createTextNode(l.textContent):r.createTextNode(l.substringData(o,l.length-o)),d.length>0?l.data=d.data:g(l));else if(1===n.nodeType?c=r.createTextNode(n.textContent):t===l?(c=r.createTextNode(n.substringData(0,s)+l.substringData(o,l.length-o)),i=s):c=r.createTextNode(n.substringData(0,s)),c.length>0?n.data=c.data:g(n),t===l)break}return t=l&&l.parentNode?l:n&&n.parentNode?n:e.endContainer||e.startContainer,this.setRange(t,i,t,i),this.history.push(!0),{container:t,offset:i}},applyRangeFormatElement:function(e){const t=this.getSelectedElementsAndComponents(!1);if(!t||0===t.length)return;e:for(let e,i,n,l,s,o,a=0,c=t.length;a-1&&(l=i.lastElementChild,t.indexOf(l)>-1)){let e=null;for(;e=l.lastElementChild;)if(r.isList(e)){if(!(t.indexOf(e.lastElementChild)>-1))continue e;l=e.lastElementChild}n=i.firstElementChild,s=t.indexOf(n),o=t.indexOf(l),t.splice(s,o-s+1),c=t.length}else;let i,n,l,s=t[t.length-1];i=r.isRangeFormatElement(s)||r.isFormatElement(s)?s:r.getRangeFormatElement(s)||r.getFormatElement(s),r.isCell(i)?(n=null,l=i):(n=i.nextSibling,l=i.parentNode);let o=r.getElementDepth(i),a=null;const c=[],d=function(e,t,i){let n=null;if(e!==t&&!r.isTable(t)){if(t&&r.getElementDepth(e)===r.getElementDepth(t))return i;n=r.removeItemAllParents(t,null,e)}return n?n.ec:i};for(let i,s,u,h,p,g,m,f=0,_=t.length;f<_;f++)if(i=t[f],s=i.parentNode,s&&!e.contains(s))if(u=r.getElementDepth(i),r.isList(s)){if(null===a&&(g?(a=g,m=!0,g=null):a=s.cloneNode(!1)),c.push(i),p=t[f+1],f===_-1||p&&p.parentNode!==s){p&&i.contains(p.parentNode)&&(g=p.parentNode.cloneNode(!1));let t,f=s.parentNode;for(;r.isList(f);)t=r.createElement(f.nodeName),t.appendChild(a),a=t,f=f.parentNode;const _=this.detachRangeFormatElement(s,c,null,!0,!0);o>=u?(o=u,l=_.cc,n=d(l,s,_.ec),n&&(l=n.parentNode)):l===_.cc&&(n=_.ec),l!==_.cc&&(h=d(l,_.cc,h),n=void 0!==h?h:_.cc);for(let e=0,t=_.removeArray.length;e=u&&(o=u,l=s,n=i.nextSibling),e.appendChild(i),l!==s&&(h=d(l,s),void 0!==h&&(n=h));if(this._lastEffectNode=null,r.mergeSameTags(e,null,null,!1),r.mergeNestedTags(e,function(e){return this.isList(e)}.bind(r)),n&&r.getElementDepth(n)>0&&(r.isList(n.parentNode)||r.isList(n.parentNode.parentNode))){const t=r.getParentElement(n,function(e){return this.isRangeFormatElement(e)&&!this.isList(e)}.bind(r)),i=r.splitElement(n,null,t?r.getElementDepth(t)+1:0);i.parentNode.insertBefore(e,i)}else l.insertBefore(e,n),d(e,n);const u=r.getEdgeChildNodes(e.firstElementChild,e.lastElementChild);t.length>1?this.setRange(u.sc,0,u.ec,u.ec.textContent.length):this.setRange(u.ec,u.ec.textContent.length,u.ec,u.ec.textContent.length),this.history.push(!1)},detachRangeFormatElement:function(e,t,i,n,l){const s=this.getRange(),o=s.startOffset,a=s.endOffset;let c=r.getListChildNodes(e,(function(t){return t.parentNode===e})),d=e.parentNode,u=null,h=null,p=e.cloneNode(!1);const g=[],m=r.isList(i);let f=!1,_=!1,b=!1;function y(t,i,n,l){if(r.onlyZeroWidthSpace(i)&&(i.innerHTML=r.zeroWidthSpace),3===i.nodeType)return t.insertBefore(i,n),i;const s=(b?i:l).childNodes;let o=i.cloneNode(!1),a=null,c=null;for(;s[0];)c=s[0],!r._notTextNode(c)||r.isBreak(c)||r.isListCell(o)?o.appendChild(c):(o.childNodes.length>0&&(a||(a=o),t.insertBefore(o,n),o=i.cloneNode(!1)),t.insertBefore(c,n),a||(a=c));if(o.childNodes.length>0){if(r.isListCell(t)&&r.isListCell(o)&&r.isList(n))if(m){for(a=n;n;)o.appendChild(n),n=n.nextSibling;t.parentNode.insertBefore(o,t.nextElementSibling)}else{const t=l.nextElementSibling,i=r.detachNestedList(l,!1);e===i&&t===l.nextElementSibling||(e=i,_=!0)}else t.insertBefore(o,n);a||(a=o)}return a}for(let l,s,o,a=0,v=c.length;a0&&(d.insertBefore(p,e),p=null),!m&&r.isListCell(l))if(r.getElementDepth(l)!==r.getElementDepth(o)&&(r.isListCell(d)||r.getArrayItem(l.children,r.isList,!1))){const t=l.nextElementSibling,i=r.detachNestedList(l,!1);e===i&&t===l.nextElementSibling||(e=i,_=!0)}else{const t=l;l=r.createElement(n?t.nodeName:r.isList(e.parentNode)||r.isListCell(e.parentNode)?"LI":r.isCell(e.parentNode)?"DIV":"P");const i=t.childNodes;for(;i[0];)l.appendChild(i[0]);r.copyFormatAttributes(l,t),b=!0}else l=l.cloneNode(!1);if(_){_=b=!1,c=r.getListChildNodes(e,(function(t){return t.parentNode===e})),p=e.cloneNode(!1),d=e.parentNode,a=-1,v=c.length;continue}n?(g.push(l),r.removeItem(c[a])):(i?(f||(d.insertBefore(i,e),f=!0),l=y(i,l,null,c[a])):l=y(d,l,e,c[a]),t?(h=l,u||(u=l)):u||(u=h=l))}const v=e.parentNode;let x=e.nextSibling;p&&p.children.length>0&&v.insertBefore(p,x),i?u=i.previousSibling:u||(u=e.previousSibling),x=e.nextSibling,r.removeItem(e);let C=null;if(n)C={cc:v,sc:u,ec:x,removeArray:g};else{const e=r.getEdgeChildNodes(u,h&&h.parentNode?h:u);C={cc:(e.sc||e.ec).parentNode,sc:e.sc,ec:e.ec}}if(this._lastEffectNode=null,l)return C;!n&&C&&(t?this.setRange(C.sc,o,C.ec,a):this.setRange(C.sc,0,C.sc,0)),this.history.push(!1)},detachList:function(e,t){let i={},n=!1,l=!1,s=null,o=null;const a=function(e){return!this.isComponent(e)}.bind(r);for(let c,d,u,h,p=0,g=e.length;p0)&&t,i=!!(i&&i.length>0)&&i;const s=!e,o=s&&!i&&!t;let c=l.startContainer,d=l.startOffset,u=l.endContainer,h=l.endOffset;if(o&&l.collapsed&&r.isFormatElement(c.parentNode)&&r.isFormatElement(u.parentNode)||c===u&&1===c.nodeType&&"false"===c.getAttribute("contenteditable"))return;if(l.collapsed&&!o&&1===c.nodeType&&!r.isBreak(c)){let e=null;const t=c.childNodes[d];t&&(t.nextSibling?e=r.isBreak(t)?t:t.nextSibling:(c.removeChild(t),e=null));const i=r.createTextNode(r.zeroWidthSpace);c.insertBefore(i,e),this.setRange(i,1,i,1),l=this.getRange(),c=l.startContainer,d=l.startOffset,u=l.endContainer,h=l.endOffset}r.isFormatElement(c)&&(c=c.childNodes[d],d=0),r.isFormatElement(u)&&(u=u.childNodes[h],h=u.textContent.length),s&&(e=r.createElement("DIV"));const p=e.nodeName;if(!o&&c===u&&!i&&e){let t=c,i=0;const n=[],l=e.style;for(let e=0,t=l.length;e0){for(;!r.isFormatElement(t)&&!r.isWysiwygDiv(t);){for(let l=0;l=n.length)return}}let g,m={},f={},_="",b="",y="";if(t){for(let e,i=0,n=t.length;i0&&(c=l.replace(_,"").trim(),c!==l&&(v.v=!0));const d=t.className;let u="";return b&&d.length>0&&(u=d.replace(b,"").trim(),u!==d&&(v.v=!0)),(!s||!b&&d||!_&&l||c||u||!i)&&(c||u||t.nodeName!==p||a.Boolean(_)!==a.Boolean(l)||a.Boolean(b)!==a.Boolean(d))?(_&&l.length>0&&(t.style.cssText=c),t.style.cssText||t.removeAttribute("style"),b&&d.length>0&&(t.className=u.trim()),t.className.trim()||t.removeAttribute("class"),t.style.cssText||t.className||t.nodeName!==p&&!i?t:(v.v=!0,null)):(v.v=!0,null)},C=this.getSelectedElements();r.getFormatElement(c)||(c=r.getChildElement(C[0],(function(e){return 3===e.nodeType})),d=0),r.getFormatElement(u)||(u=r.getChildElement(C[C.length-1],(function(e){return 3===e.nodeType})),h=u.textContent.length);const w=r.getFormatElement(c)===r.getFormatElement(u),N=C.length-(w?0:1);g=e.cloneNode(!1);const E=o||s&&function(e,t){for(let i=0,n=e.length;i0&&(g=e.cloneNode(!1),f=this._nodeChange_endLine(C[N],g,x,u,h,o,s,v,S,k));for(let t=N-1;t>0;t--)g=e.cloneNode(!1),this._nodeChange_middleLine(C[t],g,x,o,s,v);g=e.cloneNode(!1),m=this._nodeChange_startLine(C[0],g,x,c,d,o,s,v,S,k),N<=0&&(f=m)}this.controllersOff(),this.setRange(m.container,m.offset,f.container,f.offset),this.history.push(!1)},_stripRemoveNode:function(e){const t=e.parentNode;if(!e||3===e.nodeType||!t)return;const i=e.childNodes;for(;i[0];)t.insertBefore(i[0],e);t.removeChild(e)},_util_getMaintainedNode:function(e,t){return t&&!e?this.getParentElement(t,function(e){return this._isMaintainedNode(e)}.bind(this)):null},_util_isMaintainedNode:function(e,t){return t&&!e&&3!==t.nodeType&&this._isMaintainedNode(t)},_nodeChange_oneLine:function(e,t,i,n,l,s,o,c,d,u,h,p,g){let m=n.parentNode;for(;!(m.nextSibling||m.previousSibling||r.isFormatElement(m.parentNode)||r.isWysiwygDiv(m.parentNode))&&m.nodeName!==t.nodeName;)m=m.parentNode;if(!d&&m===s.parentNode&&m.nodeName===t.nodeName&&r.onlyZeroWidthSpace(n.textContent.slice(0,l))&&r.onlyZeroWidthSpace(s.textContent.slice(o))){const e=m.childNodes;let i=!0;for(let t,l,o,a,c=0,d=e.length;c0&&(i=t.test(e.style.cssText)),!i}if(function e(n,l){const s=n.childNodes;for(let n,o=0,a=s.length;o=S?T-S:E.data.length-S));if(N){const t=p(l);if(t&&t.parentNode!==e){let i=t,n=null;for(;i.parentNode!==e;){for(l=n=i.parentNode.cloneNode(!1);i.childNodes[0];)n.appendChild(i.childNodes[0]);i.appendChild(n),i=i.parentNode}i.parentNode.appendChild(t)}N=N.cloneNode(!1)}r.onlyZeroWidthSpace(s)||l.appendChild(s);const a=p(l);for(a&&(N=a),N&&(e=N),x=d,v=[],w="";x!==e&&x!==f&&null!==x;)n=g(x)?null:i(x),n&&1===x.nodeType&&A(x)&&(v.push(n),w+=x.style.cssText.substr(0,x.style.cssText.indexOf(":"))+"|"),x=x.parentNode;const c=v.pop()||o;for(C=x=c;v.length>0;)x=v.pop(),C.appendChild(x),C=x;if(t.appendChild(c),e.appendChild(t),N&&!p(k)&&(t=t.cloneNode(!1),b.appendChild(t),_.push(t)),E=o,S=0,z=!0,x!==o&&x.appendChild(E),!y)continue}if(L||d!==k){if(z){if(1===d.nodeType&&!r.isBreak(d)){r._isIgnoreNodeChange(d)?(b.appendChild(d),o--,a--,u||(t=t.cloneNode(!1),b.appendChild(t),_.push(t))):e(d,d);continue}x=d,v=[],w="";const s=[];for(;null!==x.parentNode&&x!==f&&x!==t;)n=L?x.cloneNode(!1):i(x),1===x.nodeType&&!r.isBreak(d)&&n&&A(x)&&(n&&(g(n)?N||s.push(n):v.push(n)),w+=x.style.cssText.substr(0,x.style.cssText.indexOf(":"))+"|"),x=x.parentNode;v=v.concat(s);const c=v.pop()||d;for(C=x=c;v.length>0;)x=v.pop(),C.appendChild(x),C=x;if(g(t.parentNode)&&!g(c)&&(t=t.cloneNode(!1),b.appendChild(t),_.push(t)),L||N||!g(c))c===d?l=L?b:t:L?(b.appendChild(c),l=x):(t.appendChild(c),l=x);else{t=t.cloneNode(!1);const e=c.childNodes;for(let i=0,n=e.length;i0?x:t}if(N&&3===d.nodeType)if(p(d)){const e=r.getParentElement(l,function(e){return this._isMaintainedNode(e.parentNode)||e.parentNode===b}.bind(r));N.appendChild(e),t=e.cloneNode(!1),_.push(t),b.appendChild(t)}else N=null}h=d.cloneNode(!1),l.appendChild(h),1!==d.nodeType||r.isBreak(d)||(m=h),e(d,m)}else{N=p(d);const e=r.createTextNode(1===k.nodeType?"":k.substringData(T,k.length-T)),l=r.createTextNode(y||1===k.nodeType?"":k.substringData(0,T));if(N?N=N.cloneNode(!1):g(t.parentNode)&&!N&&(t=t.cloneNode(!1),b.appendChild(t),_.push(t)),!r.onlyZeroWidthSpace(e)){x=d,w="",v=[];const t=[];for(;x!==b&&x!==f&&null!==x;)1===x.nodeType&&A(x)&&(g(x)?t.push(x.cloneNode(!1)):v.push(x.cloneNode(!1)),w+=x.style.cssText.substr(0,x.style.cssText.indexOf(":"))+"|"),x=x.parentNode;for(v=v.concat(t),h=C=x=v.pop()||e;v.length>0;)x=v.pop(),C.appendChild(x),C=x;b.appendChild(h),x.textContent=e.data}if(N&&h){const e=p(h);e&&(N=e)}for(x=d,v=[],w="";x!==b&&x!==f&&null!==x;)n=g(x)?null:i(x),n&&1===x.nodeType&&A(x)&&(v.push(n),w+=x.style.cssText.substr(0,x.style.cssText.indexOf(":"))+"|"),x=x.parentNode;const s=v.pop()||l;for(C=x=s;v.length>0;)x=v.pop(),C.appendChild(x),C=x;N?((t=t.cloneNode(!1)).appendChild(s),N.insertBefore(t,N.firstChild),b.appendChild(N),_.push(t),N=null):t.appendChild(s),k=l,T=l.data.length,L=!0,!c&&u&&(t=l,l.textContent=r.zeroWidthSpace),x!==l&&x.appendChild(k)}}}(e,b),d&&!c&&!h.v)return{startContainer:n,startOffset:l,endContainer:s,endOffset:o};if(c=c&&d)for(let e=0;e<_.length;e++){let t=_[e],i=r.createTextNode(r.zeroWidthSpace);if(u)b.replaceChild(i,t);else{const e=t.childNodes;for(;e[0];)i=e[0],b.insertBefore(i,t);r.removeItem(t)}0===e&&(E=k=i)}else{if(d)for(let e=0;e<_.length;e++)this._stripRemoveNode(_[e]);u&&(E=k=t)}r.removeEmptyNode(b,t),u&&(S=E.textContent.length,T=k.textContent.length);const B=c||0===k.textContent.length;0===k.textContent.length&&(r.removeItem(k),k=E),T=B?k.textContent.length:T;const I={s:0,e:0},R=r.getNodePath(E,b,I),D=!k.parentNode;D&&(k=E);const M={s:0,e:0},O=r.getNodePath(k,b,D||B?null:M);S+=I.s,T=u?S:D?E.textContent.length:B?T+I.s:T+M.s;const P=r.mergeSameTags(b,R,O,!0);return e.parentNode.replaceChild(b,e),E=r.getNodeFromPath(R,b),k=r.getNodeFromPath(O,b),{startContainer:E,startOffset:S+P.a,endContainer:k,endOffset:T+P.b}},_nodeChange_startLine:function(e,t,i,n,l,s,o,a,c,d){let u=n.parentNode;for(;!(u.nextSibling||u.previousSibling||r.isFormatElement(u.parentNode)||r.isWysiwygDiv(u.parentNode))&&u.nodeName!==t.nodeName;)u=u.parentNode;if(!o&&u.nodeName===t.nodeName&&!r.isFormatElement(u)&&!u.nextSibling&&r.onlyZeroWidthSpace(n.textContent.slice(0,l))){let e=!0,i=n.previousSibling;for(;i;){if(!r.onlyZeroWidthSpace(i)){e=!1;break}i=i.previousSibling}if(e)return r.copyTagAttributes(u,t),{container:n,offset:l}}a.v=!1;const h=e,p=[t],g=e.cloneNode(!1);let m,f,_,b,y=n,v=l,x=!1;if(function e(n,l){const s=n.childNodes;for(let n,o=0,a=s.length;o0,v=m.pop()||u;for(_=f=v;m.length>0;)f=m.pop(),_.appendChild(f),_=f;if(d(t.parentNode)&&!d(v)&&(t=t.cloneNode(!1),g.appendChild(t),p.push(t)),!b&&d(v)){t=t.cloneNode(!1);const e=v.childNodes;for(let i=0,n=e.length;i0;)f=m.pop(),_.appendChild(f),_=f;d!==l?(t.appendChild(d),l=f):l=t,r.isBreak(u)&&t.appendChild(u.cloneNode(!1)),e.appendChild(t),y=o,v=0,x=!0,l.appendChild(y)}}}(e,g),o&&!s&&!a.v)return{container:n,offset:l};if(s=s&&o)for(let e=0;e0&&c===d)return void(e.innerHTML=i.innerHTML)}s.v=!1;const o=e.cloneNode(!1),a=[t];let c=!0;if(function e(n,l){const s=n.childNodes;for(let n,d=0,u=s.length;d0&&(o.appendChild(t),t=t.cloneNode(!1)),o.appendChild(h),o.appendChild(t),a.push(t),l=t,d--,u--)}}(e,t),!c&&(!l||n||s.v)){if(o.appendChild(t),n&&l)for(let e=0;e0,y=m.pop()||a;for(_=f=y;m.length>0;)f=m.pop(),_.appendChild(f),_=f;if(d(t.parentNode)&&!d(y)&&(t=t.cloneNode(!1),g.insertBefore(t,g.firstChild),p.push(t)),!b&&d(y)){t=t.cloneNode(!1);const e=y.childNodes;for(let i=0,n=e.length;i0?f:t}else u?(t.insertBefore(y,t.firstChild),l=f):l=t;if(b&&3===a.nodeType)if(c(a)){const e=r.getParentElement(l,function(e){return this._isMaintainedNode(e.parentNode)||e.parentNode===g}.bind(r));b.appendChild(e),t=e.cloneNode(!1),p.push(t),g.insertBefore(t,g.firstChild)}else b=null}if(x||a!==y)n=x?i(a):a.cloneNode(!1),n&&(l.insertBefore(n,l.firstChild),1!==a.nodeType||r.isBreak(a)||(u=n)),e(a,u);else{b=c(a);const e=r.createTextNode(1===y.nodeType?"":y.substringData(v,y.length-v)),s=r.createTextNode(1===y.nodeType?"":y.substringData(0,v));if(b){b=b.cloneNode(!1);const e=c(l);if(e&&e.parentNode!==g){let t=e,i=null;for(;t.parentNode!==g;){for(l=i=t.parentNode.cloneNode(!1);t.childNodes[0];)i.appendChild(t.childNodes[0]);t.appendChild(i),t=t.parentNode}t.parentNode.insertBefore(e,t.parentNode.firstChild)}b=b.cloneNode(!1)}else d(t.parentNode)&&!b&&(t=t.cloneNode(!1),g.appendChild(t),p.push(t));for(r.onlyZeroWidthSpace(e)||l.insertBefore(e,l.firstChild),f=l,m=[];f!==g&&null!==f;)n=d(f)?null:i(f),n&&1===f.nodeType&&m.push(n),f=f.parentNode;const o=m.pop()||l;for(_=f=o;m.length>0;)f=m.pop(),_.appendChild(f),_=f;o!==l?(t.insertBefore(o,t.firstChild),l=f):l=t,r.isBreak(a)&&t.appendChild(a.cloneNode(!1)),b?(b.insertBefore(t,b.firstChild),g.insertBefore(b,g.firstChild),b=null):g.insertBefore(t,g.firstChild),y=s,v=s.data.length,x=!0,l.insertBefore(y,l.firstChild)}}}(e,g),o&&!s&&!a.v)return{container:n,offset:l};if(s=s&&o)for(let e=0;e0&&this.plugins.list.editInsideList.call(this,l,n),this._lastEffectNode=null,this.setRange(s,a,o,c),this.history.push(!1)},toggleDisplayBlocks:function(){r.toggleClass(e.element.wysiwyg,"se-show-block"),this._resourcesStateChange()},toggleCodeView:function(){const t=this._variable.isCodeView,i=this.codeViewDisabledButtons;for(let e=0,n=i.length;e0?e.element.code.scrollHeight+"px":"auto"),l.codeMirrorEditor&&l.codeMirrorEditor.refresh(),this._variable.isCodeView=!0,this._variable.isFullScreen||(this._notHideToolbar=!0,this._isBalloon&&(e.element._arrow.style.display="none",e.element.toolbar.style.left="",this._isInline=!0,this._isBalloon=!1,d._showToolbarInline())),this._variable._range=null,e.element.code.focus()),this._checkPlaceholder()},_setCodeDataToEditor:function(){const t=this._getCodeView();if(l.fullPage){const e=(new this._w.DOMParser).parseFromString(t,"text/html"),i=e.head.children;for(let t=0,n=i.length;t0?this.convertContentsForEditor(t):"


    "},_setEditorDataToCodeView:function(){const t=this.convertHTMLForCodeView(e.element.wysiwyg);let i="";if(l.fullPage){const e=r.getAttributesToString(this._wd.body,null);i="\n\n"+this._wd.head.outerHTML.replace(/>(?!\n)/g,">\n")+"\n"+t+"\n"}else i=t;e.element.code.style.display="block",e.element.wysiwygFrame.style.display="none",this._setCodeView(i)},toggleFullScreen:function(t){const i=e.element.topArea,n=e.element.toolbar,o=e.element.editorArea,c=e.element.wysiwygFrame,u=e.element.code,h=this._variable;h.isFullScreen?(h.isFullScreen=!1,c.style.cssText=h._wysiwygOriginCssText,u.style.cssText=h._codeOriginCssText,n.style.cssText="",o.style.cssText=h._editorAreaOriginCssText,i.style.cssText=h._originCssText,s.body.style.overflow=h._bodyOverflow,l.stickyToolbar>-1&&r.removeClass(n,"se-toolbar-sticky"),h._fullScreenAttrs.sticky&&(h._fullScreenAttrs.sticky=!1,e.element._stickyDummy.style.display="block",r.addClass(n,"se-toolbar-sticky")),this._isInline=h._fullScreenAttrs.inline,this._isBalloon=h._fullScreenAttrs.balloon,this._isInline&&d._showToolbarInline(),d.onScroll_window(),r.removeClass(t.firstElementChild,"se-icon-reduction"),r.addClass(t.firstElementChild,"se-icon-expansion")):(h.isFullScreen=!0,h._fullScreenAttrs.inline=this._isInline,h._fullScreenAttrs.balloon=this._isBalloon,(this._isInline||this._isBalloon)&&(this._isInline=!1,this._isBalloon=!1),i.style.position="fixed",i.style.top="0",i.style.left="0",i.style.width="100%",i.style.height="100%",i.style.zIndex="2147483647",""!==e.element._stickyDummy.style.display&&(h._fullScreenAttrs.sticky=!0,e.element._stickyDummy.style.display="none",r.removeClass(n,"se-toolbar-sticky")),h._bodyOverflow=s.body.style.overflow,s.body.style.overflow="hidden",h._editorAreaOriginCssText=o.style.cssText,h._wysiwygOriginCssText=c.style.cssText,h._codeOriginCssText=u.style.cssText,o.style.cssText=n.style.cssText="",c.style.cssText=(c.style.cssText.match(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/)||[""])[0],u.style.cssText=(u.style.cssText.match(/\s?display(\s+)?:(\s+)?[a-zA-Z]+;/)||[""])[0],n.style.width=c.style.height=u.style.height="100%",n.style.position="relative",n.style.display="block",h.innerHeight_fullScreen=a.innerHeight-n.offsetHeight,o.style.height=h.innerHeight_fullScreen+"px",r.removeClass(t.firstElementChild,"se-icon-expansion"),r.addClass(t.firstElementChild,"se-icon-reduction"),l.iframe&&"auto"===l.height&&(o.style.overflow="auto",this._iframeAutoHeight()))},print:function(){const t=r.createElement("IFRAME");t.style.display="none",s.body.appendChild(t);const i=r.getIframeDocument(t),n=this.getContents(!0);if(l.iframe){const t=r.getIframeDocument(e.element.wysiwygFrame),s=l.fullPage?r.getAttributesToString(t.body,["contenteditable"]):'class="sun-editor-editable"';i.write(""+t.head.innerHTML+""+n+"")}else{const e=r.createElement("DIV"),t=r.createElement("STYLE");t.innerHTML=r.getPageStyle(),e.className="sun-editor-editable",e.innerHTML=n,i.head.appendChild(t),i.body.appendChild(e)}try{if(t.focus(),-1!==a.navigator.userAgent.indexOf("MSIE")||s.documentMode||a.StyleMedia)try{t.contentWindow.document.execCommand("print",!1,null)}catch(e){t.contentWindow.print()}else t.contentWindow.print()}catch(e){throw Error("[SUNEDITOR.core.print.fail] error: "+e)}finally{r.removeItem(t)}},preview:function(){const t=this.getContents(!0),i=a.open("","_blank");if(i.mimeType="text/html",l.iframe){const n=r.getIframeDocument(e.element.wysiwygFrame),s=l.fullPage?r.getAttributesToString(n.body,["contenteditable"]):'class="sun-editor-editable"';i.document.write(""+n.head.innerHTML+""+t+"")}else i.document.write(''+n.toolbar.preview+"'+t+"")},setContents:function(t){const i=this.convertContentsForEditor(t);if(this._resetComponents(),c._variable.isCodeView){const e=this.convertHTMLForCodeView(i);c._setCodeView(e)}else e.element.wysiwyg.innerHTML=i,c.history.push(!1)},getContents:function(t){const i=e.element.wysiwyg.innerHTML,n=r.createElement("DIV");n.innerHTML=i;const s=r.getListChildren(n,(function(e){return/FIGCAPTION/i.test(e.nodeName)}));for(let e=0,t=s.length;e"+this._wd.head.outerHTML+""+n.innerHTML+""}return n.innerHTML},cleanHTML:function(e,t){const i=new this._w.RegExp("^(meta|script|link|style|[a-z]+:[a-z]+)$","i"),n=this._d.createRange().createContextualFragment(e).childNodes;let l="";for(let e=0,t=n.length;e(\n|.)*<\/(script|style)>/g,"").replace(/(<[a-zA-Z0-9]+)[^>]*(?=>)/g,function(e,t){let i=null;const n=this._attributesTagsWhitelist[t.match(/(?!<)[a-zA-Z]+/)[0].toLowerCase()];if(i=n?e.match(n):e.match(this._attributesWhitelistRegExp),i)for(let e=0,n=i.length;e^<]*)>/g,""),r._tagConvertor(l?t?l.replace("string"==typeof t?r.createTagsWhitelist(t):t,""):l:e)},addDocEvent:function(e,t,i){s.addEventListener(e,t,i),l.iframe&&this._wd.addEventListener(e,t)},removeDocEvent:function(e,t){s.removeEventListener(e,t),l.iframe&&this._wd.removeEventListener(e,t)},convertContentsForEditor:function(e){let t="",i=this._d.createRange().createContextualFragment(e).childNodes;for(let e,n=0,l=i.length;n0&&(t+="

    "+n+"

    ")}else t+=e.replace(/<(?!span|font|b|strong|var|i|em|u|ins|s|strike|del|sub|sup|mark|a|label)[^>^<]+>\s+(?=<)/g,(function(e){return e.trim()}));return 0===t.length&&(t="

    "+((e=r._HTMLConvertor(e)).length>0?e:"
    ")+"

    "),r._tagConvertor(t.replace(this.editorTagsWhitelistRegExp,""))},convertHTMLForCodeView:function(e){let t="";const i=this._w.RegExp,n=new i("^(BLOCKQUOTE|PRE|TABLE|THEAD|TBODY|TR|TH|TD|OL|UL|IMG|IFRAME|VIDEO|AUDIO|FIGURE|FIGCAPTION|HR|BR|CANVAS|SELECT)$","i"),l=r.isFormatElement.bind(r),s="string"==typeof e?this._d.createRange().createContextualFragment(e):e;let o=1*this._variable.codeIndent;return o=o>0?new this._w.Array(o+1).join(" "):"",function e(s,a,c){const d=s.childNodes,u=n.test(s.nodeName),h=u?a:"";for(let p,g,m,f=0,_=d.length;f<_;f++){if(p=d[f],m=n.test(p.nodeName),g=m?"\n":"",c=!l(p)||u||/^(TH|TD)$/i.test(s.nodeName)?"":"\n",3===p.nodeType){t+=r._HTMLConvertor(/^\n+$/.test(p.data)?"":p.data);continue}if(0===p.childNodes.length){t+=(/^(HR)$/i.test(p.nodeName)?"\n":"")+h+p.outerHTML+g;continue}p.innerHTML=p.innerHTML;const _=p.nodeName.toLowerCase();t+=(c||(u?"":g))+(h||m?a:"")+p.outerHTML.match(i("<"+_+"[^>]*>","i"))[0]+g,e(p,a+o,""),t+=(m?a:"")+""+(c||g||u?"\n":/^(TH|TD)$/i.test(p.nodeName)?"\n":"")}}(s,"","\n"),t.trim()+"\n"},_charCount:function(t,i){const n=e.element.charCounter;if(!n)return!0;(!t||t<0)&&(t=0);const s=l.maxCharCount;if(a.setTimeout((function(){n.textContent=e.element.wysiwyg.textContent.length})),s>0){let l=!1;const o=e.element.wysiwyg.textContent.length;if(o>s){c._editorRange();const e=c.getRange(),t=e.endOffset-1,i=c.getSelectionNode().textContent;c.getSelectionNode().textContent=i.slice(0,e.endOffset-1)+i.slice(e.endOffset,i.length),c.setRange(e.endContainer,t,e.endContainer,t),l=!0}else o+t>s&&(l=!0);if(l)return i&&!r.hasClass(n,"se-blink")&&(r.addClass(n,"se-blink"),a.setTimeout((function(){r.removeClass(n,"se-blink")}),600)),!1}return!0},_checkComponents:function(){this.plugins.image&&(this.initPlugins.image?this.plugins.image.checkImagesInfo.call(this):this.callPlugin("image",this.plugins.image.checkImagesInfo.bind(this))),this.plugins.video&&(this.initPlugins.video?this.plugins.video.checkVideosInfo.call(this):this.callPlugin("video",this.plugins.video.checkVideosInfo.bind(this)))},_resetComponents:function(){this._variable._imagesInfo=[],this._variable._imageIndex=0,this._variable._videosCnt=0},_setCodeView:function(t){l.codeMirrorEditor?l.codeMirrorEditor.getDoc().setValue(t):e.element.code.value=t},_getCodeView:function(){return l.codeMirrorEditor?l.codeMirrorEditor.getDoc().getValue():e.element.code.value},_init:function(n,o){this._ww=l.iframe?e.element.wysiwygFrame.contentWindow:a,this._wd=s,a.setTimeout(function(){if(this._checkComponents(),this._imagesInfoInit=!1,this._imagesInfoReset=!1,this.history.reset(!0),l.iframe&&(this._wd=e.element.wysiwygFrame.contentDocument,e.element.wysiwyg=this._wd.body,"auto"===l.height&&(this._iframeAuto=this._wd.body),this._iframeAutoHeight()),"function"==typeof g.onload)return g.onload(c,n)}.bind(this)),this.editorTagsWhitelistRegExp=r.createTagsWhitelist(l._editorTagsWhitelist),this.pasteTagsWhitelistRegExp=r.createTagsWhitelist(l.pasteTagsWhitelist);const u=l.attributesWhitelist,h={};let p,m,f="";if(u){const e=a.Object.keys(u);for(let t,i=0,n=e.length;ir&&(c=c.slice(0,r),o&&o.setAttribute("disabled",!0)),c[r]={contents:i,s:{path:l.getNodePath(n.startContainer,null),offset:n.startOffset},e:{path:l.getNodePath(n.endContainer,null),offset:n.endOffset}},1===r&&s&&s.removeAttribute("disabled"),e._checkComponents(),e._charCount(0,!1),t()}return{stack:c,push:function(t){i.setTimeout(e._resourcesStateChange),t&&!a||(i.clearTimeout(a),t)?a=i.setTimeout((function(){i.clearTimeout(a),a=null,u()}),350):u()},undo:function(){r>0&&(r--,d())},redo:function(){c.length-1>r&&(r++,d())},go:function(e){r=e<0?c.length-1:e,d()},reset:function(i){s&&s.setAttribute("disabled",!0),o&&o.setAttribute("disabled",!0),e.context.tool.save&&e.context.tool.save.setAttribute("disabled",!0),c.splice(0),r=0,c[r]={contents:e.getContents(!0),s:{path:[0,0],offset:0},e:{path:[0,0],offset:0}},i||t()},_destroy:function(){a&&i.clearTimeout(a),c=null}}}(this,d._onChange_historyStack)},_resourcesStateChange:function(){c._iframeAutoHeight(),c._checkPlaceholder()},_iframeAutoHeight:function(){this._iframeAuto&&(e.element.wysiwygFrame.style.height=this._iframeAuto.offsetHeight+"px")},_checkPlaceholder:function(){if(this._placeholder){if(this._variable.isCodeView)return void(this._placeholder.style.display="none");const t=e.element.wysiwyg;!r.onlyZeroWidthSpace(t.textContent)||t.querySelector(".se-component, pre, blockquote, hr, li, table, img, iframe, video")||(t.innerText.match(/\n/g)||"").length>1?this._placeholder.style.display="none":this._placeholder.style.display="block"}}},d={_directionKeyCode:new a.RegExp("^(8|13|3[2-9]|40|46)$"),_nonTextKeyCode:new a.RegExp("^(8|13|1[6-9]|20|27|3[3-9]|40|45|46|11[2-9]|12[0-3]|144|145)$"),_historyIgnoreKeyCode:new a.RegExp("^(1[6-9]|20|27|3[3-9]|40|45|11[2-9]|12[0-3]|144|145)$"),_onButtonsCheck:new a.RegExp("^(STRONG|INS|EM|DEL|SUB|SUP)$"),_frontZeroWidthReg:new a.RegExp(r.zeroWidthSpace+"+",""),_keyCodeShortcut:{65:"A",66:"B",83:"S",85:"U",73:"I",89:"Y",90:"Z",219:"[",221:"]"},_shortcutCommand:function(e,t){let i=null;switch(d._keyCodeShortcut[e]){case"A":i="selectAll";break;case"B":i="STRONG";break;case"S":t&&(i="DEL");break;case"U":i="INS";break;case"I":i="EM";break;case"Z":i=t?"redo":"undo";break;case"Y":i="redo";break;case"[":i="outdent";break;case"]":i="indent"}return!!i&&(c.commandHandler(c.commandMap[i],i),!0)},_applyTagEffects:function(){let t=c.getSelectionNode();if(t===c._lastEffectNode)return;c._lastEffectNode=t;const n=c.commandMap,s=this._onButtonsCheck,o=[],a=[],d=c.activePlugins,u=d.length;let h="";for(;t.firstChild;)t=t.firstChild;for(let e=t;!r.isWysiwygDiv(e)&&e;e=e.parentNode)if(1===e.nodeType&&!r.isBreak(e)){h=e.nodeName.toUpperCase(),a.push(h);for(let t,n=0;n0)&&(o.push("OUTDENT"),n.OUTDENT.removeAttribute("disabled")),-1===o.indexOf("INDENT")&&n.INDENT&&r.isListCell(e)&&!e.previousElementSibling&&(o.push("INDENT"),n.INDENT.setAttribute("disabled",!0))):s.test(h)&&(o.push(h),r.addClass(n[h],"active"))}for(let e in n)o.indexOf(e)>-1||(d.indexOf(e)>-1?i[e].active.call(c,null):n.OUTDENT&&/^OUTDENT$/i.test(e)?n.OUTDENT.setAttribute("disabled",!0):n.INDENT&&/^INDENT$/i.test(e)?n.INDENT.removeAttribute("disabled"):r.removeClass(n[e],"active"));c._variable.currentNodes=a.reverse(),l.showPathLabel&&(e.element.navigation.textContent=c._variable.currentNodes.join(" > "))},_cancelCaptionEdit:function(){this.setAttribute("contenteditable",!1),this.removeEventListener("blur",d._cancelCaptionEdit)},onMouseDown_toolbar:function(e){let t=e.target;if(r.getParentElement(t,".se-submenu"))e.stopPropagation(),c._notHideToolbar=!0;else{e.preventDefault();let i=t.getAttribute("data-command"),n=t.className;for(;!i&&!/se-menu-list/.test(n)&&!/se-toolbar/.test(n);)t=t.parentNode,i=t.getAttribute("data-command"),n=t.className;i!==c._submenuName&&i!==c._containerName||e.stopPropagation()}},onClick_toolbar:function(e){e.preventDefault(),e.stopPropagation();let t=e.target,i=t.getAttribute("data-display"),n=t.getAttribute("data-command"),l=t.className;for(;!n&&!/se-menu-list/.test(l)&&!/se-toolbar/.test(l);)t=t.parentNode,n=t.getAttribute("data-command"),i=t.getAttribute("data-display"),l=t.className;(n||i)&&(t.disabled||(c.hasFocus||c.focus(),c._editorRange(),c.actionCall(n,i,t)))},onMouseDown_wysiwyg:function(t){if("false"===e.element.wysiwyg.getAttribute("contenteditable"))return;const i=r.getParentElement(t.target,r.isCell);if(i){const e=c.plugins.table;e&&i!==e._fixedCell&&!e._shift&&c.callPlugin("table",(function(){e.onTableCellMultiSelect.call(c,i,!1)}))}c._isBalloon&&d._hideToolbar(),g.onMouseDown&&g.onMouseDown(t,c)},onClick_wysiwyg:function(t){const i=t.target;if("false"===e.element.wysiwyg.getAttribute("contenteditable"))return;if(t.stopPropagation(),/^FIGURE$/i.test(i.nodeName)){const e=i.querySelector("IMG"),n=i.querySelector("IFRAME");if(e)return t.preventDefault(),void c.selectComponent(e,"image");if(n)return t.preventDefault(),void c.selectComponent(n,"video")}const n=r.getParentElement(i,"FIGCAPTION");if(n&&(!n.getAttribute("contenteditable")||"false"===n.getAttribute("contenteditable"))&&(t.preventDefault(),n.setAttribute("contenteditable",!0),n.focus(),c._isInline&&!c._inlineToolbarAttr.isShow)){d._showToolbarInline();const e=function(){d._hideToolbar(),n.removeEventListener("blur",e)};n.addEventListener("blur",e)}c._editorRange(),a.setTimeout(c._editorRange.bind(c));const l=c.getSelectionNode(),s=r.getFormatElement(l),o=r.getRangeFormatElement(l);if(!c.getRange().collapsed||s&&s!==o||"false"===i.getAttribute("contenteditable"))d._applyTagEffects();else{if(r.isList(o)){const e=r.createElement("LI"),t=l.nextElementSibling;e.appendChild(l),o.insertBefore(e,t)}else c.execCommand("formatBlock",!1,r.isRangeFormatElement(o)?"DIV":"P");t.preventDefault(),c.focus()}c._isBalloon&&a.setTimeout(d._toggleToolbarBalloon),g.onClick&&g.onClick(t,c)},_balloonDelay:null,_showToolbarBalloonDelay:function(){d._balloonDelay&&a.clearTimeout(d._balloonDelay),d._balloonDelay=a.setTimeout(function(){a.clearTimeout(this._balloonDelay),this._balloonDelay=null,this._showToolbarBalloon()}.bind(d),350)},_toggleToolbarBalloon:function(){c._editorRange();const e=c.getRange();"table"===c.currentControllerName||!c._isBalloonAlways&&e.collapsed?d._hideToolbar():d._showToolbarBalloon(e)},_showToolbarBalloon:function(t){if(!c._isBalloon)return;const i=t||c.getRange(),n=e.element.toolbar,l=c.getSelection();let s;if(l.focusNode===l.anchorNode)s=l.focusOffsetn.offsetWidth?n.offsetWidth-u:b",!o.nextElementSibling){const e=o.attributes;for(;e[0];)o.removeAttribute(e[0].name);c.execCommand("formatBlock",!1,"P")}return!1}}const i=u.commonAncestorContainer;if(m=r.getFormatElement(u.startContainer),f=r.getRangeFormatElement(m),f&&m&&!r.isCell(f)&&!/^FIGCAPTION$/i.test(f.nodeName)){if(r.isListCell(m)&&r.isList(f)&&(r.isListCell(f.parentNode)||m.previousElementSibling)&&(o===m||3===o.nodeType&&(!o.previousSibling||r.isList(o.previousSibling)))&&(r.getFormatElement(u.startContainer)!==r.getFormatElement(u.endContainer)?f.contains(u.startContainer):0===u.startOffset&&u.collapsed)){if(u.startContainer!==u.endContainer)t.preventDefault(),c.removeNode(),3===u.startContainer.nodeType&&c.setRange(u.startContainer,u.startContainer.textContent.length,u.startContainer,u.startContainer.textContent.length),c.history.push(!0);else{let e=m.previousElementSibling||f.parentNode;if(r.isListCell(e)){t.preventDefault();const i=e.lastElementChild;r.isList(i)&&(e=i.lastElementChild);let n=e===f.parentNode?f.previousSibling:e.lastChild;n||(n=r.createTextNode(r.zeroWidthSpace),f.parentNode.insertBefore(n,f.parentNode.firstChild));const l=3===n.nodeType?n.textContent.length:1,s=m.childNodes;let o=n,a=s[0];for(;a=s[0];)e.insertBefore(a,o.nextSibling),o=a;r.removeItem(m),0===f.children.length&&r.removeItem(f),c.setRange(n,l,n,l),c.history.push(!0)}}break}if(!h&&0===u.startOffset){let e=!0,n=i;for(;n&&n!==f&&!r.isWysiwygDiv(n);){if(n.previousSibling&&(1===n.previousSibling.nodeType||!r.onlyZeroWidthSpace(n.previousSibling.textContent.trim()))){e=!1;break}n=n.parentNode}if(e&&f.parentNode){t.preventDefault(),c.detachRangeFormatElement(f,r.isListCell(m)?[m]:null,null,!1,!1),c.history.push(!0);break}}}if(!h&&0===u.startOffset&&(r.isComponent(i.previousSibling)||3===i.nodeType&&!i.previousSibling&&0===u.startOffset&&0===u.endOffset&&r.isComponent(m.previousSibling))){const e=m.previousSibling;r.removeItem(e)}break;case 46:if(p){t.preventDefault(),t.stopPropagation(),c.plugins[p].destroy.call(c);break}if((r.isFormatElement(o)||null===o.nextSibling)&&u.startOffset===o.textContent.length){let e=m.nextElementSibling;if(r.isComponent(e)){t.preventDefault(),r.onlyZeroWidthSpace(m)&&r.removeItem(m),(r.hasClass(e,"se-component")||/^IMG$/i.test(e.nodeName))&&(t.stopPropagation(),r.hasClass(e,"se-image-container")||/^IMG$/i.test(e.nodeName)?(e=/^IMG$/i.test(e.nodeName)?e:e.querySelector("img"),c.selectComponent(e,"image")):r.hasClass(e,"se-video-container")&&c.selectComponent(e.querySelector("iframe"),"video"));break}}if(m=r.getFormatElement(u.startContainer),f=r.getRangeFormatElement(m),r.isListCell(m)&&r.isList(f)&&(o===m||3===o.nodeType&&(!o.nextSibling||r.isList(o.nextSibling))&&(r.getFormatElement(u.startContainer)!==r.getFormatElement(u.endContainer)?f.contains(u.endContainer):u.endOffset===o.textContent.length&&u.collapsed))){u.startContainer!==u.endContainer&&c.removeNode();let e=r.getArrayItem(m.children,r.isList,!1);if(e=e||m.nextElementSibling||f.parentNode.nextElementSibling,e&&(r.isList(e)||r.getArrayItem(e.children,r.isList,!1))){let i,n;if(t.preventDefault(),r.isList(e)){const t=e.firstElementChild;for(n=t.childNodes,i=n[0];n[0];)m.insertBefore(n[0],e);r.removeItem(t)}else{for(i=e.firstChild,n=e.childNodes;n[0];)m.appendChild(n[0]);r.removeItem(e)}c.setRange(i,0,i,0),c.history.push(!0)}break}break;case 9:if(t.preventDefault(),l||s||r.isWysiwygDiv(o))break;c.controllersOff();const g=!u.collapsed||c.isEdgePoint(u.startContainer,u.startOffset),_=c.getSelectedElements(),b=[];let y=[],v=r.isListCell(_[0]),x=r.isListCell(_[_.length-1]),C={sc:u.startContainer,so:u.startOffset,ec:u.endContainer,eo:u.endOffset};for(let e,t=0,i=_.length;t0&&g&&c.plugins.list)c.plugins.list.editInsideList.call(c,n,b);else{const e=r.getParentElement(o,r.isCell);if(e&&g){const t=r.getParentElement(e,"table"),i=r.getListChildren(t,r.isCell);let l=n?r.prevIdx(i,e):r.nextIdx(i,e);l!==i.length||n||(l=0),-1===l&&n&&(l=i.length-1);const s=i[l];if(!s)return!1;c.setRange(s,0,s,0);break}y=y.concat(b),v=x=null}if(y.length>0)if(n){const e=y.length-1;for(let t,i=0;i<=e;i++){t=y[i].childNodes;for(let e,i=0,n=t.length;i0&&r.isBreak(n[l-1])||!e&&r.onlyZeroWidthSpace(o.textContent)&&r.isBreak(s)&&(r.isBreak(s.previousSibling)||!r.onlyZeroWidthSpace(s.previousSibling.textContent))&&(!a||!r.isBreak(a)&&r.onlyZeroWidthSpace(a.textContent))){e?r.removeItem(n[l-1]):r.removeItem(o);const t=c.appendFormatTag(w,r.isFormatElement(w.nextElementSibling)?w.nextElementSibling:null);r.copyFormatAttributes(t,w),c.setRange(t,1,t,1);break}if(e){c.execCommand("insertHTML",!1,"

    ");let e=i.focusNode;const t=i.focusOffset;e=w===e?e.childNodes[t-l>1?t-1:t]:e.previousSibling,c.setRange(e,1,e,1)}else{const e=i.focusNode.nextSibling,t=r.createElement("BR");c.insertNode(t);const n=t.previousSibling,l=t.nextSibling;r.isBreak(e)||r.isBreak(n)||l&&!r.onlyZeroWidthSpace(l)?c.setRange(l,0,l,0):(t.parentNode.insertBefore(t.cloneNode(!1),t),c.setRange(t,1,t,1))}d._onShortcutKey=!0;break}if(h)break;if(f&&m&&!r.isCell(f)&&!/^FIGCAPTION$/i.test(f.nodeName)){const e=c.getRange();if((3!==e.commonAncestorContainer.nodeType||!e.commonAncestorContainer.nextElementSibling)&&r.onlyZeroWidthSpace(m.innerText.trim())){t.preventDefault();let e=null;if(r.isListCell(f.parentNode)){f=m.parentNode.parentNode.parentNode;const t=r.splitElement(m,null,r.getElementDepth(m)-2);e=r.createElement("LI"),f.insertBefore(e,t)}else{const t=r.isCell(f.parentNode)?"DIV":r.isList(f.parentNode)?"LI":r.isFormatElement(f.nextElementSibling)?f.nextElementSibling.nodeName:r.isFormatElement(f.previousElementSibling)?f.previousElementSibling.nodeName:"P";e=r.createElement(t);const i=c.detachRangeFormatElement(f,[m],null,!0,!0);i.cc.insertBefore(e,i.ec)}e.innerHTML="
    ",r.copyFormatAttributes(e,m),r.removeItemAllParents(m,null),c.setRange(e,1,e,1);break}}if(f&&r.getParentElement(f,"FIGCAPTION")&&r.getParentElement(f,r.isList)&&(t.preventDefault(),m=c.appendFormatTag(m,null),c.setRange(m,0,m,0)),p){t.preventDefault(),t.stopPropagation();const i=e[p],n=i._container,l=n.previousElementSibling||n.nextElementSibling;let s=null;r.isListCell(n.parentNode)?s=r.createElement("BR"):(s=r.createElement(r.isFormatElement(l)?l.nodeName:"P"),s.innerHTML="
    "),n.parentNode.insertBefore(s,n),c.callPlugin(p,(function(){const e=c.plugins.resizing.call_controller_resize.call(c,i._element,p);c.plugins[p].onModifyMode.call(c,i._element,e)}))}}if(n&&/16/.test(i)){t.preventDefault(),t.stopPropagation();const e=c.plugins.table;if(e&&!e._shift&&!e._ref){const t=r.getParentElement(m,r.isCell);if(t)return void e.onTableCellMultiSelect.call(c,t,!0)}}const _=!(l||s||h||d._nonTextKeyCode.test(i));if(!c._charCount(1,_)&&_)return t.preventDefault(),t.stopPropagation(),!1;g.onKeyDown&&g.onKeyDown(t,c)},onKeyUp_wysiwyg:function(e){if(d._onShortcutKey)return;c._editorRange();const t=c.getRange(),i=e.keyCode,n=e.ctrlKey||e.metaKey||91===i||92===i,l=e.altKey;let s=c.getSelectionNode();if(c._isBalloon&&(c._isBalloonAlways&&27!==i||!t.collapsed)){if(!c._isBalloonAlways)return void d._showToolbarBalloon();d._showToolbarBalloonDelay()}if(8===i&&r.isWysiwygDiv(s)&&""===s.textContent){e.preventDefault(),e.stopPropagation(),s.innerHTML="";const t=r.createElement(r.isFormatElement(c._variable.currentNodes[0])?c._variable.currentNodes[0]:"P");return t.innerHTML="
    ",s.appendChild(t),c.setRange(t,0,t,0),d._applyTagEffects(),c._checkComponents(),void c.history.push(!1)}const o=r.getFormatElement(s),a=r.getRangeFormatElement(s);(!o&&t.collapsed||o===a)&&(c.execCommand("formatBlock",!1,r.isRangeFormatElement(a)?"DIV":"P"),c.focus(),s=c.getSelectionNode()),d._directionKeyCode.test(i)&&d._applyTagEffects(),c._checkComponents();const u=!n&&!l&&!d._nonTextKeyCode.test(i);if(u&&3===s.nodeType&&r.zeroWidthRegExp.test(s.textContent)){let e=t.startOffset,i=t.endOffset;const n=(s.textContent.substring(0,i).match(d._frontZeroWidthReg)||"").length;e=t.startOffset-n,i=t.endOffset-n,s.textContent=s.textContent.replace(r.zeroWidthRegExp,""),c.setRange(s,e<0?0:e,s,i<0?0:i)}if(!c._charCount(1,u)&&1===e.key.length)return e.preventDefault(),e.stopPropagation(),!1;!n&&!l&&!d._historyIgnoreKeyCode.test(i)&&c.history.push(!0),g.onKeyUp&&g.onKeyUp(e,c)},onScroll_wysiwyg:function(e){c.controllersOff(),c._isBalloon&&d._hideToolbar(),g.onScroll&&g.onScroll(e,c)},onFocus_wysiwyg:function(e){c.hasFocus=!0,c._isInline&&d._showToolbarInline(),g.onFocus&&g.onFocus(e,c)},onBlur_wysiwyg:function(e){c.hasFocus=!1,(c._isInline||c._isBalloon)&&d._hideToolbar(),g.onBlur&&g.onBlur(e,c)},onMouseDown_resizingBar:function(t){t.stopPropagation(),c._variable.resizeClientY=t.clientY,e.element.resizeBackground.style.display="block",s.addEventListener("mousemove",d._resize_editor),s.addEventListener("mouseup",(function t(){e.element.resizeBackground.style.display="none",s.removeEventListener("mousemove",d._resize_editor),s.removeEventListener("mouseup",t)}))},_resize_editor:function(t){const i=e.element.editorArea.offsetHeight+(t.clientY-c._variable.resizeClientY);e.element.wysiwygFrame.style.height=e.element.code.style.height=(i=i+o?(c._sticky||d._onStickyToolbar(),t.toolbar.style.top=i+o+l.stickyToolbar-n-c._variable.minResizingSize+"px"):n>=o&&d._onStickyToolbar()},_getStickyOffsetTop:function(){let t=e.element.topArea,i=0;for(;t;)i+=t.offsetTop,t=t.offsetParent;return i},_onStickyToolbar:function(){const t=e.element;c._isInline||(t._stickyDummy.style.height=t.toolbar.offsetHeight+"px",t._stickyDummy.style.display="block"),t.toolbar.style.top=l.stickyToolbar+"px",t.toolbar.style.width=c._isInline?c._inlineToolbarAttr.width:t.toolbar.offsetWidth+"px",r.addClass(t.toolbar,"se-toolbar-sticky"),c._sticky=!0},_offStickyToolbar:function(){const t=e.element;t._stickyDummy.style.display="none",t.toolbar.style.top=c._isInline?c._inlineToolbarAttr.top:"",t.toolbar.style.width=c._isInline?c._inlineToolbarAttr.width:"",t.editorArea.style.marginTop="",r.removeClass(t.toolbar,"se-toolbar-sticky"),c._sticky=!1},_codeViewAutoHeight:function(){e.element.code.style.height=e.element.code.scrollHeight+"px"},onPaste_wysiwyg:function(e){const t=e.clipboardData;if(!t)return!0;const i=c._charCount(t.getData("text/plain").length,!0),n=c.cleanHTML(t.getData("text/html"),c.pasteTagsWhitelistRegExp);return("function"!=typeof g.onPaste||g.onPaste(e,n,i,c))&&i?void(n?(e.stopPropagation(),e.preventDefault(),c.execCommand("insertHTML",!1,n)):c.history.push(!0)):(e.preventDefault(),e.stopPropagation(),!1)},onCut_wysiwyg:function(){a.setTimeout((function(){c._resourcesStateChange(),c._charCount(0,!1),c.history.push(!1)}))},onDragOver_wysiwyg:function(e){e.preventDefault()},onDrop_wysiwyg:function(t){const i=t.dataTransfer;if(!i)return!0;const n=i.files;if(n.length>0&&c.plugins.image)d._setDropLocationSelection(t),c.callPlugin("image",(function(){e.image.imgInputFile.files=n,c.plugins.image.onRender_imgInput.call(c),e.image.imgInputFile.files=null}));else{if(!c._charCount(i.getData("text/plain").length,!0))return t.preventDefault(),t.stopPropagation(),!1;{const e=c.cleanHTML(i.getData("text/html"),c.pasteTagsWhitelistRegExp);e&&(d._setDropLocationSelection(t),c.execCommand("insertHTML",!1,e))}}g.onDrop&&g.onDrop(t,c)},_setDropLocationSelection:function(e){e.stopPropagation(),e.preventDefault();const t=c.getRange();c.setRange(t.startContainer,t.startOffset,t.endContainer,t.endOffset)},_onChange_historyStack:function(){d._applyTagEffects(),e.tool.save&&e.tool.save.removeAttribute("disabled"),g.onChange&&g.onChange(c.getContents(!0),c)},_addEvent:function(){const t=l.iframe?c._ww:e.element.wysiwyg;e.element.toolbar.addEventListener("mousedown",d.onMouseDown_toolbar,!1),e.element.toolbar.addEventListener("click",d.onClick_toolbar,!1),t.addEventListener("mousedown",d.onMouseDown_wysiwyg,!1),t.addEventListener("click",d.onClick_wysiwyg,!1),t.addEventListener("keydown",d.onKeyDown_wysiwyg,!1),t.addEventListener("keyup",d.onKeyUp_wysiwyg,!1),t.addEventListener("paste",d.onPaste_wysiwyg,!1),t.addEventListener("cut",d.onCut_wysiwyg,!1),t.addEventListener("dragover",d.onDragOver_wysiwyg,!1),t.addEventListener("drop",d.onDrop_wysiwyg,!1),t.addEventListener("scroll",d.onScroll_wysiwyg,!1),t.addEventListener("focus",d.onFocus_wysiwyg,!1),t.addEventListener("blur",d.onBlur_wysiwyg,!1),c.plugins.table&&t.addEventListener("touchstart",d.onMouseDown_wysiwyg,{passive:!0,useCapture:!1}),"auto"!==l.height||l.codeMirrorEditor||(e.element.code.addEventListener("keydown",d._codeViewAutoHeight,!1),e.element.code.addEventListener("keyup",d._codeViewAutoHeight,!1),e.element.code.addEventListener("paste",d._codeViewAutoHeight,!1)),e.element.resizingBar&&(/\d+/.test(l.height)?e.element.resizingBar.addEventListener("mousedown",d.onMouseDown_resizingBar,!1):r.addClass(e.element.resizingBar,"se-resizing-none")),a.removeEventListener("resize",d.onResize_window),a.removeEventListener("scroll",d.onScroll_window),a.addEventListener("resize",d.onResize_window,!1),l.stickyToolbar>-1&&a.addEventListener("scroll",d.onScroll_window,!1)},_removeEvent:function(){const t=l.iframe?c._ww:e.element.wysiwyg;e.element.toolbar.removeEventListener("mousedown",d.onMouseDown_toolbar),e.element.toolbar.removeEventListener("click",d.onClick_toolbar),t.removeEventListener("click",d.onClick_wysiwyg),t.removeEventListener("keydown",d.onKeyDown_wysiwyg),t.removeEventListener("keyup",d.onKeyUp_wysiwyg),t.removeEventListener("paste",d.onPaste_wysiwyg),t.removeEventListener("cut",d.onCut_wysiwyg),t.removeEventListener("dragover",d.onDragOver_wysiwyg),t.removeEventListener("drop",d.onDrop_wysiwyg),t.removeEventListener("scroll",d.onScroll_wysiwyg),t.removeEventListener("mousedown",d.onMouseDown_wysiwyg),t.removeEventListener("touchstart",d.onMouseDown_wysiwyg,{passive:!0,useCapture:!1}),t.removeEventListener("focus",d.onFocus_wysiwyg),t.removeEventListener("blur",d.onBlur_wysiwyg),e.element.code.removeEventListener("keydown",d._codeViewAutoHeight),e.element.code.removeEventListener("keyup",d._codeViewAutoHeight),e.element.code.removeEventListener("paste",d._codeViewAutoHeight),e.element.resizingBar&&e.element.resizingBar.removeEventListener("mousedown",d.onMouseDown_resizingBar),a.removeEventListener("resize",d.onResize_window),a.removeEventListener("scroll",d.onScroll_window)}},g={core:c,util:r,onload:null,onScroll:null,onMouseDown:null,onClick:null,onKeyDown:null,onKeyUp:null,onDrop:null,onChange:null,onPaste:null,onFocus:null,onBlur:null,showInline:null,imageUploadHandler:null,onImageUploadBefore:null,onImageUpload:null,onImageUploadError:null,setOptions:function(s){d._removeEvent(),c.plugins=s.plugins||c.plugins;const o=[s,s].reduce((function(e,t){for(let i in t)if("plugins"===i&&t[i]&&e[i]){let n=e[i],l=t[i];n=n.length?n:a.Object.keys(n).map((function(e){return n[e]})),l=l.length?l:a.Object.keys(l).map((function(e){return l[e]})),e[i]=l.filter((function(e){return-1===n.indexOf(e)})).concat(n)}else e[i]=t[i];return e}),{}),r=h._setOptions(o,e,c.plugins,s);r.callButtons&&(t=r.callButtons,c.initPlugins={}),r.plugins&&(c.plugins=i=r.plugins);const u=e.element.wysiwyg.innerHTML,g=e.element,m={_top:g.topArea,_relative:g.relative,_toolBar:g.toolbar,_editorArea:g.editorArea,_wysiwygArea:g.wysiwygFrame,_codeArea:g.code,_placeholder:g.placeholder,_resizingBar:g.resizingBar,_navigation:g.navigation,_charCounter:g.charCounter,_loading:g.loading,_resizeBack:g.resizeBackground,_stickyDummy:g._stickyDummy,_arrow:g._arrow};l=o,c.lang=n=l.lang,c.context=e=p(e.element.originElement,m,l),c._imagesInfoReset=!0,c._init(!0,u),d._addEvent(),c._charCount(0,!1),d._offStickyToolbar(),d.onResize_window(),c.focus()},noticeOpen:function(e){c.addModule([o]),o.open.call(c,e)},noticeClose:function(){c.addModule([o]),o.close.call(c)},save:function(){e.element.originElement.value=c.getContents(!1)},getContext:function(){return e},getContents:function(e){return c.getContents(e)},getImagesInfo:function(){return c._variable._imagesInfo},insertImage:function(e){c.plugins.image&&e&&(c.initPlugins.image?c.plugins.image.submitAction.call(c,e):c.callPlugin("image",c.plugins.image.submitAction.bind(c,e)),c.focus())},insertHTML:function(e){if(!e.nodeType||1!==e.nodeType){const t=r.createElement("DIV");t.innerHTML=e,e=t.firstChild||t.content.firstChild}let t=null;(r.isFormatElement(e)||/^(IMG|IFRAME)$/i.test(e.nodeName))&&(t=r.getFormatElement(c.getSelectionNode())),r.isComponent(e)?c.insertComponent(e,!1):c.insertNode(e,t),c.focus()},setContents:function(e){c.setContents(e)},appendContents:function(t){const i=c.convertContentsForEditor(t);if(c._variable.isCodeView)c._setCodeView(c._getCodeView()+"\n"+c.convertHTMLForCodeView(i));else{const t=r.createElement("DIV");t.innerHTML=i;const n=e.element.wysiwyg,l=t.children;for(let e=0,t=l.length;e 0) { - core.plugins.list.editInsideList.call(core, shift, cells); + this.plugins.list.editInsideList.call(this, shift, cells); } this._lastEffectNode = null; - event._applyTagEffects(); + this.setRange(sc, so, ec, eo); + // history stack this.history.push(false); }, @@ -4504,6 +4548,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } } + // nested list const commonCon = range.commonAncestorContainer; formatEl = util.getFormatElement(range.startContainer); rangeEl = util.getRangeFormatElement(formatEl); @@ -4517,13 +4562,13 @@ export default function (context, pluginCallButtons, plugins, lang, options) { if (range.startContainer.nodeType === 3) { core.setRange(range.startContainer, range.startContainer.textContent.length, range.startContainer, range.startContainer.textContent.length); } - // history stack core.history.push(true); } else { let prev = formatEl.previousElementSibling || rangeEl.parentNode; if (util.isListCell(prev)) { e.preventDefault(); + const prevLast = prev.lastElementChild; if (util.isList(prevLast)) { prev = prevLast.lastElementChild; @@ -4555,13 +4600,16 @@ export default function (context, pluginCallButtons, plugins, lang, options) { break; } + // detach range if (!selectRange && range.startOffset === 0) { let detach = true; let comm = commonCon; while (comm && comm !== rangeEl && !util.isWysiwygDiv(comm)) { if (comm.previousSibling) { - detach = false; - break; + if (comm.previousSibling.nodeType === 1 || !util.onlyZeroWidthSpace(comm.previousSibling.textContent.trim())) { + detach = false; + break; + } } comm = comm.parentNode; } @@ -4576,6 +4624,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } } + // component if (!selectRange && range.startOffset === 0) { if (util.isComponent(commonCon.previousSibling) || (commonCon.nodeType === 3 && !commonCon.previousSibling && range.startOffset === 0 && range.endOffset === 0 && util.isComponent(formatEl.previousSibling))) { const previousEl = formatEl.previousSibling; @@ -4592,6 +4641,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { break; } + // component if ((util.isFormatElement(selectionNode) || selectionNode.nextSibling === null) && range.startOffset === selectionNode.textContent.length) { let nextEl = formatEl.nextElementSibling; if (util.isComponent(nextEl)) { @@ -4614,6 +4664,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } } + // nested list formatEl = util.getFormatElement(range.startContainer); rangeEl = util.getRangeFormatElement(formatEl); if (util.isListCell(formatEl) && util.isList(rangeEl) && (selectionNode === formatEl || (selectionNode.nodeType === 3 && (!selectionNode.nextSibling || util.isList(selectionNode.nextSibling)) && @@ -4660,7 +4711,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { const cells = []; let lines = []; let fc = util.isListCell(selectedFormats[0]), lc = util.isListCell(selectedFormats[selectedFormats.length - 1]); - let r = {sc: null, so: null, ec: null, eo: null}; + let r = {sc: range.startContainer, so: range.startOffset, ec: range.endContainer, eo: range.endOffset}; for (let i = 0, len = selectedFormats.length, f; i < len; i++) { f = selectedFormats[i]; if (util.isListCell(f)) { @@ -4676,15 +4727,7 @@ export default function (context, pluginCallButtons, plugins, lang, options) { // Nested list if (cells.length > 0 && isEdge && core.plugins.list) { - const listRange = core.plugins.list.editInsideList.call(core, shift, cells); - if (fc) { - r.sc = listRange.sc; - r.so = listRange.so; - } - if (lc) { - r.ec = listRange.ec; - r.eo = listRange.eo; - } + core.plugins.list.editInsideList.call(core, shift, cells); } else { // table const tableCell = util.getParentElement(selectionNode, util.isCell); @@ -4747,14 +4790,20 @@ export default function (context, pluginCallButtons, plugins, lang, options) { } } else { const len = lines.length - 1; - for (let i = 0, child; i <= len; i++) { - child = lines[i].firstChild; - if (!child) continue; - - if (/^\s{1,4}$/.test(child.textContent)) { - util.removeItem(child); - } else if (/^\s{1,4}/.test(child.textContent)) { - child.textContent = child.textContent.replace(/^\s{1,4}/, ''); + for (let i = 0, line; i <= len; i++) { + line = lines[i].childNodes; + for (let c = 0, cLen = line.length, child; c < cLen; c++) { + child = line[c]; + if (!child) break; + if (util.onlyZeroWidthSpace(child)) continue; + + if (/^\s{1,4}$/.test(child.textContent)) { + util.removeItem(child); + } else if (/^\s{1,4}/.test(child.textContent)) { + child.textContent = child.textContent.replace(/^\s{1,4}/, ''); + } + + break; } } diff --git a/src/plugins/dialog/image.js b/src/plugins/dialog/image.js index b6871d4e9..f74040ca7 100644 --- a/src/plugins/dialog/image.js +++ b/src/plugins/dialog/image.js @@ -632,7 +632,7 @@ export default { contextImage._container = container; // set size - this.plugins.image.applySize.call(this); + this.plugins.image.applySize.call(this, width, height); // align this.plugins.image.setAlign.call(this, align, oImg, cover, container); diff --git a/test/dev/suneditor_build_test.js b/test/dev/suneditor_build_test.js index 66a9fcdb4..2cffc5c59 100644 --- a/test/dev/suneditor_build_test.js +++ b/test/dev/suneditor_build_test.js @@ -49,7 +49,7 @@ suneditor.create("sample1", { let s1 = suneditor.create('editor', { plugins: plugins, - mode: 'balloon-always', + // mode: 'balloon-always', katex: Katex, // attributesWhitelist: 'style', buttonList: [ From f4c5e2a1efca4540de1737cf1753ffbe777b9485 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Wed, 11 Mar 2020 22:20:02 +0900 Subject: [PATCH 97/99] update sample --- README.md | 5 +-- sample/html/customPlugins.html | 58 ++++++++++++++++++++++++++++++++-- sample/html/options.html | 2 +- sample/index.html | 14 ++++---- 4 files changed, 67 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index b2f0b6388..4411d3cec 100644 --- a/README.md +++ b/README.md @@ -317,8 +317,9 @@ addTagsWhitelist : Add tags to the default tags whitelist of editor. defaul pasteTagsWhitelist : Whitelist of tags when pasting. default: _editorTagsWhitelist {String} ex) 'p|h[1-6]' attributesWhitelist : Add attributes whitelist of tags that should be kept undeleted from the editor. - // Base whitelist: 'contenteditable|colspan|rowspan|target|href|src|class|type' - // Attributes used in the editor: 'data-format|data-size|data-file-size|data-file-name|data-origin|data-align|data-image-link|data-rotate|data-proportion|data-percentage|origin-size' + // -- Fixed whitelist -- + // Native attributes: 'contenteditable|colspan|rowspan|target|href|src|class|type' + // Editor attributes: 'data-format|data-size|data-file-size|data-file-name|data-origin|data-align|data-image-link|data-rotate|data-proportion|data-percentage|origin-size' ex) { 'all': 'style', // Apply to all tags 'input': 'checked' // Apply to input tag diff --git a/sample/html/customPlugins.html b/sample/html/customPlugins.html index abc0da7aa..35283e25a 100644 --- a/sample/html/customPlugins.html +++ b/sample/html/customPlugins.html @@ -24,11 +24,17 @@ font-size: 15px; transition: 0.4s; } - - .active, .accordion:hover { + .accordion.active, .accordion:hover { background-color: #ffc449; } + .acc-desc { + background-color: #ffafaf; + } + .acc-desc.active, .acc-desc:hover { + background-color: #fc6868; + } + .panel { padding: 0; background-color: black; @@ -94,6 +100,54 @@
    + + +
    +
    // Define custom plugin
    +var customPlugin = {
    +    // @Required common
    +    name: 'custom_example',
    +    display: ('container' || 'command' || 'submenu' || 'dialog'),
    +    add: (core, targetElement) {},
    +    ...
    +}
    +
    +SUNEDITOR.create(document.getElementById('ex_custom'), {
    +    // --- When using CDN ---
    +    plugins: [customPlugin],
    +    
    +    // --- When using node.js ---
    +    plugins: [custom_container, plugins.blockquote, plugins.link],
    +    // ------ all plguins
    +    plugins: {
    +        ...plugins,
    +        ...{custom_container}
    +    },
    +    
    +    // --- Add button list ---
    +    buttonList: [
    +        [
    +            {
    +                // plugin's name attribute
    +                name: 'custom_example', 
    +                // name of the plugin to be recognized by the toolbar.
    +                // It must be the same as the name attribute of the plugin 
    +                dataCommand: 'custom_example',
    +                // button's class ("se-btn" class is registered, basic button click css is applied.)
    +                buttonClass:'', 
    +                // HTML title attribute
    +                title: 'Custom plugin', 
    +                // Enter the "display" attribute value of your custom plugin.
    +                dataDisplay: ('container' || 'command' || 'submenu' || 'dialog'),
    +                // HTML to be append to button
    +                innerHTML:'<i class="se-icon-add"></i>'
    +            }
    +        ]
    +    ]
    +})
    +
    + +

    1. Plugins container

    diff --git a/sample/html/options.html b/sample/html/options.html index 3328c379d..57749590a 100644 --- a/sample/html/options.html +++ b/sample/html/options.html @@ -276,8 +276,8 @@

    --ETC

    -

    Applied options

    +
    console.log.apply(console, options);
    diff --git a/sample/index.html b/sample/index.html index c927ce862..879641bab 100644 --- a/sample/index.html +++ b/sample/index.html @@ -123,7 +123,7 @@

    Here is an example of math -> i=1k+1i\displaystyle\sum_{i=1}^{k+1}i 123

    Sunset image

    Insert description

    The Suneditor is based on pure JavaScript, with no dependencies.

    -
    Suneditor is a lightweight, flexible, customizable WYSIWYG text editor for your web applications.
    +
    Suneditor is a lightweight, flexible, customizable WYSIWYG text editor for your web applications.

    Supports Chrome, Safari, Opera, Firefox, Edge, IE11, Mobile web browser.

    SunEditor distributed under the MIT license.


    @@ -142,7 +142,7 @@

    The Suneditor is based on pure JavaScript, with no dependencies.


    - +
    @@ -156,7 +156,7 @@

    The Suneditor is based on pure JavaScript, with no dependencies.

    @@ -167,16 +167,16 @@

    The Suneditor is based on pure JavaScript, with no dependencies.

    Sunset image

    Insert description


    -
    + -
    + < id="balloon" class="tabcontent">
    @@ -187,7 +187,7 @@

    The Suneditor is based on pure JavaScript, with no dependencies.

    From cf59f482d5ccd841aa8dd721ef24245fc65c0c93 Mon Sep 17 00:00:00 2001 From: JiHong88 <0125ses@hanmail.net> Date: Wed, 11 Mar 2020 22:29:03 +0900 Subject: [PATCH 98/99] fix: sample index --- sample/index.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sample/index.html b/sample/index.html index 879641bab..2fa8969e3 100644 --- a/sample/index.html +++ b/sample/index.html @@ -142,7 +142,7 @@

    The Suneditor is based on pure JavaScript, with no dependencies.


    - +
    @@ -167,9 +167,9 @@

    The Suneditor is based on pure JavaScript, with no dependencies.

    Sunset image

    Insert description


    - +
    - < id="balloon" class="tabcontent"> +