blob: ef05607ffedfd46b34b0f6a18b5783c12964e3f0 [file] [log] [blame]
Nils Diewald0e6992a2015-04-14 20:13:52 +00001 /**
2 * Information about a match.
3 */
Nils Diewald7c8ced22015-04-15 19:21:00 +00004define([
5 'match/infolayer',
6 'match/table',
7 'match/tree',
8 'match/treemenu',
9 'util'
10], function (infoLayerClass,
11 matchTableClass,
12 matchTreeClass,
13 matchTreeMenuClass) {
Nils Diewald0e6992a2015-04-14 20:13:52 +000014
Nils Diewald7148c6f2015-05-04 15:07:53 +000015 // Override
Nils Diewald0e6992a2015-04-14 20:13:52 +000016 KorAP.API.getMatchInfo = KorAP.API.getMatchInfo || function () {
17 KorAP.log(0, 'KorAP.API.getMatchInfo() not implemented')
18 return {};
19 };
20
21 var loc = KorAP.Locale;
22
Nils Diewald0e6992a2015-04-14 20:13:52 +000023 return {
Nils Diewald7148c6f2015-05-04 15:07:53 +000024
25 /**
26 * Create new match object
27 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000028 create : function (match) {
29 return Object.create(this)._init(match);
30 },
31
32 /**
33 * Initialize object
34 */
35 _init : function (match) {
36 this._match = match;
37 this.opened = false;
38 return this;
39 },
40
41 /**
42 * Get match object
43 */
44 match : function () {
45 return this._match;
46 },
47
Nils Diewald7148c6f2015-05-04 15:07:53 +000048
49 /**
50 * Open the information view,
51 * if closed, otherwise close.
52 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000053 toggle : function () {
54 if (this.opened == true) {
55 this._match.element().children[0].removeChild(
56 this.element()
57 );
58 this.opened = false;
59 }
60 else {
61 // Append element to match
62 this._match.element().children[0].appendChild(
63 this.element()
64 );
65 this.opened = true;
66 };
67
68 return this.opened;
69 },
70
71
72 /**
Nils Diewald7148c6f2015-05-04 15:07:53 +000073 * Retrieve and parse snippet for table
74 * representation
Nils Diewald0e6992a2015-04-14 20:13:52 +000075 */
76 getTable : function (tokens, cb) {
77 var focus = [];
78
79 // Get all tokens
80 if (tokens === undefined) {
81 focus = this._match.getTokens();
82 }
83
84 // Get only some tokens
85 else {
86
87 // Push newly to focus array
88 for (var i = 0; i < tokens.length; i++) {
89 var term = tokens[i];
90 try {
91 // Create info layer objects
92 var layer = infoLayerClass.create(term);
93 layer.type = "tokens";
94 focus.push(layer);
95 }
96 catch (e) {
97 continue;
98 };
99 };
100 };
101
102 // No tokens chosen
103 if (focus.length == 0)
104 cb(null);
105
106 // Get info (may be cached)
Nils Diewald0e6992a2015-04-14 20:13:52 +0000107 KorAP.API.getMatchInfo(
108 this._match,
109 { 'spans' : false, 'layer' : focus },
110
111 // Callback for retrieval
112 function (matchResponse) {
113 // Get snippet from match info
114 if (matchResponse["snippet"] !== undefined) {
115 this._table = matchTableClass.create(matchResponse["snippet"]);
116 cb(this._table);
117 };
118 }.bind(this)
119 );
120
121 /*
122 // Todo: Store the table as a hash of the focus
123 return null;
124 */
125 },
126
127
128 /**
129 * Retrieve and parse snippet for tree representation
130 */
131 getTree : function (foundry, layer, cb) {
132 var focus = [];
133
134 // TODO: Support and cache multiple trees
135 KorAP.API.getMatchInfo(
Akronc56cf2d2016-11-09 22:02:38 +0100136 this._match, {
137 'spans' : true,
138 'foundry' : foundry,
139 'layer' : layer
140 },
141 function (matchResponse) {
142 // Get snippet from match info
143 if (matchResponse["snippet"] !== undefined) {
144 // Todo: This should be cached somehow
145
146 cb(matchTreeClass.create(matchResponse["snippet"]));
147 }
148 else {
149 cb(null);
150 };
151 }.bind(this)
Nils Diewald0e6992a2015-04-14 20:13:52 +0000152 );
153 },
154
155 /**
156 * Destroy this match information view.
157 */
158 destroy : function () {
159
160 // Remove circular reference
161 if (this._treeMenu !== undefined)
162 delete this._treeMenu["info"];
163
164 this._treeMenu.destroy();
165 this._treeMenu = undefined;
166 this._match = undefined;
167
168 // Element destroy
169 },
170
171 /**
172 * Add a new tree view to the list
173 */
174 addTree : function (foundry, layer, cb) {
175 var matchtree = document.createElement('div');
176 matchtree.classList.add('matchtree');
177
178 var h6 = matchtree.appendChild(document.createElement('h6'));
179 h6.appendChild(document.createElement('span'))
180 .appendChild(document.createTextNode(foundry));
181 h6.appendChild(document.createElement('span'))
182 .appendChild(document.createTextNode(layer));
183
184 var tree = matchtree.appendChild(
Akronc56cf2d2016-11-09 22:02:38 +0100185 document.createElement('div')
Nils Diewald0e6992a2015-04-14 20:13:52 +0000186 );
187
188 this._element.insertBefore(matchtree, this._element.lastChild);
189
Akronc56cf2d2016-11-09 22:02:38 +0100190 var actions = tree.appendChild(document.createElement('ul'));
191 actions.classList.add('action', 'image');
192 var close = actions.appendChild(document.createElement('li'));
193 close.className = 'close';
194 close.appendChild(document.createElement('span'));
Nils Diewald0e6992a2015-04-14 20:13:52 +0000195 close.addEventListener(
Akronc56cf2d2016-11-09 22:02:38 +0100196 'click', function (e) {
197 matchtree.parentNode.removeChild(matchtree);
198 e.halt();
199 }
Nils Diewald0e6992a2015-04-14 20:13:52 +0000200 );
201
Nils Diewald0ec142f2015-05-05 00:29:23 +0000202 tree.classList.add('loading');
203
Nils Diewald0e6992a2015-04-14 20:13:52 +0000204 // Get tree data async
205 this.getTree(foundry, layer, function (treeObj) {
Nils Diewald0ec142f2015-05-05 00:29:23 +0000206
Akronc56cf2d2016-11-09 22:02:38 +0100207 tree.classList.remove('loading');
Nils Diewald0ec142f2015-05-05 00:29:23 +0000208
Akronc56cf2d2016-11-09 22:02:38 +0100209 // Something went wrong - probably log!!!
Nils Diewald0ec142f2015-05-05 00:29:23 +0000210
Akronc56cf2d2016-11-09 22:02:38 +0100211 if (treeObj === null) {
212 tree.appendChild(document.createTextNode('No data available.'));
213 }
214 else {
215 tree.appendChild(treeObj.element());
216 // Reposition the view to the center
217 // (This may in a future release be a reposition
218 // to move the root into the center or the actual
219 // match)
220
221 var dl = document.createElement('li');
222 dl.className = 'download';
223 dl.addEventListener(
224 'click', function (e) {
225
226 var a = document.createElement('a');
227 a.setAttribute('href-lang', 'image/svg+xml');
228 a.setAttribute('href', 'data:image/svg+xml;base64,'+treeObj.toBase64());
229 a.setAttribute('download', 'tree.svg');
230 a.target = '_blank';
231
232 document.body.appendChild(a);
233 a.click();
234 document.body.removeChild(a)
235
236 e.halt();
237 }
238 );
239 actions.appendChild(dl);
240 treeObj.center();
241 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000242
Akronc56cf2d2016-11-09 22:02:38 +0100243 if (cb !== undefined)
244 cb(treeObj);
Nils Diewald0e6992a2015-04-14 20:13:52 +0000245 });
246 },
247
248 /**
249 * Create match information view.
250 */
251 element : function () {
252
253 if (this._element !== undefined)
Akronc56cf2d2016-11-09 22:02:38 +0100254 return this._element;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000255
256 // Create info table
257 var info = document.createElement('div');
258 info.classList.add('matchinfo');
259
260 // Append default table
261 var matchtable = document.createElement('div');
Nils Diewald0ec142f2015-05-05 00:29:23 +0000262 matchtable.classList.add('matchtable', 'loading');
Nils Diewald0e6992a2015-04-14 20:13:52 +0000263 info.appendChild(matchtable);
264
265 // Create the table asynchronous
266 this.getTable(undefined, function (table) {
267 if (table !== null) {
Nils Diewald0ec142f2015-05-05 00:29:23 +0000268 matchtable.classList.remove('loading');
Nils Diewald0e6992a2015-04-14 20:13:52 +0000269 matchtable.appendChild(table.element());
270 };
271 });
272
273 // Get spans
274 var spanLayers = this._match.getSpans().sort(
275 function (a, b) {
276 if (a.foundry < b.foundry) {
277 return -1;
278 }
279 else if (a.foundry > b.foundry) {
280 return 1;
281 }
282 else if (a.layer < b.layer) {
283 return -1;
284 }
285 else if (a.layer > b.layer) {
286 return 1;
287 };
288 return 0;
289 });
290
291 var menuList = [];
292
293 // Show tree views
294 for (var i = 0; i < spanLayers.length; i++) {
295 var span = spanLayers[i];
296
297 // Add foundry/layer to menu list
298 menuList.push([
299 span.foundry + '/' + span.layer,
300 span.foundry,
301 span.layer
302 ]);
303 };
304
305 // Create tree menu
306 var treemenu = this.treeMenu(menuList);
307 var span = info.appendChild(document.createElement('p'));
308 span.classList.add('addtree');
309 span.appendChild(document.createTextNode(loc.ADDTREE));
310
311 var treeElement = treemenu.element();
312 span.appendChild(treeElement);
313
314 span.addEventListener('click', function (e) {
Akron6ed13992016-05-23 18:06:05 +0200315 treemenu.show();
Nils Diewald0e6992a2015-04-14 20:13:52 +0000316 treemenu.focus();
317 });
318
319 this._element = info;
320
321 return info;
322 },
323
324
325 /**
326 * Get tree menu.
327 * There is only one menu rendered
328 * - no matter how many trees exist
329 */
330 treeMenu : function (list) {
331 if (this._treeMenu !== undefined)
332 return this._treeMenu;
333
334 return this._treeMenu = matchTreeMenuClass.create(this, list);
335 }
336 };
337});