blob: 92d4e5a92bb1c5a98925c2ee5472b060ab86867d [file] [log] [blame]
Nils Diewald7148c6f2015-05-04 15:07:53 +00001/**
Akronb6685bb2018-02-04 00:44:47 +01002 * Table representation of token-based
Nils Diewald7148c6f2015-05-04 15:07:53 +00003 * annotations of a match.
4 */
Akronb6685bb2018-02-04 00:44:47 +01005define([
6 'match/querycreator',
7 "util"
8], function (matchQueryCreator) {
9 /*
10 * TODO:
11 * Create base object for all matchinfo classes!
12 * TODO:
13 * Rename to match/annotationtable
14 */
Akron0b489ad2018-02-02 16:49:32 +010015 const _TermRE = new RegExp("^(?:([^\/]+?)\/)?([^:]+?):(.+?)$");
16 const d = document;
17
Nils Diewald0e6992a2015-04-14 20:13:52 +000018 return {
Nils Diewald7148c6f2015-05-04 15:07:53 +000019
20 /**
21 * Create new table view for a match
22 * based on a snippet string.
23 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000024 create : function (snippet) {
25 return Object.create(this)._init(snippet);
26 },
Nils Diewald7148c6f2015-05-04 15:07:53 +000027
28 // Initialize table based on snippet
Nils Diewald0e6992a2015-04-14 20:13:52 +000029 _init : function (snippet) {
30 // Create html for traversal
Akron0b489ad2018-02-02 16:49:32 +010031 var html = d.createElement("div");
Nils Diewald0e6992a2015-04-14 20:13:52 +000032 html.innerHTML = snippet;
33
34 this._pos = 0;
35 this._token = [];
Akronad1e46a2018-09-19 15:55:40 +020036 this._mark = [];
37 this._markE = undefined;
Akron1a780fe2019-05-21 15:59:00 +020038 this._cutted = [];
Nils Diewald0e6992a2015-04-14 20:13:52 +000039 this._info = [];
40 this._foundry = {};
41 this._layer = {};
42
43 // Parse the snippet
Akronad1e46a2018-09-19 15:55:40 +020044 this._parse(html.childNodes, false);
Akronb6685bb2018-02-04 00:44:47 +010045
Nils Diewald0e6992a2015-04-14 20:13:52 +000046 html.innerHTML = '';
47 return this;
48 },
Akronb6685bb2018-02-04 00:44:47 +010049
50 // TODO: Destroy match!
51 destroy : function () {
52 this._matchCreator = undefined;
53 },
Nils Diewald7148c6f2015-05-04 15:07:53 +000054
55 /**
56 * Length of the table (columns),
57 * aka the number of tokens
58 * in the snippet.
59 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000060 length : function () {
61 return this._pos;
62 },
63
Akronad1e46a2018-09-19 15:55:40 +020064
65 /**
66 * Move the viewport to the match
67 */
68 toMark : function () {
69 if (this._markE === undefined)
70 return;
71 this._markE.scrollIntoView({
72 inline: "start",
73 block: "nearest"
74 });
75 },
76
Nils Diewald7148c6f2015-05-04 15:07:53 +000077 /**
78 * Get the token in the snippet
79 * At a given position.
80 *
81 * @param pos
82 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000083 getToken : function (pos) {
84 if (pos === undefined)
Akron916ec252016-11-10 17:06:32 +010085 return this._token;
Nils Diewald0e6992a2015-04-14 20:13:52 +000086 return this._token[pos];
87 },
Nils Diewald7148c6f2015-05-04 15:07:53 +000088
89 /**
90 * Get the annotation of a token
91 * in the snippet based on the position,
92 * the foundry, and the layer.
93 *
94 * @param pos
95 * @param foundry
96 * @param layer
97 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000098 getValue : function (pos, foundry, layer) {
99 return this._info[pos][foundry + '/' + layer]
100 },
Nils Diewald0e6992a2015-04-14 20:13:52 +0000101
Akronaeceda72018-02-02 20:44:06 +0100102
Nils Diewald0e6992a2015-04-14 20:13:52 +0000103 // Parse the snippet
Akronad1e46a2018-09-19 15:55:40 +0200104 _parse : function (children, mark) {
Nils Diewald0e6992a2015-04-14 20:13:52 +0000105
106 // Get all children
Akron678c26f2020-10-09 08:52:50 +0200107 children.forEach(function(c) {
Nils Diewald0e6992a2015-04-14 20:13:52 +0000108
Akron916ec252016-11-10 17:06:32 +0100109 // Create object on position unless it exists
110 if (this._info[this._pos] === undefined) {
111 this._info[this._pos] = {};
112 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000113
Akron916ec252016-11-10 17:06:32 +0100114 // Store at position in foundry/layer as array
115 var found = this._info[this._pos];
Nils Diewald0e6992a2015-04-14 20:13:52 +0000116
Akron916ec252016-11-10 17:06:32 +0100117 // Element with title
118 if (c.nodeType === 1) {
Akronad1e46a2018-09-19 15:55:40 +0200119 var newMark = mark;
120
121 if (c.tagName === 'MARK') {
122 newMark = true;
123 }
124
Akron083ec572019-05-16 18:30:40 +0200125 else if (c.hasAttribute("title") &&
Akron916ec252016-11-10 17:06:32 +0100126 _TermRE.exec(c.getAttribute("title"))) {
Nils Diewald0e6992a2015-04-14 20:13:52 +0000127
Akron916ec252016-11-10 17:06:32 +0100128 // Fill position with info
129 var foundry, layer, value;
130 if (RegExp.$2) {
131 foundry = RegExp.$1;
132 layer = RegExp.$2;
133 }
134 else {
135 foundry = "base";
136 layer = RegExp.$1
137 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000138
Akron916ec252016-11-10 17:06:32 +0100139 value = RegExp.$3;
140
141 if (found[foundry + "/" + layer] === undefined) {
142 found[foundry + "/" + layer] = [value];
143 }
144 else {
Akron3b253d32018-07-15 10:16:06 +0200145 // if (found[foundry + "/" + layer].indexOf(value) === -1) {
146 if (!found[foundry + "/" + layer].includes(value)) {
Akron916ec252016-11-10 17:06:32 +0100147 // Push value to foundry/layer at correct position
148 found[foundry + "/" + layer].push(value);
149 };
150 }
Nils Diewald0e6992a2015-04-14 20:13:52 +0000151
Akron916ec252016-11-10 17:06:32 +0100152 // Set foundry
153 if (this._foundry[foundry] === undefined)
154 this._foundry[foundry] = {};
155 this._foundry[foundry][layer] = 1;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000156
Akron916ec252016-11-10 17:06:32 +0100157 // Set layer
158 if (this._layer[layer] === undefined)
159 this._layer[layer] = {};
160 this._layer[layer][foundry] = 1;
Akron083ec572019-05-16 18:30:40 +0200161 }
162
163 // The current position marks a cut
164 else if (c.hasAttribute("class") && c.getAttribute("class") == "cutted") {
Akron1a780fe2019-05-21 15:59:00 +0200165 this._cutted.push(this._pos);
Akron083ec572019-05-16 18:30:40 +0200166 this._token[this._pos++] = "";
167 }
Nils Diewald0e6992a2015-04-14 20:13:52 +0000168
Akron916ec252016-11-10 17:06:32 +0100169 // depth search
170 if (c.hasChildNodes())
Akronad1e46a2018-09-19 15:55:40 +0200171 this._parse(c.childNodes, newMark);
Akron916ec252016-11-10 17:06:32 +0100172 }
Nils Diewald0e6992a2015-04-14 20:13:52 +0000173
Akron916ec252016-11-10 17:06:32 +0100174 // Leaf node
175 // store string on position and go to next string
176 else if (c.nodeType === 3) {
Akron158fce12019-12-17 14:43:29 +0100177 if (c.nodeValue.match(/[a-z0-9\u25ae]/iu)) {
Akronad1e46a2018-09-19 15:55:40 +0200178 this._mark[this._pos] = mark ? true : false;
Akron916ec252016-11-10 17:06:32 +0100179 this._token[this._pos++] = c.nodeValue;
Akronad1e46a2018-09-19 15:55:40 +0200180 };
Akron916ec252016-11-10 17:06:32 +0100181 };
Akron678c26f2020-10-09 08:52:50 +0200182 }, this);
Nils Diewald0e6992a2015-04-14 20:13:52 +0000183
184 delete this._info[this._pos];
185 },
186
187
188 /**
189 * Get HTML table view of annotations.
190 */
191 element : function () {
192 if (this._element !== undefined)
Akron916ec252016-11-10 17:06:32 +0100193 return this._element;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000194
195 // First the legend table
Akronaeceda72018-02-02 20:44:06 +0100196 var wrap = d.createElement('div');
197
198 var table = wrap.addE('table');
199
200 this._element = wrap;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000201
202 // Single row in head
Akron0b489ad2018-02-02 16:49:32 +0100203 var tr = table.addE('thead').addE('tr');
Nils Diewald0e6992a2015-04-14 20:13:52 +0000204
Akronf2279c42017-12-21 13:48:46 +0100205 var ah = KorAP.annotationHelper || { "getDesc" : function () {}};
206
Nils Diewald0e6992a2015-04-14 20:13:52 +0000207 // Add cell to row
Akronf2279c42017-12-21 13:48:46 +0100208 var addCell = function (type, key, value) {
Akron0b489ad2018-02-02 16:49:32 +0100209 var c = this.addE(type);
210
Akronf2279c42017-12-21 13:48:46 +0100211 if (value === undefined)
Akron916ec252016-11-10 17:06:32 +0100212 return c;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000213
Akronf2279c42017-12-21 13:48:46 +0100214 if (key && value instanceof Array && value[1] !== undefined) {
Akron4e47d0b2017-07-03 17:58:37 +0200215
216 // There are multiple values to add
Akron856af1e2017-07-03 19:57:46 +0200217 c.classList.add('matchkeyvalues');
Akronf2279c42017-12-21 13:48:46 +0100218
Akronb50964a2020-10-12 11:44:37 +0200219 let e, anno;
220 value.forEach(function(v) {
221 e = c.addE('div');
222 e.addT(v);
223
224 anno = ah.getDesc(key, v);
Akronf2279c42017-12-21 13:48:46 +0100225
226 if (anno)
227 e.setAttribute("title", anno);
Akronb50964a2020-10-12 11:44:37 +0200228 });
Akron916ec252016-11-10 17:06:32 +0100229 }
Akronf2279c42017-12-21 13:48:46 +0100230
Akron916ec252016-11-10 17:06:32 +0100231 else {
Akronf2279c42017-12-21 13:48:46 +0100232
233 if (value instanceof Array)
234 value = value[0];
235
Akron0b489ad2018-02-02 16:49:32 +0100236 c.addT(value);
Akronf2279c42017-12-21 13:48:46 +0100237
238 // Add tooltip
239 var anno = ah.getDesc(key, value);
240 if (anno)
241 c.setAttribute("title", anno);
Akron916ec252016-11-10 17:06:32 +0100242 };
Akron80055992017-12-20 16:30:52 +0100243
244 return c;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000245 };
246
247 tr.addCell = addCell;
248
249 // Add header information
Akronf2279c42017-12-21 13:48:46 +0100250 tr.addCell('th', undefined, 'Foundry');
251 tr.addCell('th', undefined, 'Layer');
Nils Diewald0e6992a2015-04-14 20:13:52 +0000252
253 // Add tokens
Akron678c26f2020-10-09 08:52:50 +0200254 Object.keys(this._token).forEach(function(i) {
Akron5dc31172019-05-15 18:43:48 +0200255 let surface = this.getToken(i);
256 var c = tr.addCell('th', undefined, surface);
Akronad1e46a2018-09-19 15:55:40 +0200257 if (this._mark[i]) {
258 c.classList.add('mark');
259 if (this._markE === undefined) {
260 this._markE = c;
261 };
Akron083ec572019-05-16 18:30:40 +0200262 }
Akron1a780fe2019-05-21 15:59:00 +0200263 else if (this._cutted[0] == i || this._cutted[1] == i) {
Akron083ec572019-05-16 18:30:40 +0200264 c.classList.add('cutted');
Akronad1e46a2018-09-19 15:55:40 +0200265 };
Akron5dc31172019-05-15 18:43:48 +0200266
267 // In case the title is very long - add a title attribute
268 if (surface.length > 20) {
269 c.setAttribute("title", surface)
270 }
Akron678c26f2020-10-09 08:52:50 +0200271 }, this);
Akron916ec252016-11-10 17:06:32 +0100272
Akron0b489ad2018-02-02 16:49:32 +0100273 var tbody = table.addE('tbody');
Nils Diewald0e6992a2015-04-14 20:13:52 +0000274
275 var foundryList = Object.keys(this._foundry).sort();
276
Akronb50964a2020-10-12 11:44:37 +0200277 let layerList, key, v, value, cell;
278
279 foundryList.forEach(function(foundry) {
280 let layerList =
Akron99713ef2017-06-28 18:19:28 +0200281 Object.keys(this._foundry[foundry]).sort();
Nils Diewald0e6992a2015-04-14 20:13:52 +0000282
Akronb50964a2020-10-12 11:44:37 +0200283 layerList.forEach(function(layer) {
284
Akron0b489ad2018-02-02 16:49:32 +0100285 tr = tbody.addE('tr');
Akron99713ef2017-06-28 18:19:28 +0200286 tr.setAttribute('tabindex', 0);
287 tr.addCell = addCell;
Akronf2279c42017-12-21 13:48:46 +0100288 tr.addCell('th', undefined, foundry);
289 tr.addCell('th', undefined, layer);
Nils Diewald0e6992a2015-04-14 20:13:52 +0000290
Akronb50964a2020-10-12 11:44:37 +0200291 key = foundry + '/' + layer + '=';
Akron80055992017-12-20 16:30:52 +0100292
Akronb50964a2020-10-12 11:44:37 +0200293 for (v = 0; v < this.length(); v++) {
Akron80055992017-12-20 16:30:52 +0100294
295 // Get the cell value
Akronb50964a2020-10-12 11:44:37 +0200296 value = this.getValue(v, foundry, layer);
Akron80055992017-12-20 16:30:52 +0100297
298 // Add cell to row
Akronb50964a2020-10-12 11:44:37 +0200299 cell = tr.addCell(
Akron99713ef2017-06-28 18:19:28 +0200300 'td',
Akronf2279c42017-12-21 13:48:46 +0100301 key,
Akron80055992017-12-20 16:30:52 +0100302 value
Akron99713ef2017-06-28 18:19:28 +0200303 );
Akronad1e46a2018-09-19 15:55:40 +0200304
305 if (this._mark[v]) {
306 cell.classList.add('mark');
307 };
Akron99713ef2017-06-28 18:19:28 +0200308 };
Akronb50964a2020-10-12 11:44:37 +0200309 }, this);
310 }, this);
Akronb6685bb2018-02-04 00:44:47 +0100311
312 // Add query creator
313 this._matchCreator = matchQueryCreator.create(this._element);
314
Akronaeceda72018-02-02 20:44:06 +0100315 return this._element;
316 },
Nils Diewald0e6992a2015-04-14 20:13:52 +0000317 };
318});