@@ -4,45 +4,17 @@ import Suggest from './suggest';
4
4
import Datepicker from './datepicker' ;
5
5
import { cssPrefix } from '../config' ;
6
6
// import { mouseMoveUp } from '../event';
7
-
8
- function resetTextareaSize ( ) {
9
- const { inputText } = this ;
10
- if ( ! / ^ \s * $ / . test ( inputText ) ) {
11
- const {
12
- textlineEl, textEl, areaOffset,
13
- } = this ;
14
- const txts = inputText . split ( '\n' ) ;
15
- const maxTxtSize = Math . max ( ...txts . map ( it => it . length ) ) ;
16
- const tlOffset = textlineEl . offset ( ) ;
17
- const fontWidth = tlOffset . width / inputText . length ;
18
- const tlineWidth = ( maxTxtSize + 1 ) * fontWidth + 5 ;
19
- const maxWidth = this . viewFn ( ) . width - areaOffset . left - fontWidth ;
20
- let h1 = txts . length ;
21
- if ( tlineWidth > areaOffset . width ) {
22
- let twidth = tlineWidth ;
23
- if ( tlineWidth > maxWidth ) {
24
- twidth = maxWidth ;
25
- h1 += parseInt ( tlineWidth / maxWidth , 10 ) ;
26
- h1 += ( tlineWidth % maxWidth ) > 0 ? 1 : 0 ;
27
- }
28
- textEl . css ( 'width' , `${ twidth } px` ) ;
29
- }
30
- h1 *= this . rowHeight ;
31
- if ( h1 > areaOffset . height ) {
32
- textEl . css ( 'height' , `${ h1 } px` ) ;
33
- }
34
- }
35
- }
7
+ import Formula from './formula' ;
8
+ import { setCaretPosition , saveCaretPosition } from '../core/caret' ;
36
9
37
10
function insertText ( { target } , itxt ) {
38
11
const { value, selectionEnd } = target ;
39
12
const ntxt = `${ value . slice ( 0 , selectionEnd ) } ${ itxt } ${ value . slice ( selectionEnd ) } ` ;
40
13
target . value = ntxt ;
41
- target . setSelectionRange ( selectionEnd + 1 , selectionEnd + 1 ) ;
42
-
43
14
this . inputText = ntxt ;
44
- this . textlineEl . html ( ntxt ) ;
45
- resetTextareaSize . call ( this ) ;
15
+ this . render ( ) ;
16
+
17
+ setCaretPosition ( target , selectionEnd + 1 ) ;
46
18
}
47
19
48
20
function keydownEventHandler ( evt ) {
@@ -55,72 +27,36 @@ function keydownEventHandler(evt) {
55
27
if ( keyCode === 13 && ! altKey ) evt . preventDefault ( ) ;
56
28
}
57
29
58
- function inputEventHandler ( evt ) {
59
- const v = evt . target . value ;
30
+ function inputEventHandler ( ) {
31
+ // save caret position
32
+ const restore = saveCaretPosition ( this . textEl . el ) ;
33
+
34
+ const text = this . textEl . el . textContent ;
35
+ this . inputText = text ;
60
36
// console.log(evt, 'v:', v);
61
- const { suggest, textlineEl, validator } = this ;
62
- const { cell } = this ;
63
- if ( cell !== null ) {
64
- if ( ( 'editable' in cell && cell . editable === true ) || ( cell . editable === undefined ) ) {
65
- this . inputText = v ;
66
- if ( validator ) {
67
- if ( validator . type === 'list' ) {
68
- suggest . search ( v ) ;
69
- } else {
70
- suggest . hide ( ) ;
71
- }
72
- } else {
73
- const start = v . lastIndexOf ( '=' ) ;
74
- if ( start !== - 1 ) {
75
- suggest . search ( v . substring ( start + 1 ) ) ;
76
- } else {
77
- suggest . hide ( ) ;
78
- }
79
- }
80
- textlineEl . html ( v ) ;
81
- resetTextareaSize . call ( this ) ;
82
- this . change ( 'input' , v ) ;
37
+
38
+ const { suggest, validator } = this ;
39
+
40
+ if ( validator ) {
41
+ if ( validator . type === 'list' ) {
42
+ suggest . search ( text ) ;
83
43
} else {
84
- evt . target . value = cell . text ;
44
+ suggest . hide ( ) ;
85
45
}
86
46
} else {
87
- this . inputText = v ;
88
- if ( validator ) {
89
- if ( validator . type === 'list' ) {
90
- suggest . search ( v ) ;
91
- } else {
92
- suggest . hide ( ) ;
93
- }
47
+ const start = text . lastIndexOf ( '=' ) ;
48
+ if ( start !== - 1 ) {
49
+ suggest . search ( text . substring ( start + 1 ) ) ;
94
50
} else {
95
- const start = v . lastIndexOf ( '=' ) ;
96
- if ( start !== - 1 ) {
97
- suggest . search ( v . substring ( start + 1 ) ) ;
98
- } else {
99
- suggest . hide ( ) ;
100
- }
51
+ suggest . hide ( ) ;
101
52
}
102
- textlineEl . html ( v ) ;
103
- resetTextareaSize . call ( this ) ;
104
- this . change ( 'input' , v ) ;
105
53
}
106
- }
54
+ this . render ( ) ;
55
+ this . change ( 'input' , text ) ;
107
56
108
- function setTextareaRange ( position ) {
109
- const { el } = this . textEl ;
110
- setTimeout ( ( ) => {
111
- el . focus ( ) ;
112
- el . setSelectionRange ( position , position ) ;
113
- } , 0 ) ;
114
- }
115
-
116
- function setText ( text , position ) {
117
- const { textEl, textlineEl } = this ;
118
- // firefox bug
119
- textEl . el . blur ( ) ;
120
-
121
- textEl . val ( text ) ;
122
- textlineEl . html ( text ) ;
123
- setTextareaRange . call ( this , position ) ;
57
+ // restore caret postion
58
+ // to avoid caret postion missing when this.el.innerHTML changed
59
+ restore ( ) ;
124
60
}
125
61
126
62
function suggestItemClick ( it ) {
@@ -143,7 +79,8 @@ function suggestItemClick(it) {
143
79
position = this . inputText . length ;
144
80
this . inputText += `)${ eit } ` ;
145
81
}
146
- setText . call ( this , this . inputText , position ) ;
82
+ this . render ( ) ;
83
+ setCaretPosition ( this . textEl . el , position ) ;
147
84
}
148
85
149
86
function resetSuggestItems ( ) {
@@ -159,9 +96,10 @@ function dateFormat(d) {
159
96
}
160
97
161
98
export default class Editor {
162
- constructor ( formulas , viewFn , rowHeight ) {
99
+ constructor ( formulas , viewFn , data ) {
100
+ this . data = data ;
163
101
this . viewFn = viewFn ;
164
- this . rowHeight = rowHeight ;
102
+ this . rowHeight = data . rows . height ;
165
103
this . formulas = formulas ;
166
104
this . suggest = new Suggest ( formulas , ( it ) => {
167
105
suggestItemClick . call ( this , it ) ;
@@ -172,27 +110,34 @@ export default class Editor {
172
110
this . setText ( dateFormat ( d ) ) ;
173
111
this . clear ( ) ;
174
112
} ) ;
113
+ this . composing = false ;
175
114
this . areaEl = h ( 'div' , `${ cssPrefix } -editor-area` )
176
115
. children (
177
- this . textEl = h ( 'textarea' , '' )
116
+ this . textEl = h ( 'div' , 'textarea' )
117
+ . attr ( 'contenteditable' , 'true' )
178
118
. on ( 'input' , evt => inputEventHandler . call ( this , evt ) )
179
- . on ( 'paste.stop' , ( ) => { } )
180
- . on ( 'keydown' , evt => keydownEventHandler . call ( this , evt ) ) ,
119
+ . on ( 'paste.stop' , ( ) => { } )
120
+ . on ( 'keydown' , evt => keydownEventHandler . call ( this , evt ) )
121
+ . on ( 'compositionstart.stop' , ( ) => this . composing = true )
122
+ . on ( 'compositionend.stop' , ( ) => this . composing = false ) ,
181
123
this . textlineEl = h ( 'div' , 'textline' ) ,
182
124
this . suggest . el ,
183
125
this . datepicker . el ,
184
126
)
185
- . on ( 'mousemove.stop' , ( ) => { } )
186
- . on ( 'mousedown.stop' , ( ) => { } ) ;
127
+ . on ( 'mousemove.stop' , ( ) => { } )
128
+ . on ( 'mousedown.stop' , ( ) => { } ) ;
187
129
this . el = h ( 'div' , `${ cssPrefix } -editor` )
188
- . child ( this . areaEl ) . hide ( ) ;
130
+ . children ( this . areaEl ) . hide ( ) ;
131
+ this . cellEl = h ( 'div' , `${ cssPrefix } -formula-cell` )
189
132
this . suggest . bindInputEvents ( this . textEl ) ;
190
133
191
134
this . areaOffset = null ;
192
135
this . freeze = { w : 0 , h : 0 } ;
193
136
this . cell = null ;
194
137
this . inputText = '' ;
195
- this . change = ( ) => { } ;
138
+ this . change = ( ) => { } ;
139
+
140
+ this . formula = new Formula ( this ) ;
196
141
}
197
142
198
143
setFreezeLengths ( width , height ) {
@@ -212,13 +157,19 @@ export default class Editor {
212
157
this . el . hide ( ) ;
213
158
this . textEl . val ( '' ) ;
214
159
this . textlineEl . html ( '' ) ;
160
+ this . formula . clear ( ) ;
215
161
resetSuggestItems . call ( this ) ;
216
162
this . datepicker . hide ( ) ;
217
163
}
218
164
165
+ resetData ( data ) {
166
+ this . data = data ;
167
+ this . rowHeight = data . rows . height ;
168
+ }
169
+
219
170
setOffset ( offset , suggestPosition = 'top' ) {
220
171
const {
221
- textEl, areaEl, suggest, freeze, el,
172
+ textEl, areaEl, suggest, freeze, el, formula
222
173
} = this ;
223
174
if ( offset ) {
224
175
this . areaOffset = offset ;
@@ -240,11 +191,13 @@ export default class Editor {
240
191
}
241
192
el . offset ( elOffset ) ;
242
193
areaEl . offset ( { left : left - elOffset . left - 0.8 , top : top - elOffset . top - 0.8 } ) ;
243
- textEl . offset ( { width : width - 9 + 0.8 , height : height - 3 + 0.8 } ) ;
194
+ textEl . css ( 'min-width' , `${ width - 9 + 0.8 } px` ) ;
195
+ textEl . css ( 'min-height' , `${ height - 3 + 0.8 } px` ) ;
244
196
const sOffset = { left : 0 } ;
245
197
sOffset [ suggestPosition ] = height ;
246
198
suggest . setOffset ( sOffset ) ;
247
199
suggest . hide ( ) ;
200
+ formula . renderCells ( ) ;
248
201
}
249
202
}
250
203
@@ -275,7 +228,35 @@ export default class Editor {
275
228
setText ( text ) {
276
229
this . inputText = text ;
277
230
// console.log('text>>:', text);
278
- setText . call ( this , text , text . length ) ;
279
- resetTextareaSize . call ( this ) ;
231
+
232
+ // firefox bug
233
+ this . textEl . el . blur ( ) ;
234
+
235
+ this . render ( ) ;
236
+ setTimeout ( ( ) => {
237
+ setCaretPosition ( this . textEl . el , text . length ) ;
238
+ } )
239
+ }
240
+
241
+ render ( ) {
242
+ if ( this . composing ) return ;
243
+
244
+ const text = this . inputText ;
245
+
246
+ if ( text [ 0 ] != '=' ) {
247
+ this . textEl . html ( text ) ;
248
+ } else {
249
+ this . formula . render ( ) ;
250
+ }
251
+
252
+ this . textlineEl . html ( text ) ;
253
+ }
254
+
255
+ formulaCellSelecting ( ) {
256
+ return Boolean ( this . formula . cell ) ;
257
+ }
258
+
259
+ formulaSelectCell ( ri , ci ) {
260
+ this . formula . selectCell ( ri , ci ) ;
280
261
}
281
262
}
0 commit comments