blob: c2154a512f7ae87b72a32c4090cfb3678bd1d6e6 [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',
8 'match/treemenu',
Akron99713ef2017-06-28 18:19:28 +02009 'match/querycreator',
Nils Diewald7c8ced22015-04-15 19:21:00 +000010 'util'
11], function (infoLayerClass,
Akron3bb91bc2016-12-02 16:43:17 +010012 matchTableClass,
13 matchTreeClass,
Akron99713ef2017-06-28 18:19:28 +020014 matchTreeMenuClass,
15 matchQueryCreator) {
Akron3bb91bc2016-12-02 16:43:17 +010016
Nils Diewald7148c6f2015-05-04 15:07:53 +000017 // Override
Nils Diewald0e6992a2015-04-14 20:13:52 +000018 KorAP.API.getMatchInfo = KorAP.API.getMatchInfo || function () {
19 KorAP.log(0, 'KorAP.API.getMatchInfo() not implemented')
20 return {};
21 };
22
23 var loc = KorAP.Locale;
24
Nils Diewald0e6992a2015-04-14 20:13:52 +000025 return {
Nils Diewald7148c6f2015-05-04 15:07:53 +000026
27 /**
28 * Create new match object
29 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000030 create : function (match) {
31 return Object.create(this)._init(match);
32 },
33
34 /**
35 * Initialize object
36 */
37 _init : function (match) {
38 this._match = match;
39 this.opened = false;
40 return this;
41 },
42
43 /**
44 * Get match object
45 */
46 match : function () {
47 return this._match;
48 },
49
Nils Diewald7148c6f2015-05-04 15:07:53 +000050
51 /**
52 * Open the information view,
53 * if closed, otherwise close.
54 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000055 toggle : function () {
Akron3bb91bc2016-12-02 16:43:17 +010056
Akron08b82d62016-12-05 15:06:05 +010057 var elem = this._match.element();
Akron3bb91bc2016-12-02 16:43:17 +010058
59 if (this.opened == true) {
Akrond67d45b2017-05-18 21:47:38 +020060 elem.removeChild(
61 this.element()
62 );
63 this.opened = false;
Nils Diewald0e6992a2015-04-14 20:13:52 +000064 }
65 else {
Akrond67d45b2017-05-18 21:47:38 +020066 // Append element to match
Akron3bb91bc2016-12-02 16:43:17 +010067 elem.appendChild(
Akrond67d45b2017-05-18 21:47:38 +020068 this.element()
69 );
70 this.opened = true;
Nils Diewald0e6992a2015-04-14 20:13:52 +000071 };
72
73 return this.opened;
74 },
75
76
77 /**
Nils Diewald7148c6f2015-05-04 15:07:53 +000078 * Retrieve and parse snippet for table
79 * representation
Nils Diewald0e6992a2015-04-14 20:13:52 +000080 */
81 getTable : function (tokens, cb) {
82 var focus = [];
83
84 // Get all tokens
85 if (tokens === undefined) {
Akrond67d45b2017-05-18 21:47:38 +020086 focus = this._match.getTokens();
Nils Diewald0e6992a2015-04-14 20:13:52 +000087 }
88
89 // Get only some tokens
90 else {
Akrond67d45b2017-05-18 21:47:38 +020091
92 // Push newly to focus array
93 for (var i = 0; i < tokens.length; i++) {
94 var term = tokens[i];
95 try {
96 // Create info layer objects
97 var layer = infoLayerClass.create(term);
98 layer.type = "tokens";
99 focus.push(layer);
100 }
101 catch (e) {
102 continue;
103 };
104 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000105 };
106
107 // No tokens chosen
108 if (focus.length == 0)
Akrond67d45b2017-05-18 21:47:38 +0200109 cb(null);
Nils Diewald0e6992a2015-04-14 20:13:52 +0000110
111 // Get info (may be cached)
Nils Diewald0e6992a2015-04-14 20:13:52 +0000112 KorAP.API.getMatchInfo(
Akrond67d45b2017-05-18 21:47:38 +0200113 this._match,
114 { 'spans' : false, 'layer' : focus },
115
116 // Callback for retrieval
117 function (matchResponse) {
Akron3bb91bc2016-12-02 16:43:17 +0100118
Akron515851a2017-05-02 12:53:17 +0200119 if (matchResponse === undefined)
120 cb(null);
121
Akrond67d45b2017-05-18 21:47:38 +0200122 // Get snippet from match info
123 if (matchResponse["snippet"] !== undefined) {
124 this._table = matchTableClass.create(matchResponse["snippet"]);
125 cb(this._table);
126 };
127 }.bind(this)
Nils Diewald0e6992a2015-04-14 20:13:52 +0000128 );
129
130 /*
131 // Todo: Store the table as a hash of the focus
132 return null;
133 */
134 },
135
136
137 /**
138 * Retrieve and parse snippet for tree representation
139 */
140 getTree : function (foundry, layer, cb) {
141 var focus = [];
142
143 // TODO: Support and cache multiple trees
144 KorAP.API.getMatchInfo(
Akrond67d45b2017-05-18 21:47:38 +0200145 this._match, {
146 'spans' : true,
147 'foundry' : foundry,
148 'layer' : layer
149 },
150 function (matchResponse) {
151 // Get snippet from match info
152 if (matchResponse["snippet"] !== undefined) {
153 // Todo: This should be cached somehow
Akronc56cf2d2016-11-09 22:02:38 +0100154
Akrond67d45b2017-05-18 21:47:38 +0200155 cb(matchTreeClass.create(matchResponse["snippet"]));
156 }
157 else {
158 cb(null);
159 };
160 }.bind(this)
Nils Diewald0e6992a2015-04-14 20:13:52 +0000161 );
162 },
163
164 /**
165 * Destroy this match information view.
166 */
167 destroy : function () {
168
169 // Remove circular reference
170 if (this._treeMenu !== undefined)
Akron99713ef2017-06-28 18:19:28 +0200171 delete this._treeMenu["info"];
Nils Diewald0e6992a2015-04-14 20:13:52 +0000172
173 this._treeMenu.destroy();
174 this._treeMenu = undefined;
175 this._match = undefined;
Akron99713ef2017-06-28 18:19:28 +0200176 this._matchCreator = undefined;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000177 // Element destroy
178 },
179
180 /**
181 * Add a new tree view to the list
182 */
183 addTree : function (foundry, layer, cb) {
184 var matchtree = document.createElement('div');
185 matchtree.classList.add('matchtree');
186
187 var h6 = matchtree.appendChild(document.createElement('h6'));
188 h6.appendChild(document.createElement('span'))
Akron99713ef2017-06-28 18:19:28 +0200189 .appendChild(document.createTextNode(foundry));
Nils Diewald0e6992a2015-04-14 20:13:52 +0000190 h6.appendChild(document.createElement('span'))
Akrond67d45b2017-05-18 21:47:38 +0200191 .appendChild(document.createTextNode(layer));
192
Nils Diewald0e6992a2015-04-14 20:13:52 +0000193 var tree = matchtree.appendChild(
Akrond67d45b2017-05-18 21:47:38 +0200194 document.createElement('div')
Nils Diewald0e6992a2015-04-14 20:13:52 +0000195 );
196
197 this._element.insertBefore(matchtree, this._element.lastChild);
198
Akronc56cf2d2016-11-09 22:02:38 +0100199 var actions = tree.appendChild(document.createElement('ul'));
200 actions.classList.add('action', 'image');
201 var close = actions.appendChild(document.createElement('li'));
202 close.className = 'close';
203 close.appendChild(document.createElement('span'));
Nils Diewald0e6992a2015-04-14 20:13:52 +0000204 close.addEventListener(
Akrond67d45b2017-05-18 21:47:38 +0200205 'click', function (e) {
206 matchtree.parentNode.removeChild(matchtree);
207 e.halt();
208 }
Nils Diewald0e6992a2015-04-14 20:13:52 +0000209 );
210
Nils Diewald0ec142f2015-05-05 00:29:23 +0000211 tree.classList.add('loading');
212
Nils Diewald0e6992a2015-04-14 20:13:52 +0000213 // Get tree data async
214 this.getTree(foundry, layer, function (treeObj) {
Nils Diewald0ec142f2015-05-05 00:29:23 +0000215
Akrond67d45b2017-05-18 21:47:38 +0200216 tree.classList.remove('loading');
Nils Diewald0ec142f2015-05-05 00:29:23 +0000217
Akrond67d45b2017-05-18 21:47:38 +0200218 // Something went wrong - probably log!!!
Nils Diewald0ec142f2015-05-05 00:29:23 +0000219
Akrond67d45b2017-05-18 21:47:38 +0200220 if (treeObj === null) {
221 tree.appendChild(document.createTextNode('No data available.'));
222 }
223 else {
224 tree.appendChild(treeObj.element());
225 // Reposition the view to the center
226 // (This may in a future release be a reposition
227 // to move the root into the center or the actual
228 // match)
Akronc56cf2d2016-11-09 22:02:38 +0100229
230 var dl = document.createElement('li');
231 dl.className = 'download';
232 dl.addEventListener(
Akrond67d45b2017-05-18 21:47:38 +0200233 'click', function (e) {
Akronc56cf2d2016-11-09 22:02:38 +0100234
235 var a = document.createElement('a');
236 a.setAttribute('href-lang', 'image/svg+xml');
237 a.setAttribute('href', 'data:image/svg+xml;base64,'+treeObj.toBase64());
238 a.setAttribute('download', 'tree.svg');
239 a.target = '_blank';
240
241 document.body.appendChild(a);
242 a.click();
243 document.body.removeChild(a)
244
245 e.halt();
Akrond67d45b2017-05-18 21:47:38 +0200246 }
Akronc56cf2d2016-11-09 22:02:38 +0100247 );
248 actions.appendChild(dl);
249 treeObj.center();
Akrond67d45b2017-05-18 21:47:38 +0200250 };
251
252 if (cb !== undefined)
253 cb(treeObj);
Nils Diewald0e6992a2015-04-14 20:13:52 +0000254 });
255 },
256
257 /**
258 * Create match information view.
259 */
260 element : function () {
261
262 if (this._element !== undefined)
Akrond67d45b2017-05-18 21:47:38 +0200263 return this._element;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000264
265 // Create info table
266 var info = document.createElement('div');
267 info.classList.add('matchinfo');
268
269 // Append default table
270 var matchtable = document.createElement('div');
Nils Diewald0ec142f2015-05-05 00:29:23 +0000271 matchtable.classList.add('matchtable', 'loading');
Nils Diewald0e6992a2015-04-14 20:13:52 +0000272 info.appendChild(matchtable);
273
274 // Create the table asynchronous
275 this.getTable(undefined, function (table) {
Akron3bb91bc2016-12-02 16:43:17 +0100276
Akrond67d45b2017-05-18 21:47:38 +0200277 if (table !== null) {
Akron3bb91bc2016-12-02 16:43:17 +0100278 matchtable.appendChild(table.element());
279 };
Akron515851a2017-05-02 12:53:17 +0200280 matchtable.classList.remove('loading');
Akron99713ef2017-06-28 18:19:28 +0200281
282 // Add query creator
Akrone8ea0002017-06-28 18:51:52 +0200283 this._matchCreator = matchQueryCreator.create(info);
Nils Diewald0e6992a2015-04-14 20:13:52 +0000284 });
285
Akrond67d45b2017-05-18 21:47:38 +0200286 // Join spans and relations
287 var treeLayers = []
288 var spans = this._match.getSpans();
289 var rels = this._match.getRels();
290 var i;
291 for (i in spans) {
292 treeLayers.push(spans[i]);
293 };
294 for (i in rels) {
295 treeLayers.push(rels[i]);
296 };
297
Nils Diewald0e6992a2015-04-14 20:13:52 +0000298 // Get spans
Akrond67d45b2017-05-18 21:47:38 +0200299 treeLayers = treeLayers.sort(
300 function (a, b) {
301 if (a.foundry < b.foundry) {
302 return -1;
303 }
304 else if (a.foundry > b.foundry) {
305 return 1;
306 }
307 else if (a.layer < b.layer) {
308 return -1;
309 }
310 else if (a.layer > b.layer) {
311 return 1;
312 };
313 return 0;
314 });
Nils Diewald0e6992a2015-04-14 20:13:52 +0000315
316 var menuList = [];
317
318 // Show tree views
Akrond67d45b2017-05-18 21:47:38 +0200319 for (var i = 0; i < treeLayers.length; i++) {
320 var span = treeLayers[i];
321
322 // Add foundry/layer to menu list
323 menuList.push([
324 span.foundry + '/' + span.layer,
325 span.foundry,
326 span.layer
327 ]);
Nils Diewald0e6992a2015-04-14 20:13:52 +0000328 };
329
330 // Create tree menu
331 var treemenu = this.treeMenu(menuList);
332 var span = info.appendChild(document.createElement('p'));
333 span.classList.add('addtree');
334 span.appendChild(document.createTextNode(loc.ADDTREE));
335
336 var treeElement = treemenu.element();
337 span.appendChild(treeElement);
338
339 span.addEventListener('click', function (e) {
Akrond67d45b2017-05-18 21:47:38 +0200340 treemenu.show();
341 treemenu.focus();
Nils Diewald0e6992a2015-04-14 20:13:52 +0000342 });
343
344 this._element = info;
345
346 return info;
347 },
348
349
350 /**
351 * Get tree menu.
352 * There is only one menu rendered
353 * - no matter how many trees exist
354 */
355 treeMenu : function (list) {
356 if (this._treeMenu !== undefined)
Akrond67d45b2017-05-18 21:47:38 +0200357 return this._treeMenu;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000358
359 return this._treeMenu = matchTreeMenuClass.create(this, list);
360 }
361 };
362});