blob: e88bf98830d3d694ba6cb4e5200dc75b694374cb [file] [log] [blame]
Nils Diewalde8518f82015-03-18 22:41:49 +00001/**
Nils Diewalda297f062015-04-02 00:23:46 +00002 * Get information on matches,
3 * generate annotation tables and trees.
Nils Diewalde8518f82015-03-18 22:41:49 +00004 *
5 * @author Nils Diewald
6 */
7/*
Nils Diewald6e43ffd2015-03-25 18:55:39 +00008 * - Highlight (at least mark as bold) the match
9 * - Scroll to match vertically per default
Akron02360e42016-06-07 13:41:12 +020010 * - A click on a table field and a tree node should at the field description to the fragments list.
Nils Diewalde8518f82015-03-18 22:41:49 +000011 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000012define([
Akron24866cf2018-01-23 20:22:01 +010013 'match/info', // rename to anno
Akron8b592d42018-01-26 18:33:06 +010014 'match/treemenu',
15 'util'
16], function (infoClass,matchTreeMenuClass) { //, refClass) {
Nils Diewald4f6521a2015-03-20 21:30:13 +000017
Nils Diewald6e43ffd2015-03-25 18:55:39 +000018 // Localization values
Akron0b489ad2018-02-02 16:49:32 +010019 const loc = KorAP.Locale;
Akron24866cf2018-01-23 20:22:01 +010020 loc.SHOWINFO = loc.SHOWINFO || 'Show information';
Akrond5436a42018-02-09 11:09:16 +010021 loc.ADDTREE = loc.ADDTREE || 'Relations';
22 loc.SHOWANNO = loc.SHOWANNO || 'Tokens';
Akron24866cf2018-01-23 20:22:01 +010023 loc.CLOSE = loc.CLOSE || 'Close';
Akrond5436a42018-02-09 11:09:16 +010024 loc.SHOW_META = loc.SHOW_META || 'Metadata';
Nils Diewald0e6992a2015-04-14 20:13:52 +000025
Akron0a6768f2016-07-13 18:00:43 +020026 // 'corpusID', 'docID', 'textID'
Akron0b489ad2018-02-02 16:49:32 +010027 const _matchTerms = ['textSigle', 'matchID', 'available'];
28
29 const d = document;
Nils Diewalda297f062015-04-02 00:23:46 +000030
31 /**
32 * Match object
33 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000034 return {
Nils Diewalde8518f82015-03-18 22:41:49 +000035
36 /**
37 * Create a new annotation object.
38 * Expects an array of available foundry/layer=type terms.
39 * Supported types are 'spans', 'tokens' and 'rels'.
40 */
Nils Diewalda297f062015-04-02 00:23:46 +000041 create : function (match) {
Nils Diewald0e6992a2015-04-14 20:13:52 +000042 return Object.create(this)._init(match);
Nils Diewalde8518f82015-03-18 22:41:49 +000043 },
44
Nils Diewald7c8ced22015-04-15 19:21:00 +000045
Nils Diewald6e43ffd2015-03-25 18:55:39 +000046 /**
Nils Diewalda297f062015-04-02 00:23:46 +000047 * Initialize match.
Nils Diewald6e43ffd2015-03-25 18:55:39 +000048 */
Nils Diewalda297f062015-04-02 00:23:46 +000049 _init : function (match) {
50 this._element = null;
Nils Diewald6e43ffd2015-03-25 18:55:39 +000051
Nils Diewalda297f062015-04-02 00:23:46 +000052 // No match defined
53 if (arguments.length < 1 ||
Akron19d97fe2016-09-06 20:47:05 +020054 match === null ||
55 match === undefined) {
56 throw new Error('Missing parameters');
Nils Diewalda297f062015-04-02 00:23:46 +000057 }
Nils Diewald6e43ffd2015-03-25 18:55:39 +000058
Nils Diewalda297f062015-04-02 00:23:46 +000059 // Match defined as a node
60 else if (match instanceof Node) {
Akron19d97fe2016-09-06 20:47:05 +020061 this._element = match;
Nils Diewald6e43ffd2015-03-25 18:55:39 +000062
Akron19d97fe2016-09-06 20:47:05 +020063 // Circular reference !!
64 match["_match"] = this;
Nils Diewalda297f062015-04-02 00:23:46 +000065
Akron19d97fe2016-09-06 20:47:05 +020066 /*
67 this.corpusID = match.getAttribute('data-corpus-id'),
68 this.docID = match.getAttribute('data-doc-id'),
69 this.textID = match.getAttribute('data-text-id'),
70 */
71 if (match.hasAttribute('data-text-sigle')) {
72 this.textSigle = match.getAttribute('data-text-sigle')
73 }
74 else {
75 this.textSigle = match.getAttribute('data-corpus-id') +
76 '/' +
77 match.getAttribute('data-doc-id') +
78 '/' +
79 match.getAttribute('data-text-id');
80 };
Akron0a6768f2016-07-13 18:00:43 +020081
Akron19d97fe2016-09-06 20:47:05 +020082 this.matchID = match.getAttribute('data-match-id');
Nils Diewalda297f062015-04-02 00:23:46 +000083
Akron19d97fe2016-09-06 20:47:05 +020084 // List of available annotations
85 this.available = match.getAttribute('data-available-info').split(' ');
Nils Diewalda297f062015-04-02 00:23:46 +000086 }
87
88 // Match as an object
89 else {
90
Akron19d97fe2016-09-06 20:47:05 +020091 // Iterate over allowed match terms
92 for (var i in _matchTerms) {
93 var term = _matchTerms[i];
94 this[term] = match[term] !== undefined ? match[term] : undefined;
95 };
Nils Diewalda297f062015-04-02 00:23:46 +000096 };
Nils Diewald0e6992a2015-04-14 20:13:52 +000097
Nils Diewald7c8ced22015-04-15 19:21:00 +000098 this._avail = {
Akron19d97fe2016-09-06 20:47:05 +020099 tokens : [],
100 spans : [],
101 rels : []
Nils Diewalde8518f82015-03-18 22:41:49 +0000102 };
Nils Diewalda297f062015-04-02 00:23:46 +0000103
104 // Iterate over info layers
105 for (var i = 0; i < this.available.length; i++) {
Akron19d97fe2016-09-06 20:47:05 +0200106 var term = this.available[i];
Nils Diewalda297f062015-04-02 00:23:46 +0000107
Akron19d97fe2016-09-06 20:47:05 +0200108 // Create info layer objects
109 try {
110 var layer = require('match/infolayer').create(term);
111 this._avail[layer.type].push(layer);
112 }
113 catch (e) {
114 continue;
115 };
Nils Diewalde8518f82015-03-18 22:41:49 +0000116 };
Akron3a4a08e2017-05-23 22:34:18 +0200117
Nils Diewalde8518f82015-03-18 22:41:49 +0000118 return this;
119 },
120
Nils Diewalde8518f82015-03-18 22:41:49 +0000121 /**
122 * Return a list of parseable tree annotations.
123 */
124 getSpans : function () {
Nils Diewald7c8ced22015-04-15 19:21:00 +0000125 return this._avail.spans;
Nils Diewalde8518f82015-03-18 22:41:49 +0000126 },
127
128
129 /**
130 * Return a list of parseable token annotations.
131 */
132 getTokens : function () {
Nils Diewald7c8ced22015-04-15 19:21:00 +0000133 return this._avail.tokens;
Nils Diewalde8518f82015-03-18 22:41:49 +0000134 },
135
136
137 /**
138 * Return a list of parseable relation annotations.
139 */
140 getRels : function () {
Nils Diewald7c8ced22015-04-15 19:21:00 +0000141 return this._avail.rels;
Nils Diewalde8518f82015-03-18 22:41:49 +0000142 },
143
Nils Diewald7c8ced22015-04-15 19:21:00 +0000144
Nils Diewalda297f062015-04-02 00:23:46 +0000145 /**
146 * Open match
147 */
148 open : function () {
149
150 // Add actions unless it's already activated
151 var element = this._element;
152
153 // There is an element to open
154 if (this._element === undefined || this._element === null)
Akron19d97fe2016-09-06 20:47:05 +0200155 return false;
Nils Diewalda297f062015-04-02 00:23:46 +0000156
157 // The element is already opened
158 if (element.classList.contains('active'))
Akron19d97fe2016-09-06 20:47:05 +0200159 return false;
Nils Diewalda297f062015-04-02 00:23:46 +0000160
161 // Add active class to element
162 element.classList.add('active');
163
Nils Diewald7c8ced22015-04-15 19:21:00 +0000164 // Already there
165 if (element.classList.contains('action'))
Akron19d97fe2016-09-06 20:47:05 +0200166 return true;
Nils Diewald7c8ced22015-04-15 19:21:00 +0000167
Nils Diewalda297f062015-04-02 00:23:46 +0000168 // Create action buttons
Akron0b489ad2018-02-02 16:49:32 +0100169 var ul = d.createElement('ul');
Nils Diewalda297f062015-04-02 00:23:46 +0000170 ul.classList.add('action', 'right');
Nils Diewalda297f062015-04-02 00:23:46 +0000171
Nils Diewald7c8ced22015-04-15 19:21:00 +0000172 element.appendChild(ul);
173 element.classList.add('action');
174
175 // Todo: Open in new frame
Nils Diewalda297f062015-04-02 00:23:46 +0000176
177 // Add close button
Akron0b489ad2018-02-02 16:49:32 +0100178 var close = d.createElement('li');
179 close.addE('span').addT(loc.CLOSE);
Nils Diewalda297f062015-04-02 00:23:46 +0000180 close.classList.add('close');
181 close.setAttribute('title', loc.CLOSE);
Nils Diewald0e6992a2015-04-14 20:13:52 +0000182
Nils Diewalda297f062015-04-02 00:23:46 +0000183 var that = this;
184
Akron24866cf2018-01-23 20:22:01 +0100185 // Add meta button
186 var refLine = element.querySelector("p.ref");
187
Akron0b489ad2018-02-02 16:49:32 +0100188 // No reference found
Akron151bc872018-02-02 14:04:15 +0100189 if (!refLine)
190 return;
191
Akron0b489ad2018-02-02 16:49:32 +0100192 var ops = d.createElement('div');
Akron151bc872018-02-02 14:04:15 +0100193 ops.classList.add('action', 'bottom', 'button-group');
Akron0ad7cd22018-02-08 18:03:06 +0100194
195 /*
196 Temporarily disabled
Akron0b489ad2018-02-02 16:49:32 +0100197 var meta = ops.addE('span');
198 meta.addT('Meta');
Akron151bc872018-02-02 14:04:15 +0100199 meta.setAttribute('title', loc.SHOW_META);
200 meta.classList.add('meta');
Akron0ad7cd22018-02-08 18:03:06 +0100201 */
Akron8b592d42018-01-26 18:33:06 +0100202
Akron0ad7cd22018-02-08 18:03:06 +0100203 // TODO: Rename anno
Akron0b489ad2018-02-02 16:49:32 +0100204 var info = ops.addE('span');
Akrond5436a42018-02-09 11:09:16 +0100205 info.addT(loc.SHOWANNO);
206 info.setAttribute('title', loc.SHOWANNO);
Akron151bc872018-02-02 14:04:15 +0100207 info.classList.add('info');
Akron8b592d42018-01-26 18:33:06 +0100208
Akron0b489ad2018-02-02 16:49:32 +0100209 var tree = ops.addE('span');
Akron0ad7cd22018-02-08 18:03:06 +0100210 tree.addT(loc.ADDTREE);
Akron151bc872018-02-02 14:04:15 +0100211 tree.setAttribute('title', loc.ADDTREE);
212 tree.classList.add('tree');
Akron8b592d42018-01-26 18:33:06 +0100213
Akron151bc872018-02-02 14:04:15 +0100214 // Insert before reference line
215 refLine.insertBefore(
216 ops,
217 refLine.firstChild
218 );
Akron8b592d42018-01-26 18:33:06 +0100219
Akron151bc872018-02-02 14:04:15 +0100220 // Click on meta - add meta (unless already there)
Akron0ad7cd22018-02-08 18:03:06 +0100221 /*
Akron151bc872018-02-02 14:04:15 +0100222 meta.addEventListener(
223 'click', function (e) {
224 e.halt();
225 that.info().showMeta();
226 }
227 );
Akron0ad7cd22018-02-08 18:03:06 +0100228 */
Akron8b592d42018-01-26 18:33:06 +0100229
Akron151bc872018-02-02 14:04:15 +0100230 // Click on token annotations - add token annotations (unless already there)
231 info.addEventListener(
232 'click', function (e) {
233 e.halt();
234 that.info().showTable();
235 }
236 );
Akron24866cf2018-01-23 20:22:01 +0100237
Akron151bc872018-02-02 14:04:15 +0100238 // Click to show tree menu
239 tree.addEventListener(
240 'click', function (e) {
241 e.halt();
Akron8b592d42018-01-26 18:33:06 +0100242
Akron151bc872018-02-02 14:04:15 +0100243 if (KorAP.TreeMenu === undefined) {
244 KorAP.TreeMenu = matchTreeMenuClass.create([]);
245 };
Akron8b592d42018-01-26 18:33:06 +0100246
Akron151bc872018-02-02 14:04:15 +0100247 var tm = KorAP.TreeMenu;
Akron8b592d42018-01-26 18:33:06 +0100248
Akron151bc872018-02-02 14:04:15 +0100249 // Reread list
250 tm.info(that.info());
251 tm.readItems(that.treeMenuList());
Akroneaba63e2018-01-26 19:49:30 +0100252
Akron151bc872018-02-02 14:04:15 +0100253 // Reposition and show menu
Akron151bc872018-02-02 14:04:15 +0100254 tm.show();
Akronc6967d72018-02-05 18:39:39 +0100255 tm.attachTo(this);
Akron151bc872018-02-02 14:04:15 +0100256 tm.focus();
257 }
258 );
Akron24866cf2018-01-23 20:22:01 +0100259
Nils Diewalda297f062015-04-02 00:23:46 +0000260 // Close match
261 close.addEventListener('click', function (e) {
Akron19d97fe2016-09-06 20:47:05 +0200262 e.halt();
263 that.close()
Nils Diewalda297f062015-04-02 00:23:46 +0000264 });
265
Nils Diewalda297f062015-04-02 00:23:46 +0000266 ul.appendChild(close);
Nils Diewalda297f062015-04-02 00:23:46 +0000267
268 return true;
269 },
270
Akron8c468a12016-11-13 23:57:41 +0100271
Akron6a535d42015-08-26 20:16:58 +0200272 // Todo: Test toggle
273 toggle : function () {
274 if (this._element.classList.contains('active'))
Akron19d97fe2016-09-06 20:47:05 +0200275 this.close();
Akron6a535d42015-08-26 20:16:58 +0200276 else
Akron19d97fe2016-09-06 20:47:05 +0200277 this.open();
Akron6a535d42015-08-26 20:16:58 +0200278 },
279
Nils Diewald7c8ced22015-04-15 19:21:00 +0000280
Nils Diewald8bc7e412015-03-19 22:08:27 +0000281 /**
Nils Diewalda297f062015-04-02 00:23:46 +0000282 * Close info view
283 */
284 close : function () {
285 this._element.classList.remove('active');
Akron151bc872018-02-02 14:04:15 +0100286 /*
287 if (this._info !== undefined) {
288 this._info.destroy();
289 };
290 */
Nils Diewalda297f062015-04-02 00:23:46 +0000291 },
292
293
Nils Diewalda297f062015-04-02 00:23:46 +0000294 /**
Akron151bc872018-02-02 14:04:15 +0100295 * Get and open associated match infos.
Nils Diewalda297f062015-04-02 00:23:46 +0000296 */
297 info : function () {
298
299 // Create match info
300 if (this._info === undefined)
Akron19d97fe2016-09-06 20:47:05 +0200301 this._info = infoClass.create(this);
Nils Diewalda297f062015-04-02 00:23:46 +0000302
303 // There is an element to append
304 if (this._element === undefined ||
Akron19d97fe2016-09-06 20:47:05 +0200305 this._element === null)
306 return this._info;
Nils Diewald7c8ced22015-04-15 19:21:00 +0000307
Nils Diewalda297f062015-04-02 00:23:46 +0000308 // Info is already activated
Nils Diewald5c5a7472015-04-02 22:13:38 +0000309 if (this._info._element !== undefined)
Akron19d97fe2016-09-06 20:47:05 +0200310 return this._info;
Nils Diewalda297f062015-04-02 00:23:46 +0000311
Akronbd342982018-01-25 18:01:46 +0100312 var refLine = this._element.querySelector("p.ref");
313 this._element.insertBefore(
314 this._info.element(),
315 refLine
316 );
317
Nils Diewalda297f062015-04-02 00:23:46 +0000318 return this._info;
319 },
320
Akron8b592d42018-01-26 18:33:06 +0100321
Akron151bc872018-02-02 14:04:15 +0100322 // Return tree menu list
Akroneaba63e2018-01-26 19:49:30 +0100323 treeMenuList : function () {
324
325 if (this._menuList)
326 return this._menuList;
Akron8b592d42018-01-26 18:33:06 +0100327
328 // Join spans and relations
329 var treeLayers = []
330 var spans = this.getSpans();
331 var rels = this.getRels();
332 var i;
333 for (i in spans) {
334 treeLayers.push(spans[i]);
335 };
336 for (i in rels) {
337 treeLayers.push(rels[i]);
338 };
339
340 // Get spans
341 treeLayers = treeLayers.sort(
342 function (a, b) {
343 if (a.foundry < b.foundry) {
344 return -1;
345 }
346 else if (a.foundry > b.foundry) {
347 return 1;
348 }
349 else if (a.layer < b.layer) {
350 return -1;
351 }
352 else if (a.layer > b.layer) {
353 return 1;
354 };
355 return 0;
356 });
357
358 var menuList = [];
359
360 // Show tree views
361 for (var i = 0; i < treeLayers.length; i++) {
362 var span = treeLayers[i];
363
364 // Add foundry/layer to menu list
365 menuList.push([
366 span.foundry + '/' + span.layer,
367 span.foundry,
368 span.layer,
369 span.type
370 ]);
371 };
372
373 // Create tree menu
Akroneaba63e2018-01-26 19:49:30 +0100374 this._menuList = menuList;
375 return menuList;
Akron8b592d42018-01-26 18:33:06 +0100376 },
377
Nils Diewald7c8ced22015-04-15 19:21:00 +0000378
Nils Diewalda297f062015-04-02 00:23:46 +0000379 /**
380 * Get match element.
381 */
382 element : function () {
Nils Diewald7c8ced22015-04-15 19:21:00 +0000383 return this._element; // May be null
Nils Diewalda297f062015-04-02 00:23:46 +0000384 }
385 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000386});