Skip to content

Commit

Permalink
Merge pull request #2133 from microsoft/u/juliaroldi/trigger-image
Browse files Browse the repository at this point in the history
Trigger apply changed when mouse up
  • Loading branch information
juliaroldi authored Oct 17, 2023
2 parents a7a7853 + de9c13c commit 07ff0b6
Show file tree
Hide file tree
Showing 10 changed files with 128 additions and 10 deletions.
1 change: 1 addition & 0 deletions demo/scripts/controls/BuildInPluginState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export default interface BuildInPluginState {
isRtl: boolean;
cacheModel?: boolean;
tableFeaturesContainerSelector: string;
applyChangesOnMouseUp?: boolean;
}

export interface BuildInPluginProps extends BuildInPluginState, SidePaneElementProps {}
1 change: 1 addition & 0 deletions demo/scripts/controls/getToggleablePlugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ export default function getToggleablePlugins(initState: BuildInPluginState) {
const imageEdit = pluginList.imageEdit
? new ImageEdit({
preserveRatio: initState.forcePreserveRatio,
applyChangesOnMouseUp: initState.applyChangesOnMouseUp,
})
: null;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const initialState: BuildInPluginState = {
linkTitle: 'Ctrl+Click to follow the link:' + UrlPlaceholder,
watermarkText: 'Type content here ...',
forcePreserveRatio: false,
applyChangesOnMouseUp: false,
experimentalFeatures: [],
isRtl: false,
cacheModel: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ export default class ContentModelOptionsPane extends React.Component<
defaultFormat: { ...this.state.defaultFormat },
experimentalFeatures: this.state.experimentalFeatures,
forcePreserveRatio: this.state.forcePreserveRatio,
applyChangesOnMouseUp: this.state.applyChangesOnMouseUp,
isRtl: this.state.isRtl,
cacheModel: this.state.cacheModel,
tableFeaturesContainerSelector: this.state.tableFeaturesContainerSelector,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export default class ContentModelPlugins extends React.Component<PluginsProps, {
private linkTitle = React.createRef<HTMLInputElement>();
private watermarkText = React.createRef<HTMLInputElement>();
private forcePreserveRatio = React.createRef<HTMLInputElement>();
private applyChangesOnMouseUp = React.createRef<HTMLInputElement>();

render() {
return (
Expand Down Expand Up @@ -52,6 +53,16 @@ export default class ContentModelPlugins extends React.Component<PluginsProps, {
(state, value) => (state.forcePreserveRatio = value)
)
)}
{this.renderPluginItem(
'imageEdit',
'Image Edit Plugin',
this.renderCheckBox(
'Apply changed on mouse up',
this.applyChangesOnMouseUp,
this.props.state.applyChangesOnMouseUp,
(state, value) => (state.applyChangesOnMouseUp = value)
)
)}
{this.renderPluginItem('tableResize', 'Table Resize Plugin')}
{this.renderPluginItem('customReplace', 'Custom Replace Plugin (autocomplete)')}
{this.renderPluginItem(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const DefaultOptions: Required<ImageEditOptions> = {
disableRotate: false,
disableSideResize: false,
onSelectState: ImageEditOperation.ResizeAndRotate,
applyChangesOnMouseUp: false,
};

/**
Expand Down Expand Up @@ -222,11 +223,12 @@ export default class ImageEdit implements EditorPlugin {
}
break;
case PluginEventType.MouseUp:
// When mouse up, if the image and the shadow span exists, the editing mode is on.
// To make sure the selection did not jump to the shadow root, reselect the image.
if (this.image && this.shadowSpan) {
this.editor?.select(this.image);
if (this.editor && this.image && this.shadowSpan) {
// When mouse up, if the image and the shadow span exists, the editing mode is on.
// To make sure the selection did not jump to the shadow root, reselect the image.
this.editor.select(this.image);
}

break;
case PluginEventType.KeyDown:
this.setEditingImage(null);
Expand Down Expand Up @@ -474,7 +476,12 @@ export default class ImageEdit implements EditorPlugin {
}
}

private insertImageWrapper(wrapper: HTMLSpanElement) {
/**
* EXPORTED FOR TESTING PURPOSES ONLY
* @param wrapper
*/

public insertImageWrapper(wrapper: HTMLSpanElement) {
if (this.image) {
this.shadowSpan = wrap(this.image, 'span');
if (this.shadowSpan) {
Expand All @@ -484,7 +491,13 @@ export default class ImageEdit implements EditorPlugin {

this.shadowSpan.style.verticalAlign = 'bottom';
wrapper.style.fontSize = '24px';

if (this.options.applyChangesOnMouseUp) {
wrapper.addEventListener(
'mouseup',
this.changesWhenMouseUp,
true /* useCapture*/
);
}
shadowRoot.appendChild(wrapper);
}
}
Expand All @@ -497,10 +510,31 @@ export default class ImageEdit implements EditorPlugin {
if (this.shadowSpan) {
unwrap(this.shadowSpan);
}
if (this.options.applyChangesOnMouseUp) {
this.wrapper?.removeEventListener(
'mouseup',
this.changesWhenMouseUp,
true /* useCapture*/
);
}
this.wrapper = null;
this.shadowSpan = null;
};

private changesWhenMouseUp = () => {
if (this.editor && this.image && this.editInfo && this.lastSrc && this.clonedImage) {
applyChange(
this.editor,
this.image,
this.editInfo,
this.lastSrc,
this.wasResized,
this.clonedImage,
this.options.applyChangesOnMouseUp
);
}
};

/**
* Update image edit elements to reflect current editing result
* @param context
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import checkEditInfoState, { ImageEditInfoState } from './checkEditInfoState';
import generateDataURL from './generateDataURL';
import getGeneratedImageSize from './getGeneratedImageSize';
import { ChangeSource, PluginEventType } from 'roosterjs-editor-types';
import { deleteEditInfo, getEditInfoFromImage, saveEditInfo } from './editInfo';
import { PluginEventType } from 'roosterjs-editor-types';
import type ImageEditInfo from '../types/ImageEditInfo';
import type { IEditor } from 'roosterjs-editor-types';

Expand All @@ -22,7 +22,8 @@ export default function applyChange(
editInfo: ImageEditInfo,
previousSrc: string,
wasResizedOrCropped: boolean,
editingImage?: HTMLImageElement
editingImage?: HTMLImageElement,
applyChangesOnMouseUp?: boolean
) {
let newSrc = '';

Expand Down Expand Up @@ -57,6 +58,10 @@ export default function applyChange(
newSrc,
});
newSrc = event.newSrc;
} else if (applyChangesOnMouseUp) {
editor.triggerPluginEvent(PluginEventType.ContentChanged, {
source: ChangeSource.ImageResize,
});
}

if (newSrc == editInfo.src) {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import applyChange from '../../lib/plugins/ImageEdit/editInfoUtils/applyChange';
import { ChangeSource, IEditor, PluginEventType } from 'roosterjs-editor-types';
import { getEditInfoFromImage } from '../../lib/plugins/ImageEdit/editInfoUtils/editInfo';
import { IEditor, PluginEventType } from 'roosterjs-editor-types';

const IMG_SRC =
'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAKCAYAAAC0VX7mAAAALUlEQVQ4EWNgYGD4T2U8lAz8TyZACzKEl8k0Dz0OhpKBaGGB7hVi+QgvD0oDATe/bqDDw39VAAAAAElFTkSuQmCC';
Expand Down Expand Up @@ -367,6 +367,16 @@ xdescribe('applyChange', () => {
expect(img.height).toBe(21);
expect(img.src).toBe(newSrc);
});

it('trigger Content Change', async () => {
let editInfo = getEditInfoFromImage(img);
applyChange(editor, img, editInfo, IMG_SRC, false, undefined, true);
const triggerPluginEventSpy = spyOn(editor, 'triggerPluginEvent');
expect(triggerPluginEventSpy).toHaveBeenCalled();
expect(triggerPluginEventSpy).toHaveBeenCalledWith(PluginEventType.ContentChanged, {
source: ChangeSource.ImageResize,
});
});
});

function loadImage(src: string): Promise<HTMLImageElement> {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import * as applyChange from '../../lib/plugins/ImageEdit/editInfoUtils/applyChange';
import * as TestHelper from '../TestHelper';
import ImageEditInfo from '../../lib/plugins/ImageEdit/types/ImageEditInfo';
import { ImageEdit } from '../../lib/ImageEdit';
Expand All @@ -18,7 +19,9 @@ describe('ImageEdit | rotate and flip', () => {
const TEST_ID = 'imageEditTest';
let plugin: ImageEdit;
beforeEach(() => {
plugin = new ImageEdit();
plugin = new ImageEdit({
applyChangesOnMouseUp: true,
});
editor = TestHelper.initEditor(TEST_ID, [plugin]);
});

Expand Down Expand Up @@ -390,3 +393,49 @@ describe('ImageEdit | wrapper', () => {
expect(imageShadow?.style.width).toBe('300px');
});
});

describe('ImageEdit | applyChangesOnMouseUp', () => {
let editor: IEditor;
const TEST_ID = 'imageEditTest';
let plugin: ImageEdit;
beforeEach(() => {
plugin = new ImageEdit({
applyChangesOnMouseUp: true,
});
editor = TestHelper.initEditor(TEST_ID, [plugin]);
});

afterEach(() => {
let element = document.getElementById(TEST_ID);
if (element) {
element.parentElement.removeChild(element);
}
editor.dispose();
});

const mouseUp = (target: HTMLElement, keyNumber: number) => {
const event = new MouseEvent('mouseup', {
view: window,
bubbles: true,
cancelable: true,
shiftKey: false,
button: keyNumber,
});
target.dispatchEvent(event);
};

it('should call apply changed', () => {
const IMG_ID = 'IMAGE_ID_MOUSE';
const wrapperId = 'WRAPPER_ID';
const content = `<span id="${wrapperId}"></span><img id="${IMG_ID}" src='test'/>`;
editor.setContent(content);
const applyChangeSpy = spyOn(applyChange, 'default');
const image = document.getElementById(IMG_ID) as HTMLImageElement;
const wrapper = document.getElementById(wrapperId) as HTMLImageElement;
editor.focus();
editor.select(image);
plugin.insertImageWrapper(wrapper);
mouseUp(wrapper!, 2);
expect(applyChangeSpy).toHaveBeenCalled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -71,4 +71,9 @@ export default interface ImageEditOptions {
* @default ImageEditOperation.ResizeAndRotate
*/
onSelectState?: ImageEditOperation | CompatibleImageEditOperation;

/**
* Apply changes when mouse upp
*/
applyChangesOnMouseUp?: boolean;
}

0 comments on commit 07ff0b6

Please sign in to comment.