Skip to content

Commit

Permalink
feat: support focus listener
Browse files Browse the repository at this point in the history
  • Loading branch information
neuqzxy committed Dec 17, 2024
1 parent 22c9b10 commit 3c38d06
Show file tree
Hide file tree
Showing 3 changed files with 317 additions and 5 deletions.
30 changes: 30 additions & 0 deletions packages/vrender-core/src/plugins/builtin-plugin/edit-module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,9 @@ export class EditModule {
onInputCbList: Array<(text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void>;
// change的回调(composing确认才会触发)
onChangeCbList: Array<(text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void>;
onFocusInList: Array<() => void>;
onFocusOutList: Array<() => void>;
focusOutTimer: number;

constructor(container?: HTMLElement) {
this.container = container ?? document.body;
Expand All @@ -101,6 +104,8 @@ export class EditModule {
this.isComposing = false;
this.onInputCbList = [];
this.onChangeCbList = [];
this.onFocusInList = [];
this.onFocusOutList = [];
}

onInput(cb: (text: string, isComposing: boolean, cursorIdx: number, rt: IRichText) => void) {
Expand All @@ -111,6 +116,14 @@ export class EditModule {
this.onChangeCbList.push(cb);
}

onFocusIn(cb: () => void) {
this.onFocusInList.push(cb);
}

onFocusOut(cb: () => void) {
this.onFocusOutList.push(cb);
}

applyStyle(textAreaDom: HTMLTextAreaElement) {
textAreaDom.setAttribute(
'style',
Expand All @@ -120,9 +133,24 @@ export class EditModule {
textAreaDom.addEventListener('input', this.handleInput);
textAreaDom.addEventListener('compositionstart', this.handleCompositionStart);
textAreaDom.addEventListener('compositionend', this.handleCompositionEnd);
// 监听焦点
textAreaDom.addEventListener('focusin', this.handleFocusIn);
textAreaDom.addEventListener('focusout', this.handleFocusOut);
application.global.addEventListener('keydown', this.handleKeyDown);
}

handleFocusIn = () => {
this.focusOutTimer && clearTimeout(this.focusOutTimer);
this.focusOutTimer = 0;
this.onFocusInList && this.onFocusInList.forEach(cb => cb());
};
handleFocusOut = () => {
// 延时触发,避免误关闭
this.focusOutTimer = setTimeout(() => {
this.onFocusOutList && this.onFocusOutList.forEach(cb => cb());
}, 100);
};

handleKeyDown = (e: KeyboardEvent) => {
if (e.key === 'Delete' || e.key === 'Backspace') {
this.handleInput({ data: null, type: 'Backspace' });
Expand Down Expand Up @@ -280,6 +308,8 @@ export class EditModule {
this.textAreaDom.removeEventListener('input', this.handleInput);
this.textAreaDom.removeEventListener('compositionstart', this.handleCompositionStart);
this.textAreaDom.removeEventListener('compositionend', this.handleCompositionEnd);
this.textAreaDom.addEventListener('focusin', this.handleFocusOut);
this.textAreaDom.addEventListener('focusout', this.handleFocusOut);
application.global.removeEventListener('keydown', this.handleKeyDown);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@ export class RichTextEditPlugin implements IPlugin {

this.editModule.onInput(this.handleInput);
this.editModule.onChange(this.handleChange);
this.editModule.onFocusOut(this.handleFocusOut);
}

copyToClipboard(e: KeyboardEvent): boolean {
Expand Down Expand Up @@ -334,6 +335,8 @@ export class RichTextEditPlugin implements IPlugin {

// const pos = this.computedCursorPosByCursorIdx(this.curCursorIdx, this.currRt);
const { lineInfo, columnInfo } = this.getColumnByIndex(cache, Math.round(this.curCursorIdx));
const { lines } = cache;
const totalCursorCount = lines.reduce((total, line) => total + line.paragraphs.length, 0) - 1;
if (x) {
// 快接近首尾需要特殊处理
if (
Expand All @@ -355,6 +358,11 @@ export class RichTextEditPlugin implements IPlugin {
} else {
this.curCursorIdx += x;
}
if (this.curCursorIdx < -0.1) {
this.curCursorIdx = -0.1;
} else if (this.curCursorIdx > totalCursorCount + 0.1) {
this.curCursorIdx = totalCursorCount + 0.1;
}

const pos = this.computedCursorPosByCursorIdx(this.curCursorIdx, this.currRt);
this.setCursorAndTextArea(pos.x, pos.y1, pos.y2, this.currRt);
Expand All @@ -381,9 +389,15 @@ export class RichTextEditPlugin implements IPlugin {
if (!columnInfo) {
return;
}
const cursorIdx = this.getColumnIndex(cache, columnInfo) + delta;
let cursorIdx = this.getColumnIndex(cache, columnInfo) + delta;
const data = this.computedCursorPosByCursorIdx(cursorIdx, this.currRt);

if (cursorIdx < -0.1) {
cursorIdx = -0.1;
} else if (cursorIdx > totalCursorCount + 0.1) {
cursorIdx = totalCursorCount + 0.1;
}

this.curCursorIdx = cursorIdx;
this.selectionStartCursorIdx = cursorIdx;
this.setCursorAndTextArea(data.x, data.y1, data.y2, this.currRt);
Expand Down Expand Up @@ -432,6 +446,18 @@ export class RichTextEditPlugin implements IPlugin {
this.updateCbs.forEach(cb => cb('change', this));
};

handleFocusIn = () => {
// this.updateCbs.forEach(cb => cb(this.editing ? 'onfocus' : 'defocus', this));
};

handleFocusOut = () => {
this.editing = false;
this.deFocus();
this.pointerDown = false;
this.triggerRender();
this.updateCbs.forEach(cb => cb('defocus', this));
};

deactivate(context: IPluginService): void {
// context.stage.off('pointerdown', this.handleClick);
context.stage.off('pointermove', this.handleMove);
Expand Down Expand Up @@ -470,7 +496,7 @@ export class RichTextEditPlugin implements IPlugin {
if (this.editing) {
this.onFocus(e);
} else {
this.deFocus(e);
this.deFocus();
}
this.triggerRender();
this.pointerDown = true;
Expand All @@ -488,7 +514,7 @@ export class RichTextEditPlugin implements IPlugin {
};

onFocus(e: PointerEvent) {
this.deFocus(e);
this.deFocus();
this.currRt = e.target as IRichText;

// 创建shadowGraphic
Expand Down Expand Up @@ -528,7 +554,7 @@ export class RichTextEditPlugin implements IPlugin {
}
}

protected deFocus(e: PointerEvent) {
protected deFocus() {
const target = this.currRt as IRichText;
if (!target) {
return;
Expand Down
Loading

0 comments on commit 3c38d06

Please sign in to comment.