-
Notifications
You must be signed in to change notification settings - Fork 477
Expand file tree
/
Copy pathinput-editor.ts
More file actions
160 lines (144 loc) · 4.82 KB
/
input-editor.ts
File metadata and controls
160 lines (144 loc) · 4.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
import type { CellAddress, EditContext, IEditor, PrepareEditContext, RectProps } from './types';
import type { ValidateEnum } from './types';
export interface InputEditorConfig {
readonly?: boolean;
}
export class InputEditor implements IEditor {
editorType: string = 'Input';
editorConfig: InputEditorConfig;
container: HTMLElement;
successCallback?: () => void;
element?: HTMLInputElement;
table?: any;
col?: number;
row?: number;
constructor(editorConfig?: InputEditorConfig) {
this.editorConfig = editorConfig;
}
getInputElement(): HTMLInputElement {
return this.element;
}
createElement() {
const input = document.createElement('input');
input.setAttribute('type', 'text');
if (this.editorConfig?.readonly) {
input.setAttribute('readonly', `${this.editorConfig.readonly}`);
}
input.style.position = 'absolute';
input.style.padding = '4px';
input.style.width = '100%';
input.style.boxSizing = 'border-box';
input.style.backgroundColor = '#FFFFFF';
input.style.borderRadius = '0px';
input.style.border = '2px solid #d9d9d9';
// #region 为了保证input在focus时,没有圆角
input.addEventListener('focus', () => {
input.style.borderColor = '#4A90E2';
input.style.outline = 'none';
});
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;
this.container.appendChild(input);
// 监听键盘事件
input.addEventListener('keydown', (e: KeyboardEvent) => {
if (e.key === 'a' && (e.ctrlKey || e.metaKey)) {
// 阻止冒泡 防止处理成表格全选事件
e.stopPropagation();
}
});
// hack for preventing drag touch cause page jump
input.addEventListener('wheel', e => {
e.preventDefault();
});
}
setValue(value: string) {
this.element.value = typeof value !== 'undefined' ? value : '';
}
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;
this.table = table;
this.col = col;
this.row = row;
if (!this.element) {
this.createElement();
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
}
adjustPosition(rect: RectProps) {
//使border均分input位置rect的上下左右
const borderWidth = 2;
const top = rect.top - borderWidth / 2;
const left = rect.left - borderWidth / 2;
const width = rect.width + borderWidth;
const height = rect.height + borderWidth;
this.element.style.top = top + 'px';
this.element.style.left = left + 'px';
this.element.style.width = width + 'px';
this.element.style.height = height + 'px';
}
endEditing() {
// do nothing
}
onEnd() {
// do nothing
if (this.container?.contains(this.element)) {
this.container.removeChild(this.element);
this.element = undefined;
}
}
isEditorElement(target: HTMLElement) {
return target === this.element;
}
validateValue(newValue?: any, oldValue?: any, position?: CellAddress, table?: any): boolean | ValidateEnum {
return true;
}
}