diff --git a/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/switchShadowEdit.ts b/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/switchShadowEdit.ts index 0abc929e901..cc312a5117c 100644 --- a/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/switchShadowEdit.ts +++ b/packages-content-model/roosterjs-content-model-editor/lib/editor/coreApi/switchShadowEdit.ts @@ -1,6 +1,6 @@ import { ContentModelEditorCore } from '../../publicTypes/ContentModelEditorCore'; import { getSelectionPath } from 'roosterjs-editor-dom'; -import { SwitchShadowEdit } from 'roosterjs-editor-types'; +import { PluginEventType, SwitchShadowEdit } from 'roosterjs-editor-types'; /** * @internal @@ -23,10 +23,28 @@ export const switchShadowEdit: SwitchShadowEdit = (editorCore, isOn): void => { core.lifecycle.shadowEditSelectionPath = range && getSelectionPath(core.contentDiv, range); core.lifecycle.shadowEditFragment = core.contentDiv.ownerDocument.createDocumentFragment(); + + core.api.triggerEvent( + core, + { + eventType: PluginEventType.EnteredShadowEdit, + fragment: core.lifecycle.shadowEditFragment, + selectionPath: core.lifecycle.shadowEditSelectionPath, + }, + false /*broadcast*/ + ); } else { core.lifecycle.shadowEditFragment = null; core.lifecycle.shadowEditSelectionPath = null; + core.api.triggerEvent( + core, + { + eventType: PluginEventType.LeavingShadowEdit, + }, + false /*broadcast*/ + ); + if (core.cachedModel) { core.api.setContentModel(core, core.cachedModel); } diff --git a/packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/switchShadowEditTest.ts b/packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/switchShadowEditTest.ts index 36275c82607..8ec02383909 100644 --- a/packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/switchShadowEditTest.ts +++ b/packages-content-model/roosterjs-content-model-editor/test/editor/coreApi/switchShadowEditTest.ts @@ -1,4 +1,5 @@ import { ContentModelEditorCore } from '../../../lib/publicTypes/ContentModelEditorCore'; +import { PluginEventType } from 'roosterjs-editor-types'; import { switchShadowEdit } from '../../../lib/editor/coreApi/switchShadowEdit'; const mockedModel = 'MODEL' as any; @@ -9,17 +10,20 @@ describe('switchShadowEdit', () => { let createContentModel: jasmine.Spy; let setContentModel: jasmine.Spy; let getSelectionRange: jasmine.Spy; + let triggerEvent: jasmine.Spy; beforeEach(() => { createContentModel = jasmine.createSpy('createContentModel').and.returnValue(mockedModel); setContentModel = jasmine.createSpy('setContentModel'); getSelectionRange = jasmine.createSpy('getSelectionRange'); + triggerEvent = jasmine.createSpy('triggerEvent'); core = ({ api: { createContentModel, setContentModel, getSelectionRange, + triggerEvent, }, lifecycle: {}, contentDiv: document.createElement('div'), @@ -33,6 +37,16 @@ describe('switchShadowEdit', () => { expect(createContentModel).toHaveBeenCalledWith(core); expect(setContentModel).not.toHaveBeenCalled(); expect(core.cachedModel).toBe(mockedModel); + expect(triggerEvent).toHaveBeenCalledTimes(1); + expect(triggerEvent).toHaveBeenCalledWith( + core, + { + eventType: PluginEventType.EnteredShadowEdit, + fragment: document.createDocumentFragment(), + selectionPath: undefined, + }, + false + ); }); it('with cache, isOn', () => { @@ -43,6 +57,17 @@ describe('switchShadowEdit', () => { expect(createContentModel).not.toHaveBeenCalled(); expect(setContentModel).not.toHaveBeenCalled(); expect(core.cachedModel).toBe(mockedCachedModel); + + expect(triggerEvent).toHaveBeenCalledTimes(1); + expect(triggerEvent).toHaveBeenCalledWith( + core, + { + eventType: PluginEventType.EnteredShadowEdit, + fragment: document.createDocumentFragment(), + selectionPath: undefined, + }, + false + ); }); it('no cache, isOff', () => { @@ -51,6 +76,8 @@ describe('switchShadowEdit', () => { expect(createContentModel).not.toHaveBeenCalled(); expect(setContentModel).not.toHaveBeenCalled(); expect(core.cachedModel).toBe(undefined); + + expect(triggerEvent).not.toHaveBeenCalled(); }); it('with cache, isOff', () => { @@ -61,6 +88,8 @@ describe('switchShadowEdit', () => { expect(createContentModel).not.toHaveBeenCalled(); expect(setContentModel).not.toHaveBeenCalled(); expect(core.cachedModel).toBe(mockedCachedModel); + + expect(triggerEvent).not.toHaveBeenCalled(); }); }); @@ -75,6 +104,8 @@ describe('switchShadowEdit', () => { expect(createContentModel).not.toHaveBeenCalled(); expect(setContentModel).not.toHaveBeenCalled(); expect(core.cachedModel).toBe(undefined); + + expect(triggerEvent).not.toHaveBeenCalled(); }); it('with cache, isOn', () => { @@ -85,6 +116,8 @@ describe('switchShadowEdit', () => { expect(createContentModel).not.toHaveBeenCalled(); expect(setContentModel).not.toHaveBeenCalled(); expect(core.cachedModel).toBe(mockedCachedModel); + + expect(triggerEvent).not.toHaveBeenCalled(); }); it('no cache, isOff', () => { @@ -93,6 +126,15 @@ describe('switchShadowEdit', () => { expect(createContentModel).not.toHaveBeenCalled(); expect(setContentModel).not.toHaveBeenCalled(); expect(core.cachedModel).toBe(undefined); + + expect(triggerEvent).toHaveBeenCalledTimes(1); + expect(triggerEvent).toHaveBeenCalledWith( + core, + { + eventType: PluginEventType.LeavingShadowEdit, + }, + false + ); }); it('with cache, isOff', () => { @@ -103,6 +145,15 @@ describe('switchShadowEdit', () => { expect(createContentModel).not.toHaveBeenCalled(); expect(setContentModel).toHaveBeenCalledWith(core, mockedCachedModel); expect(core.cachedModel).toBe(mockedCachedModel); + + expect(triggerEvent).toHaveBeenCalledTimes(1); + expect(triggerEvent).toHaveBeenCalledWith( + core, + { + eventType: PluginEventType.LeavingShadowEdit, + }, + false + ); }); }); });