@@ -2,20 +2,31 @@ const WordCollapser = (function() {
22
33 let div = { } ;
44 let selecting ;
5+ let unjoin ;
56 let leftWord ;
67
78 function listenForLeftWord ( ) {
89 selecting = true ;
10+ if ( leftWord ) { leftWord . unhover ( ) ; }
911 leftWord = null ;
1012 div . className = 'bracket-left' ;
1113 }
1214
1315 function listenForRightWord ( ) {
16+ if ( leftWord ) { leftWord . hover ( ) ; }
1417 div . className = 'bracket-right' ;
1518 }
1619
20+ function listenForUnjoin ( ) {
21+ cancel ( ) ;
22+ selecting = true ;
23+ unjoin = true ;
24+ }
25+
1726 function cancel ( ) {
27+ if ( leftWord ) { leftWord . unhover ( ) ; }
1828 selecting = false ;
29+ unjoin = false ;
1930 leftWord = null ;
2031 div . className = null ;
2132 }
@@ -30,16 +41,144 @@ const WordCollapser = (function() {
3041 }
3142 } ) ;
3243
44+ function joinWords ( word ) {
45+ let lIndex = wordObjs . indexOf ( leftWord ) ;
46+ let rIndex = wordObjs . indexOf ( word ) ;
47+ let text = leftWord . val ;
48+ for ( let i = lIndex + 1 ; i <= rIndex ; ++ i ) {
49+ text += ' ' + wordObjs [ i ] . val ;
50+ }
51+
52+ // condense text if too long
53+ if ( text . length > 25 ) {
54+ text = text . slice ( 0 , 12 ) + "…" + text . slice ( - 12 ) ;
55+ }
56+
57+ let phrase = new Word ( text , leftWord . idx ) ;
58+
59+ let row = leftWord . row ;
60+
61+ let numberToSplice = 1 + rIndex - lIndex ;
62+
63+ // remove word refs from wordObjs
64+ let removedWords = wordObjs . splice ( lIndex , numberToSplice , phrase ) ;
65+
66+ // remove word refs from rows
67+ numberToSplice -= row . words . splice ( row . words . indexOf ( leftWord ) , numberToSplice , phrase ) . length ;
68+ let i = row . idx + 1 ;
69+
70+ while ( numberToSplice > 0 && rows [ i ] ) {
71+ numberToSplice -= rows [ i ] . words . splice ( 0 , numberToSplice ) . length ;
72+ ++ i ;
73+ }
74+
75+ // reassign link-word references and hide svgs
76+ removedWords . forEach ( word => {
77+
78+ // replace backreferences of word in link with phrase
79+ function replaceLinkWordObject ( link ) {
80+ [ 'leftWord' , 'rightWord' , 'nearestConnectedMaxWord' , 'nearestConnectedMinWord' , 'rootMaxWord' , 'rootMinWord' ] . forEach ( prop => {
81+ if ( link [ prop ] === word ) {
82+ link [ prop ] = phrase ;
83+ if ( ! link [ '_' + prop ] ) {
84+ link [ '_' + prop ] = word ;
85+ }
86+ }
87+ let idx = link . words . indexOf ( word ) ;
88+ if ( idx > - 1 ) {
89+ link . words [ idx ] = phrase ;
90+ }
91+ } ) ;
92+
93+ if ( ! link . _words ) {
94+ link . _words = link . words . slice ( ) ;
95+ }
96+ link . parents . forEach ( replaceLinkWordObject ) ;
97+ }
98+
99+ // relink word links to phrase
100+ [ 'parentsL' , 'parentsC' , 'parentsR' ] . forEach ( prop => {
101+ phrase [ prop ] = phrase [ prop ] . concat ( word [ prop ] ) ;
102+ } ) ;
103+ [ 'slotsL' , 'slotsR' ] . forEach ( prop => {
104+ word [ prop ] . forEach ( slot => {
105+ if ( phrase [ prop ] . indexOf ( slot ) < 0 ) {
106+ phrase [ prop ] . push ( slot ) ;
107+ }
108+ } ) ;
109+ } )
110+
111+ // recurse through word's ancestor links
112+ word . parents . forEach ( replaceLinkWordObject ) ;
113+
114+ // make svg invisible
115+ word . svg . hide ( ) ;
116+
117+ } ) ;
118+
119+ phrase . removedWords = Array . prototype . concat . apply ( [ ] , removedWords . map ( word => word . removedWords || word ) ) ;
120+
121+ phrase . leftX = leftWord . leftX ;
122+ phrase . row = row ;
123+ phrase . draw ( ) ;
124+ redrawLinks ( true ) ;
125+ cancel ( ) ;
126+ }
127+
128+ function unjoinWord ( word ) {
129+ [ ] . splice . apply ( wordObjs , [ wordObjs . indexOf ( word ) , 1 ] . concat ( word . removedWords ) ) ;
130+ [ ] . splice . apply ( word . row . words , [ word . row . words . indexOf ( word ) , 1 ] . concat ( word . removedWords ) ) ;
131+
132+ word . removedWords . forEach ( word => {
133+ word . svg . show ( ) ;
134+ } ) ;
135+
136+ // revert assigned references to word in link
137+ function revertLinkWordObject ( link ) {
138+ [ 'leftWord' , 'rightWord' , 'nearestConnectedMaxWord' , 'nearestConnectedMinWord' , 'rootMaxWord' , 'rootMinWord' ] . forEach ( prop => {
139+ let _prop = '_' + prop ;
140+ if ( link [ _prop ] ) {
141+ link [ prop ] = link [ _prop ] ;
142+ delete link [ '_' ]
143+ }
144+ } ) ;
145+
146+ if ( link . _words ) {
147+ link . words = link . _words ;
148+ delete link . _words ;
149+ }
150+ link . parents . forEach ( revertLinkWordObject ) ;
151+ } ;
152+
153+ word . parents . forEach ( revertLinkWordObject ) ;
154+
155+ word . svg . hide ( ) ;
156+
157+ // todo: make it go on the correct row and leftX and make enough room
158+
159+ redrawLinks ( true ) ;
160+ }
161+
33162 class WordCollapser {
34163
35164 constructor ( ) {
36165 div = document . getElementById ( 'drawing' ) ;
166+ let buttons = document . querySelectorAll ( '#collapse button' ) ;
167+ buttons [ 0 ] . onclick = listenForLeftWord ;
168+ buttons [ 1 ] . onclick = listenForUnjoin ;
37169 }
38170
39171 setClick ( word ) {
40172 if ( selecting ) {
173+ // unjoin collapsed word
174+ if ( unjoin ) {
175+ if ( word . removedWords ) {
176+ unjoinWord ( word ) ;
177+ }
178+ cancel ( ) ;
179+ }
41180 // selecting left word
42- if ( leftWord === null ) {
181+ else if ( leftWord === null ) {
43182 leftWord = word ;
44183 listenForRightWord ( ) ;
45184 console . log ( 'left' , word ) ;
@@ -52,72 +191,7 @@ const WordCollapser = (function() {
52191 // select second word
53192 else {
54193 console . log ( 'right' , word ) ;
55-
56- let lIndex = wordObjs . indexOf ( leftWord ) ;
57- let rIndex = wordObjs . indexOf ( word ) ;
58- let text = leftWord . val ;
59- for ( let i = lIndex + 1 ; i <= rIndex ; ++ i ) {
60- text += ' ' + wordObjs [ i ] . val ;
61- }
62-
63- // condense text if too long
64- if ( text . length > 25 ) {
65- text = text . slice ( 0 , 12 ) + "…" + text . slice ( - 12 ) ;
66- }
67-
68- let phrase = new Word ( text , leftWord . idx ) ;
69-
70- let row = leftWord . row ;
71-
72- let numberToSplice = 1 + rIndex - lIndex ;
73-
74- // todo: correct number over multi rows
75- let removedWords = wordObjs . splice ( lIndex , numberToSplice , phrase ) ;
76- row . words . splice ( row . words . indexOf ( leftWord ) , numberToSplice , phrase ) ;
77-
78-
79- removedWords . forEach ( word => {
80-
81- // replace backreferences of word in link with phrase
82- function replaceLinkWordObject ( link ) {
83- [ 'leftWord' , 'rightWord' , 'nearestConnectedMaxWord' , 'nearestConnectedMinWord' , 'rootMaxWord' , 'rootMinWord' ] . forEach ( prop => {
84- if ( link [ prop ] === word ) {
85- link [ prop ] = phrase ;
86- }
87- let idx = link . words . indexOf ( word ) ;
88- if ( idx > - 1 ) {
89- link . words [ idx ] = phrase ;
90- }
91- } ) ;
92-
93- link . parents . forEach ( replaceLinkWordObject ) ;
94- }
95-
96- // relink word links to phrase
97- [ 'parentsL' , 'parentsC' , 'parentsR' ] . forEach ( prop => {
98- phrase [ prop ] = phrase [ prop ] . concat ( word [ prop ] ) ;
99- } ) ;
100- [ 'slotsL' , 'slotsR' ] . forEach ( prop => {
101- word [ prop ] . forEach ( slot => {
102- if ( phrase [ prop ] . indexOf ( slot ) < 0 ) {
103- phrase [ prop ] . push ( slot ) ;
104- }
105- } ) ;
106- } )
107-
108- // recurse through word's ancestor links
109- word . parents . forEach ( replaceLinkWordObject ) ;
110-
111- // make svg invisible
112- word . svg . hide ( ) ;
113-
114- } ) ;
115-
116- phrase . leftX = leftWord . leftX ;
117- phrase . row = row ;
118- phrase . draw ( ) ;
119- redrawLinks ( true ) ;
120- cancel ( ) ;
194+ joinWords ( word ) ;
121195 }
122196 }
123197 }
0 commit comments