Skip to content

Commit

Permalink
Standalone Editor: Selection API step 3: Port ImageSelection plugin (#…
Browse files Browse the repository at this point in the history
…2235)

* Standalone Editor: CreateStandaloneEditorCore

* Standalone Editor: Port LifecyclePlugin

* fix build

* fix test

* improve

* fix test

* Standalone Editor: Support keyboard input (init step)

* Standalone Editor: Port EntityPlugin

* improve

* Add test

* improve

* port selection api

* improve

* improve

* fix build

* fix build

* fix build

* improve

* Improve

* improve

* improve

* fix test

* improve

* add test

* remove unused code

* Standalone Editor: port ImageSelection plugin

* add test

* improve
  • Loading branch information
JiuqingSong authored Dec 8, 2023
1 parent f136d03 commit 312e55a
Show file tree
Hide file tree
Showing 7 changed files with 518 additions and 124 deletions.
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import type { IEditor, PluginWithState } from 'roosterjs-editor-types';
import { isElementOfType, isNodeOfType, toArray } from 'roosterjs-content-model-dom';
import { isModifierKey } from '../publicApi/domUtils/eventUtils';
import { PluginEventType } from 'roosterjs-editor-types';
import type { IEditor, PluginEvent, PluginWithState } from 'roosterjs-editor-types';
import type {
DOMSelection,
IStandaloneEditor,
SelectionPluginState,
StandaloneEditorOptions,
} from 'roosterjs-content-model-types';

const MouseMiddleButton = 1;

class SelectionPlugin implements PluginWithState<SelectionPluginState> {
private editor: (IStandaloneEditor & IEditor) | null = null;
private state: SelectionPluginState;
Expand Down Expand Up @@ -77,6 +83,98 @@ class SelectionPlugin implements PluginWithState<SelectionPluginState> {
return this.state;
}

onPluginEvent(event: PluginEvent) {
if (!this.editor) {
return;
}

let image: HTMLImageElement | null;
let selection: DOMSelection | null;

switch (event.eventType) {
case PluginEventType.MouseUp:
if (
(image = this.getClickingImage(event.rawEvent)) &&
image.isContentEditable &&
event.rawEvent.button != MouseMiddleButton &&
event.isClicking
) {
this.selectImage(this.editor, image);
}
break;

case PluginEventType.MouseDown:
selection = this.editor.getDOMSelection();

if (selection?.type == 'image' && selection.image !== event.rawEvent.target) {
this.selectBeforeImage(this.editor, selection.image);
}
break;

case PluginEventType.KeyDown:
const rawEvent = event.rawEvent;
const key = rawEvent.key;
selection = this.editor.getDOMSelection();

if (
!isModifierKey(rawEvent) &&
!rawEvent.shiftKey &&
selection?.type == 'image' &&
selection.image.parentNode
) {
if (key === 'Escape') {
this.selectBeforeImage(this.editor, selection.image);
event.rawEvent.stopPropagation();
} else if (key !== 'Delete' && key !== 'Backspace') {
this.selectBeforeImage(this.editor, selection.image);
}
}
break;

case PluginEventType.ContextMenu:
selection = this.editor.getDOMSelection();

if (
(image = this.getClickingImage(event.rawEvent)) &&
(selection?.type != 'image' || selection.image != image)
) {
this.selectImage(this.editor, image);
}
}
}

private selectImage(editor: IStandaloneEditor, image: HTMLImageElement) {
editor.setDOMSelection({
type: 'image',
image: image,
});
}

private selectBeforeImage(editor: IStandaloneEditor, image: HTMLImageElement) {
const doc = editor.getDocument();
const parent = image.parentNode;
const index = parent && toArray(parent.childNodes).indexOf(image);

if (parent && index !== null && index >= 0) {
const range = doc.createRange();
range.setStart(parent, index);
range.collapse();

editor.setDOMSelection({
type: 'range',
range: range,
});
}
}

private getClickingImage(event: UIEvent): HTMLImageElement | null {
const target = event.target as Node;

return isNodeOfType(target, 'ELEMENT_NODE') && isElementOfType(target, 'img')
? target
: null;
}

private onFocus = () => {
if (!this.state.skipReselectOnFocus && this.state.selection) {
this.editor?.setDOMSelection(this.state.selection);
Expand Down
Loading

0 comments on commit 312e55a

Please sign in to comment.