suneditor 3.1.4 → 3.2.0
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/dist/suneditor-contents.min.css +1 -1
- package/dist/suneditor.min.css +28 -1
- package/dist/suneditor.min.js +1 -1
- package/package.json +2 -1
- package/src/assets/design/color.css +12 -0
- package/src/assets/design/size.css +9 -2
- package/src/assets/icons/defaultIcons.js +96 -47
- package/src/assets/suneditor-contents.css +3 -2
- package/src/assets/suneditor.css +480 -31
- package/src/core/config/contextProvider.js +2 -1
- package/src/core/config/eventManager.js +41 -2
- package/src/core/config/optionProvider.js +23 -2
- package/src/core/editor.js +32 -14
- package/src/core/event/actions/index.js +76 -9
- package/src/core/event/effects/common.registry.js +2 -1
- package/src/core/event/effects/keydown.registry.js +169 -33
- package/src/core/event/effects/ruleHelpers.js +20 -6
- package/src/core/event/eventOrchestrator.js +136 -23
- package/src/core/event/handlers/handler_toolbar.js +4 -2
- package/src/core/event/handlers/handler_ww_dragDrop.js +10 -0
- package/src/core/event/handlers/handler_ww_input.js +9 -2
- package/src/core/event/handlers/handler_ww_key.js +86 -17
- package/src/core/event/handlers/handler_ww_mouse.js +45 -8
- package/src/core/event/ports.js +23 -5
- package/src/core/event/reducers/keydown.reducer.js +15 -2
- package/src/core/event/rules/keydown.rule.arrow.js +12 -2
- package/src/core/event/rules/keydown.rule.backspace.js +110 -15
- package/src/core/event/rules/keydown.rule.delete.js +62 -7
- package/src/core/event/rules/keydown.rule.enter.js +62 -31
- package/src/core/event/support/defaultLineManager.js +9 -2
- package/src/core/event/support/selectionState.js +13 -3
- package/src/core/kernel/coreKernel.js +1 -0
- package/src/core/logic/dom/char.js +13 -3
- package/src/core/logic/dom/format.js +171 -39
- package/src/core/logic/dom/html.js +350 -72
- package/src/core/logic/dom/inline.js +229 -34
- package/src/core/logic/dom/listFormat.js +111 -20
- package/src/core/logic/dom/nodeTransform.js +36 -11
- package/src/core/logic/dom/offset.js +116 -31
- package/src/core/logic/dom/selection.js +147 -29
- package/src/core/logic/panel/blockHandle.js +785 -0
- package/src/core/logic/panel/blockResolver.js +278 -0
- package/src/core/logic/panel/finder.js +16 -6
- package/src/core/logic/panel/menu.js +119 -18
- package/src/core/logic/panel/toolbar.js +75 -19
- package/src/core/logic/panel/viewer.js +76 -20
- package/src/core/logic/shell/_commandExecutor.js +44 -9
- package/src/core/logic/shell/commandDispatcher.js +46 -4
- package/src/core/logic/shell/component.js +102 -25
- package/src/core/logic/shell/focusManager.js +13 -3
- package/src/core/logic/shell/history.js +21 -6
- package/src/core/logic/shell/pluginManager.js +21 -13
- package/src/core/logic/shell/shortcuts.js +9 -1
- package/src/core/logic/shell/ui.js +139 -37
- package/src/core/schema/frameContext.js +34 -3
- package/src/core/schema/options.js +46 -4
- package/src/core/section/constructor.js +537 -93
- package/src/core/section/documentType.js +35 -6
- package/src/helper/converter.js +24 -7
- package/src/helper/dom/domCheck.js +25 -5
- package/src/helper/dom/domQuery.js +2 -1
- package/src/helper/dom/domUtils.js +17 -4
- package/src/helper/env.js +11 -2
- package/src/helper/keyCodeMap.js +6 -2
- package/src/helper/markdown.js +24 -5
- package/src/helper/msOffice.js +9 -2
- package/src/interfaces/plugins.js +1 -1
- package/src/langs/ckb.js +0 -1
- package/src/langs/cs.js +0 -1
- package/src/langs/da.js +0 -1
- package/src/langs/de.js +0 -1
- package/src/langs/en.js +0 -1
- package/src/langs/es.js +0 -1
- package/src/langs/fa.js +0 -1
- package/src/langs/fr.js +0 -1
- package/src/langs/he.js +0 -1
- package/src/langs/hu.js +0 -1
- package/src/langs/index.js +27 -1
- package/src/langs/it.js +0 -1
- package/src/langs/ja.js +0 -1
- package/src/langs/km.js +0 -1
- package/src/langs/ko.js +0 -1
- package/src/langs/lv.js +0 -1
- package/src/langs/nl.js +0 -1
- package/src/langs/pl.js +0 -1
- package/src/langs/pt_br.js +0 -1
- package/src/langs/ro.js +0 -1
- package/src/langs/ru.js +0 -1
- package/src/langs/se.js +0 -1
- package/src/langs/tr.js +0 -1
- package/src/langs/uk.js +0 -1
- package/src/langs/ur.js +0 -1
- package/src/langs/zh_cn.js +0 -1
- package/src/modules/contract/Browser.js +58 -14
- package/src/modules/contract/ColorPicker.js +12 -4
- package/src/modules/contract/Controller.js +37 -7
- package/src/modules/contract/Figure.js +156 -36
- package/src/modules/contract/HueSlider.js +27 -4
- package/src/modules/contract/Modal.js +50 -10
- package/src/modules/manager/FileManager.js +50 -8
- package/src/modules/ui/CommandMenu.js +597 -0
- package/src/modules/ui/ModalAnchorEditor.js +33 -6
- package/src/modules/ui/SelectMenu.js +481 -36
- package/src/modules/ui/index.js +1 -0
- package/src/plugins/browser/audioGallery.js +2 -1
- package/src/plugins/browser/fileBrowser.js +9 -2
- package/src/plugins/browser/fileGallery.js +2 -1
- package/src/plugins/browser/imageGallery.js +18 -3
- package/src/plugins/browser/videoGallery.js +13 -4
- package/src/plugins/command/blockquote.js +6 -1
- package/src/plugins/command/codeBlock.js +43 -5
- package/src/plugins/command/exportPDF.js +20 -4
- package/src/plugins/command/fileUpload.js +46 -11
- package/src/plugins/command/list_bulleted.js +6 -1
- package/src/plugins/command/list_numbered.js +6 -1
- package/src/plugins/dropdown/align.js +21 -33
- package/src/plugins/dropdown/backgroundColor.js +10 -2
- package/src/plugins/dropdown/blockStyle.js +17 -22
- package/src/plugins/dropdown/font.js +34 -34
- package/src/plugins/dropdown/hr.js +15 -43
- package/src/plugins/dropdown/layout.js +10 -27
- package/src/plugins/dropdown/lineHeight.js +10 -33
- package/src/plugins/dropdown/list.js +19 -25
- package/src/plugins/dropdown/paragraphStyle.js +16 -24
- package/src/plugins/dropdown/table/index.js +72 -17
- package/src/plugins/dropdown/table/render/table.html.js +3 -1
- package/src/plugins/dropdown/table/services/table.cell.js +33 -7
- package/src/plugins/dropdown/table/services/table.clipboard.js +5 -1
- package/src/plugins/dropdown/table/services/table.grid.js +40 -9
- package/src/plugins/dropdown/table/services/table.resize.js +55 -11
- package/src/plugins/dropdown/table/services/table.selection.js +27 -7
- package/src/plugins/dropdown/table/services/table.style.js +120 -20
- package/src/plugins/dropdown/template.js +13 -29
- package/src/plugins/dropdown/textStyle.js +22 -35
- package/src/plugins/field/autocomplete.js +8 -4
- package/src/plugins/field/slashCommand.js +297 -0
- package/src/plugins/index.js +3 -0
- package/src/plugins/input/fontSize.js +37 -8
- package/src/plugins/input/pageNavigator.js +7 -1
- package/src/plugins/modal/audio.js +71 -17
- package/src/plugins/modal/drawing.js +41 -11
- package/src/plugins/modal/embed.js +92 -22
- package/src/plugins/modal/image/index.js +114 -28
- package/src/plugins/modal/image/services/image.size.js +9 -2
- package/src/plugins/modal/image/services/image.upload.js +38 -4
- package/src/plugins/modal/link.js +9 -2
- package/src/plugins/modal/math.js +10 -2
- package/src/plugins/modal/video/index.js +112 -26
- package/src/plugins/modal/video/render/video.html.js +4 -1
- package/src/plugins/modal/video/services/video.size.js +15 -4
- package/src/plugins/modal/video/services/video.upload.js +10 -2
- package/src/plugins/popup/anchor.js +14 -2
- package/src/suneditor.js +8 -2
- package/src/themes/cobalt.css +12 -0
- package/src/themes/cream.css +12 -0
- package/src/themes/dark.css +12 -0
- package/src/themes/midnight.css +12 -0
- package/src/typedef.js +32 -21
- package/types/assets/icons/defaultIcons.d.ts +1 -0
- package/types/core/config/contextProvider.d.ts +7 -1
- package/types/core/config/eventManager.d.ts +37 -4
- package/types/core/config/optionProvider.d.ts +5 -1
- package/types/core/event/actions/index.d.ts +44 -6
- package/types/core/event/effects/keydown.registry.d.ts +37 -7
- package/types/core/event/effects/ruleHelpers.d.ts +6 -1
- package/types/core/event/eventOrchestrator.d.ts +6 -1
- package/types/core/event/handlers/handler_ww_clipboard.d.ts +15 -3
- package/types/core/event/handlers/handler_ww_dragDrop.d.ts +14 -2
- package/types/core/event/handlers/handler_ww_input.d.ts +10 -2
- package/types/core/event/handlers/handler_ww_key.d.ts +10 -2
- package/types/core/event/handlers/handler_ww_mouse.d.ts +25 -5
- package/types/core/event/ports.d.ts +7 -2
- package/types/core/event/rules/keydown.rule.backspace.d.ts +6 -1
- package/types/core/kernel/store.d.ts +4 -1
- package/types/core/logic/dom/format.d.ts +32 -14
- package/types/core/logic/dom/html.d.ts +11 -3
- package/types/core/logic/dom/nodeTransform.d.ts +6 -6
- package/types/core/logic/panel/blockHandle.d.ts +64 -0
- package/types/core/logic/panel/blockResolver.d.ts +50 -0
- package/types/core/logic/panel/menu.d.ts +72 -3
- package/types/core/logic/shell/commandDispatcher.d.ts +8 -0
- package/types/core/logic/shell/component.d.ts +5 -3
- package/types/core/logic/shell/shortcuts.d.ts +10 -1
- package/types/core/logic/shell/ui.d.ts +7 -1
- package/types/core/schema/context.d.ts +7 -1
- package/types/core/schema/frameContext.d.ts +36 -4
- package/types/core/schema/options.d.ts +83 -2
- package/types/core/section/constructor.d.ts +38 -1
- package/types/events.d.ts +208 -32
- package/types/helper/converter.d.ts +4 -2
- package/types/helper/dom/domCheck.d.ts +12 -2
- package/types/helper/dom/domQuery.d.ts +35 -7
- package/types/helper/dom/domUtils.d.ts +4 -1
- package/types/interfaces/plugins.d.ts +2 -2
- package/types/langs/_Lang.d.ts +0 -1
- package/types/modules/contract/ColorPicker.d.ts +2 -2
- package/types/modules/contract/Controller.d.ts +7 -0
- package/types/modules/contract/Figure.d.ts +31 -4
- package/types/modules/ui/CommandMenu.d.ts +262 -0
- package/types/modules/ui/SelectMenu.d.ts +56 -3
- package/types/modules/ui/index.d.ts +1 -0
- package/types/plugins/browser/audioGallery.d.ts +1 -1
- package/types/plugins/browser/fileBrowser.d.ts +1 -1
- package/types/plugins/browser/fileGallery.d.ts +1 -1
- package/types/plugins/browser/imageGallery.d.ts +1 -1
- package/types/plugins/browser/videoGallery.d.ts +1 -1
- package/types/plugins/dropdown/align.d.ts +1 -1
- package/types/plugins/dropdown/blockStyle.d.ts +3 -1
- package/types/plugins/dropdown/table/index.d.ts +4 -1
- package/types/plugins/dropdown/table/services/table.clipboard.d.ts +5 -1
- package/types/plugins/dropdown/table/services/table.grid.d.ts +10 -2
- package/types/plugins/field/autocomplete.d.ts +0 -1
- package/types/plugins/field/slashCommand.d.ts +165 -0
- package/types/plugins/index.d.ts +3 -0
- package/types/plugins/modal/link.d.ts +4 -1
- package/types/typedef.d.ts +48 -23
|
@@ -4,7 +4,13 @@ import { _DragHandle } from '../../modules/ui';
|
|
|
4
4
|
|
|
5
5
|
// event handlers
|
|
6
6
|
import { ButtonsHandler, OnClick_menuTray, OnClick_toolbar } from '../event/handlers/handler_toolbar';
|
|
7
|
-
import {
|
|
7
|
+
import {
|
|
8
|
+
OnMouseDown_wysiwyg,
|
|
9
|
+
OnMouseUp_wysiwyg,
|
|
10
|
+
OnClick_wysiwyg,
|
|
11
|
+
OnMouseMove_wysiwyg,
|
|
12
|
+
OnMouseLeave_wysiwyg,
|
|
13
|
+
} from '../event/handlers/handler_ww_mouse';
|
|
8
14
|
import { OnBeforeInput_wysiwyg, OnInput_wysiwyg } from '../event/handlers/handler_ww_input';
|
|
9
15
|
import { OnKeyDown_wysiwyg, OnKeyUp_wysiwyg } from '../event/handlers/handler_ww_key';
|
|
10
16
|
import { OnPaste_wysiwyg, OnCopy_wysiwyg, OnCut_wysiwyg } from '../event/handlers/handler_ww_clipboard';
|
|
@@ -245,14 +251,21 @@ class EventOrchestrator extends KernelInjector {
|
|
|
245
251
|
// SE copy data
|
|
246
252
|
const SEData = this.__secopy === plainText;
|
|
247
253
|
// MS word, OneNode, Excel
|
|
248
|
-
const MSData =
|
|
254
|
+
const MSData =
|
|
255
|
+
/class=["']*Mso(Normal|List)/i.test(cleanData) ||
|
|
256
|
+
/content=["']*Word.Document/i.test(cleanData) ||
|
|
257
|
+
/content=["']*OneNote.File/i.test(cleanData) ||
|
|
258
|
+
/content=["']*Excel.Sheet/i.test(cleanData);
|
|
249
259
|
// from
|
|
250
260
|
const from = SEData ? 'SE' : MSData ? 'MS' : '';
|
|
251
261
|
|
|
252
262
|
if (onlyText) {
|
|
253
263
|
cleanData = converter.htmlToEntity(plainText).replace(/\n/g, '<br>');
|
|
254
264
|
} else {
|
|
255
|
-
cleanData = cleanData.replace(
|
|
265
|
+
cleanData = cleanData.replace(
|
|
266
|
+
/^<html>\r?\n?<body>\r?\n?\x3C!--StartFragment-->|\x3C!--EndFragment-->\r?\n?<\/body>\r?\n?<\/html>$/g,
|
|
267
|
+
'',
|
|
268
|
+
);
|
|
256
269
|
if (MSData) {
|
|
257
270
|
cleanData = cleanData.replace(/\n/g, ' ');
|
|
258
271
|
plainText = plainText.replace(/\n/g, ' ');
|
|
@@ -273,10 +286,19 @@ class EventOrchestrator extends KernelInjector {
|
|
|
273
286
|
cleanData = this.$.html.clean(cleanData, { forceFormat: false, whitelist: null, blacklist: null });
|
|
274
287
|
}
|
|
275
288
|
|
|
276
|
-
const maxCharCount = this.$.char.test(
|
|
289
|
+
const maxCharCount = this.$.char.test(
|
|
290
|
+
this.$.frameOptions.get('charCounter_type') === 'byte-html' ? cleanData : plainText,
|
|
291
|
+
false,
|
|
292
|
+
);
|
|
277
293
|
// user event - paste
|
|
278
294
|
if (type === 'paste') {
|
|
279
|
-
const value = await this.#eventManager.triggerEvent('onPaste', {
|
|
295
|
+
const value = await this.#eventManager.triggerEvent('onPaste', {
|
|
296
|
+
frameContext,
|
|
297
|
+
event: e,
|
|
298
|
+
data: cleanData,
|
|
299
|
+
maxCharCount,
|
|
300
|
+
from,
|
|
301
|
+
});
|
|
280
302
|
if (value === false) {
|
|
281
303
|
return false;
|
|
282
304
|
} else if (typeof value === 'string') {
|
|
@@ -286,7 +308,13 @@ class EventOrchestrator extends KernelInjector {
|
|
|
286
308
|
}
|
|
287
309
|
// user event - drop
|
|
288
310
|
if (type === 'drop') {
|
|
289
|
-
const value = await this.#eventManager.triggerEvent('onDrop', {
|
|
311
|
+
const value = await this.#eventManager.triggerEvent('onDrop', {
|
|
312
|
+
frameContext,
|
|
313
|
+
event: e,
|
|
314
|
+
data: cleanData,
|
|
315
|
+
maxCharCount,
|
|
316
|
+
from,
|
|
317
|
+
});
|
|
290
318
|
if (value === false) {
|
|
291
319
|
return false;
|
|
292
320
|
} else if (typeof value === 'string') {
|
|
@@ -311,7 +339,14 @@ class EventOrchestrator extends KernelInjector {
|
|
|
311
339
|
|
|
312
340
|
if (cleanData) {
|
|
313
341
|
const domParser = new DOMParser().parseFromString(cleanData, 'text/html');
|
|
314
|
-
if (
|
|
342
|
+
if (
|
|
343
|
+
(await this._callPluginEventAsync('onPaste', {
|
|
344
|
+
frameContext,
|
|
345
|
+
event: e,
|
|
346
|
+
data: cleanData,
|
|
347
|
+
doc: domParser,
|
|
348
|
+
})) !== false
|
|
349
|
+
) {
|
|
315
350
|
this.$.html.insert(cleanData, { selectInserted: false, skipCharCount: true, skipCleaning: true });
|
|
316
351
|
}
|
|
317
352
|
|
|
@@ -422,12 +457,21 @@ class EventOrchestrator extends KernelInjector {
|
|
|
422
457
|
this.#eventManager.addEvent(
|
|
423
458
|
eventWysiwyg,
|
|
424
459
|
'dragover',
|
|
425
|
-
OnDragOver_wysiwyg.bind(
|
|
460
|
+
OnDragOver_wysiwyg.bind(
|
|
461
|
+
this,
|
|
462
|
+
fc,
|
|
463
|
+
dragCursor,
|
|
464
|
+
isIframe ? this.$.frameContext.get('topArea') : null,
|
|
465
|
+
!this.#options.get('toolbar_container') && !this.#store.mode.isBalloon && !this.#store.mode.isInline,
|
|
466
|
+
),
|
|
426
467
|
false,
|
|
427
468
|
);
|
|
428
469
|
this.#eventManager.addEvent(eventWysiwyg, 'dragend', OnDragEnd_wysiwyg.bind(this, dragCursor), false);
|
|
429
470
|
this.#eventManager.addEvent(eventWysiwyg, 'drop', OnDrop_wysiwyg.bind(this, fc, dragCursor), false);
|
|
430
|
-
this.#eventManager.addEvent(eventWysiwyg, 'scroll', this.#OnScroll_wysiwyg.bind(this, fc, eventWysiwyg), {
|
|
471
|
+
this.#eventManager.addEvent(eventWysiwyg, 'scroll', this.#OnScroll_wysiwyg.bind(this, fc, eventWysiwyg), {
|
|
472
|
+
passive: true,
|
|
473
|
+
capture: false,
|
|
474
|
+
});
|
|
431
475
|
this.#eventManager.addEvent(eventWysiwyg, 'focus', this.#OnFocus_wysiwyg.bind(this, fc), false);
|
|
432
476
|
this.#eventManager.addEvent(eventWysiwyg, 'blur', this.#OnBlur_wysiwyg.bind(this, fc), false);
|
|
433
477
|
this.#eventManager.addEvent(codeArea, 'mousedown', this.#OnFocus_code.bind(this, fc), false);
|
|
@@ -445,8 +489,18 @@ class EventOrchestrator extends KernelInjector {
|
|
|
445
489
|
);
|
|
446
490
|
|
|
447
491
|
/** line breaker */
|
|
448
|
-
this.#eventManager.addEvent(
|
|
449
|
-
|
|
492
|
+
this.#eventManager.addEvent(
|
|
493
|
+
fc.get('lineBreaker_t'),
|
|
494
|
+
'pointerdown',
|
|
495
|
+
this.#DisplayLineBreak.bind(this, 't'),
|
|
496
|
+
false,
|
|
497
|
+
);
|
|
498
|
+
this.#eventManager.addEvent(
|
|
499
|
+
fc.get('lineBreaker_b'),
|
|
500
|
+
'pointerdown',
|
|
501
|
+
this.#DisplayLineBreak.bind(this, 'b'),
|
|
502
|
+
false,
|
|
503
|
+
);
|
|
450
504
|
|
|
451
505
|
/** Events are registered mobile. */
|
|
452
506
|
if (isTouchDevice) {
|
|
@@ -459,7 +513,12 @@ class EventOrchestrator extends KernelInjector {
|
|
|
459
513
|
/** code view area auto line */
|
|
460
514
|
if (!this.#options.get('hasCodeMirror')) {
|
|
461
515
|
const codeNumbers = fc.get('codeNumbers');
|
|
462
|
-
const cvAuthHeight = this.$.viewer._codeViewAutoHeight.bind(
|
|
516
|
+
const cvAuthHeight = this.$.viewer._codeViewAutoHeight.bind(
|
|
517
|
+
this.$.viewer,
|
|
518
|
+
fc.get('code'),
|
|
519
|
+
codeNumbers,
|
|
520
|
+
this.$.frameOptions.get('height') === 'auto',
|
|
521
|
+
);
|
|
463
522
|
|
|
464
523
|
this.#eventManager.addEvent(codeArea, 'keydown', cvAuthHeight, false);
|
|
465
524
|
this.#eventManager.addEvent(codeArea, 'keyup', cvAuthHeight, false);
|
|
@@ -471,7 +530,13 @@ class EventOrchestrator extends KernelInjector {
|
|
|
471
530
|
}
|
|
472
531
|
|
|
473
532
|
/** code view numbers */
|
|
474
|
-
if (codeNumbers)
|
|
533
|
+
if (codeNumbers)
|
|
534
|
+
this.#eventManager.addEvent(
|
|
535
|
+
codeArea,
|
|
536
|
+
'scroll',
|
|
537
|
+
this.$.viewer._scrollLineNumbers.bind(codeArea, codeNumbers),
|
|
538
|
+
false,
|
|
539
|
+
);
|
|
475
540
|
}
|
|
476
541
|
|
|
477
542
|
/** markdown view area */
|
|
@@ -480,7 +545,12 @@ class EventOrchestrator extends KernelInjector {
|
|
|
480
545
|
this.#eventManager.addEvent(markdownArea, 'mousedown', this.#OnFocus_markdown.bind(this, fc), false);
|
|
481
546
|
|
|
482
547
|
const mdNumbers = fc.get('markdownNumbers');
|
|
483
|
-
const mdAutoHeight = this.$.viewer._markdownViewAutoHeight.bind(
|
|
548
|
+
const mdAutoHeight = this.$.viewer._markdownViewAutoHeight.bind(
|
|
549
|
+
this.$.viewer,
|
|
550
|
+
markdownArea,
|
|
551
|
+
mdNumbers,
|
|
552
|
+
this.$.frameOptions.get('height') === 'auto',
|
|
553
|
+
);
|
|
484
554
|
|
|
485
555
|
this.#eventManager.addEvent(markdownArea, 'keydown', mdAutoHeight, false);
|
|
486
556
|
this.#eventManager.addEvent(markdownArea, 'keyup', mdAutoHeight, false);
|
|
@@ -491,7 +561,13 @@ class EventOrchestrator extends KernelInjector {
|
|
|
491
561
|
this.#eventManager.addEvent(markdownArea, 'keydown', InsertTab, false);
|
|
492
562
|
}
|
|
493
563
|
|
|
494
|
-
if (mdNumbers)
|
|
564
|
+
if (mdNumbers)
|
|
565
|
+
this.#eventManager.addEvent(
|
|
566
|
+
markdownArea,
|
|
567
|
+
'scroll',
|
|
568
|
+
this.$.viewer._scrollMarkdownLineNumbers.bind(markdownArea, mdNumbers),
|
|
569
|
+
false,
|
|
570
|
+
);
|
|
495
571
|
}
|
|
496
572
|
|
|
497
573
|
if (fc.has('statusbar')) this.__addStatusbarEvent(fc, fc.get('options'));
|
|
@@ -509,7 +585,12 @@ class EventOrchestrator extends KernelInjector {
|
|
|
509
585
|
/** document event */
|
|
510
586
|
if (this.__eventDoc !== fc.get('_wd')) {
|
|
511
587
|
this.__eventDoc = fc.get('_wd');
|
|
512
|
-
this.#eventManager.addEvent(
|
|
588
|
+
this.#eventManager.addEvent(
|
|
589
|
+
this.__eventDoc,
|
|
590
|
+
'selectionchange',
|
|
591
|
+
this.#OnSelectionchange_document.bind(this, this.__eventDoc),
|
|
592
|
+
false,
|
|
593
|
+
);
|
|
513
594
|
}
|
|
514
595
|
}
|
|
515
596
|
|
|
@@ -522,7 +603,15 @@ class EventOrchestrator extends KernelInjector {
|
|
|
522
603
|
*/
|
|
523
604
|
__addStatusbarEvent(fc, fo) {
|
|
524
605
|
if (/\d+/.test(fo.get('height')) && fo.get('statusbar_resizeEnable')) {
|
|
525
|
-
fo.set(
|
|
606
|
+
fo.set(
|
|
607
|
+
'__statusbarEvent',
|
|
608
|
+
this.#eventManager.addEvent(
|
|
609
|
+
fc.get('statusbar'),
|
|
610
|
+
'mousedown',
|
|
611
|
+
this.#OnMouseDown_statusbar.bind(this),
|
|
612
|
+
false,
|
|
613
|
+
),
|
|
614
|
+
);
|
|
526
615
|
} else {
|
|
527
616
|
dom.utils.addClass(fc.get('statusbar'), 'se-resizing-none');
|
|
528
617
|
}
|
|
@@ -673,6 +762,9 @@ class EventOrchestrator extends KernelInjector {
|
|
|
673
762
|
// sticky
|
|
674
763
|
this.#toolbar._resetSticky();
|
|
675
764
|
|
|
765
|
+
// placeholder
|
|
766
|
+
this.#ui._updatePlaceholder(frameContext);
|
|
767
|
+
|
|
676
768
|
// user event
|
|
677
769
|
this.#eventManager.triggerEvent('onFocus', { frameContext, event });
|
|
678
770
|
// plugin event
|
|
@@ -735,12 +827,14 @@ class EventOrchestrator extends KernelInjector {
|
|
|
735
827
|
}
|
|
736
828
|
|
|
737
829
|
const toolbar = this.#context.get('toolbar_main');
|
|
738
|
-
const isToolbarHidden =
|
|
830
|
+
const isToolbarHidden =
|
|
831
|
+
toolbar.style.display === 'none' || (this.#store.mode.isInline && !this.#toolbar.inlineToolbarAttr.isShow);
|
|
739
832
|
if (toolbar.offsetWidth === 0 && !isToolbarHidden) return;
|
|
740
833
|
|
|
741
834
|
const opendBrowser = this.#ui.opendBrowser;
|
|
742
835
|
if (opendBrowser && opendBrowser.area.style.display === 'block') {
|
|
743
|
-
opendBrowser.body.style.maxHeight =
|
|
836
|
+
opendBrowser.body.style.maxHeight =
|
|
837
|
+
dom.utils.getClientSize().h - opendBrowser.header.offsetHeight - 50 + 'px';
|
|
744
838
|
}
|
|
745
839
|
|
|
746
840
|
if (this.#menu.currentDropdownActiveButton && this.#menu.currentDropdown) {
|
|
@@ -812,7 +906,11 @@ class EventOrchestrator extends KernelInjector {
|
|
|
812
906
|
return;
|
|
813
907
|
}
|
|
814
908
|
|
|
815
|
-
if (
|
|
909
|
+
if (
|
|
910
|
+
(this.#store.get('rootKey') === rootKey && this.#store.get('_preventBlur')) ||
|
|
911
|
+
this.#store.get('_preventFocus')
|
|
912
|
+
)
|
|
913
|
+
return;
|
|
816
914
|
this.#store.set('_preventFocus', true);
|
|
817
915
|
|
|
818
916
|
dom.utils.removeClass(this.$.commandDispatcher.targets.get('codeView'), 'active');
|
|
@@ -838,6 +936,9 @@ class EventOrchestrator extends KernelInjector {
|
|
|
838
936
|
this.#store.set('_lastSelectionNode', null);
|
|
839
937
|
this.#eventManager.triggerEvent('onNativeBlur', { frameContext, event: e });
|
|
840
938
|
|
|
939
|
+
// Drop the per-line placeholder on blur; the empty-editor placeholder takes over if applicable.
|
|
940
|
+
this.#ui._updatePlaceholder(frameContext);
|
|
941
|
+
|
|
841
942
|
if (this._inputFocus || this.#store.get('_preventBlur')) return;
|
|
842
943
|
this.#store.set('_preventFocus', false);
|
|
843
944
|
|
|
@@ -897,7 +998,9 @@ class EventOrchestrator extends KernelInjector {
|
|
|
897
998
|
if (!component) return;
|
|
898
999
|
|
|
899
1000
|
const isList = dom.check.isListCell(component.parentElement);
|
|
900
|
-
const format = dom.utils.createElement(
|
|
1001
|
+
const format = dom.utils.createElement(
|
|
1002
|
+
isList ? 'BR' : dom.check.isTableCell(component.parentElement) ? 'DIV' : this.#options.get('defaultLine'),
|
|
1003
|
+
);
|
|
901
1004
|
if (!isList) format.innerHTML = '<br>';
|
|
902
1005
|
|
|
903
1006
|
if (this.$.frameOptions.get('charCounter_type') === 'byte-html' && !this.$.char.check(format.outerHTML)) return;
|
|
@@ -939,7 +1042,11 @@ class EventOrchestrator extends KernelInjector {
|
|
|
939
1042
|
this.__setViewportSize();
|
|
940
1043
|
|
|
941
1044
|
if (isMobile && prevHeight > 0 && prevHeight - _w.visualViewport.height > 100 && this.#store.get('hasFocus')) {
|
|
942
|
-
this.$.selection.scrollTo(this.$.selection.getRange(), {
|
|
1045
|
+
this.$.selection.scrollTo(this.$.selection.getRange(), {
|
|
1046
|
+
behavior: 'auto',
|
|
1047
|
+
block: 'nearest',
|
|
1048
|
+
inline: 'nearest',
|
|
1049
|
+
});
|
|
943
1050
|
}
|
|
944
1051
|
}
|
|
945
1052
|
|
|
@@ -984,6 +1091,9 @@ class EventOrchestrator extends KernelInjector {
|
|
|
984
1091
|
this.$.selection.init();
|
|
985
1092
|
this.applyTagEffect();
|
|
986
1093
|
|
|
1094
|
+
// Notion-style per-line placeholder follows the caret's line.
|
|
1095
|
+
this.#ui._updatePlaceholder(root);
|
|
1096
|
+
|
|
987
1097
|
// balloon toolbar - touch devices
|
|
988
1098
|
if (isTouchDevice && (this.#store.mode.isBalloon || this.#store.mode.isSubBalloon)) {
|
|
989
1099
|
this.#toggleToolbarBalloonDelay();
|
|
@@ -991,7 +1101,10 @@ class EventOrchestrator extends KernelInjector {
|
|
|
991
1101
|
|
|
992
1102
|
// document type
|
|
993
1103
|
if (root.has('documentType_use_header')) {
|
|
994
|
-
const el = dom.query.getParentElement(
|
|
1104
|
+
const el = dom.query.getParentElement(
|
|
1105
|
+
this.$.selection.selectionNode,
|
|
1106
|
+
this.$.format.isLine.bind(this.$.format),
|
|
1107
|
+
);
|
|
995
1108
|
root.get('documentType').on(el);
|
|
996
1109
|
}
|
|
997
1110
|
}
|
|
@@ -53,13 +53,15 @@ export function ButtonsHandler(e) {
|
|
|
53
53
|
if (this.__inputBlurEvent) this.__removeInput();
|
|
54
54
|
|
|
55
55
|
// blur event
|
|
56
|
-
if (typeof plugin.toolbarInputChange === 'function')
|
|
56
|
+
if (typeof plugin.toolbarInputChange === 'function')
|
|
57
|
+
this.__inputPlugin = { obj: plugin, target: eventTarget, value: eventTarget.value };
|
|
57
58
|
this.__inputBlurEvent = this.$.eventManager.addEvent(eventTarget, 'blur', (ev) => {
|
|
58
59
|
if (plugin.isInputActive) return;
|
|
59
60
|
|
|
60
61
|
try {
|
|
61
62
|
const value = eventTarget.value.trim();
|
|
62
|
-
if (typeof plugin.toolbarInputChange === 'function' && value !== this.__inputPlugin.value)
|
|
63
|
+
if (typeof plugin.toolbarInputChange === 'function' && value !== this.__inputPlugin.value)
|
|
64
|
+
plugin.toolbarInputChange({ target: eventTarget, value, event: ev });
|
|
63
65
|
} finally {
|
|
64
66
|
// Defer flag reset — wysiwyg focus event fires synchronously during blur and checks this flag
|
|
65
67
|
_w.setTimeout(() => (this._inputFocus = false), 0);
|
|
@@ -16,6 +16,11 @@ const { _w } = env;
|
|
|
16
16
|
* @param {DragEvent} e - Event object
|
|
17
17
|
*/
|
|
18
18
|
export function OnDragOver_wysiwyg(fc, dragCursor, _iframeTopArea, _innerToolbar, e) {
|
|
19
|
+
// Block-handle drag uses its own indicator + drop logic — skip the component
|
|
20
|
+
if (e.dataTransfer && Array.from(e.dataTransfer.types || []).includes('application/x-suneditor-block-drag')) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
19
24
|
const { sc, so, ec, eo } = this.$.selection.getDragEventLocationRange(e);
|
|
20
25
|
if (!sc) return;
|
|
21
26
|
|
|
@@ -91,6 +96,11 @@ export function OnDrop_wysiwyg(fc, dragCursor, e) {
|
|
|
91
96
|
const dataTransfer = e.dataTransfer;
|
|
92
97
|
if (!dataTransfer) return true;
|
|
93
98
|
|
|
99
|
+
// Block-handle drag handles its own drop — skip the text-insertion path.
|
|
100
|
+
if (Array.from(dataTransfer.types || []).includes('application/x-suneditor-block-drag')) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
|
|
94
104
|
const { sc, so, ec, eo } = this.$.selection.getDragEventLocationRange(e);
|
|
95
105
|
if (!sc) return;
|
|
96
106
|
|
|
@@ -29,7 +29,8 @@ export async function OnBeforeInput_wysiwyg(fc, e) {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
// user event
|
|
32
|
-
if ((await this.$.eventManager.triggerEvent('onBeforeInput', { frameContext: fc, event: e, data })) === false)
|
|
32
|
+
if ((await this.$.eventManager.triggerEvent('onBeforeInput', { frameContext: fc, event: e, data })) === false)
|
|
33
|
+
return;
|
|
33
34
|
// plugin event
|
|
34
35
|
await this._callPluginEventAsync('onBeforeInput', { frameContext: fc, event: e, data });
|
|
35
36
|
}
|
|
@@ -49,7 +50,13 @@ export async function OnInput_wysiwyg(fc, e) {
|
|
|
49
50
|
const range = this.$.selection.getRange();
|
|
50
51
|
const selectionNode = this.$.selection.getNode();
|
|
51
52
|
const formatEl = this.$.format.getLine(selectionNode, null);
|
|
52
|
-
if (
|
|
53
|
+
if (
|
|
54
|
+
!this.$.format.isNormalLine(formatEl) &&
|
|
55
|
+
!this.$.format.isBrLine(formatEl) &&
|
|
56
|
+
range.collapsed &&
|
|
57
|
+
!this.$.component.is(selectionNode) &&
|
|
58
|
+
!dom.check.isList(selectionNode)
|
|
59
|
+
) {
|
|
53
60
|
const rangeEl = this.$.format.getBlock(selectionNode, null);
|
|
54
61
|
this._setDefaultLine(this.$.format.isBlock(rangeEl) ? 'DIV' : this.$.options.get('defaultLine'));
|
|
55
62
|
}
|
|
@@ -47,12 +47,22 @@ export async function OnKeyDown_wysiwyg(fc, e) {
|
|
|
47
47
|
if (!this.$.store.mode.isSubBalloonAlways) this._hideToolbar_sub();
|
|
48
48
|
}
|
|
49
49
|
|
|
50
|
-
|
|
51
|
-
if ((await this.$.eventManager.triggerEvent('onKeyDown', { frameContext: fc, event: e })) === false) return;
|
|
52
|
-
|
|
53
|
-
/** default key action */
|
|
50
|
+
/** default key action — normalize the Enter range before the reducer reads it */
|
|
54
51
|
if (keyCodeMap.isEnter(keyCode) && this.$.format.isLine(this.$.selection.getRange()?.startContainer)) {
|
|
55
52
|
this.$.selection.resetRangeToTextNode();
|
|
53
|
+
|
|
54
|
+
const r = this.$.selection.getRange();
|
|
55
|
+
if (
|
|
56
|
+
r.startContainer === r.endContainer &&
|
|
57
|
+
r.startOffset !== r.endOffset &&
|
|
58
|
+
r.startContainer.nodeType === 3 &&
|
|
59
|
+
dom.check.isZeroWidth(r.startContainer)
|
|
60
|
+
) {
|
|
61
|
+
const br = r.startContainer.nextSibling;
|
|
62
|
+
if (br && dom.check.isBreak(br)) this.$.selection.setRange(br, 0, br, 0);
|
|
63
|
+
else this.$.selection.setRange(r.endContainer, r.endOffset, r.endContainer, r.endOffset);
|
|
64
|
+
}
|
|
65
|
+
|
|
56
66
|
selectionNode = this.$.selection.getNode();
|
|
57
67
|
}
|
|
58
68
|
|
|
@@ -60,12 +70,22 @@ export async function OnKeyDown_wysiwyg(fc, e) {
|
|
|
60
70
|
const formatEl = /** @type {HTMLElement} */ (this.$.format.getLine(selectionNode, null) || selectionNode);
|
|
61
71
|
|
|
62
72
|
/** Shortcuts */
|
|
63
|
-
if (
|
|
73
|
+
if (
|
|
74
|
+
ctrl &&
|
|
75
|
+
!keyCodeMap.isNonTextKey(keyCode) &&
|
|
76
|
+
this.$.shortcuts.command(e, ctrl, shift, keyCode, '', false, null, null)
|
|
77
|
+
) {
|
|
64
78
|
this._onShortcutKey = true;
|
|
65
79
|
e.preventDefault();
|
|
66
80
|
e.stopPropagation();
|
|
67
81
|
return false;
|
|
68
|
-
} else if (
|
|
82
|
+
} else if (
|
|
83
|
+
!ctrl &&
|
|
84
|
+
!keyCodeMap.isNonTextKey(keyCode) &&
|
|
85
|
+
this.$.format.isLine(formatEl) &&
|
|
86
|
+
range.collapsed &&
|
|
87
|
+
dom.check.isEdgePoint(range.startContainer, 0, 'front')
|
|
88
|
+
) {
|
|
69
89
|
const keyword = /** @type {Text} */ (range.startContainer).substringData?.(0, range.startOffset);
|
|
70
90
|
if (keyword && this.$.shortcuts.command(e, false, shift, keyCode, keyword, true, formatEl, range)) {
|
|
71
91
|
this._onShortcutKey = true;
|
|
@@ -77,16 +97,36 @@ export async function OnKeyDown_wysiwyg(fc, e) {
|
|
|
77
97
|
this._onShortcutKey = false;
|
|
78
98
|
}
|
|
79
99
|
|
|
80
|
-
// plugin event
|
|
81
|
-
if ((await this._callPluginEventAsync('onKeyDown', { frameContext: fc, event: e, range, line: formatEl })) === false) return;
|
|
82
|
-
|
|
83
100
|
// reducer / actions
|
|
84
101
|
/** @type {import('../reducers/keydown.reducer').KeydownReducerCtx} */
|
|
85
|
-
const ctx = {
|
|
102
|
+
const ctx = {
|
|
103
|
+
e,
|
|
104
|
+
fc,
|
|
105
|
+
store: this.$.store,
|
|
106
|
+
options: this.$.options,
|
|
107
|
+
frameOptions: this.$.frameOptions,
|
|
108
|
+
range,
|
|
109
|
+
selectionNode,
|
|
110
|
+
formatEl,
|
|
111
|
+
keyCode,
|
|
112
|
+
ctrl,
|
|
113
|
+
alt,
|
|
114
|
+
shift,
|
|
115
|
+
};
|
|
86
116
|
const ports = makePorts(this, { _styleNodes });
|
|
87
117
|
|
|
88
118
|
// action execute
|
|
89
119
|
const actions = await reduceKeydown(ports, ctx);
|
|
120
|
+
|
|
121
|
+
if ((await this.$.eventManager.triggerEvent('onKeyDown', { frameContext: fc, event: e })) === false) return;
|
|
122
|
+
|
|
123
|
+
// plugin event
|
|
124
|
+
if (
|
|
125
|
+
(await this._callPluginEventAsync('onKeyDown', { frameContext: fc, event: e, range, line: formatEl })) === false
|
|
126
|
+
)
|
|
127
|
+
return;
|
|
128
|
+
|
|
129
|
+
// action execute
|
|
90
130
|
await actionExecutor(actions, { ports, ctx });
|
|
91
131
|
}
|
|
92
132
|
|
|
@@ -110,7 +150,11 @@ export async function OnKeyUp_wysiwyg(fc, e) {
|
|
|
110
150
|
const range = this.$.selection.getRange();
|
|
111
151
|
let selectionNode = this.$.selection.getNode();
|
|
112
152
|
|
|
113
|
-
if (
|
|
153
|
+
if (
|
|
154
|
+
(this.$.store.mode.isBalloon || this.$.store.mode.isSubBalloon) &&
|
|
155
|
+
(((this.$.store.mode.isBalloonAlways || this.$.store.mode.isSubBalloonAlways) && !keyCodeMap.isEsc(keyCode)) ||
|
|
156
|
+
!range.collapsed)
|
|
157
|
+
) {
|
|
114
158
|
if (this.$.store.mode.isBalloonAlways || this.$.store.mode.isSubBalloonAlways) {
|
|
115
159
|
if (!keyCodeMap.isEsc(keyCode)) this._showToolbarBalloonDelay();
|
|
116
160
|
} else {
|
|
@@ -121,14 +165,25 @@ export async function OnKeyUp_wysiwyg(fc, e) {
|
|
|
121
165
|
}
|
|
122
166
|
|
|
123
167
|
/** when format tag deleted */
|
|
124
|
-
if (
|
|
168
|
+
if (
|
|
169
|
+
keyCodeMap.isBackspace(keyCode) &&
|
|
170
|
+
dom.check.isWysiwygFrame(selectionNode) &&
|
|
171
|
+
selectionNode.textContent === '' &&
|
|
172
|
+
selectionNode.children.length === 0
|
|
173
|
+
) {
|
|
125
174
|
e.preventDefault();
|
|
126
175
|
e.stopPropagation();
|
|
127
176
|
|
|
128
177
|
selectionNode.innerHTML = '';
|
|
129
178
|
|
|
130
179
|
const currentNodeName = this.$.store.get('currentNodes')[0];
|
|
131
|
-
const oFormatTag = dom.utils.createElement(
|
|
180
|
+
const oFormatTag = dom.utils.createElement(
|
|
181
|
+
this.$.format.isLine(currentNodeName) && !dom.check.isListCell(currentNodeName)
|
|
182
|
+
? currentNodeName
|
|
183
|
+
: this.$.options.get('defaultLine'),
|
|
184
|
+
null,
|
|
185
|
+
'<br>',
|
|
186
|
+
);
|
|
132
187
|
selectionNode.appendChild(oFormatTag);
|
|
133
188
|
this.$.selection.setRange(oFormatTag, 0, oFormatTag, 0);
|
|
134
189
|
this.applyTagEffect();
|
|
@@ -172,7 +227,12 @@ export async function OnKeyUp_wysiwyg(fc, e) {
|
|
|
172
227
|
}
|
|
173
228
|
|
|
174
229
|
const textKey = !keyState.ctrl && !keyState.alt && !keyCodeMap.isNonTextKey(keyCode);
|
|
175
|
-
if (
|
|
230
|
+
if (
|
|
231
|
+
textKey &&
|
|
232
|
+
selectionNode.nodeType === 3 &&
|
|
233
|
+
unicode.zeroWidthRegExp.test(selectionNode.textContent) &&
|
|
234
|
+
!(e.isComposing !== undefined ? e.isComposing : this.isComposing)
|
|
235
|
+
) {
|
|
176
236
|
let so = range.startOffset,
|
|
177
237
|
eo = range.endOffset;
|
|
178
238
|
const frontZeroWidthCnt = (selectionNode.textContent.substring(0, eo).match(FRONT_ZEROWIDTH) || '').length;
|
|
@@ -182,7 +242,12 @@ export async function OnKeyUp_wysiwyg(fc, e) {
|
|
|
182
242
|
this.$.selection.setRange(selectionNode, so < 0 ? 0 : so, selectionNode, eo < 0 ? 0 : eo);
|
|
183
243
|
}
|
|
184
244
|
|
|
185
|
-
if (
|
|
245
|
+
if (
|
|
246
|
+
keyCodeMap.isRemoveKey(keyCode) &&
|
|
247
|
+
dom.check.isZeroWidth(formatEl?.textContent) &&
|
|
248
|
+
!formatEl.previousElementSibling &&
|
|
249
|
+
!dom.check.isListCell(formatEl)
|
|
250
|
+
) {
|
|
186
251
|
const rsMode = this.$.options.get('retainStyleMode');
|
|
187
252
|
if (rsMode !== 'none' && _styleNodes.value?.length > 0) {
|
|
188
253
|
if (rsMode === 'repeat') {
|
|
@@ -209,7 +274,10 @@ export async function OnKeyUp_wysiwyg(fc, e) {
|
|
|
209
274
|
if (fc.has('documentType_use_header')) {
|
|
210
275
|
if (keyCodeMap.isDocumentTypeObserverKey(keyCode)) {
|
|
211
276
|
fc.get('documentType').reHeader();
|
|
212
|
-
const el = dom.query.getParentElement(
|
|
277
|
+
const el = dom.query.getParentElement(
|
|
278
|
+
this.$.selection.selectionNode,
|
|
279
|
+
this.$.format.isLine.bind(this.$.format),
|
|
280
|
+
);
|
|
213
281
|
fc.get('documentType').on(el);
|
|
214
282
|
} else {
|
|
215
283
|
const el = dom.query.getParentElement(selectionNode, (current) => current.nodeType === 1);
|
|
@@ -220,7 +288,8 @@ export async function OnKeyUp_wysiwyg(fc, e) {
|
|
|
220
288
|
// user event
|
|
221
289
|
if ((await this.$.eventManager.triggerEvent('onKeyUp', { frameContext: fc, event: e })) === false) return;
|
|
222
290
|
// plugin event
|
|
223
|
-
if ((await this._callPluginEventAsync('onKeyUp', { frameContext: fc, event: e, range, line: formatEl })) === false)
|
|
291
|
+
if ((await this._callPluginEventAsync('onKeyUp', { frameContext: fc, event: e, range, line: formatEl })) === false)
|
|
292
|
+
return;
|
|
224
293
|
|
|
225
294
|
if (keyCodeMap.isHistoryRelevantKey(keyCode)) {
|
|
226
295
|
this.$.history.push(true);
|
|
@@ -3,6 +3,12 @@ import { _DragHandle } from '../../../modules/ui';
|
|
|
3
3
|
|
|
4
4
|
const { _w } = env;
|
|
5
5
|
|
|
6
|
+
/**
|
|
7
|
+
* Per-frame rAF state for wysiwyg mousemove coalescing.
|
|
8
|
+
* @type {WeakMap<*, {rafId: ?number, event: ?MouseEvent}>}
|
|
9
|
+
*/
|
|
10
|
+
const __wwMousemoveRaf = new WeakMap();
|
|
11
|
+
|
|
6
12
|
/**
|
|
7
13
|
* @typedef {import('../eventOrchestrator').default} EventManagerThis_handler_ww_mouse
|
|
8
14
|
*/
|
|
@@ -102,7 +108,12 @@ export async function OnClick_wysiwyg(fc, e) {
|
|
|
102
108
|
if (e.detail === 3) {
|
|
103
109
|
const range = this.$.selection.getRange();
|
|
104
110
|
if (this.$.format.isLine(range.endContainer) && range.endOffset === 0) {
|
|
105
|
-
this.$.selection.setRange(
|
|
111
|
+
this.$.selection.setRange(
|
|
112
|
+
range.startContainer,
|
|
113
|
+
range.startOffset,
|
|
114
|
+
range.startContainer,
|
|
115
|
+
range.startContainer.textContent.length,
|
|
116
|
+
);
|
|
106
117
|
}
|
|
107
118
|
}
|
|
108
119
|
|
|
@@ -122,7 +133,8 @@ export async function OnClick_wysiwyg(fc, e) {
|
|
|
122
133
|
!dom.check.isWysiwygFrame(selectionNode) &&
|
|
123
134
|
!this.$.component.is(selectionNode) &&
|
|
124
135
|
(!dom.check.isTableElements(selectionNode) || dom.check.isTableCell(selectionNode)) &&
|
|
125
|
-
this._setDefaultLine(this.$.format.isBlock(rangeEl) ? 'DIV' : this.$.options.get('defaultLine')) !==
|
|
136
|
+
this._setDefaultLine(this.$.format.isBlock(rangeEl) ? 'DIV' : this.$.options.get('defaultLine')) !==
|
|
137
|
+
null
|
|
126
138
|
) {
|
|
127
139
|
e.preventDefault();
|
|
128
140
|
this.$.focusManager.focus();
|
|
@@ -134,7 +146,8 @@ export async function OnClick_wysiwyg(fc, e) {
|
|
|
134
146
|
this.$.commandDispatcher._copyFormat();
|
|
135
147
|
|
|
136
148
|
// Defer balloon toggle — selection range is finalized after mouseup event returns
|
|
137
|
-
if (this.$.store.mode.isBalloon || this.$.store.mode.isSubBalloon)
|
|
149
|
+
if (this.$.store.mode.isBalloon || this.$.store.mode.isSubBalloon)
|
|
150
|
+
_w.setTimeout(this._toggleToolbarBalloon.bind(this), 0);
|
|
138
151
|
}
|
|
139
152
|
|
|
140
153
|
/**
|
|
@@ -144,14 +157,35 @@ export async function OnClick_wysiwyg(fc, e) {
|
|
|
144
157
|
*/
|
|
145
158
|
export function OnMouseMove_wysiwyg(fc, e) {
|
|
146
159
|
if (fc.get('isReadOnly') || fc.get('isDisabled')) return false;
|
|
147
|
-
const eventTarget = dom.query.getEventTarget(e);
|
|
148
160
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
161
|
+
let s = __wwMousemoveRaf.get(fc);
|
|
162
|
+
|
|
163
|
+
if (!s) {
|
|
164
|
+
s = { rafId: null, event: null };
|
|
165
|
+
__wwMousemoveRaf.set(fc, s);
|
|
152
166
|
}
|
|
153
167
|
|
|
154
|
-
|
|
168
|
+
s.event = e;
|
|
169
|
+
if (s.rafId !== null) return;
|
|
170
|
+
|
|
171
|
+
s.rafId = _w.requestAnimationFrame(() => {
|
|
172
|
+
const ev = s.event;
|
|
173
|
+
s.rafId = null;
|
|
174
|
+
s.event = null;
|
|
175
|
+
if (!ev) return;
|
|
176
|
+
|
|
177
|
+
const eventTarget = dom.query.getEventTarget(ev);
|
|
178
|
+
|
|
179
|
+
// over component — skip while select menu (block handle menu) is open
|
|
180
|
+
if (_DragHandle.get('__overInfo') !== false && !this.$.ui.selectMenuOn) {
|
|
181
|
+
this.$.component.hoverSelect(eventTarget);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// block handle
|
|
185
|
+
this.$.ui.blockHandle?.positionForTarget(eventTarget, ev.clientY);
|
|
186
|
+
|
|
187
|
+
this._callPluginEvent('onMouseMove', { frameContext: fc, event: ev });
|
|
188
|
+
});
|
|
155
189
|
}
|
|
156
190
|
|
|
157
191
|
/**
|
|
@@ -160,6 +194,9 @@ export function OnMouseMove_wysiwyg(fc, e) {
|
|
|
160
194
|
* @param {MouseEvent} e - Event object
|
|
161
195
|
*/
|
|
162
196
|
export async function OnMouseLeave_wysiwyg(fc, e) {
|
|
197
|
+
// block handle hide
|
|
198
|
+
this.$.ui.blockHandle?.hide(e);
|
|
199
|
+
|
|
163
200
|
// user event
|
|
164
201
|
if ((await this.$.eventManager.triggerEvent('onMouseLeave', { frameContext: fc, event: e })) === false) return;
|
|
165
202
|
// plugin event
|