blob: 969de7797e3b58a69d0ff7afe28916352ad138eb [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 = [];
36 this._info = [];
37 this._foundry = {};
38 this._layer = {};
39
40 // Parse the snippet
41 this._parse(html.childNodes);
Akronb6685bb2018-02-04 00:44:47 +010042
Nils Diewald0e6992a2015-04-14 20:13:52 +000043 html.innerHTML = '';
44 return this;
45 },
Akronb6685bb2018-02-04 00:44:47 +010046
47 // TODO: Destroy match!
48 destroy : function () {
49 this._matchCreator = undefined;
50 },
Nils Diewald7148c6f2015-05-04 15:07:53 +000051
52 /**
53 * Length of the table (columns),
54 * aka the number of tokens
55 * in the snippet.
56 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000057 length : function () {
58 return this._pos;
59 },
60
Nils Diewald7148c6f2015-05-04 15:07:53 +000061 /**
62 * Get the token in the snippet
63 * At a given position.
64 *
65 * @param pos
66 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000067 getToken : function (pos) {
68 if (pos === undefined)
Akron916ec252016-11-10 17:06:32 +010069 return this._token;
Nils Diewald0e6992a2015-04-14 20:13:52 +000070 return this._token[pos];
71 },
Nils Diewald7148c6f2015-05-04 15:07:53 +000072
73 /**
74 * Get the annotation of a token
75 * in the snippet based on the position,
76 * the foundry, and the layer.
77 *
78 * @param pos
79 * @param foundry
80 * @param layer
81 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000082 getValue : function (pos, foundry, layer) {
83 return this._info[pos][foundry + '/' + layer]
84 },
Nils Diewald0e6992a2015-04-14 20:13:52 +000085
Akronaeceda72018-02-02 20:44:06 +010086
Nils Diewald0e6992a2015-04-14 20:13:52 +000087 // Parse the snippet
88 _parse : function (children) {
89
90 // Get all children
91 for (var i in children) {
Akron916ec252016-11-10 17:06:32 +010092 var c = children[i];
Nils Diewald0e6992a2015-04-14 20:13:52 +000093
Akron916ec252016-11-10 17:06:32 +010094 // Create object on position unless it exists
95 if (this._info[this._pos] === undefined) {
96 this._info[this._pos] = {};
97 };
Nils Diewald0e6992a2015-04-14 20:13:52 +000098
Akron916ec252016-11-10 17:06:32 +010099 // Store at position in foundry/layer as array
100 var found = this._info[this._pos];
Nils Diewald0e6992a2015-04-14 20:13:52 +0000101
Akron916ec252016-11-10 17:06:32 +0100102 // Element with title
103 if (c.nodeType === 1) {
104 if (c.getAttribute("title") &&
105 _TermRE.exec(c.getAttribute("title"))) {
Nils Diewald0e6992a2015-04-14 20:13:52 +0000106
Akron916ec252016-11-10 17:06:32 +0100107 // Fill position with info
108 var foundry, layer, value;
109 if (RegExp.$2) {
110 foundry = RegExp.$1;
111 layer = RegExp.$2;
112 }
113 else {
114 foundry = "base";
115 layer = RegExp.$1
116 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000117
Akron916ec252016-11-10 17:06:32 +0100118 value = RegExp.$3;
119
120 if (found[foundry + "/" + layer] === undefined) {
121 found[foundry + "/" + layer] = [value];
122 }
123 else {
Akron3b253d32018-07-15 10:16:06 +0200124 // if (found[foundry + "/" + layer].indexOf(value) === -1) {
125 if (!found[foundry + "/" + layer].includes(value)) {
Akron916ec252016-11-10 17:06:32 +0100126 // Push value to foundry/layer at correct position
127 found[foundry + "/" + layer].push(value);
128 };
129 }
Nils Diewald0e6992a2015-04-14 20:13:52 +0000130
Akron916ec252016-11-10 17:06:32 +0100131 // Set foundry
132 if (this._foundry[foundry] === undefined)
133 this._foundry[foundry] = {};
134 this._foundry[foundry][layer] = 1;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000135
Akron916ec252016-11-10 17:06:32 +0100136 // Set layer
137 if (this._layer[layer] === undefined)
138 this._layer[layer] = {};
139 this._layer[layer][foundry] = 1;
140 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000141
Akron916ec252016-11-10 17:06:32 +0100142 // depth search
143 if (c.hasChildNodes())
144 this._parse(c.childNodes);
145 }
Nils Diewald0e6992a2015-04-14 20:13:52 +0000146
Akron916ec252016-11-10 17:06:32 +0100147 // Leaf node
148 // store string on position and go to next string
149 else if (c.nodeType === 3) {
150 if (c.nodeValue.match(/[a-z0-9]/i))
151 this._token[this._pos++] = c.nodeValue;
152 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000153 };
154
155 delete this._info[this._pos];
156 },
157
158
159 /**
160 * Get HTML table view of annotations.
161 */
162 element : function () {
163 if (this._element !== undefined)
Akron916ec252016-11-10 17:06:32 +0100164 return this._element;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000165
166 // First the legend table
Akronaeceda72018-02-02 20:44:06 +0100167 var wrap = d.createElement('div');
168
169 var table = wrap.addE('table');
170
171 this._element = wrap;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000172
173 // Single row in head
Akron0b489ad2018-02-02 16:49:32 +0100174 var tr = table.addE('thead').addE('tr');
Nils Diewald0e6992a2015-04-14 20:13:52 +0000175
Akronf2279c42017-12-21 13:48:46 +0100176 var ah = KorAP.annotationHelper || { "getDesc" : function () {}};
177
Nils Diewald0e6992a2015-04-14 20:13:52 +0000178 // Add cell to row
Akronf2279c42017-12-21 13:48:46 +0100179 var addCell = function (type, key, value) {
Akron0b489ad2018-02-02 16:49:32 +0100180 var c = this.addE(type);
181
Akronf2279c42017-12-21 13:48:46 +0100182 if (value === undefined)
Akron916ec252016-11-10 17:06:32 +0100183 return c;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000184
Akronf2279c42017-12-21 13:48:46 +0100185 if (key && value instanceof Array && value[1] !== undefined) {
Akron4e47d0b2017-07-03 17:58:37 +0200186
187 // There are multiple values to add
Akron856af1e2017-07-03 19:57:46 +0200188 c.classList.add('matchkeyvalues');
Akronf2279c42017-12-21 13:48:46 +0100189 for (var n = 0; n < value.length; n++) {
Akron5b1a6af2018-02-05 15:41:16 +0100190 var e = c.addE('div');
191 e.addT(value[n]);
Akronf2279c42017-12-21 13:48:46 +0100192
193 var anno = ah.getDesc(key, value[n]);
194
195 if (anno)
196 e.setAttribute("title", anno);
Akron856af1e2017-07-03 19:57:46 +0200197 };
Akron916ec252016-11-10 17:06:32 +0100198 }
Akronf2279c42017-12-21 13:48:46 +0100199
Akron916ec252016-11-10 17:06:32 +0100200 else {
Akronf2279c42017-12-21 13:48:46 +0100201
202 if (value instanceof Array)
203 value = value[0];
204
Akron0b489ad2018-02-02 16:49:32 +0100205 c.addT(value);
Akronf2279c42017-12-21 13:48:46 +0100206
207 // Add tooltip
208 var anno = ah.getDesc(key, value);
209 if (anno)
210 c.setAttribute("title", anno);
Akron916ec252016-11-10 17:06:32 +0100211 };
Akron80055992017-12-20 16:30:52 +0100212
213 return c;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000214 };
215
216 tr.addCell = addCell;
217
218 // Add header information
Akronf2279c42017-12-21 13:48:46 +0100219 tr.addCell('th', undefined, 'Foundry');
220 tr.addCell('th', undefined, 'Layer');
Nils Diewald0e6992a2015-04-14 20:13:52 +0000221
222 // Add tokens
223 for (var i in this._token) {
Akronf2279c42017-12-21 13:48:46 +0100224 tr.addCell('th', undefined, this.getToken(i));
Nils Diewald0e6992a2015-04-14 20:13:52 +0000225 };
Akron916ec252016-11-10 17:06:32 +0100226
Akron0b489ad2018-02-02 16:49:32 +0100227 var tbody = table.addE('tbody');
Nils Diewald0e6992a2015-04-14 20:13:52 +0000228
229 var foundryList = Object.keys(this._foundry).sort();
230
231 for (var f = 0; f < foundryList.length; f++) {
Akron99713ef2017-06-28 18:19:28 +0200232 var foundry = foundryList[f];
233 var layerList =
234 Object.keys(this._foundry[foundry]).sort();
Nils Diewald0e6992a2015-04-14 20:13:52 +0000235
Akron99713ef2017-06-28 18:19:28 +0200236 for (var l = 0; l < layerList.length; l++) {
237 var layer = layerList[l];
Akron0b489ad2018-02-02 16:49:32 +0100238 tr = tbody.addE('tr');
Akron99713ef2017-06-28 18:19:28 +0200239 tr.setAttribute('tabindex', 0);
240 tr.addCell = addCell;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000241
Akronf2279c42017-12-21 13:48:46 +0100242 tr.addCell('th', undefined, foundry);
243 tr.addCell('th', undefined, layer);
Nils Diewald0e6992a2015-04-14 20:13:52 +0000244
Akron80055992017-12-20 16:30:52 +0100245 var key = foundry + '/' + layer + '=';
Akron80055992017-12-20 16:30:52 +0100246
Akron99713ef2017-06-28 18:19:28 +0200247 for (var v = 0; v < this.length(); v++) {
Akron80055992017-12-20 16:30:52 +0100248
249 // Get the cell value
250 var value = this.getValue(v, foundry, layer);
251
252 // Add cell to row
253 var cell = tr.addCell(
Akron99713ef2017-06-28 18:19:28 +0200254 'td',
Akronf2279c42017-12-21 13:48:46 +0100255 key,
Akron80055992017-12-20 16:30:52 +0100256 value
Akron99713ef2017-06-28 18:19:28 +0200257 );
258 };
259 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000260 };
Akronb6685bb2018-02-04 00:44:47 +0100261
262 // Add query creator
263 this._matchCreator = matchQueryCreator.create(this._element);
264
Akronaeceda72018-02-02 20:44:06 +0100265 return this._element;
266 },
Nils Diewald0e6992a2015-04-14 20:13:52 +0000267 };
268});