Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"comment": "refactor: when set editCellTrigger keydown input chinese first letter problem #4847\n\n",
"type": "none",
"packageName": "@visactor/vtable"
}
],
"packageName": "@visactor/vtable",
"email": "892739385@qq.com"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
{
"changes": [
{
"comment": "fix: editor support keydown chinese #4847\n\n",
"type": "none",
"packageName": "@visactor/vtable"
}
],
"packageName": "@visactor/vtable",
"email": "892739385@qq.com"
}
52 changes: 43 additions & 9 deletions packages/vtable-editors/src/input-editor.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { CellAddress, EditContext, IEditor, RectProps } from './types';
import type { CellAddress, EditContext, IEditor, PrepareEditContext, RectProps } from './types';
import type { ValidateEnum } from './types';

export interface InputEditorConfig {
Expand All @@ -14,10 +14,12 @@ export class InputEditor implements IEditor {
table?: any;
col?: number;
row?: number;

constructor(editorConfig?: InputEditorConfig) {
this.editorConfig = editorConfig;
}
getInputElement(): HTMLInputElement {
return this.element;
}

createElement() {
const input = document.createElement('input');
Expand All @@ -40,9 +42,15 @@ export class InputEditor implements IEditor {
input.style.outline = 'none';
});

input.addEventListener('blur', () => {
input.addEventListener('blur', e => {
input.style.borderColor = '#d9d9d9';
// input.style.boxShadow = 'none';
if (this.table && this.element.style.opacity === '0') {
const selectCell = this.table.stateManager.select.cellPos;
if (selectCell.col !== this.col || selectCell.row !== this.row) {
this.onEnd();
}
}
});
// #endregion
this.element = input;
Expand All @@ -69,7 +77,31 @@ export class InputEditor implements IEditor {
getValue() {
return this.element.value;
}

/**
* 如果表格编辑时机配置editCellTrigger为keydown,则需要调用prepareEdit来准备编辑环境,否则中文输入法第一个字符会被当做英文字符
* @param param0
*/
prepareEdit({ referencePosition, container, table, col, row }: PrepareEditContext<string>) {
this.container = container;
this.table = table;
this.col = col;
this.row = row;
const selectCell = this.table.stateManager.select.cellPos;
if (selectCell.col !== this.col || selectCell.row !== this.row) {
return;
}
if (!this.element) {
this.createElement();
}
this.element.style.opacity = '0';
//这个pointerEvents = 'none'很重要,如果没有的话会引起vtable.getElement()元素和这里的element元素的focus和blur的切换,
//也会引起mouseleave_table mouseleave_cell和mouseenter的切换
this.element.style.pointerEvents = 'none';
if (referencePosition?.rect) {
this.adjustPosition(referencePosition.rect);
}
this.element.focus();
}
onStart({ value, referencePosition, container, endEdit, table, col, row }: EditContext<string>) {
this.container = container;
this.successCallback = endEdit;
Expand All @@ -78,14 +110,16 @@ export class InputEditor implements IEditor {
this.row = row;
if (!this.element) {
this.createElement();

if (value !== undefined && value !== null) {
this.setValue(value);
}
if (referencePosition?.rect) {
this.adjustPosition(referencePosition.rect);
}
}
if (value !== undefined && value !== null) {
this.setValue(value);
}
//防止调用过prepareEdit 后,元素的显示和可操作性被影响
this.element.style.opacity = '1';
this.element.style.pointerEvents = 'auto';
this.element.focus();
// do nothing
}
Expand All @@ -112,8 +146,8 @@ export class InputEditor implements IEditor {
// do nothing
if (this.container?.contains(this.element)) {
this.container.removeChild(this.element);
this.element = undefined;
}
this.element = undefined;
}

isEditorElement(target: HTMLElement) {
Expand Down
14 changes: 14 additions & 0 deletions packages/vtable-editors/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ export interface IEditor<V = any, T = any> {
*/
onEnd: () => void;
getInputElement?: () => HTMLElement;
setElement?: (element: HTMLInputElement) => void;
/**
* Called when user click somewhere while editor is in edit mode.
*
Expand Down Expand Up @@ -46,6 +47,11 @@ export interface IEditor<V = any, T = any> {
* Expected to return the current value of the cell.
*/
getValue: () => V;
/**
* If the table editing trigger is configured as keydown, you need to call prepareEdit to prepare the editing environment, otherwise the first character of the Chinese input method will be treated as an English character.
* @param param0
*/
prepareEdit?: (context: PrepareEditContext<V, T>) => void;
/**
* Called when cell enter edit mode.
* @deprecated use `onStart` instead.
Expand All @@ -68,6 +74,7 @@ export interface IEditor<V = any, T = any> {
* @deprecated callback is provided as `endEdit` in `EditContext`, use `onStart` instead.
*/
bindSuccessCallback?: (callback: () => void) => void;
adjustPosition?: (rect: RectProps) => void;
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
Expand Down Expand Up @@ -96,6 +103,13 @@ export interface EditContext<V = any, T = any> {
row: number;
}

export interface PrepareEditContext<V = any, T = any> {
container: HTMLElement;
table: T;
col: number;
row: number;
referencePosition: ReferencePosition;
}
export interface RectProps {
left: number;
top: number;
Expand Down
1 change: 1 addition & 0 deletions packages/vtable/examples/editor/custom-date-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ export function createTable() {
container: document.getElementById(CONTAINER_ID),
records,
columns,
editCellTrigger: ['keydown', 'doubleclick'],
keyboardOptions: {
copySelected: true,
pasteValueToCell: true,
Expand Down
4 changes: 3 additions & 1 deletion packages/vtable/examples/editor/date-editor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -179,8 +179,10 @@ export function createTable() {
heightMode: 'autoHeight',
autoWrapText: true,
editCellTrigger: ['keydown', 'doubleclick'],

keyboardOptions: {
moveFocusCellOnEnter: true
moveFocusCellOnEnter: true,
moveEditCellOnArrowKeys: true
},
editor(args) {
return new InputEditor({});
Expand Down
34 changes: 31 additions & 3 deletions packages/vtable/examples/editor/input-editor.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as VTable from '../../src';
import { InputEditor } from '@visactor/vtable-editors';
import { bindDebugTool } from '../../src/scenegraph/debug-tool';
import { TABLE_EVENT_TYPE } from '../../src';
const ListTable = VTable.ListTable;
const CONTAINER_ID = 'vTable';
const input_editor = new InputEditor({});
Expand Down Expand Up @@ -136,6 +137,7 @@ export function createTable() {
const option: VTable.ListTableConstructorOptions = {
emptyTip: true,
container: document.getElementById(CONTAINER_ID),
editCellTrigger: 'keydown',
columns: [
{
field: 'progress',
Expand Down Expand Up @@ -170,6 +172,12 @@ export function createTable() {
}
}
],
hover: {
highlightMode: 'cross'
},
keyboardOptions: {
selectAllOnCtrlA: true
},
showFrozenIcon: true, //显示VTable内置冻结列图标
widthMode: 'standard',
autoFillWidth: true,
Expand All @@ -185,10 +193,30 @@ export function createTable() {
field: 'progress',
order: 'desc'
});

instance.on('change_cell_value', arg => {
console.log(arg);
// instance.on(TABLE_EVENT_TYPE.CLICK_CELL, e => {
// console.log('click-cell', e);
// });
// instance.on(TABLE_EVENT_TYPE.SELECTED_CHANGED, e => {
// console.log('selected_changed', e);
// });
instance.on(TABLE_EVENT_TYPE.DRAG_SELECT_END, e => {
console.log('drag_select_end', e);
});
// instance.on('change_cell_value', arg => {
// console.log('.....change_cell_value');
// });
// instance.on('mouseleave_cell', arg => {
// console.log('.....mouseleave_cell');
// });
// instance.on('mouseenter_cell', arg => {
// console.log('.....mouseenter_cell');
// });
// instance.on('mouseleave_table', arg => {
// console.log('.....mouseleave_table');
// });
// instance.on('mouseenter_table', arg => {
// console.log('.....mouseenter_table');
// });

// bindDebugTool(instance.scenegraph.stage as any, {
// customGrapicKeys: ['role', '_updateTag']
Expand Down
7 changes: 7 additions & 0 deletions packages/vtable/examples/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@
<div class="container">
<div class="sidebar" id="sidebar"></div>
<div class="content">
<div id="input-test">
<input type="text" />
</div>
<br />
<div id="textarea-test">
<textarea></textarea>
</div>
<div id="chartContainer">
<div id="vTable" style="position: relative; height: 100%; width: 100%; overflow: hidden"></div>
</div>
Expand Down
18 changes: 12 additions & 6 deletions packages/vtable/src/ListTable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1532,25 +1532,31 @@ export class ListTable extends BaseTable implements ListTableAPI {
}
/** 获取单元格对应的编辑器 */
getEditor(col: number, row: number) {
const lastSelectedCellEditor = this.editorManager.cacheLastSelectedCellEditor[`${col}-${row}`];
if (lastSelectedCellEditor) {
return lastSelectedCellEditor;
}
const define = this.getBodyColumnDefine(col, row);
let editorDefine = this.isHeader(col, row)
let editor = this.isHeader(col, row)
? (define as ColumnDefine)?.headerEditor ?? this.options.headerEditor
: (define as ColumnDefine)?.editor ?? this.options.editor;

if (typeof editorDefine === 'function') {
if (typeof editor === 'function') {
const arg = {
col,
row,
dataValue: this.getCellOriginValue(col, row),
value: this.getCellValue(col, row) || '',
table: this
};
editorDefine = (editorDefine as Function)(arg);
editor = (editor as Function)(arg);
}
if (typeof editorDefine === 'string') {
return editors.get(editorDefine);
if (typeof editor === 'string') {
editor = editors.get(editor);
}
return editorDefine as IEditor;
this.editorManager.cacheLastSelectedCellEditor = {};
this.editorManager.cacheLastSelectedCellEditor[`${col}-${row}`] = editor as IEditor;
return editor as IEditor;
}
/** 检查单元格是否定义过编辑器 不管编辑器是否有效 只要有定义就返回true */
isHasEditorDefine(col: number, row: number) {
Expand Down
24 changes: 15 additions & 9 deletions packages/vtable/src/PivotTable.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1755,31 +1755,37 @@ export class PivotTable extends BaseTable implements PivotTableAPI {
}
/** 获取单元格对应的编辑器 */
getEditor(col: number, row: number) {
let editorDefine;
const lastSelectedCellEditor = this.editorManager.cacheLastSelectedCellEditor[`${col}-${row}`];
if (lastSelectedCellEditor) {
return lastSelectedCellEditor;
}
let editor;
if (this.isCornerHeader(col, row)) {
const define = this.getHeaderDefine(col, row);
editorDefine = (define as ColumnDefine)?.headerEditor ?? this.options.headerEditor;
editor = (define as ColumnDefine)?.headerEditor ?? this.options.headerEditor;
} else if (this.isHeader(col, row)) {
const define = this.getHeaderDefine(col, row);
editorDefine = (define as ColumnDefine)?.headerEditor ?? this.options.headerEditor;
editor = (define as ColumnDefine)?.headerEditor ?? this.options.headerEditor;
} else {
const define = this.getBodyColumnDefine(col, row);
editorDefine = (define as ColumnDefine)?.editor ?? this.options.editor;
editor = (define as ColumnDefine)?.editor ?? this.options.editor;
}
if (typeof editorDefine === 'function') {
if (typeof editor === 'function') {
const arg = {
col,
row,
dataValue: this.getCellOriginValue(col, row),
value: this.getCellValue(col, row) || '',
table: this
};
editorDefine = (editorDefine as Function)(arg);
editor = (editor as Function)(arg);
}
if (typeof editorDefine === 'string') {
return editors.get(editorDefine);
if (typeof editor === 'string') {
editor = editors.get(editor);
}
return editorDefine as IEditor;
this.editorManager.cacheLastSelectedCellEditor = {};
this.editorManager.cacheLastSelectedCellEditor[`${col}-${row}`] = editor as IEditor;
return editor as IEditor;
}
/** 检查单元格是否定义过编辑器 不管编辑器是否有效 只要有定义就返回true */
isHasEditorDefine(col: number, row: number) {
Expand Down
Loading
Loading