suneditor 2.42.0 → 2.43.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/lib/core.js CHANGED
@@ -40,6 +40,9 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
40
40
  _w: _w,
41
41
  _parser: new _w.DOMParser(),
42
42
  _prevRtl: options.rtl,
43
+ _editorHeight: 0,
44
+ _listCamel: options.__listCommonStyle,
45
+ _listKebab: util.camelToKebabCase(options.__listCommonStyle),
43
46
 
44
47
  /**
45
48
  * @description Document object of the iframe if created as an iframe || _d
@@ -1056,12 +1059,12 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
1056
1059
  if (startOff > startCon.textContent.length) startOff = startCon.textContent.length;
1057
1060
  if (endOff > endCon.textContent.length) endOff = endCon.textContent.length;
1058
1061
  if (util.isFormatElement(startCon)) {
1059
- startCon = startCon.childNodes[startOff] || startCon;
1060
- startOff = 0;
1062
+ startCon = startCon.childNodes[startOff] || startCon.childNodes[startOff - 1] || startCon;
1063
+ startOff = startOff > 0 ? startCon.nodeType === 1 ? 1 : startCon.textContent ? startCon.textContent.length : 0 : 0;
1061
1064
  }
1062
1065
  if (util.isFormatElement(endCon)) {
1063
- endCon = endCon.childNodes[endOff] || endCon;
1064
- endOff = startOff > 1 ? startOff : 0;
1066
+ endCon = endCon.childNodes[endOff] || endCon.childNodes[endOff - 1] || endCon;
1067
+ endOff = endOff > 0 ? endCon.nodeType === 1 ? 1 : endCon.textContent ? endCon.textContent.length : 0 : 0;
1065
1068
  }
1066
1069
 
1067
1070
  const range = this._wd.createRange();
@@ -1876,7 +1879,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
1876
1879
  this.setRange(oNode, newRange.startOffset, oNode, newRange.endOffset);
1877
1880
 
1878
1881
  return newRange;
1879
- } else if (!util.isBreak(oNode) && util.isFormatElement(parentNode)) {
1882
+ } else if (!util.isBreak(oNode) && !util.isListCell(oNode) && util.isFormatElement(parentNode)) {
1880
1883
  let zeroWidth = null;
1881
1884
  if (!oNode.previousSibling || util.isBreak(oNode.previousSibling)) {
1882
1885
  zeroWidth = util.createTextNode(util.zeroWidthSpace);
@@ -2585,8 +2588,9 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
2585
2588
  let endCon = range.endContainer;
2586
2589
  let endOff = range.endOffset;
2587
2590
 
2588
- if ((isRemoveFormat && range.collapsed && util.isFormatElement(startCon.parentNode) && util.isFormatElement(endCon.parentNode)) || (startCon === endCon && startCon.nodeType === 1 && util.isNonEditable(startCon))) {
2589
- return;
2591
+ if ((isRemoveFormat && range.collapsed && util.isFormatElement(startCon.parentNode)) || (startCon === endCon && startCon.nodeType === 1 && util.isNonEditable(startCon))) {
2592
+ const format = startCon.parentNode;
2593
+ if (!util.isListCell(format) || !util.getValues(format.style).some(function(k) { return this._listKebab.indexOf(k) > -1; }.bind(this))) return;
2590
2594
  }
2591
2595
 
2592
2596
  if (range.collapsed && !isRemoveFormat) {
@@ -2806,6 +2810,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
2806
2810
 
2807
2811
  // one line
2808
2812
  if (oneLine) {
2813
+ this._resetCommonListCell(lineNodes[0], styleArray);
2809
2814
  const newRange = this._nodeChange_oneLine(lineNodes[0], newNode, validation, startCon, startOff, endCon, endOff, isRemoveFormat, isRemoveNode, range.collapsed, _removeCheck, _getMaintainedNode, _isMaintainedNode);
2810
2815
  start.container = newRange.startContainer;
2811
2816
  start.offset = newRange.startOffset;
@@ -2818,12 +2823,14 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
2818
2823
  } else { // multi line
2819
2824
  // end
2820
2825
  if (endLength > 0) {
2826
+ this._resetCommonListCell(lineNodes[endLength], styleArray);
2821
2827
  newNode = appendNode.cloneNode(false);
2822
2828
  end = this._nodeChange_endLine(lineNodes[endLength], newNode, validation, endCon, endOff, isRemoveFormat, isRemoveNode, _removeCheck, _getMaintainedNode, _isMaintainedNode);
2823
2829
  }
2824
2830
 
2825
2831
  // mid
2826
2832
  for (let i = endLength - 1, newRange; i > 0; i--) {
2833
+ this._resetCommonListCell(lineNodes[i], styleArray);
2827
2834
  newNode = appendNode.cloneNode(false);
2828
2835
  newRange = this._nodeChange_middleLine(lineNodes[i], newNode, validation, isRemoveFormat, isRemoveNode, _removeCheck, end.container);
2829
2836
  if (newRange.endContainer && newRange.ancestor.contains(newRange.endContainer)) {
@@ -2834,6 +2841,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
2834
2841
  }
2835
2842
 
2836
2843
  // start
2844
+ this._resetCommonListCell(lineNodes[0], styleArray);
2837
2845
  newNode = appendNode.cloneNode(false);
2838
2846
  start = this._nodeChange_startLine(lineNodes[0], newNode, validation, startCon, startOff, isRemoveFormat, isRemoveNode, _removeCheck, _getMaintainedNode, _isMaintainedNode, end.container);
2839
2847
 
@@ -2862,6 +2870,55 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
2862
2870
  this.history.push(false);
2863
2871
  },
2864
2872
 
2873
+ /**
2874
+ * @description Reset common style of list cell
2875
+ * @param {Element} el List cell element. <li>
2876
+ * @param {Array|null} styleArray Style array
2877
+ * @private
2878
+ */
2879
+ _resetCommonListCell: function (el, styleArray) {
2880
+ if (!util.isListCell(el)) return;
2881
+ if (!styleArray) styleArray = this._listKebab;
2882
+
2883
+ const children = util.getArrayItem((el).childNodes, function (current) { return !util.isBreak(current); }, true);
2884
+ const elStyles = el.style;
2885
+
2886
+ const ec = [], ek = [], elKeys = util.getValues(elStyles);
2887
+ for (let i = 0, len = this._listKebab.length; i < len; i++) {
2888
+ if (elKeys.indexOf(this._listKebab[i]) > -1 && styleArray.indexOf(this._listKebab[i]) > -1) {
2889
+ ec.push(this._listCamel[i]);
2890
+ ek.push(this._listKebab[i]);
2891
+ }
2892
+ }
2893
+
2894
+ if (!ec.length) return;
2895
+
2896
+ // reset cell style---
2897
+ const refer = util.createElement('SPAN');
2898
+ for (let i = 0, len = ec.length; i < len; i++) {
2899
+ refer.style[ec[i]] = elStyles[ek[i]];
2900
+ elStyles.removeProperty(ek[i]);
2901
+ }
2902
+
2903
+ let sel = refer.cloneNode(false);
2904
+ let r = null;
2905
+ for (let i = 0, len = children.length, c, s; i < len; i++) {
2906
+ c = children[i];
2907
+ s = util.getValues(c.style);
2908
+ if (s.length === 0 || (ec.some(function (k) {return s.indexOf(k) === -1;}) && s.some(function(k) {ec.indexOf(k) > -1;}))) {
2909
+ r = c.nextSibling;
2910
+ sel.appendChild(c);
2911
+ } else if (sel.childNodes.length > 0) {
2912
+ el.insertBefore(sel, r);
2913
+ sel = refer.cloneNode(false);
2914
+ r = null;
2915
+ }
2916
+ }
2917
+
2918
+ if (sel.childNodes.length > 0) el.insertBefore(sel, r);
2919
+ if (!elStyles.length) el.removeAttribute('style');
2920
+ },
2921
+
2865
2922
  /**
2866
2923
  * @description If certain styles are applied to all child nodes of the list cell, the style of the list cell is also changed. (bold, color, size)
2867
2924
  * @param {Element} el List cell element. <li>
@@ -2870,27 +2927,47 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
2870
2927
  */
2871
2928
  _setCommonListStyle: function (el, child) {
2872
2929
  if (!util.isListCell(el)) return;
2873
- if (!child) el.removeAttribute('style');
2874
2930
 
2875
2931
  const children = util.getArrayItem((child || el).childNodes, function (current) { return !util.isBreak(current); }, true);
2876
- if (children[0] && children.length === 1){
2877
- child = children[0];
2878
- if (!child || child.nodeType !== 1) return;
2932
+ child = children[0];
2933
+
2934
+ if (!child || children.length > 1 || child.nodeType !== 1) return;
2935
+
2936
+ // set cell style---
2937
+ const commonStyleElements = [];
2938
+ const childStyle = child.style;
2939
+ const elStyle = el.style;
2879
2940
 
2880
- const childStyle = child.style;
2881
- const elStyle = el.style;
2941
+ // bold, italic
2942
+ if (options._textTagsMap[child.nodeName.toLowerCase()] === this._defaultCommand.bold.toLowerCase()) elStyle.fontWeight = 'bold'; // bold
2943
+ else if (childStyle.fontWeight) elStyle.fontWeight = childStyle.fontWeight;
2944
+ if (options._textTagsMap[child.nodeName.toLowerCase()] === this._defaultCommand.italic.toLowerCase()) elStyle.fontStyle = 'italic'; // italic
2945
+ else if (childStyle.fontStyle) elStyle.fontStyle = childStyle.fontStyle;
2882
2946
 
2883
- // bold, italic
2884
- if (options._textTagsMap[child.nodeName.toLowerCase()] === this._defaultCommand.bold.toLowerCase()) elStyle.fontWeight = 'bold'; // bold
2885
- else if (childStyle.fontWeight) elStyle.fontWeight = childStyle.fontWeight;
2886
- if (options._textTagsMap[child.nodeName.toLowerCase()] === this._defaultCommand.italic.toLowerCase()) elStyle.fontStyle = 'italic'; // italic
2887
- else if (childStyle.fontStyle) elStyle.fontStyle = childStyle.fontStyle;
2947
+ // styles
2948
+ const cKeys = util.getValues(childStyle);
2949
+ for (let i = 0, len = this._listCamel.length; i < len; i++) {
2950
+ if (cKeys.indexOf(this._listKebab[i]) > -1) {
2951
+ elStyle[this._listCamel[i]] = childStyle[this._listCamel[i]];
2952
+ childStyle.removeProperty(this._listKebab[i]);
2953
+ }
2954
+ }
2955
+
2956
+ // remove child
2957
+ if (!childStyle.length) commonStyleElements.push(child);
2888
2958
 
2889
- // styles
2890
- if (childStyle.color) elStyle.color = childStyle.color; // color
2891
- if (childStyle.fontSize) elStyle.fontSize = childStyle.fontSize; // size
2959
+ this._setCommonListStyle(el, child);
2892
2960
 
2893
- this._setCommonListStyle(el, child);
2961
+ // common style
2962
+ for (let i = 0, len = commonStyleElements.length, n, ch, p; i < len; i++) {
2963
+ n = commonStyleElements[i];
2964
+ ch = n.childNodes;
2965
+ p = n.parentNode;
2966
+ n = n.nextSibling;
2967
+ while (ch.length > 0) {
2968
+ p.insertBefore(ch[0], n);
2969
+ }
2970
+ util.removeItem(commonStyleElements[i]);
2894
2971
  }
2895
2972
  },
2896
2973
 
@@ -2983,6 +3060,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
2983
3060
  util.copyTagAttributes(parentCon, newInnerNode);
2984
3061
 
2985
3062
  return {
3063
+ ancestor: element,
2986
3064
  startContainer: startCon,
2987
3065
  startOffset: startOff,
2988
3066
  endContainer: endCon,
@@ -4638,8 +4716,8 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
4638
4716
  _w.setTimeout(function () {
4639
4717
  try {
4640
4718
  iframe.focus();
4641
- // IE or Edge
4642
- if (util.isIE_Edge || !!_d.documentMode || !!_w.StyleMedia) {
4719
+ // IE or Edge, Chromium
4720
+ if (util.isIE_Edge || util.isChromium || !!_d.documentMode || !!_w.StyleMedia) {
4643
4721
  try {
4644
4722
  iframe.contentWindow.document.execCommand('print', false, null);
4645
4723
  } catch (e) {
@@ -4828,6 +4906,16 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
4828
4906
  }
4829
4907
  },
4830
4908
 
4909
+ /**
4910
+ * @description Gets the current contents with containing parent div(div.sun-editor-editable).
4911
+ * <div class="sun-editor-editable">{contents}</div>
4912
+ * @param {Boolean} onlyContents Return only the contents of the body without headers when the "fullPage" option is true
4913
+ * @returns {String}
4914
+ */
4915
+ getFullContents: function (onlyContents) {
4916
+ return '<div class="sun-editor-editable' + (options.rtl ? ' se-rtl' : '') + '">' + this.getContents(onlyContents) + '</div>';
4917
+ },
4918
+
4831
4919
  /**
4832
4920
  * @description Returns HTML string according to tag type and configuration.
4833
4921
  * Use only "cleanHTML"
@@ -5060,9 +5148,10 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5060
5148
  }
5061
5149
 
5062
5150
  const domTree = dom.childNodes;
5063
- let cleanHTML = '';
5064
- for (let i = 0, t, p; i < domTree.length; i++) {
5151
+ let cleanHTML = '', p = null;
5152
+ for (let i = 0, t; i < domTree.length; i++) {
5065
5153
  t = domTree[i];
5154
+
5066
5155
  if (!util.isFormatElement(t) && !util.isComponent(t) && !util.isMedia(t)) {
5067
5156
  if (!p) p = util.createElement(options.defaultTag);
5068
5157
  p.appendChild(t);
@@ -5074,8 +5163,14 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5074
5163
  p = null;
5075
5164
  }
5076
5165
  }
5166
+
5167
+ if (p) {
5168
+ cleanHTML += this._makeLine(p, true);
5169
+ p = null;
5170
+ }
5077
5171
  cleanHTML += this._makeLine(t, true);
5078
5172
  }
5173
+ if (p) cleanHTML += this._makeLine(p, true);
5079
5174
 
5080
5175
  if (cleanHTML.length === 0) return '<' + options.defaultTag + '><br></' + options.defaultTag + '>';
5081
5176
 
@@ -5238,6 +5333,36 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5238
5333
  return /byte/.test(charCounterType) ? util.getByteLength(content) : content.length;
5239
5334
  },
5240
5335
 
5336
+ /**
5337
+ * @description Reset buttons of the responsive toolbar.
5338
+ */
5339
+ resetResponsiveToolbar: function () {
5340
+ core.controllersOff();
5341
+
5342
+ const responsiveSize = event._responsiveButtonSize;
5343
+ if (responsiveSize) {
5344
+ let w = 0;
5345
+ if ((core._isBalloon || core._isInline) && options.toolbarWidth === 'auto') {
5346
+ w = context.element.topArea.offsetWidth;
5347
+ } else {
5348
+ w = context.element.toolbar.offsetWidth;
5349
+ }
5350
+
5351
+ let responsiveWidth = 'default';
5352
+ for (let i = 1, len = responsiveSize.length; i < len; i++) {
5353
+ if (w < responsiveSize[i]) {
5354
+ responsiveWidth = responsiveSize[i] + '';
5355
+ break;
5356
+ }
5357
+ }
5358
+
5359
+ if (event._responsiveCurrentSize !== responsiveWidth) {
5360
+ event._responsiveCurrentSize = responsiveWidth;
5361
+ functions.setToolbarButtons(event._responsiveButtons[responsiveWidth]);
5362
+ }
5363
+ }
5364
+ },
5365
+
5241
5366
  /**
5242
5367
  * @description Set the char count to charCounter element textContent.
5243
5368
  * @private
@@ -5337,6 +5462,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5337
5462
  this._wd = _d;
5338
5463
  this._charTypeHTML = options.charCounterType === 'byte-html';
5339
5464
  this.wwComputedStyle = _w.getComputedStyle(context.element.wysiwyg);
5465
+ this._editorHeight = context.element.wysiwygFrame.offsetHeight;
5340
5466
 
5341
5467
  if (!options.iframe && typeof _w.ShadowRoot === 'function') {
5342
5468
  let child = context.element.wysiwygFrame;
@@ -5439,7 +5565,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5439
5565
  if (!util.hasOwn(plugins, key)) continue;
5440
5566
  plugin = plugins[key];
5441
5567
  button = pluginCallButtons[key];
5442
- if (plugin.active && button) {
5568
+ if ((plugin.active || plugin.action) && button) {
5443
5569
  this.callPlugin(key, null, button);
5444
5570
  }
5445
5571
  if (typeof plugin.checkFileInfo === 'function' && typeof plugin.resetFileInfo === 'function') {
@@ -5465,8 +5591,8 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5465
5591
 
5466
5592
  this.managedTagsInfo.query = managedClass.toString();
5467
5593
  this._fileManager.queryString = this._fileManager.tags.join(',');
5468
- this._fileManager.regExp = new wRegExp('^(' + this._fileManager.tags.join('|') + ')$', 'i');
5469
- this._fileManager.pluginRegExp = new wRegExp('^(' + (filePluginRegExp.length === 0 ? 'undefined' : filePluginRegExp.join('|')) + ')$', 'i');
5594
+ this._fileManager.regExp = new wRegExp('^(' + (this._fileManager.tags.join('|') || '^') + ')$', 'i');
5595
+ this._fileManager.pluginRegExp = new wRegExp('^(' + (filePluginRegExp.length === 0 ? '^' : filePluginRegExp.join('|')) + ')$', 'i');
5470
5596
 
5471
5597
  // cache editor's element
5472
5598
  this._variable._originCssText = context.element.topArea.style.cssText;
@@ -5559,7 +5685,21 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5559
5685
  */
5560
5686
  _iframeAutoHeight: function () {
5561
5687
  if (this._iframeAuto) {
5562
- _w.setTimeout(function () { context.element.wysiwygFrame.style.height = core._iframeAuto.offsetHeight + 'px'; });
5688
+ _w.setTimeout(function () {
5689
+ const h = core._iframeAuto.offsetHeight;
5690
+ context.element.wysiwygFrame.style.height = h + 'px';
5691
+ if (util.isIE) core.__callResizeFunction(h, null);
5692
+ });
5693
+ } else if (util.isIE) {
5694
+ core.__callResizeFunction(context.element.wysiwygFrame.offsetHeight, null);
5695
+ }
5696
+ },
5697
+
5698
+ __callResizeFunction: function (h, resizeObserverEntry) {
5699
+ h = h === -1 ? resizeObserverEntry.borderBoxSize[0].blockSize : h;
5700
+ if (this._editorHeight !== h) {
5701
+ if (typeof functions.onResizeEditor === 'function') functions.onResizeEditor(h, this._editorHeight, core, resizeObserverEntry);
5702
+ this._editorHeight = h;
5563
5703
  }
5564
5704
  },
5565
5705
 
@@ -5703,6 +5843,9 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5703
5843
  this._resourcesStateChange();
5704
5844
 
5705
5845
  _w.setTimeout(function () {
5846
+ // observer
5847
+ if (event._resizeObserver) event._resizeObserver.observe(context.element.wysiwygFrame);
5848
+ if (event._toolbarObserver) event._toolbarObserver.observe(context.element._toolbarShadow);
5706
5849
  // user event
5707
5850
  if (typeof functions.onload === 'function') functions.onload(core, reload);
5708
5851
  });
@@ -5719,6 +5862,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5719
5862
  _top: contextEl.topArea,
5720
5863
  _relative: contextEl.relative,
5721
5864
  _toolBar: contextEl.toolbar,
5865
+ _toolbarShadow: contextEl._toolbarShadow,
5722
5866
  _menuTray: contextEl._menuTray,
5723
5867
  _editorArea: contextEl.editorArea,
5724
5868
  _wysiwygArea: contextEl.wysiwygFrame,
@@ -5821,7 +5965,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5821
5965
  break;
5822
5966
  }
5823
5967
 
5824
- if (!command) return false;
5968
+ if (!command) return keyStr === 'B'; // chromium - bold disabled
5825
5969
 
5826
5970
  core.commandHandler(core.commandMap[command], command);
5827
5971
  return true;
@@ -5885,7 +6029,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
5885
6029
  }
5886
6030
 
5887
6031
  /** default active buttons [strong, ins, em, del, sub, sup] */
5888
- if (classOnCheck.test(nodeName)) {
6032
+ if (classOnCheck && classOnCheck.test(nodeName)) {
5889
6033
  commandMapNodes.push(nodeName);
5890
6034
  util.addClass(commandMap[nodeName], 'active');
5891
6035
  }
@@ -6005,7 +6149,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
6005
6149
  }
6006
6150
 
6007
6151
  const figcaption = util.getParentElement(targetElement, 'FIGCAPTION');
6008
- if (util.isNonEditable(figcaption)) {
6152
+ if (figcaption && (util.isNonEditable(figcaption) || !figcaption.getAttribute("contenteditable"))) {
6009
6153
  e.preventDefault();
6010
6154
  figcaption.setAttribute('contenteditable', true);
6011
6155
  figcaption.focus();
@@ -6795,7 +6939,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
6795
6939
  temp = !temp ? newFormat.firstChild : temp.appendChild(newFormat.firstChild);
6796
6940
  core.setRange(temp, 0, temp, 0);
6797
6941
  break;
6798
- } else if (options.lineAttrReset && formatEl) {
6942
+ } else if (options.lineAttrReset && formatEl && !util.isListCell(formatEl)) {
6799
6943
  e.preventDefault();
6800
6944
  e.stopPropagation();
6801
6945
 
@@ -6817,7 +6961,8 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
6817
6961
  newEl = util.splitElement(r.container, r.offset, 0);
6818
6962
  }
6819
6963
  } else {
6820
- newEl = util.splitElement(range.endContainer, range.endOffset, 0);
6964
+ if (util.onlyZeroWidthSpace(formatEl)) newEl = core.appendFormatTag(formatEl, formatEl.cloneNode(false));
6965
+ else newEl = util.splitElement(range.endContainer, range.endOffset, 0);
6821
6966
  }
6822
6967
 
6823
6968
  const resetAttr = options.lineAttrReset === '*' ? null : options.lineAttrReset;
@@ -7077,7 +7222,7 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
7077
7222
  onFocus_wysiwyg: function (e) {
7078
7223
  if (core._antiBlur) return;
7079
7224
  core.hasFocus = true;
7080
- event._applyTagEffects();
7225
+ _w.setTimeout(event._applyTagEffects);
7081
7226
 
7082
7227
  if (core._isInline) event._showToolbarInline();
7083
7228
 
@@ -7107,7 +7252,6 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
7107
7252
  core.submenuOff();
7108
7253
  core.controllersOff();
7109
7254
 
7110
- const prevHeight = util.getNumber(context.element.wysiwygFrame.style.height, 0);
7111
7255
  core._variable.resizeClientY = e.clientY;
7112
7256
  context.element.resizeBackground.style.display = 'block';
7113
7257
 
@@ -7115,7 +7259,6 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
7115
7259
  context.element.resizeBackground.style.display = 'none';
7116
7260
  _d.removeEventListener('mousemove', event._resize_editor);
7117
7261
  _d.removeEventListener('mouseup', closureFunc);
7118
- if (typeof functions.onResizeEditor === 'function') functions.onResizeEditor(util.getNumber(context.element.wysiwygFrame.style.height, 0), prevHeight, core);
7119
7262
  }
7120
7263
 
7121
7264
  _d.addEventListener('mousemove', event._resize_editor);
@@ -7124,35 +7267,14 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
7124
7267
 
7125
7268
  _resize_editor: function (e) {
7126
7269
  const resizeInterval = context.element.editorArea.offsetHeight + (e.clientY - core._variable.resizeClientY);
7127
- context.element.wysiwygFrame.style.height = context.element.code.style.height = (resizeInterval < core._variable.minResizingSize ? core._variable.minResizingSize : resizeInterval) + 'px';
7270
+ const h = (resizeInterval < core._variable.minResizingSize ? core._variable.minResizingSize : resizeInterval);
7271
+ context.element.wysiwygFrame.style.height = context.element.code.style.height = h + 'px';
7128
7272
  core._variable.resizeClientY = e.clientY;
7273
+ if (util.isIE) core.__callResizeFunction(h, null);
7129
7274
  },
7130
7275
 
7131
7276
  onResize_window: function () {
7132
- core.controllersOff();
7133
-
7134
- const responsiveSize = event._responsiveButtonSize;
7135
- if (responsiveSize) {
7136
- let w = 0;
7137
- if ((core._isBalloon || core._isInline) && options.toolbarWidth === 'auto') {
7138
- w = context.element.topArea.offsetWidth;
7139
- } else {
7140
- w = context.element.toolbar.offsetWidth;
7141
- }
7142
-
7143
- let responsiveWidth = 'default';
7144
- for (let i = 1, len = responsiveSize.length; i < len; i++) {
7145
- if (w < responsiveSize[i]) {
7146
- responsiveWidth = responsiveSize[i] + '';
7147
- break;
7148
- }
7149
- }
7150
-
7151
- if (event._responsiveCurrentSize !== responsiveWidth) {
7152
- event._responsiveCurrentSize = responsiveWidth;
7153
- functions.setToolbarButtons(event._responsiveButtons[responsiveWidth]);
7154
- }
7155
- }
7277
+ if (util.isIE) core.resetResponsiveToolbar();
7156
7278
 
7157
7279
  if (context.element.toolbar.offsetWidth === 0) return;
7158
7280
 
@@ -7465,11 +7587,39 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
7465
7587
  }
7466
7588
 
7467
7589
  if (cleanData) {
7590
+ if (util.isListCell(util.getFormatElement(core.getSelectionNode(), null))) {
7591
+ const dom = (_d.createRange().createContextualFragment(cleanData));
7592
+ if (dom.childNodes[0].nodeType === 1) {
7593
+ cleanData = event._convertListCell(dom);
7594
+ }
7595
+ }
7468
7596
  functions.insertHTML(cleanData, true, false);
7469
7597
  return false;
7470
7598
  }
7471
7599
  },
7472
7600
 
7601
+ _convertListCell: function (dom) {
7602
+ const domTree = dom.childNodes;
7603
+ let html = '';
7604
+
7605
+ for (let i = 0, len = domTree.length, node; i < len; i++) {
7606
+ node = domTree[i];
7607
+ if (node.nodeType === 1) {
7608
+ if (util.isFormatElement(node)) {
7609
+ html += '<li>' +(node.innerHTML.trim() || '<br>') + '</li>';
7610
+ } else if (util.isRangeFormatElement(node) && !util.isTable(node)) {
7611
+ html += event._convertListCell(node);
7612
+ } else {
7613
+ html += '<li>' + node.outerHTML + '</li>';
7614
+ }
7615
+ } else {
7616
+ html += '<li>' + (node.textContent || '<br>') + '</li>';
7617
+ }
7618
+ }
7619
+
7620
+ return html;
7621
+ },
7622
+
7473
7623
  onMouseMove_wysiwyg: function (e) {
7474
7624
  if (core.isDisabled || core.isReadOnly) return false;
7475
7625
  const component = util.getParentElement(e.target, util.isComponent);
@@ -7540,8 +7690,15 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
7540
7690
  core.history.push(false);
7541
7691
  },
7542
7692
 
7693
+ _resizeObserver: null,
7694
+ _toolbarObserver: null,
7543
7695
  _addEvent: function () {
7544
7696
  const eventWysiwyg = options.iframe ? core._ww : context.element.wysiwyg;
7697
+ if (!util.isIE) {
7698
+ this._resizeObserver = new _w.ResizeObserver(function(entries) {
7699
+ core.__callResizeFunction(-1, entries[0]);
7700
+ });
7701
+ }
7545
7702
 
7546
7703
  /** toolbar event */
7547
7704
  context.element.toolbar.addEventListener('mousedown', event._buttonsEventHandler, false);
@@ -7590,11 +7747,13 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
7590
7747
  }
7591
7748
  }
7592
7749
 
7593
- /** window event */
7750
+ /** set response toolbar */
7594
7751
  event._setResponsiveToolbar();
7595
- _w.removeEventListener('resize', event.onResize_window);
7596
- _w.removeEventListener('scroll', event.onScroll_window);
7597
7752
 
7753
+ /** responsive toolbar observer */
7754
+ if (!util.isIE) this._toolbarObserver = new _w.ResizeObserver(core.resetResponsiveToolbar);
7755
+
7756
+ /** window event */
7598
7757
  _w.addEventListener('resize', event.onResize_window, false);
7599
7758
  if (options.stickyToolbar > -1) {
7600
7759
  _w.addEventListener('scroll', event.onScroll_window, false);
@@ -7627,7 +7786,6 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
7627
7786
  event._lineBreakerBind = null;
7628
7787
 
7629
7788
  eventWysiwyg.removeEventListener('touchstart', event.onMouseDown_wysiwyg, {passive: true, useCapture: false});
7630
-
7631
7789
  eventWysiwyg.removeEventListener('focus', event.onFocus_wysiwyg);
7632
7790
  eventWysiwyg.removeEventListener('blur', event.onBlur_wysiwyg);
7633
7791
 
@@ -7639,6 +7797,16 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
7639
7797
  context.element.resizingBar.removeEventListener('mousedown', event.onMouseDown_resizingBar);
7640
7798
  }
7641
7799
 
7800
+ if (event._resizeObserver) {
7801
+ event._resizeObserver.unobserve(context.element.wysiwygFrame);
7802
+ event._resizeObserver = null;
7803
+ }
7804
+
7805
+ if (event._toolbarObserver) {
7806
+ event._toolbarObserver.unobserve(context.element._toolbarShadow);
7807
+ event._toolbarObserver = null;
7808
+ }
7809
+
7642
7810
  _w.removeEventListener('resize', event.onResize_window);
7643
7811
  _w.removeEventListener('scroll', event.onScroll_window);
7644
7812
  },
@@ -8166,6 +8334,8 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
8166
8334
  * @param {Boolean} rangeSelection If true, range select the inserted node.
8167
8335
  */
8168
8336
  insertHTML: function (html, notCleaningData, checkCharCount, rangeSelection) {
8337
+ if (!context.element.wysiwygFrame.contains(core.getSelection().focusNode)) core.focus();
8338
+
8169
8339
  if (typeof html === 'string') {
8170
8340
  if (!notCleaningData) html = core.cleanHTML(html, null, null);
8171
8341
  try {
@@ -8244,7 +8414,9 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
8244
8414
  const wysiwyg = context.element.wysiwyg;
8245
8415
  const children = temp.children;
8246
8416
  for (let i = 0, len = children.length; i < len; i++) {
8247
- wysiwyg.appendChild(children[i]);
8417
+ if (children[i]) {
8418
+ wysiwyg.appendChild(children[i]);
8419
+ }
8248
8420
  }
8249
8421
  } else {
8250
8422
  core._setCodeView(core._getCodeView() + '\n' + core.convertHTMLForCodeView(convertValue, false));
@@ -8272,8 +8444,10 @@ export default function (context, pluginCallButtons, plugins, lang, options, _re
8272
8444
  if (core.modalForm) core.plugins.dialog.close.call(core);
8273
8445
 
8274
8446
  context.element.code.setAttribute("readOnly", "true");
8447
+ util.addClass(context.element.wysiwygFrame, 'se-read-only');
8275
8448
  } else {
8276
8449
  context.element.code.removeAttribute("readOnly");
8450
+ util.removeClass(context.element.wysiwygFrame, 'se-read-only');
8277
8451
  }
8278
8452
 
8279
8453
  if (options.codeMirrorEditor) options.codeMirrorEditor.setOption('readOnly', !!value);
package/src/lib/util.d.ts CHANGED
@@ -29,6 +29,19 @@ declare interface util {
29
29
  */
30
30
  getXMLHttpRequest(): XMLHttpRequest | ActiveXObject;
31
31
 
32
+ /**
33
+ * @description Object.values
34
+ * @param obj Object parameter.
35
+ * @returns
36
+ */
37
+ getValues(obj?: any): any[];
38
+
39
+ /**
40
+ * @description Convert the CamelCase To the KebabCase.
41
+ * @param {String|Array} param [Camel string]
42
+ */
43
+ camelToKebabCase(param: string | string[]): string | string[],
44
+
32
45
  /**
33
46
  * @description Create Element node
34
47
  * @param elementName Element name