@@ -4,45 +4,17 @@ import Suggest from './suggest';
44import Datepicker from './datepicker' ;
55import { cssPrefix } from '../config' ;
66// 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' ;
369
3710function insertText ( { target } , itxt ) {
3811 const { value, selectionEnd } = target ;
3912 const ntxt = `${ value . slice ( 0 , selectionEnd ) } ${ itxt } ${ value . slice ( selectionEnd ) } ` ;
4013 target . value = ntxt ;
41- target . setSelectionRange ( selectionEnd + 1 , selectionEnd + 1 ) ;
42-
4314 this . inputText = ntxt ;
44- this . textlineEl . html ( ntxt ) ;
45- resetTextareaSize . call ( this ) ;
15+ this . render ( ) ;
16+
17+ setCaretPosition ( target , selectionEnd + 1 ) ;
4618}
4719
4820function keydownEventHandler ( evt ) {
@@ -55,72 +27,36 @@ function keydownEventHandler(evt) {
5527 if ( keyCode === 13 && ! altKey ) evt . preventDefault ( ) ;
5628}
5729
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 ;
6036 // 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 ) ;
8343 } else {
84- evt . target . value = cell . text ;
44+ suggest . hide ( ) ;
8545 }
8646 } 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 ) ) ;
9450 } 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 ( ) ;
10152 }
102- textlineEl . html ( v ) ;
103- resetTextareaSize . call ( this ) ;
104- this . change ( 'input' , v ) ;
10553 }
106- }
54+ this . render ( ) ;
55+ this . change ( 'input' , text ) ;
10756
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 ( ) ;
12460}
12561
12662function suggestItemClick ( it ) {
@@ -143,7 +79,8 @@ function suggestItemClick(it) {
14379 position = this . inputText . length ;
14480 this . inputText += `)${ eit } ` ;
14581 }
146- setText . call ( this , this . inputText , position ) ;
82+ this . render ( ) ;
83+ setCaretPosition ( this . textEl . el , position ) ;
14784}
14885
14986function resetSuggestItems ( ) {
@@ -159,9 +96,10 @@ function dateFormat(d) {
15996}
16097
16198export default class Editor {
162- constructor ( formulas , viewFn , rowHeight ) {
99+ constructor ( formulas , viewFn , data ) {
100+ this . data = data ;
163101 this . viewFn = viewFn ;
164- this . rowHeight = rowHeight ;
102+ this . rowHeight = data . rows . height ;
165103 this . formulas = formulas ;
166104 this . suggest = new Suggest ( formulas , ( it ) => {
167105 suggestItemClick . call ( this , it ) ;
@@ -172,27 +110,34 @@ export default class Editor {
172110 this . setText ( dateFormat ( d ) ) ;
173111 this . clear ( ) ;
174112 } ) ;
113+ this . composing = false ;
175114 this . areaEl = h ( 'div' , `${ cssPrefix } -editor-area` )
176115 . children (
177- this . textEl = h ( 'textarea' , '' )
116+ this . textEl = h ( 'div' , 'textarea' )
117+ . attr ( 'contenteditable' , 'true' )
178118 . 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 ) ,
181123 this . textlineEl = h ( 'div' , 'textline' ) ,
182124 this . suggest . el ,
183125 this . datepicker . el ,
184126 )
185- . on ( 'mousemove.stop' , ( ) => { } )
186- . on ( 'mousedown.stop' , ( ) => { } ) ;
127+ . on ( 'mousemove.stop' , ( ) => { } )
128+ . on ( 'mousedown.stop' , ( ) => { } ) ;
187129 this . el = h ( 'div' , `${ cssPrefix } -editor` )
188- . child ( this . areaEl ) . hide ( ) ;
130+ . children ( this . areaEl ) . hide ( ) ;
131+ this . cellEl = h ( 'div' , `${ cssPrefix } -formula-cell` )
189132 this . suggest . bindInputEvents ( this . textEl ) ;
190133
191134 this . areaOffset = null ;
192135 this . freeze = { w : 0 , h : 0 } ;
193136 this . cell = null ;
194137 this . inputText = '' ;
195- this . change = ( ) => { } ;
138+ this . change = ( ) => { } ;
139+
140+ this . formula = new Formula ( this ) ;
196141 }
197142
198143 setFreezeLengths ( width , height ) {
@@ -212,13 +157,19 @@ export default class Editor {
212157 this . el . hide ( ) ;
213158 this . textEl . val ( '' ) ;
214159 this . textlineEl . html ( '' ) ;
160+ this . formula . clear ( ) ;
215161 resetSuggestItems . call ( this ) ;
216162 this . datepicker . hide ( ) ;
217163 }
218164
165+ resetData ( data ) {
166+ this . data = data ;
167+ this . rowHeight = data . rows . height ;
168+ }
169+
219170 setOffset ( offset , suggestPosition = 'top' ) {
220171 const {
221- textEl, areaEl, suggest, freeze, el,
172+ textEl, areaEl, suggest, freeze, el, formula
222173 } = this ;
223174 if ( offset ) {
224175 this . areaOffset = offset ;
@@ -240,11 +191,13 @@ export default class Editor {
240191 }
241192 el . offset ( elOffset ) ;
242193 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` ) ;
244196 const sOffset = { left : 0 } ;
245197 sOffset [ suggestPosition ] = height ;
246198 suggest . setOffset ( sOffset ) ;
247199 suggest . hide ( ) ;
200+ formula . renderCells ( ) ;
248201 }
249202 }
250203
@@ -275,7 +228,35 @@ export default class Editor {
275228 setText ( text ) {
276229 this . inputText = text ;
277230 // 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 ) ;
280261 }
281262}
0 commit comments