suneditor 3.0.0-beta.3 → 3.0.0-beta.30
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/CONTRIBUTING.md +8 -8
- package/README.md +44 -49
- package/dist/suneditor.min.css +1 -1
- package/dist/suneditor.min.js +1 -1
- package/package.json +95 -53
- package/src/assets/design/color.css +2 -2
- package/src/assets/design/size.css +2 -0
- package/src/assets/icons/defaultIcons.js +16 -1
- package/src/assets/suneditor-contents.css +9 -8
- package/src/assets/suneditor.css +29 -26
- package/src/core/{section → base}/actives.js +20 -12
- package/src/core/base/history.js +4 -4
- package/src/core/class/char.js +10 -10
- package/src/core/class/component.js +146 -57
- package/src/core/class/format.js +94 -2458
- package/src/core/class/html.js +187 -129
- package/src/core/class/inline.js +1853 -0
- package/src/core/class/listFormat.js +582 -0
- package/src/core/class/menu.js +14 -3
- package/src/core/class/nodeTransform.js +9 -14
- package/src/core/class/offset.js +162 -197
- package/src/core/class/selection.js +137 -34
- package/src/core/class/toolbar.js +73 -52
- package/src/core/class/ui.js +11 -11
- package/src/core/class/viewer.js +56 -55
- package/src/core/config/context.js +122 -0
- package/src/core/config/frameContext.js +204 -0
- package/src/core/config/options.js +639 -0
- package/src/core/editor.js +181 -108
- package/src/core/event/actions/index.js +229 -0
- package/src/core/event/effects/common.registry.js +60 -0
- package/src/core/event/effects/keydown.registry.js +551 -0
- package/src/core/event/effects/ruleHelpers.js +145 -0
- package/src/core/{base → event}/eventManager.js +119 -201
- package/src/core/event/executor.js +21 -0
- package/src/core/{base/eventHandlers → event/handlers}/handler_toolbar.js +4 -4
- package/src/core/{base/eventHandlers → event/handlers}/handler_ww_dragDrop.js +2 -2
- package/src/core/event/handlers/handler_ww_input.js +77 -0
- package/src/core/event/handlers/handler_ww_key.js +228 -0
- package/src/core/{base/eventHandlers → event/handlers}/handler_ww_mouse.js +3 -3
- package/src/core/event/ports.js +211 -0
- package/src/core/event/reducers/keydown.reducer.js +89 -0
- package/src/core/event/rules/keydown.rule.arrow.js +54 -0
- package/src/core/event/rules/keydown.rule.backspace.js +202 -0
- package/src/core/event/rules/keydown.rule.delete.js +126 -0
- package/src/core/event/rules/keydown.rule.enter.js +144 -0
- package/src/core/event/rules/keydown.rule.tab.js +29 -0
- package/src/core/section/constructor.js +79 -388
- package/src/core/section/documentType.js +47 -26
- package/src/core/util/instanceCheck.js +59 -0
- package/src/editorInjector/_classes.js +4 -0
- package/src/editorInjector/_core.js +17 -7
- package/src/editorInjector/index.js +10 -2
- package/src/events.js +6 -0
- package/src/helper/clipboard.js +24 -10
- package/src/helper/converter.js +17 -12
- package/src/helper/dom/domCheck.js +22 -3
- package/src/helper/dom/domQuery.js +91 -45
- package/src/helper/dom/domUtils.js +93 -19
- package/src/helper/dom/index.js +4 -0
- package/src/helper/env.js +11 -7
- package/src/helper/keyCodeMap.js +4 -3
- package/src/langs/ckb.js +1 -1
- package/src/langs/cs.js +1 -1
- package/src/langs/da.js +1 -1
- package/src/langs/de.js +1 -1
- package/src/langs/en.js +1 -1
- package/src/langs/es.js +1 -1
- package/src/langs/fa.js +1 -1
- package/src/langs/fr.js +1 -1
- package/src/langs/he.js +1 -1
- package/src/langs/hu.js +1 -1
- package/src/langs/it.js +1 -1
- package/src/langs/ja.js +1 -1
- package/src/langs/km.js +1 -1
- package/src/langs/ko.js +1 -1
- package/src/langs/lv.js +1 -1
- package/src/langs/nl.js +1 -1
- package/src/langs/pl.js +1 -1
- package/src/langs/pt_br.js +10 -10
- package/src/langs/ro.js +1 -1
- package/src/langs/ru.js +1 -1
- package/src/langs/se.js +1 -1
- package/src/langs/tr.js +1 -1
- package/src/langs/uk.js +1 -1
- package/src/langs/ur.js +1 -1
- package/src/langs/zh_cn.js +1 -1
- package/src/modules/ApiManager.js +25 -18
- package/src/modules/Browser.js +52 -61
- package/src/modules/ColorPicker.js +37 -38
- package/src/modules/Controller.js +85 -79
- package/src/modules/Figure.js +275 -187
- package/src/modules/FileManager.js +86 -92
- package/src/modules/HueSlider.js +67 -35
- package/src/modules/Modal.js +84 -77
- package/src/modules/ModalAnchorEditor.js +62 -79
- package/src/modules/SelectMenu.js +89 -86
- package/src/plugins/browser/audioGallery.js +9 -5
- package/src/plugins/browser/fileBrowser.js +10 -6
- package/src/plugins/browser/fileGallery.js +9 -5
- package/src/plugins/browser/imageGallery.js +9 -5
- package/src/plugins/browser/videoGallery.js +11 -6
- package/src/plugins/command/blockquote.js +1 -0
- package/src/plugins/command/exportPDF.js +11 -8
- package/src/plugins/command/fileUpload.js +41 -29
- package/src/plugins/command/list_bulleted.js +2 -1
- package/src/plugins/command/list_numbered.js +2 -1
- package/src/plugins/dropdown/align.js +8 -2
- package/src/plugins/dropdown/backgroundColor.js +19 -11
- package/src/plugins/dropdown/font.js +15 -9
- package/src/plugins/dropdown/fontColor.js +19 -11
- package/src/plugins/dropdown/formatBlock.js +7 -2
- package/src/plugins/dropdown/hr.js +7 -3
- package/src/plugins/dropdown/layout.js +6 -2
- package/src/plugins/dropdown/lineHeight.js +8 -3
- package/src/plugins/dropdown/list.js +2 -1
- package/src/plugins/dropdown/paragraphStyle.js +15 -11
- package/src/plugins/dropdown/{table.js → table/index.js} +514 -362
- package/src/plugins/dropdown/template.js +6 -2
- package/src/plugins/dropdown/textStyle.js +7 -3
- package/src/plugins/field/mention.js +33 -27
- package/src/plugins/input/fontSize.js +44 -37
- package/src/plugins/input/pageNavigator.js +3 -2
- package/src/plugins/modal/audio.js +90 -85
- package/src/plugins/modal/drawing.js +58 -66
- package/src/plugins/modal/embed.js +193 -180
- package/src/plugins/modal/image.js +441 -439
- package/src/plugins/modal/link.js +31 -8
- package/src/plugins/modal/math.js +23 -22
- package/src/plugins/modal/video.js +233 -230
- package/src/plugins/popup/anchor.js +24 -18
- package/src/suneditor.js +69 -24
- package/src/typedef.js +42 -19
- package/types/assets/icons/defaultIcons.d.ts +8 -0
- package/types/core/class/char.d.ts +1 -1
- package/types/core/class/component.d.ts +29 -7
- package/types/core/class/format.d.ts +4 -354
- package/types/core/class/html.d.ts +13 -4
- package/types/core/class/inline.d.ts +263 -0
- package/types/core/class/listFormat.d.ts +135 -0
- package/types/core/class/menu.d.ts +10 -2
- package/types/core/class/offset.d.ts +24 -26
- package/types/core/class/selection.d.ts +2 -0
- package/types/core/class/toolbar.d.ts +24 -11
- package/types/core/class/ui.d.ts +1 -1
- package/types/core/class/viewer.d.ts +1 -1
- package/types/core/config/context.d.ts +157 -0
- package/types/core/config/frameContext.d.ts +367 -0
- package/types/core/config/options.d.ts +1119 -0
- package/types/core/editor.d.ts +101 -66
- package/types/core/event/actions/index.d.ts +47 -0
- package/types/core/event/effects/common.registry.d.ts +50 -0
- package/types/core/event/effects/keydown.registry.d.ts +73 -0
- package/types/core/event/effects/ruleHelpers.d.ts +31 -0
- package/types/core/{base → event}/eventManager.d.ts +15 -46
- package/types/core/event/executor.d.ts +6 -0
- package/types/core/event/handlers/handler_ww_input.d.ts +41 -0
- package/types/core/{base/eventHandlers/handler_ww_key_input.d.ts → event/handlers/handler_ww_key.d.ts} +4 -6
- package/types/core/event/ports.d.ts +255 -0
- package/types/core/event/reducers/keydown.reducer.d.ts +75 -0
- package/types/core/event/rules/keydown.rule.arrow.d.ts +8 -0
- package/types/core/event/rules/keydown.rule.backspace.d.ts +9 -0
- package/types/core/event/rules/keydown.rule.delete.d.ts +9 -0
- package/types/core/event/rules/keydown.rule.enter.d.ts +9 -0
- package/types/core/event/rules/keydown.rule.tab.d.ts +9 -0
- package/types/core/section/constructor.d.ts +101 -631
- package/types/core/section/documentType.d.ts +14 -4
- package/types/core/util/instanceCheck.d.ts +50 -0
- package/types/editorInjector/_classes.d.ts +4 -0
- package/types/editorInjector/_core.d.ts +17 -7
- package/types/editorInjector/index.d.ts +10 -2
- package/types/events.d.ts +1 -0
- package/types/helper/clipboard.d.ts +2 -2
- package/types/helper/converter.d.ts +6 -9
- package/types/helper/dom/domCheck.d.ts +7 -0
- package/types/helper/dom/domQuery.d.ts +19 -8
- package/types/helper/dom/domUtils.d.ts +24 -2
- package/types/helper/dom/index.d.ts +86 -1
- package/types/helper/env.d.ts +6 -1
- package/types/helper/index.d.ts +7 -1
- package/types/helper/keyCodeMap.d.ts +3 -3
- package/types/index.d.ts +23 -117
- package/types/langs/index.d.ts +2 -2
- package/types/modules/ApiManager.d.ts +1 -8
- package/types/modules/Browser.d.ts +4 -62
- package/types/modules/ColorPicker.d.ts +4 -21
- package/types/modules/Controller.d.ts +8 -64
- package/types/modules/Figure.d.ts +54 -50
- package/types/modules/FileManager.d.ts +1 -13
- package/types/modules/HueSlider.d.ts +13 -3
- package/types/modules/Modal.d.ts +0 -43
- package/types/modules/ModalAnchorEditor.d.ts +0 -73
- package/types/modules/SelectMenu.d.ts +0 -85
- package/types/modules/index.d.ts +3 -3
- package/types/plugins/browser/audioGallery.d.ts +29 -18
- package/types/plugins/browser/fileBrowser.d.ts +38 -27
- package/types/plugins/browser/fileGallery.d.ts +29 -18
- package/types/plugins/browser/imageGallery.d.ts +24 -16
- package/types/plugins/browser/videoGallery.d.ts +29 -18
- package/types/plugins/command/blockquote.d.ts +1 -0
- package/types/plugins/command/exportPDF.d.ts +18 -18
- package/types/plugins/command/fileUpload.d.ts +65 -45
- package/types/plugins/command/list_bulleted.d.ts +1 -0
- package/types/plugins/command/list_numbered.d.ts +1 -0
- package/types/plugins/dropdown/align.d.ts +13 -8
- package/types/plugins/dropdown/backgroundColor.d.ts +30 -19
- package/types/plugins/dropdown/font.d.ts +13 -12
- package/types/plugins/dropdown/fontColor.d.ts +30 -19
- package/types/plugins/dropdown/formatBlock.d.ts +13 -8
- package/types/plugins/dropdown/hr.d.ts +15 -11
- package/types/plugins/dropdown/layout.d.ts +15 -11
- package/types/plugins/dropdown/lineHeight.d.ts +16 -11
- package/types/plugins/dropdown/list.d.ts +1 -0
- package/types/plugins/dropdown/paragraphStyle.d.ts +31 -27
- package/types/plugins/dropdown/table/index.d.ts +582 -0
- package/types/plugins/dropdown/table.d.ts +41 -86
- package/types/plugins/dropdown/template.d.ts +15 -11
- package/types/plugins/dropdown/textStyle.d.ts +19 -11
- package/types/plugins/field/mention.d.ts +58 -56
- package/types/plugins/index.d.ts +38 -38
- package/types/plugins/input/fontSize.d.ts +46 -50
- package/types/plugins/modal/audio.d.ts +26 -56
- package/types/plugins/modal/drawing.d.ts +0 -85
- package/types/plugins/modal/embed.d.ts +15 -79
- package/types/plugins/modal/image.d.ts +24 -136
- package/types/plugins/modal/link.d.ts +34 -15
- package/types/plugins/modal/math.d.ts +0 -16
- package/types/plugins/modal/video.d.ts +17 -86
- package/types/plugins/popup/anchor.d.ts +1 -8
- package/types/suneditor.d.ts +70 -19
- package/types/typedef.d.ts +60 -46
- package/src/core/base/eventHandlers/handler_ww_key_input.js +0 -1200
- package/src/core/section/context.js +0 -102
- package/types/core/section/context.d.ts +0 -45
- package/types/langs/_Lang.d.ts +0 -194
- /package/src/core/{base/eventHandlers → event/handlers}/handler_ww_clipboard.js +0 -0
- /package/types/core/{section → base}/actives.d.ts +0 -0
- /package/types/core/{base/eventHandlers → event/handlers}/handler_toolbar.d.ts +0 -0
- /package/types/core/{base/eventHandlers → event/handlers}/handler_ww_clipboard.d.ts +0 -0
- /package/types/core/{base/eventHandlers → event/handlers}/handler_ww_dragDrop.d.ts +0 -0
- /package/types/core/{base/eventHandlers → event/handlers}/handler_ww_mouse.d.ts +0 -0
|
@@ -104,7 +104,7 @@ class ColorPicker extends CoreInjector {
|
|
|
104
104
|
this.inputElement = /** @type {HTMLInputElement} */ (this.target.querySelector('.se-color-input'));
|
|
105
105
|
this.styleProperties = styles;
|
|
106
106
|
this.splitNum = params.splitNum || 0;
|
|
107
|
-
this.defaultColor = params.defaultColor;
|
|
107
|
+
this.defaultColor = params.defaultColor || '';
|
|
108
108
|
this.hueSliderOptions = params.hueSliderOptions;
|
|
109
109
|
this.parentDisplay = '';
|
|
110
110
|
this.currentColor = '';
|
|
@@ -123,7 +123,7 @@ class ColorPicker extends CoreInjector {
|
|
|
123
123
|
this.parentFormDisplay = [];
|
|
124
124
|
this.parentForm = params.hueSliderOptions?.controllerOptions?.parents?.length > 0 && !params.hueSliderOptions?.controllerOptions?.isInsideForm ? params.hueSliderOptions.controllerOptions.parents : null;
|
|
125
125
|
// hue open
|
|
126
|
-
this.eventManager.addEvent(this.target.querySelector('.
|
|
126
|
+
this.eventManager.addEvent(this.target.querySelector('.__se_hue'), 'click', this.#OnColorPalette.bind(this));
|
|
127
127
|
this.eventManager.addEvent(this.inputElement, 'input', this.#OnChangeInput.bind(this));
|
|
128
128
|
this.eventManager.addEvent(this.target.querySelector('form'), 'submit', this.#Submit.bind(this));
|
|
129
129
|
}
|
|
@@ -140,14 +140,15 @@ class ColorPicker extends CoreInjector {
|
|
|
140
140
|
* @description Displays or resets the currently selected color at color list.
|
|
141
141
|
* @param {Node|string} nodeOrColor Current Selected node
|
|
142
142
|
* @param {Node} target target
|
|
143
|
+
* @param {?((current: Node) => boolean)=} stopCondition - A function used to stop traversing parent nodes while finding the color.
|
|
144
|
+
* - When this function returns true, the traversal ends at that node.
|
|
145
|
+
* - e.g., `(node) => this.format.isLine(node)` stops at line-level elements like <p>, <div>.
|
|
143
146
|
*/
|
|
144
|
-
init(nodeOrColor, target) {
|
|
147
|
+
init(nodeOrColor, target, stopCondition) {
|
|
145
148
|
this.targetButton = target;
|
|
149
|
+
if (typeof stopCondition !== 'function') stopCondition = () => false;
|
|
146
150
|
|
|
147
|
-
|
|
148
|
-
const defaultColor = this.defaultColor || converter.isHexColor(computedColor) ? computedColor : converter.rgb2hex(computedColor);
|
|
149
|
-
|
|
150
|
-
let fillColor = (typeof nodeOrColor === 'string' ? nodeOrColor : this._getColorInNode(nodeOrColor)) || defaultColor;
|
|
151
|
+
let fillColor = (typeof nodeOrColor === 'string' ? nodeOrColor : this.#getColorInNode(nodeOrColor, stopCondition)) || this.defaultColor;
|
|
151
152
|
fillColor = converter.isHexColor(fillColor) ? fillColor : converter.rgb2hex(fillColor) || fillColor || '';
|
|
152
153
|
|
|
153
154
|
const colorList = this.colorList;
|
|
@@ -162,7 +163,7 @@ class ColorPicker extends CoreInjector {
|
|
|
162
163
|
}
|
|
163
164
|
}
|
|
164
165
|
|
|
165
|
-
this
|
|
166
|
+
this.#setInputText(this.#colorName2hex(fillColor));
|
|
166
167
|
}
|
|
167
168
|
|
|
168
169
|
/**
|
|
@@ -182,27 +183,45 @@ class ColorPicker extends CoreInjector {
|
|
|
182
183
|
}
|
|
183
184
|
|
|
184
185
|
/**
|
|
185
|
-
* @
|
|
186
|
+
* @editorMethod Modules.HueSlider
|
|
187
|
+
* @description This method is called when the color is selected in the hue slider.
|
|
188
|
+
* @param {HueSliderColor_colorPicker} color - Color object
|
|
189
|
+
*/
|
|
190
|
+
hueSliderAction(color) {
|
|
191
|
+
this.#setInputText(color.hex);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* @editorMethod Modules.HueSlider
|
|
196
|
+
* @description This method is called when the hue slider is closed.
|
|
197
|
+
*/
|
|
198
|
+
hueSliderCancelAction() {
|
|
199
|
+
if (this.parentForm?.length > 0) {
|
|
200
|
+
this.parentFormDisplay.forEach((e) => (e[0].style.display = e[1]));
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/**
|
|
186
205
|
* @description Set color at input element
|
|
187
206
|
* @param {string} hexColorStr Hax color value
|
|
188
207
|
*/
|
|
189
|
-
|
|
190
|
-
hexColorStr = /^#/.test(hexColorStr) ? hexColorStr : '#' + hexColorStr;
|
|
208
|
+
#setInputText(hexColorStr) {
|
|
209
|
+
hexColorStr = !hexColorStr || /^#/.test(hexColorStr) ? hexColorStr : '#' + hexColorStr;
|
|
191
210
|
this.inputElement.value = hexColorStr;
|
|
192
211
|
this.setHexColor.call(this, hexColorStr);
|
|
193
212
|
}
|
|
194
213
|
|
|
195
214
|
/**
|
|
196
|
-
* @private
|
|
197
215
|
* @description Gets color value at color property of node
|
|
198
216
|
* @param {Node} node Selected node
|
|
217
|
+
* @param {(current: Node) => boolean} stopCondition - A function used to stop traversing parent nodes while finding the color.
|
|
199
218
|
* @returns {string}
|
|
200
219
|
*/
|
|
201
|
-
|
|
220
|
+
#getColorInNode(node, stopCondition) {
|
|
202
221
|
let findColor = '';
|
|
203
222
|
const sp = this.styleProperties;
|
|
204
223
|
|
|
205
|
-
while (node && !dom.check.isWysiwygFrame(node) && findColor.length === 0) {
|
|
224
|
+
while (node && !stopCondition(node) && !dom.check.isWysiwygFrame(node) && findColor.length === 0) {
|
|
206
225
|
if (isElement(node) && node.style[sp]) findColor = node.style[sp];
|
|
207
226
|
node = node.parentNode;
|
|
208
227
|
}
|
|
@@ -211,13 +230,12 @@ class ColorPicker extends CoreInjector {
|
|
|
211
230
|
}
|
|
212
231
|
|
|
213
232
|
/**
|
|
214
|
-
* @private
|
|
215
233
|
* @description Converts color values of other formats to hex color values and returns.
|
|
216
234
|
* @param {string} colorName Color value
|
|
217
235
|
* @returns {string}
|
|
218
236
|
*/
|
|
219
|
-
|
|
220
|
-
if (/^#/.test(colorName)) return colorName;
|
|
237
|
+
#colorName2hex(colorName) {
|
|
238
|
+
if (!colorName || /^#/.test(colorName)) return colorName;
|
|
221
239
|
const temp = dom.utils.createElement('div', { style: 'display: none; color: ' + colorName });
|
|
222
240
|
const colors = this._w
|
|
223
241
|
.getComputedStyle(this._d.body.appendChild(temp))
|
|
@@ -229,25 +247,6 @@ class ColorPicker extends CoreInjector {
|
|
|
229
247
|
return colors.length >= 3 ? '#' + ((1 << 24) + (colors[0] << 16) + (colors[1] << 8) + colors[2]).toString(16).substring(1) : '';
|
|
230
248
|
}
|
|
231
249
|
|
|
232
|
-
/**
|
|
233
|
-
* @editorMethod Modules.HueSlider
|
|
234
|
-
* @description This method is called when the color is selected in the hue slider.
|
|
235
|
-
* @param {HueSliderColor_colorPicker} color - Color object
|
|
236
|
-
*/
|
|
237
|
-
hueSliderAction(color) {
|
|
238
|
-
this._setInputText(color.hex);
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
/**
|
|
242
|
-
* @editorMethod Modules.HueSlider
|
|
243
|
-
* @description This method is called when the hue slider is closed.
|
|
244
|
-
*/
|
|
245
|
-
hueSliderCancelAction() {
|
|
246
|
-
if (this.parentForm?.length > 0) {
|
|
247
|
-
this.parentFormDisplay.forEach((e) => (e[0].style.display = e[1]));
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
|
|
251
250
|
#OnColorPalette() {
|
|
252
251
|
if (this.parentForm?.length > 0) {
|
|
253
252
|
this.parentForm.forEach((e) => {
|
|
@@ -303,7 +302,7 @@ class ColorPicker extends CoreInjector {
|
|
|
303
302
|
* @returns
|
|
304
303
|
*/
|
|
305
304
|
function CreateHTML({ lang, icons }, { colorList, disableHEXInput, disableRemove, splitNum }) {
|
|
306
|
-
colorList
|
|
305
|
+
colorList ||= DEFAULT_COLOR_LIST;
|
|
307
306
|
splitNum = colorList === DEFAULT_COLOR_LIST ? DEFAULLT_COLOR_SPLITNUM : splitNum;
|
|
308
307
|
|
|
309
308
|
let list = '';
|
|
@@ -325,7 +324,7 @@ function CreateHTML({ lang, icons }, { colorList, disableHEXInput, disableRemove
|
|
|
325
324
|
}
|
|
326
325
|
list += /*html*/ `
|
|
327
326
|
<form class="se-form-group se-form-w0">
|
|
328
|
-
${disableHEXInput ? '' : `<button type="button" class="se-btn
|
|
327
|
+
${disableHEXInput ? '' : `<button type="button" class="se-btn __se_hue" title="${lang.colorPicker}" aria-label="${lang.colorPicker}">${icons.color_palette}</button>`}
|
|
329
328
|
<input type="text" class="se-color-input" ${disableHEXInput ? 'readonly' : ''} placeholder="${lang.color}" />
|
|
330
329
|
${disableHEXInput ? '' : `<button type="submit" class="se-btn se-btn-success" title="${lang.submitButton}" aria-label="${lang.submitButton}">${icons.checked}</button>`}
|
|
331
330
|
${disableRemove ? '' : `<button type="button" class="se-btn __se_remove" title="${lang.remove}" aria-label="${lang.remove}">${icons.remove_color}</button>`}
|
|
@@ -2,7 +2,7 @@ import EditorInjector from '../editorInjector';
|
|
|
2
2
|
import { dom, env, keyCodeMap } from '../helper';
|
|
3
3
|
import { _DragHandle } from '../modules';
|
|
4
4
|
|
|
5
|
-
const { _w, ON_OVER_COMPONENT } = env;
|
|
5
|
+
const { _w, isMobile, ON_OVER_COMPONENT } = env;
|
|
6
6
|
const INDEX_00 = '2147483646';
|
|
7
7
|
const INDEX_0 = '2147483645';
|
|
8
8
|
const INDEX_S_1 = '2147483641';
|
|
@@ -28,7 +28,9 @@ const INDEX_1 = '2147483640';
|
|
|
28
28
|
* @property {Array<HTMLElement>=} [parents=[]] The parent "controller" array when "controller" is opened nested.
|
|
29
29
|
* @property {boolean=} [parentsHide=false] If true, the parent element is hidden when the controller is opened.
|
|
30
30
|
* @property {HTMLElement=} [sibling=null] The related sibling controller element that this controller is positioned relative to.
|
|
31
|
-
*
|
|
31
|
+
* - e.g.) table plugin :: 118
|
|
32
|
+
* @property {boolean=} [siblingMain=false] If true, This sibling controller is the main controller.
|
|
33
|
+
* - You must specify this option, if use "sibling"
|
|
32
34
|
* @property {boolean=} [isInsideForm=false] If the controller is inside a form, set it to true.
|
|
33
35
|
* @property {boolean=} [isOutsideForm=false] If the controller is outside a form, set it to true.
|
|
34
36
|
*/
|
|
@@ -38,6 +40,16 @@ const INDEX_1 = '2147483640';
|
|
|
38
40
|
* @description Controller module class that handles the UI and interaction logic for a specific editor controller element.
|
|
39
41
|
*/
|
|
40
42
|
class Controller extends EditorInjector {
|
|
43
|
+
#reserveIndex;
|
|
44
|
+
#initMethod;
|
|
45
|
+
#globalEventHandlers;
|
|
46
|
+
#bindClose_key;
|
|
47
|
+
#bindClose_mouse;
|
|
48
|
+
#addOffset;
|
|
49
|
+
#shadowRootEventForm;
|
|
50
|
+
#shadowRootEventListener;
|
|
51
|
+
#preventClose;
|
|
52
|
+
|
|
41
53
|
/**
|
|
42
54
|
* @constructor
|
|
43
55
|
* @param {*} inst The instance object that called the constructor.
|
|
@@ -61,20 +73,22 @@ class Controller extends EditorInjector {
|
|
|
61
73
|
this.parents = /** @type {Array<HTMLElement>} */ (params.parents || []);
|
|
62
74
|
this.parentsHide = !!params.parentsHide;
|
|
63
75
|
this.sibling = /** @type {HTMLElement} */ (params.sibling || null);
|
|
64
|
-
this.
|
|
76
|
+
this.siblingMain = !!params.siblingMain;
|
|
65
77
|
this.isInsideForm = !!params.isInsideForm;
|
|
66
78
|
this.isOutsideForm = !!params.isOutsideForm;
|
|
67
79
|
this.toTop = false;
|
|
68
|
-
this._reserveIndex = false;
|
|
69
|
-
this._initMethod = typeof params.initMethod === 'function' ? params.initMethod : null;
|
|
70
|
-
this.__globalEventHandlers = { keydown: this.#CloseListener_keydown.bind(this), mousedown: this.#CloseListener_mousedown.bind(this) };
|
|
71
|
-
this._bindClose_key = null;
|
|
72
|
-
this._bindClose_mouse = null;
|
|
73
80
|
/** @type {{left?: number, top?: number, addOfffset?: {left?: number, top?: number}}} */
|
|
74
81
|
this.__offset = {};
|
|
75
|
-
|
|
76
|
-
this
|
|
77
|
-
this
|
|
82
|
+
|
|
83
|
+
this.#reserveIndex = false;
|
|
84
|
+
this.#initMethod = typeof params.initMethod === 'function' ? params.initMethod : null;
|
|
85
|
+
this.#globalEventHandlers = { keydown: this.#CloseListener_keydown.bind(this), mousedown: this.#CloseListener_mousedown.bind(this) };
|
|
86
|
+
this.#bindClose_key = null;
|
|
87
|
+
this.#bindClose_mouse = null;
|
|
88
|
+
this.#addOffset = { left: 0, top: 0 };
|
|
89
|
+
this.#shadowRootEventForm = null;
|
|
90
|
+
this.#shadowRootEventListener = null;
|
|
91
|
+
this.#preventClose = false;
|
|
78
92
|
|
|
79
93
|
// add element
|
|
80
94
|
this.carrierWrapper.appendChild(element);
|
|
@@ -118,11 +132,11 @@ class Controller extends EditorInjector {
|
|
|
118
132
|
|
|
119
133
|
this.currentPositionTarget = positionTarget || target;
|
|
120
134
|
this.isWWTarget = isWWTarget ?? this.isWWTarget;
|
|
121
|
-
if (typeof initMethod === 'function') this
|
|
135
|
+
if (typeof initMethod === 'function') this.#initMethod = initMethod;
|
|
122
136
|
this.editor.currentControllerName = this.kind;
|
|
123
137
|
|
|
124
|
-
this
|
|
125
|
-
if (addOffset) this
|
|
138
|
+
this.#addOffset = { left: 0, top: 0 };
|
|
139
|
+
if (addOffset) this.#addOffset = { ...this.#addOffset, ...addOffset };
|
|
126
140
|
|
|
127
141
|
const parents = this.isOutsideForm ? this.parents : [];
|
|
128
142
|
this.editor.opendControllers?.forEach((e) => {
|
|
@@ -135,23 +149,15 @@ class Controller extends EditorInjector {
|
|
|
135
149
|
});
|
|
136
150
|
}
|
|
137
151
|
|
|
138
|
-
this
|
|
152
|
+
this.#addGlobalEvent();
|
|
139
153
|
|
|
140
|
-
// add sibling offset
|
|
141
|
-
if (this.sibling) {
|
|
142
|
-
if (this.siblingPosition === 'top') {
|
|
143
|
-
this.__addOffset.top += -this.sibling.offsetHeight + 1;
|
|
144
|
-
} else {
|
|
145
|
-
this.__addOffset.left += this.form.offsetWidth + this.sibling.offsetWidth - 1;
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
154
|
// display controller
|
|
149
|
-
this
|
|
155
|
+
this.#setControllerPosition(this.form, this.currentPositionTarget, false);
|
|
150
156
|
|
|
151
|
-
const isRangeTarget = target
|
|
157
|
+
const isRangeTarget = this.instanceCheck.isRange(target);
|
|
152
158
|
this.currentTarget = isRangeTarget ? null : target;
|
|
153
|
-
this
|
|
154
|
-
|
|
159
|
+
this.#controllerOn(this.form, target, isRangeTarget);
|
|
160
|
+
_w.setTimeout(() => _DragHandle.set('__overInfo', false), 0);
|
|
155
161
|
}
|
|
156
162
|
|
|
157
163
|
/**
|
|
@@ -160,17 +166,18 @@ class Controller extends EditorInjector {
|
|
|
160
166
|
* @param {boolean=} force If true, parent controllers are forcibly closed.
|
|
161
167
|
*/
|
|
162
168
|
close(force) {
|
|
163
|
-
if (!this.isOpen) return;
|
|
169
|
+
if (!this.isOpen || this.#preventClose) return;
|
|
164
170
|
|
|
165
171
|
this.toTop = false;
|
|
166
172
|
this.isOpen = false;
|
|
173
|
+
this.#preventClose = false;
|
|
167
174
|
this.__offset = {};
|
|
168
|
-
this
|
|
175
|
+
this.#addOffset = { left: 0, top: 0 };
|
|
169
176
|
|
|
170
|
-
this
|
|
177
|
+
this.#removeGlobalEvent();
|
|
171
178
|
|
|
172
|
-
if (typeof this
|
|
173
|
-
this
|
|
179
|
+
if (typeof this.#initMethod === 'function') this.#initMethod();
|
|
180
|
+
this.#controllerOff();
|
|
174
181
|
|
|
175
182
|
if (this.parentsHide && !force) {
|
|
176
183
|
this.parents.forEach((e) => {
|
|
@@ -194,7 +201,7 @@ class Controller extends EditorInjector {
|
|
|
194
201
|
* @description Show controller
|
|
195
202
|
*/
|
|
196
203
|
show() {
|
|
197
|
-
this
|
|
204
|
+
this.#setControllerPosition(this.form, this.currentPositionTarget, false);
|
|
198
205
|
}
|
|
199
206
|
|
|
200
207
|
/**
|
|
@@ -211,17 +218,16 @@ class Controller extends EditorInjector {
|
|
|
211
218
|
* @param {Node=} target
|
|
212
219
|
*/
|
|
213
220
|
resetPosition(target) {
|
|
214
|
-
this
|
|
221
|
+
this.#setControllerPosition(this.form, target || this.currentPositionTarget, true);
|
|
215
222
|
}
|
|
216
223
|
|
|
217
224
|
/**
|
|
218
|
-
* @private
|
|
219
225
|
* @description Show controller at editor area (controller elements, function, "controller target element(@Required)", "controller name(@Required)", etc..)
|
|
220
226
|
* @param {HTMLFormElement} form Controller element
|
|
221
227
|
* @param {Node|Range} target Controller target element
|
|
222
228
|
* @param {boolean} isRangeTarget If the target is a Range, set it to true.
|
|
223
229
|
*/
|
|
224
|
-
async
|
|
230
|
+
async #controllerOn(form, target, isRangeTarget) {
|
|
225
231
|
/** @type {ControllerInfo} */
|
|
226
232
|
const info = {
|
|
227
233
|
position: this.position,
|
|
@@ -232,16 +238,16 @@ class Controller extends EditorInjector {
|
|
|
232
238
|
notInCarrier: !this.carrierWrapper.contains(form)
|
|
233
239
|
};
|
|
234
240
|
|
|
235
|
-
if ((await this.triggerEvent('onBeforeShowController', { caller: this.kind, frameContext: this.
|
|
241
|
+
if ((await this.triggerEvent('onBeforeShowController', { caller: this.kind, frameContext: this.frameContext, info })) === false) return;
|
|
236
242
|
|
|
237
243
|
form.style.display = 'block';
|
|
238
|
-
if (this._shadowRoot) {
|
|
239
|
-
this
|
|
240
|
-
this
|
|
241
|
-
form.addEventListener('mousedown', this
|
|
244
|
+
if (this.editor._shadowRoot) {
|
|
245
|
+
this.#shadowRootEventForm = form;
|
|
246
|
+
this.#shadowRootEventListener = (e) => e.stopPropagation();
|
|
247
|
+
form.addEventListener('mousedown', this.#shadowRootEventListener);
|
|
242
248
|
}
|
|
243
249
|
|
|
244
|
-
this.editor._controllerTargetContext = this.
|
|
250
|
+
this.editor._controllerTargetContext = this.frameContext.get('topArea');
|
|
245
251
|
|
|
246
252
|
if (!this.isOpen) {
|
|
247
253
|
this.editor.opendControllers.push(info);
|
|
@@ -250,21 +256,20 @@ class Controller extends EditorInjector {
|
|
|
250
256
|
this.isOpen = true;
|
|
251
257
|
this.editor._preventBlur = true;
|
|
252
258
|
this.editor.status.onSelected = true;
|
|
253
|
-
this.triggerEvent('onShowController', { caller: this.kind, frameContext: this.
|
|
259
|
+
this.triggerEvent('onShowController', { caller: this.kind, frameContext: this.frameContext, info });
|
|
254
260
|
}
|
|
255
261
|
|
|
256
262
|
/**
|
|
257
|
-
* @private
|
|
258
263
|
* @description Hide controller at editor area (link button, image resize button..)
|
|
259
264
|
*/
|
|
260
|
-
|
|
265
|
+
#controllerOff() {
|
|
261
266
|
this.form.style.display = 'none';
|
|
262
267
|
this.editor.opendControllers = this.editor.opendControllers.filter((v) => v.form !== this.form);
|
|
263
268
|
if (this.editor.currentControllerName !== this.kind && this.editor.opendControllers.length > 0) return;
|
|
264
269
|
|
|
265
270
|
this.ui.setControllerOnDisabledButtons(false);
|
|
266
271
|
|
|
267
|
-
this.
|
|
272
|
+
this.frameContext.get('lineBreaker_t').style.display = this.frameContext.get('lineBreaker_b').style.display = 'none';
|
|
268
273
|
this.editor.effectNode = null;
|
|
269
274
|
this.editor.currentControllerName = '';
|
|
270
275
|
this.editor._preventBlur = false;
|
|
@@ -272,24 +277,28 @@ class Controller extends EditorInjector {
|
|
|
272
277
|
_w.setTimeout(() => {
|
|
273
278
|
this.editor.status.onSelected = false;
|
|
274
279
|
}, 0);
|
|
275
|
-
if (this
|
|
276
|
-
this.
|
|
277
|
-
this
|
|
280
|
+
if (this.#shadowRootEventForm) {
|
|
281
|
+
this.#shadowRootEventForm.removeEventListener('mousedown', this.#shadowRootEventListener);
|
|
282
|
+
this.#shadowRootEventForm = this.#shadowRootEventListener = null;
|
|
278
283
|
}
|
|
279
284
|
if (typeof this.inst.reset === 'function') this.inst.reset();
|
|
280
285
|
}
|
|
281
286
|
|
|
282
287
|
/**
|
|
283
|
-
* @private
|
|
284
288
|
* @description Specify the position of the controller.
|
|
285
289
|
* @param {HTMLElement} controller Controller element.
|
|
286
290
|
* @param {Node|Range} refer Element or Range that is the basis of the controller's position.
|
|
287
291
|
* @param {boolean} [skipAutoReposition=false] If true, skips scroll/resize-based automatic positioning logic.
|
|
288
292
|
*/
|
|
289
|
-
|
|
293
|
+
#setControllerPosition(controller, refer, skipAutoReposition) {
|
|
290
294
|
controller.style.visibility = 'hidden';
|
|
291
295
|
controller.style.display = 'block';
|
|
292
296
|
|
|
297
|
+
if (this.sibling && this.sibling.style.display !== 'block') {
|
|
298
|
+
this.sibling.style.visibility = 'hidden';
|
|
299
|
+
this.sibling.style.display = 'block';
|
|
300
|
+
}
|
|
301
|
+
|
|
293
302
|
if (this.selection.isRange(refer)) {
|
|
294
303
|
if (!this.offset.setRangePosition(this.form, /** @type {Range} */ (refer), { position: 'bottom' })) {
|
|
295
304
|
this.hide();
|
|
@@ -297,58 +306,56 @@ class Controller extends EditorInjector {
|
|
|
297
306
|
}
|
|
298
307
|
} else {
|
|
299
308
|
if (refer) {
|
|
300
|
-
const positionResult = this.offset.setAbsPosition(controller, /** @type {HTMLElement} */ (refer), { addOffset: this
|
|
309
|
+
const positionResult = this.offset.setAbsPosition(controller, /** @type {HTMLElement} */ (refer), { addOffset: this.#addOffset, position: this.position, isWWTarget: this.isWWTarget, inst: this, sibling: this.sibling });
|
|
301
310
|
if (!positionResult) {
|
|
302
311
|
this.hide();
|
|
303
312
|
return;
|
|
304
313
|
}
|
|
305
314
|
|
|
306
|
-
if (!skipAutoReposition && this.sibling && this.
|
|
307
|
-
const resetPosition = controller.offsetTop - this.
|
|
315
|
+
if (!skipAutoReposition && this.sibling && !this.siblingMain) {
|
|
316
|
+
const resetPosition = controller.offsetTop - this.#addOffset.top;
|
|
308
317
|
if (positionResult.position === 'bottom') {
|
|
309
|
-
this
|
|
310
|
-
controller.style.top = resetPosition + this.sibling.offsetHeight -
|
|
318
|
+
this.#reserveIndex = true;
|
|
319
|
+
controller.style.top = resetPosition + this.sibling.offsetHeight - 1 + 'px';
|
|
311
320
|
} else {
|
|
321
|
+
this.#reserveIndex = false;
|
|
312
322
|
controller.style.top = resetPosition - this.sibling.offsetHeight + 2 + 'px';
|
|
313
323
|
}
|
|
314
324
|
} else {
|
|
315
|
-
this
|
|
325
|
+
this.#reserveIndex = false;
|
|
316
326
|
}
|
|
317
327
|
}
|
|
318
328
|
}
|
|
319
329
|
|
|
320
|
-
controller.style.zIndex = this.toTop ? INDEX_0 : this
|
|
330
|
+
controller.style.zIndex = this.toTop ? INDEX_0 : this.#reserveIndex ? INDEX_S_1 : INDEX_1;
|
|
321
331
|
controller.style.visibility = '';
|
|
322
332
|
}
|
|
323
333
|
|
|
324
334
|
/**
|
|
325
|
-
* @private
|
|
326
335
|
* @description Adds global event listeners.
|
|
327
336
|
* - When the controller is opened
|
|
328
337
|
*/
|
|
329
|
-
|
|
330
|
-
this
|
|
331
|
-
this
|
|
332
|
-
this
|
|
338
|
+
#addGlobalEvent() {
|
|
339
|
+
this.#removeGlobalEvent();
|
|
340
|
+
this.#bindClose_key = this.eventManager.addGlobalEvent('keydown', this.#globalEventHandlers.keydown, true);
|
|
341
|
+
this.#bindClose_mouse = this.eventManager.addGlobalEvent(isMobile ? 'click' : 'mousedown', this.#globalEventHandlers.mousedown, true);
|
|
333
342
|
}
|
|
334
343
|
|
|
335
344
|
/**
|
|
336
|
-
* @private
|
|
337
345
|
* @description Removes global event listeners.
|
|
338
346
|
* - When the ESC key is pressed, the controller is closed.
|
|
339
347
|
*/
|
|
340
|
-
|
|
348
|
+
#removeGlobalEvent() {
|
|
341
349
|
this.component.__removeGlobalEvent();
|
|
342
|
-
|
|
343
|
-
|
|
350
|
+
this.#bindClose_key &&= this.eventManager.removeGlobalEvent(this.#bindClose_key);
|
|
351
|
+
this.#bindClose_mouse &&= this.eventManager.removeGlobalEvent(this.#bindClose_mouse);
|
|
344
352
|
}
|
|
345
353
|
|
|
346
354
|
/**
|
|
347
|
-
* @private
|
|
348
355
|
* @description Checks if the controller is fixed and should not be closed.
|
|
349
356
|
* @returns {boolean} True if the controller is fixed.
|
|
350
357
|
*/
|
|
351
|
-
|
|
358
|
+
#checkFixed() {
|
|
352
359
|
if (this.editor.selectMenuOn) return true;
|
|
353
360
|
|
|
354
361
|
const cont = this.editor.opendControllers;
|
|
@@ -361,12 +368,11 @@ class Controller extends EditorInjector {
|
|
|
361
368
|
}
|
|
362
369
|
|
|
363
370
|
/**
|
|
364
|
-
* @private
|
|
365
371
|
* @description Checks if the given target is within a form or controller.
|
|
366
372
|
* @param {Node} target The target element.
|
|
367
373
|
* @returns {boolean} True if the target is inside a form or controller.
|
|
368
374
|
*/
|
|
369
|
-
|
|
375
|
+
#checkForm(target) {
|
|
370
376
|
if (dom.check.isWysiwygFrame(target)) return false;
|
|
371
377
|
if (dom.utils.hasClass(target, 'se-drag-handle')) return true;
|
|
372
378
|
|
|
@@ -415,20 +421,20 @@ class Controller extends EditorInjector {
|
|
|
415
421
|
if (this.parents.length > 0 && this.isInsideForm) return;
|
|
416
422
|
|
|
417
423
|
const eventTarget = dom.query.getEventTarget(e);
|
|
418
|
-
eventTarget.style.zIndex = this.toTop ? INDEX_0 : this
|
|
424
|
+
eventTarget.style.zIndex = this.toTop ? INDEX_0 : this.#reserveIndex ? INDEX_S_1 : INDEX_1;
|
|
419
425
|
}
|
|
420
426
|
|
|
421
427
|
/**
|
|
422
428
|
* @param {KeyboardEvent} e - Event object
|
|
423
429
|
*/
|
|
424
430
|
#CloseListener_keydown(e) {
|
|
425
|
-
if (this
|
|
431
|
+
if (this.#checkFixed()) return;
|
|
426
432
|
const keyCode = e.code;
|
|
427
433
|
const ctrl = keyCodeMap.isCtrl(e);
|
|
428
434
|
if (ctrl || !keyCodeMap.isNonResponseKey(keyCode)) return;
|
|
429
435
|
|
|
430
436
|
const eventTarget = dom.query.getEventTarget(e);
|
|
431
|
-
if (this.form.contains(eventTarget) || this
|
|
437
|
+
if (this.form.contains(eventTarget) || this.#checkForm(eventTarget)) return;
|
|
432
438
|
if (this.editor._fileManager.pluginRegExp.test(this.kind) && !keyCodeMap.isEsc(keyCode)) return;
|
|
433
439
|
|
|
434
440
|
this.#PostCloseEvent(eventTarget);
|
|
@@ -441,17 +447,17 @@ class Controller extends EditorInjector {
|
|
|
441
447
|
#CloseListener_mousedown(e) {
|
|
442
448
|
const eventTarget = dom.query.getEventTarget(e);
|
|
443
449
|
if (this.inst?._element?.contains(eventTarget)) {
|
|
444
|
-
this
|
|
450
|
+
this.#preventClose = true;
|
|
445
451
|
return;
|
|
446
452
|
}
|
|
447
453
|
|
|
448
|
-
this
|
|
454
|
+
this.#preventClose = false;
|
|
449
455
|
if (
|
|
450
456
|
eventTarget === this.inst._element ||
|
|
451
457
|
eventTarget === this.currentTarget ||
|
|
452
|
-
this
|
|
458
|
+
this.#checkFixed() ||
|
|
453
459
|
this.form.contains(eventTarget) ||
|
|
454
|
-
this
|
|
460
|
+
this.#checkForm(eventTarget) ||
|
|
455
461
|
dom.query.getParentElement(eventTarget, '.se-line-breaker-component')
|
|
456
462
|
) {
|
|
457
463
|
return;
|
|
@@ -465,7 +471,7 @@ class Controller extends EditorInjector {
|
|
|
465
471
|
* @param {HTMLElement} eventTarget - The target element that triggered the event.
|
|
466
472
|
*/
|
|
467
473
|
#PostCloseEvent(eventTarget) {
|
|
468
|
-
if (!this.
|
|
474
|
+
if (!this.frameContext.get('wysiwyg').contains(eventTarget)) {
|
|
469
475
|
this.component.__prevent = false;
|
|
470
476
|
}
|
|
471
477
|
}
|