Skip to content

Commit 85f2443

Browse files
committed
unjoin words
1 parent efb518f commit 85f2443

File tree

3 files changed

+145
-71
lines changed

3 files changed

+145
-71
lines changed

css/style.css

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ svg text {
2929
margin-bottom: 210px;
3030
}
3131
#drawing.bracket-left, #drawing.bracket-left rect {
32-
cursor:e-resize !important;
32+
cursor: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAZCAYAAADnstS2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo4NDQxNzM1NTQ2MUMxMUU3QTRFNDkxNDI3MkNCQjJGRCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo4NDQxNzM1NjQ2MUMxMUU3QTRFNDkxNDI3MkNCQjJGRCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjg0NDE3MzUzNDYxQzExRTdBNEU0OTE0MjcyQ0JCMkZEIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjg0NDE3MzU0NDYxQzExRTdBNEU0OTE0MjcyQ0JCMkZEIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+3b/Z1wAAAR5JREFUeNrMlE2KhDAQhZNoEH9AT6E7TzJzDfEW3sFTuHA5YJ+h98qgbgbBvStxQGtSYSLdTJrWTTMFCSZ+9awqeFIAIEfDxG1ZFmjblqzrSiilchmGQaZpIrZtkziOP8T5naBy0zTg+z6YpgniJXDO8XMQhiGUZTmioKwAt7quwXEcCQhVmZSmKYzj+IVglmVsh1HZ8zwJYkKe53sjSZLwO2WEXdeVIK6qqhTMVRJyTB2wKRXzPKvH7XYa7DZzv2RMOzqt8qPQKj+Fj8QLyjilfKrmfwhv23YcRnf8hvEQVuPr+15dfd8xOqegrdApwzBctU4JguCPB6MogqIoPpUoxQ3d3XXd3hiWIxKluy3LWoW7L8Ldb/TMf+NHgAEAjFyqDEH528wAAAAASUVORK5CYII='), e-resize !important;
3333
}
3434
#drawing.bracket-right, #drawing.bracket-right rect {
35-
cursor:w-resize !important;
35+
cursor: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAsAAAAZCAYAAADnstS2AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyRpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoTWFjaW50b3NoKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo4NDQxNzM1MTQ2MUMxMUU3QTRFNDkxNDI3MkNCQjJGRCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo4NDQxNzM1MjQ2MUMxMUU3QTRFNDkxNDI3MkNCQjJGRCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjg0NDE3MzRGNDYxQzExRTdBNEU0OTE0MjcyQ0JCMkZEIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjg0NDE3MzUwNDYxQzExRTdBNEU0OTE0MjcyQ0JCMkZEIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+7MeYRQAAARlJREFUeNrEVEuKhDAQzUcRP6CXUK8yizmHeAvv4ClcuJsB7zBLQZmFm0HwCmKjpvMCpu3pYWxXXZCiEl69VIp6oUII8qwZcMuyfNR1/T6OI/F9H3sCEizOOYmiiFiWRcnGXJblIA+xEaZpCtu2hWEYQiaLtm2FwsFlWcaQMAzDT5qmCkQpVYmO44imaW5gWJIk5lZbnucKiATP8+6Zd6YSqqpSYCzXdTWY/XrwCoeHbibZdcz+ahFjt+P9zeyot4fMezvFfFfe68o4xXyq5heC13V9Cszh5OAfghFfEHRd99A23fRNKX3ff0EpkNW/SimK4juO4wcNBkGgh5/CSTV/SnW/TdPEoe55njUJZjsMQ6VueubfuAowAPZKsAzs/sUoAAAAAElFTkSuQmCC'), w-resize !important;
3636
}
3737

3838
#graph {

index.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
</select>
1818

1919
<div id="collapse" style="display:inline; float:right;">
20-
<button>[</button>
21-
<button>]</button>
20+
<button>join words</button>
21+
<button>unjoin</button>
2222
</div>
2323
</div>
2424

js/wordcollapser.js

Lines changed: 141 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)