blob: d207867c818e629d7c85e842ff4074a648f4b7f8 [file] [log] [blame]
Akron99713ef2017-06-28 18:19:28 +02001/**
2 * Information about a match.
3 */
Nils Diewald7c8ced22015-04-15 19:21:00 +00004define([
5 'match/infolayer',
6 'match/table',
7 'match/tree',
Akronbd342982018-01-25 18:01:46 +01008 'match/reference', // rename to meta
Akron0988d882017-11-10 16:13:12 +01009 'match/relations',
Nils Diewald7c8ced22015-04-15 19:21:00 +000010 'match/treemenu',
Akron99713ef2017-06-28 18:19:28 +020011 'match/querycreator',
Nils Diewald7c8ced22015-04-15 19:21:00 +000012 'util'
13], function (infoLayerClass,
Akron3bb91bc2016-12-02 16:43:17 +010014 matchTableClass,
15 matchTreeClass,
Akronbd342982018-01-25 18:01:46 +010016 matchRefClass,
Akron0988d882017-11-10 16:13:12 +010017 matchRelClass,
Akron99713ef2017-06-28 18:19:28 +020018 matchTreeMenuClass,
Akron0988d882017-11-10 16:13:12 +010019 matchQueryCreator) {
Akron3bb91bc2016-12-02 16:43:17 +010020
Nils Diewald7148c6f2015-05-04 15:07:53 +000021 // Override
Nils Diewald0e6992a2015-04-14 20:13:52 +000022 KorAP.API.getMatchInfo = KorAP.API.getMatchInfo || function () {
23 KorAP.log(0, 'KorAP.API.getMatchInfo() not implemented')
24 return {};
25 };
26
27 var loc = KorAP.Locale;
28
Nils Diewald0e6992a2015-04-14 20:13:52 +000029 return {
Nils Diewald7148c6f2015-05-04 15:07:53 +000030
31 /**
32 * Create new match object
33 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000034 create : function (match) {
35 return Object.create(this)._init(match);
36 },
37
38 /**
39 * Initialize object
40 */
41 _init : function (match) {
42 this._match = match;
43 this.opened = false;
44 return this;
45 },
46
47 /**
48 * Get match object
49 */
50 match : function () {
51 return this._match;
52 },
53
Nils Diewald7148c6f2015-05-04 15:07:53 +000054
55 /**
56 * Open the information view,
57 * if closed, otherwise close.
58 */
Akronbd342982018-01-25 18:01:46 +010059 /*
Nils Diewald0e6992a2015-04-14 20:13:52 +000060 toggle : function () {
Akron3bb91bc2016-12-02 16:43:17 +010061
Akron08b82d62016-12-05 15:06:05 +010062 var elem = this._match.element();
Akron3bb91bc2016-12-02 16:43:17 +010063
64 if (this.opened == true) {
Akrond67d45b2017-05-18 21:47:38 +020065 elem.removeChild(
66 this.element()
67 );
68 this.opened = false;
Nils Diewald0e6992a2015-04-14 20:13:52 +000069 }
70 else {
Akrond67d45b2017-05-18 21:47:38 +020071 // Append element to match
Akron3bb91bc2016-12-02 16:43:17 +010072 elem.appendChild(
Akrond67d45b2017-05-18 21:47:38 +020073 this.element()
74 );
75 this.opened = true;
Nils Diewald0e6992a2015-04-14 20:13:52 +000076 };
77
78 return this.opened;
79 },
Akronbd342982018-01-25 18:01:46 +010080 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000081
82
83 /**
Nils Diewald7148c6f2015-05-04 15:07:53 +000084 * Retrieve and parse snippet for table
85 * representation
Nils Diewald0e6992a2015-04-14 20:13:52 +000086 */
87 getTable : function (tokens, cb) {
88 var focus = [];
89
90 // Get all tokens
91 if (tokens === undefined) {
Akrond67d45b2017-05-18 21:47:38 +020092 focus = this._match.getTokens();
Nils Diewald0e6992a2015-04-14 20:13:52 +000093 }
94
95 // Get only some tokens
96 else {
Akrond67d45b2017-05-18 21:47:38 +020097
98 // Push newly to focus array
99 for (var i = 0; i < tokens.length; i++) {
100 var term = tokens[i];
101 try {
102 // Create info layer objects
103 var layer = infoLayerClass.create(term);
104 layer.type = "tokens";
105 focus.push(layer);
106 }
107 catch (e) {
108 continue;
109 };
110 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000111 };
112
113 // No tokens chosen
114 if (focus.length == 0)
Akrond67d45b2017-05-18 21:47:38 +0200115 cb(null);
Nils Diewald0e6992a2015-04-14 20:13:52 +0000116
117 // Get info (may be cached)
Nils Diewald0e6992a2015-04-14 20:13:52 +0000118 KorAP.API.getMatchInfo(
Akrond67d45b2017-05-18 21:47:38 +0200119 this._match,
120 { 'spans' : false, 'layer' : focus },
121
122 // Callback for retrieval
123 function (matchResponse) {
Akron3bb91bc2016-12-02 16:43:17 +0100124
Akron515851a2017-05-02 12:53:17 +0200125 if (matchResponse === undefined)
126 cb(null);
127
Akrond67d45b2017-05-18 21:47:38 +0200128 // Get snippet from match info
129 if (matchResponse["snippet"] !== undefined) {
130 this._table = matchTableClass.create(matchResponse["snippet"]);
131 cb(this._table);
132 };
133 }.bind(this)
Nils Diewald0e6992a2015-04-14 20:13:52 +0000134 );
135
136 /*
137 // Todo: Store the table as a hash of the focus
138 return null;
139 */
140 },
Akronbd342982018-01-25 18:01:46 +0100141
142
143 getMeta : function (metaInfo, cb) {
144
145 },
Nils Diewald0e6992a2015-04-14 20:13:52 +0000146
147
148 /**
149 * Retrieve and parse snippet for tree representation
150 */
Akron0988d882017-11-10 16:13:12 +0100151 getTree : function (foundry, layer, type, cb) {
Nils Diewald0e6992a2015-04-14 20:13:52 +0000152 var focus = [];
153
154 // TODO: Support and cache multiple trees
155 KorAP.API.getMatchInfo(
Akrond67d45b2017-05-18 21:47:38 +0200156 this._match, {
157 'spans' : true,
158 'foundry' : foundry,
159 'layer' : layer
160 },
161 function (matchResponse) {
162 // Get snippet from match info
163 if (matchResponse["snippet"] !== undefined) {
164 // Todo: This should be cached somehow
Akronc56cf2d2016-11-09 22:02:38 +0100165
Akron0988d882017-11-10 16:13:12 +0100166 if (type === "spans") {
167 cb(matchTreeClass.create(matchResponse["snippet"]));
168 }
169 else if (type === "rels") {
170 cb(matchRelClass.create(matchResponse["snippet"]));
171 }
172
173 // Unknown tree type
174 else {
175 cb(null);
176 };
Akrond67d45b2017-05-18 21:47:38 +0200177 }
178 else {
179 cb(null);
180 };
181 }.bind(this)
Nils Diewald0e6992a2015-04-14 20:13:52 +0000182 );
183 },
184
185 /**
186 * Destroy this match information view.
187 */
188 destroy : function () {
189
190 // Remove circular reference
191 if (this._treeMenu !== undefined)
Akron99713ef2017-06-28 18:19:28 +0200192 delete this._treeMenu["info"];
Nils Diewald0e6992a2015-04-14 20:13:52 +0000193
194 this._treeMenu.destroy();
195 this._treeMenu = undefined;
196 this._match = undefined;
Akron99713ef2017-06-28 18:19:28 +0200197 this._matchCreator = undefined;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000198 // Element destroy
199 },
200
201 /**
202 * Add a new tree view to the list
203 */
Akron0988d882017-11-10 16:13:12 +0100204 addTree : function (foundry, layer, type, cb) {
Nils Diewald0e6992a2015-04-14 20:13:52 +0000205 var matchtree = document.createElement('div');
206 matchtree.classList.add('matchtree');
207
208 var h6 = matchtree.appendChild(document.createElement('h6'));
209 h6.appendChild(document.createElement('span'))
Akron99713ef2017-06-28 18:19:28 +0200210 .appendChild(document.createTextNode(foundry));
Nils Diewald0e6992a2015-04-14 20:13:52 +0000211 h6.appendChild(document.createElement('span'))
Akrond67d45b2017-05-18 21:47:38 +0200212 .appendChild(document.createTextNode(layer));
213
Nils Diewald0e6992a2015-04-14 20:13:52 +0000214 var tree = matchtree.appendChild(
Akrond67d45b2017-05-18 21:47:38 +0200215 document.createElement('div')
Nils Diewald0e6992a2015-04-14 20:13:52 +0000216 );
217
218 this._element.insertBefore(matchtree, this._element.lastChild);
219
Akronc56cf2d2016-11-09 22:02:38 +0100220 var actions = tree.appendChild(document.createElement('ul'));
221 actions.classList.add('action', 'image');
222 var close = actions.appendChild(document.createElement('li'));
223 close.className = 'close';
224 close.appendChild(document.createElement('span'));
Nils Diewald0e6992a2015-04-14 20:13:52 +0000225 close.addEventListener(
Akrond67d45b2017-05-18 21:47:38 +0200226 'click', function (e) {
227 matchtree.parentNode.removeChild(matchtree);
228 e.halt();
229 }
Nils Diewald0e6992a2015-04-14 20:13:52 +0000230 );
231
Nils Diewald0ec142f2015-05-05 00:29:23 +0000232 tree.classList.add('loading');
233
Nils Diewald0e6992a2015-04-14 20:13:52 +0000234 // Get tree data async
Akron0988d882017-11-10 16:13:12 +0100235 this.getTree(foundry, layer, type, function (treeObj) {
Nils Diewald0ec142f2015-05-05 00:29:23 +0000236
Akrond67d45b2017-05-18 21:47:38 +0200237 tree.classList.remove('loading');
Nils Diewald0ec142f2015-05-05 00:29:23 +0000238
Akrond67d45b2017-05-18 21:47:38 +0200239 // Something went wrong - probably log!!!
Nils Diewald0ec142f2015-05-05 00:29:23 +0000240
Akrond67d45b2017-05-18 21:47:38 +0200241 if (treeObj === null) {
242 tree.appendChild(document.createTextNode('No data available.'));
243 }
244 else {
245 tree.appendChild(treeObj.element());
Akron0988d882017-11-10 16:13:12 +0100246 treeObj.show();
Akrond67d45b2017-05-18 21:47:38 +0200247 // Reposition the view to the center
248 // (This may in a future release be a reposition
249 // to move the root into the center or the actual
250 // match)
Akronc56cf2d2016-11-09 22:02:38 +0100251
Akron0988d882017-11-10 16:13:12 +0100252 // This is currently not supported by relations
253 if (type === "spans") {
254 var dl = document.createElement('li');
255 dl.className = 'download';
256 dl.addEventListener(
257 'click', function (e) {
Akronc56cf2d2016-11-09 22:02:38 +0100258
Akron0988d882017-11-10 16:13:12 +0100259 var a = document.createElement('a');
260 a.setAttribute('href-lang', 'image/svg+xml');
261 a.setAttribute('href', 'data:image/svg+xml;base64,'+treeObj.toBase64());
262 a.setAttribute('download', 'tree.svg');
263 a.target = '_blank';
Akrona27f0d42017-11-13 14:08:41 +0100264 a.setAttribute('rel', 'noopener noreferrer');
Akron0988d882017-11-10 16:13:12 +0100265
266 document.body.appendChild(a);
267 a.click();
268 document.body.removeChild(a)
269 e.halt();
270 }
271 );
272
273 actions.appendChild(dl);
274 };
275
Akronc56cf2d2016-11-09 22:02:38 +0100276 treeObj.center();
Akrond67d45b2017-05-18 21:47:38 +0200277 };
278
279 if (cb !== undefined)
280 cb(treeObj);
Nils Diewald0e6992a2015-04-14 20:13:52 +0000281 });
282 },
Akronbd342982018-01-25 18:01:46 +0100283
284
Akrone7679692018-01-26 12:06:33 +0100285 // Add meta information to match
Akronbd342982018-01-25 18:01:46 +0100286 addMeta : function () {
287 var matchmeta = document.createElement('div');
288 // matchRefClass.create();
289
290 // TODO: This is part of the getMeta!
291 var metaInfo = this._match.element().getAttribute('data-info');
292
293 if (metaInfo)
294 metaInfo = JSON.parse(metaInfo);
295
296 // There is metainfo
297 if (metaInfo) {
298
299 // Add metainfo to matchview
300 var metaElem = matchRefClass.create(this._match).element(metaInfo);
Akrone7679692018-01-26 12:06:33 +0100301 var elem = this.element();
Akronbd342982018-01-25 18:01:46 +0100302
Akrone7679692018-01-26 12:06:33 +0100303 elem.insertBefore(
304 metaElem,
305 elem.firstChild
306 );
307
308 console.log(elem);
Akronbd342982018-01-25 18:01:46 +0100309 };
310 },
311
312 // Add table
313 addTable : function () {
314
315 var info = this.element();
Nils Diewald0e6992a2015-04-14 20:13:52 +0000316
317 // Append default table
318 var matchtable = document.createElement('div');
Nils Diewald0ec142f2015-05-05 00:29:23 +0000319 matchtable.classList.add('matchtable', 'loading');
Nils Diewald0e6992a2015-04-14 20:13:52 +0000320 info.appendChild(matchtable);
321
322 // Create the table asynchronous
323 this.getTable(undefined, function (table) {
Akron3bb91bc2016-12-02 16:43:17 +0100324
Akrond67d45b2017-05-18 21:47:38 +0200325 if (table !== null) {
Akron3bb91bc2016-12-02 16:43:17 +0100326 matchtable.appendChild(table.element());
327 };
Akron515851a2017-05-02 12:53:17 +0200328 matchtable.classList.remove('loading');
Akron99713ef2017-06-28 18:19:28 +0200329
330 // Add query creator
Akrone8ea0002017-06-28 18:51:52 +0200331 this._matchCreator = matchQueryCreator.create(info);
Nils Diewald0e6992a2015-04-14 20:13:52 +0000332 });
333
Akronbd342982018-01-25 18:01:46 +0100334
335 info.appendChild(this.addTreeMenu());
336 },
337
338
339 addTreeMenu : function () {
340
Akrond67d45b2017-05-18 21:47:38 +0200341 // Join spans and relations
342 var treeLayers = []
343 var spans = this._match.getSpans();
344 var rels = this._match.getRels();
345 var i;
346 for (i in spans) {
347 treeLayers.push(spans[i]);
348 };
349 for (i in rels) {
350 treeLayers.push(rels[i]);
351 };
352
Nils Diewald0e6992a2015-04-14 20:13:52 +0000353 // Get spans
Akrond67d45b2017-05-18 21:47:38 +0200354 treeLayers = treeLayers.sort(
355 function (a, b) {
356 if (a.foundry < b.foundry) {
357 return -1;
358 }
359 else if (a.foundry > b.foundry) {
360 return 1;
361 }
362 else if (a.layer < b.layer) {
363 return -1;
364 }
365 else if (a.layer > b.layer) {
366 return 1;
367 };
368 return 0;
369 });
Nils Diewald0e6992a2015-04-14 20:13:52 +0000370
371 var menuList = [];
372
373 // Show tree views
Akrond67d45b2017-05-18 21:47:38 +0200374 for (var i = 0; i < treeLayers.length; i++) {
375 var span = treeLayers[i];
376
377 // Add foundry/layer to menu list
378 menuList.push([
379 span.foundry + '/' + span.layer,
380 span.foundry,
Akron0988d882017-11-10 16:13:12 +0100381 span.layer,
382 span.type
Akrond67d45b2017-05-18 21:47:38 +0200383 ]);
Nils Diewald0e6992a2015-04-14 20:13:52 +0000384 };
385
386 // Create tree menu
387 var treemenu = this.treeMenu(menuList);
Akronbd342982018-01-25 18:01:46 +0100388 var span = document.createElement('p');
Nils Diewald0e6992a2015-04-14 20:13:52 +0000389 span.classList.add('addtree');
390 span.appendChild(document.createTextNode(loc.ADDTREE));
391
392 var treeElement = treemenu.element();
393 span.appendChild(treeElement);
394
395 span.addEventListener('click', function (e) {
Akrond67d45b2017-05-18 21:47:38 +0200396 treemenu.show();
397 treemenu.focus();
Nils Diewald0e6992a2015-04-14 20:13:52 +0000398 });
Akronbd342982018-01-25 18:01:46 +0100399
400 return span;
401 },
402
403 /**
404 * Create match information view.
405 */
406 element : function () {
407
408 if (this._element !== undefined)
409 return this._element;
410
411 // Create info table
412 var info = document.createElement('div');
413 info.classList.add('matchinfo');
Nils Diewald0e6992a2015-04-14 20:13:52 +0000414
415 this._element = info;
416
Akronbd342982018-01-25 18:01:46 +0100417 return this._element;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000418 },
419
420
421 /**
422 * Get tree menu.
423 * There is only one menu rendered
424 * - no matter how many trees exist
425 */
426 treeMenu : function (list) {
427 if (this._treeMenu !== undefined)
Akrond67d45b2017-05-18 21:47:38 +0200428 return this._treeMenu;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000429
430 return this._treeMenu = matchTreeMenuClass.create(this, list);
431 }
432 };
433});