blob: 4f8abccc95a73a8bd34547b3faf9cb2910bd9b5e [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 {
124 if (found[foundry + "/" + layer].indexOf(value) === -1) {
125 // Push value to foundry/layer at correct position
126 found[foundry + "/" + layer].push(value);
127 };
128 }
Nils Diewald0e6992a2015-04-14 20:13:52 +0000129
Akron916ec252016-11-10 17:06:32 +0100130 // Set foundry
131 if (this._foundry[foundry] === undefined)
132 this._foundry[foundry] = {};
133 this._foundry[foundry][layer] = 1;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000134
Akron916ec252016-11-10 17:06:32 +0100135 // Set layer
136 if (this._layer[layer] === undefined)
137 this._layer[layer] = {};
138 this._layer[layer][foundry] = 1;
139 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000140
Akron916ec252016-11-10 17:06:32 +0100141 // depth search
142 if (c.hasChildNodes())
143 this._parse(c.childNodes);
144 }
Nils Diewald0e6992a2015-04-14 20:13:52 +0000145
Akron916ec252016-11-10 17:06:32 +0100146 // Leaf node
147 // store string on position and go to next string
148 else if (c.nodeType === 3) {
149 if (c.nodeValue.match(/[a-z0-9]/i))
150 this._token[this._pos++] = c.nodeValue;
151 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000152 };
153
154 delete this._info[this._pos];
155 },
156
157
158 /**
159 * Get HTML table view of annotations.
160 */
161 element : function () {
162 if (this._element !== undefined)
Akron916ec252016-11-10 17:06:32 +0100163 return this._element;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000164
165 // First the legend table
Akronaeceda72018-02-02 20:44:06 +0100166 var wrap = d.createElement('div');
167
168 var table = wrap.addE('table');
169
170 this._element = wrap;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000171
172 // Single row in head
Akron0b489ad2018-02-02 16:49:32 +0100173 var tr = table.addE('thead').addE('tr');
Nils Diewald0e6992a2015-04-14 20:13:52 +0000174
Akronf2279c42017-12-21 13:48:46 +0100175 var ah = KorAP.annotationHelper || { "getDesc" : function () {}};
176
Nils Diewald0e6992a2015-04-14 20:13:52 +0000177 // Add cell to row
Akronf2279c42017-12-21 13:48:46 +0100178 var addCell = function (type, key, value) {
Akron0b489ad2018-02-02 16:49:32 +0100179 var c = this.addE(type);
180
Akronf2279c42017-12-21 13:48:46 +0100181 if (value === undefined)
Akron916ec252016-11-10 17:06:32 +0100182 return c;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000183
Akronf2279c42017-12-21 13:48:46 +0100184 if (key && value instanceof Array && value[1] !== undefined) {
Akron4e47d0b2017-07-03 17:58:37 +0200185
186 // There are multiple values to add
Akron856af1e2017-07-03 19:57:46 +0200187 c.classList.add('matchkeyvalues');
Akronf2279c42017-12-21 13:48:46 +0100188 for (var n = 0; n < value.length; n++) {
Akron5b1a6af2018-02-05 15:41:16 +0100189 var e = c.addE('div');
190 e.addT(value[n]);
Akronf2279c42017-12-21 13:48:46 +0100191
192 var anno = ah.getDesc(key, value[n]);
193
194 if (anno)
195 e.setAttribute("title", anno);
Akron856af1e2017-07-03 19:57:46 +0200196 };
Akron916ec252016-11-10 17:06:32 +0100197 }
Akronf2279c42017-12-21 13:48:46 +0100198
Akron916ec252016-11-10 17:06:32 +0100199 else {
Akronf2279c42017-12-21 13:48:46 +0100200
201 if (value instanceof Array)
202 value = value[0];
203
Akron0b489ad2018-02-02 16:49:32 +0100204 c.addT(value);
Akronf2279c42017-12-21 13:48:46 +0100205
206 // Add tooltip
207 var anno = ah.getDesc(key, value);
208 if (anno)
209 c.setAttribute("title", anno);
Akron916ec252016-11-10 17:06:32 +0100210 };
Akron80055992017-12-20 16:30:52 +0100211
212 return c;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000213 };
214
215 tr.addCell = addCell;
216
217 // Add header information
Akronf2279c42017-12-21 13:48:46 +0100218 tr.addCell('th', undefined, 'Foundry');
219 tr.addCell('th', undefined, 'Layer');
Nils Diewald0e6992a2015-04-14 20:13:52 +0000220
221 // Add tokens
222 for (var i in this._token) {
Akronf2279c42017-12-21 13:48:46 +0100223 tr.addCell('th', undefined, this.getToken(i));
Nils Diewald0e6992a2015-04-14 20:13:52 +0000224 };
Akron916ec252016-11-10 17:06:32 +0100225
Akron0b489ad2018-02-02 16:49:32 +0100226 var tbody = table.addE('tbody');
Nils Diewald0e6992a2015-04-14 20:13:52 +0000227
228 var foundryList = Object.keys(this._foundry).sort();
229
230 for (var f = 0; f < foundryList.length; f++) {
Akron99713ef2017-06-28 18:19:28 +0200231 var foundry = foundryList[f];
232 var layerList =
233 Object.keys(this._foundry[foundry]).sort();
Nils Diewald0e6992a2015-04-14 20:13:52 +0000234
Akron99713ef2017-06-28 18:19:28 +0200235 for (var l = 0; l < layerList.length; l++) {
236 var layer = layerList[l];
Akron0b489ad2018-02-02 16:49:32 +0100237 tr = tbody.addE('tr');
Akron99713ef2017-06-28 18:19:28 +0200238 tr.setAttribute('tabindex', 0);
239 tr.addCell = addCell;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000240
Akronf2279c42017-12-21 13:48:46 +0100241 tr.addCell('th', undefined, foundry);
242 tr.addCell('th', undefined, layer);
Nils Diewald0e6992a2015-04-14 20:13:52 +0000243
Akron80055992017-12-20 16:30:52 +0100244 var key = foundry + '/' + layer + '=';
Akron80055992017-12-20 16:30:52 +0100245
Akron99713ef2017-06-28 18:19:28 +0200246 for (var v = 0; v < this.length(); v++) {
Akron80055992017-12-20 16:30:52 +0100247
248 // Get the cell value
249 var value = this.getValue(v, foundry, layer);
250
251 // Add cell to row
252 var cell = tr.addCell(
Akron99713ef2017-06-28 18:19:28 +0200253 'td',
Akronf2279c42017-12-21 13:48:46 +0100254 key,
Akron80055992017-12-20 16:30:52 +0100255 value
Akron99713ef2017-06-28 18:19:28 +0200256 );
257 };
258 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000259 };
Akronb6685bb2018-02-04 00:44:47 +0100260
261 // Add query creator
262 this._matchCreator = matchQueryCreator.create(this._element);
263
Akronaeceda72018-02-02 20:44:06 +0100264 return this._element;
265 },
Nils Diewald0e6992a2015-04-14 20:13:52 +0000266 };
267});