blob: 4e7bd1a5dcfcb9a057d186f2f5b09e1bdd88c675 [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',
Akron13448c22018-07-10 13:05:46 +020015 'buttongroup',
Akron8b592d42018-01-26 18:33:06 +010016 'util'
Akron13448c22018-07-10 13:05:46 +020017], function (infoClass,matchTreeMenuClass,buttonGroupClass) { //, refClass) {
Nils Diewald4f6521a2015-03-20 21:30:13 +000018
Nils Diewald6e43ffd2015-03-25 18:55:39 +000019 // Localization values
Akron0b489ad2018-02-02 16:49:32 +010020 const loc = KorAP.Locale;
Akron24866cf2018-01-23 20:22:01 +010021 loc.SHOWINFO = loc.SHOWINFO || 'Show information';
Akrond5436a42018-02-09 11:09:16 +010022 loc.ADDTREE = loc.ADDTREE || 'Relations';
23 loc.SHOWANNO = loc.SHOWANNO || 'Tokens';
Akron24866cf2018-01-23 20:22:01 +010024 loc.CLOSE = loc.CLOSE || 'Close';
Akrond5436a42018-02-09 11:09:16 +010025 loc.SHOW_META = loc.SHOW_META || 'Metadata';
Nils Diewald0e6992a2015-04-14 20:13:52 +000026
Akron0a6768f2016-07-13 18:00:43 +020027 // 'corpusID', 'docID', 'textID'
Akron0b489ad2018-02-02 16:49:32 +010028 const _matchTerms = ['textSigle', 'matchID', 'available'];
29
30 const d = document;
Nils Diewalda297f062015-04-02 00:23:46 +000031
32 /**
33 * Match object
34 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000035 return {
Nils Diewalde8518f82015-03-18 22:41:49 +000036
37 /**
38 * Create a new annotation object.
39 * Expects an array of available foundry/layer=type terms.
40 * Supported types are 'spans', 'tokens' and 'rels'.
41 */
Nils Diewalda297f062015-04-02 00:23:46 +000042 create : function (match) {
Nils Diewald0e6992a2015-04-14 20:13:52 +000043 return Object.create(this)._init(match);
Nils Diewalde8518f82015-03-18 22:41:49 +000044 },
45
Nils Diewald7c8ced22015-04-15 19:21:00 +000046
Nils Diewald6e43ffd2015-03-25 18:55:39 +000047 /**
Nils Diewalda297f062015-04-02 00:23:46 +000048 * Initialize match.
Nils Diewald6e43ffd2015-03-25 18:55:39 +000049 */
Nils Diewalda297f062015-04-02 00:23:46 +000050 _init : function (match) {
51 this._element = null;
Nils Diewald6e43ffd2015-03-25 18:55:39 +000052
Nils Diewalda297f062015-04-02 00:23:46 +000053 // No match defined
54 if (arguments.length < 1 ||
Akron19d97fe2016-09-06 20:47:05 +020055 match === null ||
56 match === undefined) {
57 throw new Error('Missing parameters');
Nils Diewalda297f062015-04-02 00:23:46 +000058 }
Nils Diewald6e43ffd2015-03-25 18:55:39 +000059
Nils Diewalda297f062015-04-02 00:23:46 +000060 // Match defined as a node
61 else if (match instanceof Node) {
Akron19d97fe2016-09-06 20:47:05 +020062 this._element = match;
Nils Diewald6e43ffd2015-03-25 18:55:39 +000063
Akron19d97fe2016-09-06 20:47:05 +020064 // Circular reference !!
65 match["_match"] = this;
Nils Diewalda297f062015-04-02 00:23:46 +000066
Akron19d97fe2016-09-06 20:47:05 +020067 /*
68 this.corpusID = match.getAttribute('data-corpus-id'),
69 this.docID = match.getAttribute('data-doc-id'),
70 this.textID = match.getAttribute('data-text-id'),
71 */
72 if (match.hasAttribute('data-text-sigle')) {
73 this.textSigle = match.getAttribute('data-text-sigle')
74 }
75 else {
76 this.textSigle = match.getAttribute('data-corpus-id') +
77 '/' +
78 match.getAttribute('data-doc-id') +
79 '/' +
80 match.getAttribute('data-text-id');
81 };
Akron0a6768f2016-07-13 18:00:43 +020082
Akron19d97fe2016-09-06 20:47:05 +020083 this.matchID = match.getAttribute('data-match-id');
Nils Diewalda297f062015-04-02 00:23:46 +000084
Akron19d97fe2016-09-06 20:47:05 +020085 // List of available annotations
86 this.available = match.getAttribute('data-available-info').split(' ');
Nils Diewalda297f062015-04-02 00:23:46 +000087 }
88
89 // Match as an object
90 else {
91
Akron19d97fe2016-09-06 20:47:05 +020092 // Iterate over allowed match terms
93 for (var i in _matchTerms) {
94 var term = _matchTerms[i];
95 this[term] = match[term] !== undefined ? match[term] : undefined;
96 };
Nils Diewalda297f062015-04-02 00:23:46 +000097 };
Nils Diewald0e6992a2015-04-14 20:13:52 +000098
Nils Diewald7c8ced22015-04-15 19:21:00 +000099 this._avail = {
Akron19d97fe2016-09-06 20:47:05 +0200100 tokens : [],
101 spans : [],
102 rels : []
Nils Diewalde8518f82015-03-18 22:41:49 +0000103 };
Nils Diewalda297f062015-04-02 00:23:46 +0000104
105 // Iterate over info layers
106 for (var i = 0; i < this.available.length; i++) {
Akron19d97fe2016-09-06 20:47:05 +0200107 var term = this.available[i];
Nils Diewalda297f062015-04-02 00:23:46 +0000108
Akron19d97fe2016-09-06 20:47:05 +0200109 // Create info layer objects
110 try {
111 var layer = require('match/infolayer').create(term);
112 this._avail[layer.type].push(layer);
113 }
114 catch (e) {
115 continue;
116 };
Nils Diewalde8518f82015-03-18 22:41:49 +0000117 };
Akron3a4a08e2017-05-23 22:34:18 +0200118
Nils Diewalde8518f82015-03-18 22:41:49 +0000119 return this;
120 },
121
Nils Diewalde8518f82015-03-18 22:41:49 +0000122 /**
123 * Return a list of parseable tree annotations.
124 */
125 getSpans : function () {
Nils Diewald7c8ced22015-04-15 19:21:00 +0000126 return this._avail.spans;
Nils Diewalde8518f82015-03-18 22:41:49 +0000127 },
128
129
130 /**
131 * Return a list of parseable token annotations.
132 */
133 getTokens : function () {
Nils Diewald7c8ced22015-04-15 19:21:00 +0000134 return this._avail.tokens;
Nils Diewalde8518f82015-03-18 22:41:49 +0000135 },
136
137
138 /**
139 * Return a list of parseable relation annotations.
140 */
141 getRels : function () {
Nils Diewald7c8ced22015-04-15 19:21:00 +0000142 return this._avail.rels;
Nils Diewalde8518f82015-03-18 22:41:49 +0000143 },
144
Nils Diewald7c8ced22015-04-15 19:21:00 +0000145
Nils Diewalda297f062015-04-02 00:23:46 +0000146 /**
147 * Open match
148 */
149 open : function () {
150
151 // Add actions unless it's already activated
152 var element = this._element;
153
154 // There is an element to open
155 if (this._element === undefined || this._element === null)
Akron19d97fe2016-09-06 20:47:05 +0200156 return false;
Nils Diewalda297f062015-04-02 00:23:46 +0000157
158 // The element is already opened
159 if (element.classList.contains('active'))
Akron19d97fe2016-09-06 20:47:05 +0200160 return false;
Nils Diewalda297f062015-04-02 00:23:46 +0000161
162 // Add active class to element
163 element.classList.add('active');
164
Nils Diewald7c8ced22015-04-15 19:21:00 +0000165 // Already there
166 if (element.classList.contains('action'))
Akron19d97fe2016-09-06 20:47:05 +0200167 return true;
Nils Diewald7c8ced22015-04-15 19:21:00 +0000168
Nils Diewalda297f062015-04-02 00:23:46 +0000169 // Create action buttons
Akron0b489ad2018-02-02 16:49:32 +0100170 var ul = d.createElement('ul');
Nils Diewalda297f062015-04-02 00:23:46 +0000171 ul.classList.add('action', 'right');
Nils Diewalda297f062015-04-02 00:23:46 +0000172
Nils Diewald7c8ced22015-04-15 19:21:00 +0000173 element.appendChild(ul);
174 element.classList.add('action');
175
176 // Todo: Open in new frame
Nils Diewalda297f062015-04-02 00:23:46 +0000177
178 // Add close button
Akron0b489ad2018-02-02 16:49:32 +0100179 var close = d.createElement('li');
180 close.addE('span').addT(loc.CLOSE);
Nils Diewalda297f062015-04-02 00:23:46 +0000181 close.classList.add('close');
182 close.setAttribute('title', loc.CLOSE);
Nils Diewald0e6992a2015-04-14 20:13:52 +0000183
Nils Diewalda297f062015-04-02 00:23:46 +0000184 var that = this;
185
Akron24866cf2018-01-23 20:22:01 +0100186 // Add meta button
187 var refLine = element.querySelector("p.ref");
188
Akron0b489ad2018-02-02 16:49:32 +0100189 // No reference found
Akron151bc872018-02-02 14:04:15 +0100190 if (!refLine)
191 return;
Akron0ad7cd22018-02-08 18:03:06 +0100192
Akron13448c22018-07-10 13:05:46 +0200193 var btns = buttonGroupClass.create(['action', 'bottom']);
Akron8b592d42018-01-26 18:33:06 +0100194
Akron13448c22018-07-10 13:05:46 +0200195 // Add meta button
196 btns.add(
197 loc.SHOW_META, ['meta'], function (e) {
Akron151bc872018-02-02 14:04:15 +0100198 that.info().showMeta();
199 }
200 );
Akron8b592d42018-01-26 18:33:06 +0100201
Akron13448c22018-07-10 13:05:46 +0200202 // Add token annotation button
203 btns.add(
204 loc.SHOWANNO, ['info'], function (e) {
Akron151bc872018-02-02 14:04:15 +0100205 that.info().showTable();
206 }
207 );
Akron24866cf2018-01-23 20:22:01 +0100208
Akron13448c22018-07-10 13:05:46 +0200209 // Add tree view button
210 btns.add(
211 loc.ADDTREE, ['tree'], function (e) {
Akron151bc872018-02-02 14:04:15 +0100212 if (KorAP.TreeMenu === undefined) {
213 KorAP.TreeMenu = matchTreeMenuClass.create([]);
214 };
Akron8b592d42018-01-26 18:33:06 +0100215
Akron151bc872018-02-02 14:04:15 +0100216 var tm = KorAP.TreeMenu;
Akron8b592d42018-01-26 18:33:06 +0100217
Akron151bc872018-02-02 14:04:15 +0100218 // Reread list
219 tm.info(that.info());
220 tm.readItems(that.treeMenuList());
Akroneaba63e2018-01-26 19:49:30 +0100221
Akron151bc872018-02-02 14:04:15 +0100222 // Reposition and show menu
Akron151bc872018-02-02 14:04:15 +0100223 tm.show();
Akronc6967d72018-02-05 18:39:39 +0100224 tm.attachTo(this);
Akron151bc872018-02-02 14:04:15 +0100225 tm.focus();
226 }
227 );
Akron24866cf2018-01-23 20:22:01 +0100228
Akron13448c22018-07-10 13:05:46 +0200229
230 // Insert before reference line
231 refLine.insertBefore(
232 btns.element(),
233 refLine.firstChild
234 );
235
236
Nils Diewalda297f062015-04-02 00:23:46 +0000237 // Close match
238 close.addEventListener('click', function (e) {
Akron19d97fe2016-09-06 20:47:05 +0200239 e.halt();
240 that.close()
Nils Diewalda297f062015-04-02 00:23:46 +0000241 });
242
Nils Diewalda297f062015-04-02 00:23:46 +0000243 ul.appendChild(close);
Nils Diewalda297f062015-04-02 00:23:46 +0000244
245 return true;
246 },
247
Akron8c468a12016-11-13 23:57:41 +0100248
Akron6a535d42015-08-26 20:16:58 +0200249 // Todo: Test toggle
250 toggle : function () {
251 if (this._element.classList.contains('active'))
Akron19d97fe2016-09-06 20:47:05 +0200252 this.close();
Akron6a535d42015-08-26 20:16:58 +0200253 else
Akron19d97fe2016-09-06 20:47:05 +0200254 this.open();
Akron6a535d42015-08-26 20:16:58 +0200255 },
256
Nils Diewald7c8ced22015-04-15 19:21:00 +0000257
Nils Diewald8bc7e412015-03-19 22:08:27 +0000258 /**
Nils Diewalda297f062015-04-02 00:23:46 +0000259 * Close info view
260 */
261 close : function () {
262 this._element.classList.remove('active');
Akron151bc872018-02-02 14:04:15 +0100263 /*
264 if (this._info !== undefined) {
265 this._info.destroy();
266 };
267 */
Nils Diewalda297f062015-04-02 00:23:46 +0000268 },
269
270
Nils Diewalda297f062015-04-02 00:23:46 +0000271 /**
Akron151bc872018-02-02 14:04:15 +0100272 * Get and open associated match infos.
Nils Diewalda297f062015-04-02 00:23:46 +0000273 */
274 info : function () {
275
276 // Create match info
277 if (this._info === undefined)
Akron19d97fe2016-09-06 20:47:05 +0200278 this._info = infoClass.create(this);
Nils Diewalda297f062015-04-02 00:23:46 +0000279
280 // There is an element to append
281 if (this._element === undefined ||
Akron19d97fe2016-09-06 20:47:05 +0200282 this._element === null)
283 return this._info;
Nils Diewald7c8ced22015-04-15 19:21:00 +0000284
Nils Diewalda297f062015-04-02 00:23:46 +0000285 // Info is already activated
Nils Diewald5c5a7472015-04-02 22:13:38 +0000286 if (this._info._element !== undefined)
Akron19d97fe2016-09-06 20:47:05 +0200287 return this._info;
Nils Diewalda297f062015-04-02 00:23:46 +0000288
Akronbd342982018-01-25 18:01:46 +0100289 var refLine = this._element.querySelector("p.ref");
290 this._element.insertBefore(
291 this._info.element(),
292 refLine
293 );
294
Nils Diewalda297f062015-04-02 00:23:46 +0000295 return this._info;
296 },
297
Akron8b592d42018-01-26 18:33:06 +0100298
Akron151bc872018-02-02 14:04:15 +0100299 // Return tree menu list
Akroneaba63e2018-01-26 19:49:30 +0100300 treeMenuList : function () {
301
302 if (this._menuList)
303 return this._menuList;
Akron8b592d42018-01-26 18:33:06 +0100304
305 // Join spans and relations
306 var treeLayers = []
307 var spans = this.getSpans();
308 var rels = this.getRels();
309 var i;
310 for (i in spans) {
311 treeLayers.push(spans[i]);
312 };
313 for (i in rels) {
314 treeLayers.push(rels[i]);
315 };
316
317 // Get spans
318 treeLayers = treeLayers.sort(
319 function (a, b) {
320 if (a.foundry < b.foundry) {
321 return -1;
322 }
323 else if (a.foundry > b.foundry) {
324 return 1;
325 }
326 else if (a.layer < b.layer) {
327 return -1;
328 }
329 else if (a.layer > b.layer) {
330 return 1;
331 };
332 return 0;
333 });
334
335 var menuList = [];
336
337 // Show tree views
338 for (var i = 0; i < treeLayers.length; i++) {
339 var span = treeLayers[i];
340
341 // Add foundry/layer to menu list
342 menuList.push([
343 span.foundry + '/' + span.layer,
344 span.foundry,
345 span.layer,
346 span.type
347 ]);
348 };
349
350 // Create tree menu
Akroneaba63e2018-01-26 19:49:30 +0100351 this._menuList = menuList;
352 return menuList;
Akron8b592d42018-01-26 18:33:06 +0100353 },
354
Nils Diewald7c8ced22015-04-15 19:21:00 +0000355
Nils Diewalda297f062015-04-02 00:23:46 +0000356 /**
357 * Get match element.
358 */
359 element : function () {
Nils Diewald7c8ced22015-04-15 19:21:00 +0000360 return this._element; // May be null
Nils Diewalda297f062015-04-02 00:23:46 +0000361 }
362 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000363});