blob: 67e20cd90f47945bce36f853be18f68b04c7995e [file] [log] [blame]
Nils Diewald7148c6f2015-05-04 15:07:53 +00001/**
2 * Table representation of morphological
3 * annotations of a match.
4 */
Akronaeceda72018-02-02 20:44:06 +01005// TODO: Create base object for all matchinfo classes!
Akron0b489ad2018-02-02 16:49:32 +01006define(["util"], function () {
7 const _TermRE = new RegExp("^(?:([^\/]+?)\/)?([^:]+?):(.+?)$");
8 const d = document;
9
Nils Diewald0e6992a2015-04-14 20:13:52 +000010 return {
Nils Diewald7148c6f2015-05-04 15:07:53 +000011
12 /**
13 * Create new table view for a match
14 * based on a snippet string.
15 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000016 create : function (snippet) {
17 return Object.create(this)._init(snippet);
18 },
Nils Diewald7148c6f2015-05-04 15:07:53 +000019
20 // Initialize table based on snippet
Nils Diewald0e6992a2015-04-14 20:13:52 +000021 _init : function (snippet) {
22 // Create html for traversal
Akron0b489ad2018-02-02 16:49:32 +010023 var html = d.createElement("div");
Nils Diewald0e6992a2015-04-14 20:13:52 +000024 html.innerHTML = snippet;
25
26 this._pos = 0;
27 this._token = [];
28 this._info = [];
29 this._foundry = {};
30 this._layer = {};
31
32 // Parse the snippet
33 this._parse(html.childNodes);
34
35 html.innerHTML = '';
36 return this;
37 },
38
Nils Diewald7148c6f2015-05-04 15:07:53 +000039
40 /**
41 * Length of the table (columns),
42 * aka the number of tokens
43 * in the snippet.
44 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000045 length : function () {
46 return this._pos;
47 },
48
Nils Diewald7148c6f2015-05-04 15:07:53 +000049 /**
50 * Get the token in the snippet
51 * At a given position.
52 *
53 * @param pos
54 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000055 getToken : function (pos) {
56 if (pos === undefined)
Akron916ec252016-11-10 17:06:32 +010057 return this._token;
Nils Diewald0e6992a2015-04-14 20:13:52 +000058 return this._token[pos];
59 },
Nils Diewald7148c6f2015-05-04 15:07:53 +000060
61 /**
62 * Get the annotation of a token
63 * in the snippet based on the position,
64 * the foundry, and the layer.
65 *
66 * @param pos
67 * @param foundry
68 * @param layer
69 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000070 getValue : function (pos, foundry, layer) {
71 return this._info[pos][foundry + '/' + layer]
72 },
Nils Diewald0e6992a2015-04-14 20:13:52 +000073
Akronaeceda72018-02-02 20:44:06 +010074
Nils Diewald0e6992a2015-04-14 20:13:52 +000075 // Parse the snippet
76 _parse : function (children) {
77
78 // Get all children
79 for (var i in children) {
Akron916ec252016-11-10 17:06:32 +010080 var c = children[i];
Nils Diewald0e6992a2015-04-14 20:13:52 +000081
Akron916ec252016-11-10 17:06:32 +010082 // Create object on position unless it exists
83 if (this._info[this._pos] === undefined) {
84 this._info[this._pos] = {};
85 };
Nils Diewald0e6992a2015-04-14 20:13:52 +000086
Akron916ec252016-11-10 17:06:32 +010087 // Store at position in foundry/layer as array
88 var found = this._info[this._pos];
Nils Diewald0e6992a2015-04-14 20:13:52 +000089
Akron916ec252016-11-10 17:06:32 +010090 // Element with title
91 if (c.nodeType === 1) {
92 if (c.getAttribute("title") &&
93 _TermRE.exec(c.getAttribute("title"))) {
Nils Diewald0e6992a2015-04-14 20:13:52 +000094
Akron916ec252016-11-10 17:06:32 +010095 // Fill position with info
96 var foundry, layer, value;
97 if (RegExp.$2) {
98 foundry = RegExp.$1;
99 layer = RegExp.$2;
100 }
101 else {
102 foundry = "base";
103 layer = RegExp.$1
104 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000105
Akron916ec252016-11-10 17:06:32 +0100106 value = RegExp.$3;
107
108 if (found[foundry + "/" + layer] === undefined) {
109 found[foundry + "/" + layer] = [value];
110 }
111 else {
112 if (found[foundry + "/" + layer].indexOf(value) === -1) {
113 // Push value to foundry/layer at correct position
114 found[foundry + "/" + layer].push(value);
115 };
116 }
Nils Diewald0e6992a2015-04-14 20:13:52 +0000117
Akron916ec252016-11-10 17:06:32 +0100118 // Set foundry
119 if (this._foundry[foundry] === undefined)
120 this._foundry[foundry] = {};
121 this._foundry[foundry][layer] = 1;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000122
Akron916ec252016-11-10 17:06:32 +0100123 // Set layer
124 if (this._layer[layer] === undefined)
125 this._layer[layer] = {};
126 this._layer[layer][foundry] = 1;
127 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000128
Akron916ec252016-11-10 17:06:32 +0100129 // depth search
130 if (c.hasChildNodes())
131 this._parse(c.childNodes);
132 }
Nils Diewald0e6992a2015-04-14 20:13:52 +0000133
Akron916ec252016-11-10 17:06:32 +0100134 // Leaf node
135 // store string on position and go to next string
136 else if (c.nodeType === 3) {
137 if (c.nodeValue.match(/[a-z0-9]/i))
138 this._token[this._pos++] = c.nodeValue;
139 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000140 };
141
142 delete this._info[this._pos];
143 },
144
145
146 /**
147 * Get HTML table view of annotations.
148 */
149 element : function () {
150 if (this._element !== undefined)
Akron916ec252016-11-10 17:06:32 +0100151 return this._element;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000152
153 // First the legend table
Akronaeceda72018-02-02 20:44:06 +0100154 var wrap = d.createElement('div');
155
156 var table = wrap.addE('table');
157
158 this._element = wrap;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000159
160 // Single row in head
Akron0b489ad2018-02-02 16:49:32 +0100161 var tr = table.addE('thead').addE('tr');
Nils Diewald0e6992a2015-04-14 20:13:52 +0000162
Akronf2279c42017-12-21 13:48:46 +0100163 var ah = KorAP.annotationHelper || { "getDesc" : function () {}};
164
Nils Diewald0e6992a2015-04-14 20:13:52 +0000165 // Add cell to row
Akronf2279c42017-12-21 13:48:46 +0100166 var addCell = function (type, key, value) {
Akron0b489ad2018-02-02 16:49:32 +0100167 var c = this.addE(type);
168
Akronf2279c42017-12-21 13:48:46 +0100169 if (value === undefined)
Akron916ec252016-11-10 17:06:32 +0100170 return c;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000171
Akronf2279c42017-12-21 13:48:46 +0100172 if (key && value instanceof Array && value[1] !== undefined) {
Akron4e47d0b2017-07-03 17:58:37 +0200173
174 // There are multiple values to add
Akron856af1e2017-07-03 19:57:46 +0200175 c.classList.add('matchkeyvalues');
Akronf2279c42017-12-21 13:48:46 +0100176 for (var n = 0; n < value.length; n++) {
Akron0b489ad2018-02-02 16:49:32 +0100177 var e = c.addE('div').addT(value[n]);
Akronf2279c42017-12-21 13:48:46 +0100178
179 var anno = ah.getDesc(key, value[n]);
180
181 if (anno)
182 e.setAttribute("title", anno);
Akron856af1e2017-07-03 19:57:46 +0200183 };
Akron916ec252016-11-10 17:06:32 +0100184 }
Akronf2279c42017-12-21 13:48:46 +0100185
Akron916ec252016-11-10 17:06:32 +0100186 else {
Akronf2279c42017-12-21 13:48:46 +0100187
188 if (value instanceof Array)
189 value = value[0];
190
Akron0b489ad2018-02-02 16:49:32 +0100191 c.addT(value);
Akronf2279c42017-12-21 13:48:46 +0100192
193 // Add tooltip
194 var anno = ah.getDesc(key, value);
195 if (anno)
196 c.setAttribute("title", anno);
Akron916ec252016-11-10 17:06:32 +0100197 };
Akron80055992017-12-20 16:30:52 +0100198
199 return c;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000200 };
201
202 tr.addCell = addCell;
203
204 // Add header information
Akronf2279c42017-12-21 13:48:46 +0100205 tr.addCell('th', undefined, 'Foundry');
206 tr.addCell('th', undefined, 'Layer');
Nils Diewald0e6992a2015-04-14 20:13:52 +0000207
208 // Add tokens
209 for (var i in this._token) {
Akronf2279c42017-12-21 13:48:46 +0100210 tr.addCell('th', undefined, this.getToken(i));
Nils Diewald0e6992a2015-04-14 20:13:52 +0000211 };
Akron916ec252016-11-10 17:06:32 +0100212
Akron0b489ad2018-02-02 16:49:32 +0100213 var tbody = table.addE('tbody');
Nils Diewald0e6992a2015-04-14 20:13:52 +0000214
215 var foundryList = Object.keys(this._foundry).sort();
216
217 for (var f = 0; f < foundryList.length; f++) {
Akron99713ef2017-06-28 18:19:28 +0200218 var foundry = foundryList[f];
219 var layerList =
220 Object.keys(this._foundry[foundry]).sort();
Nils Diewald0e6992a2015-04-14 20:13:52 +0000221
Akron99713ef2017-06-28 18:19:28 +0200222 for (var l = 0; l < layerList.length; l++) {
223 var layer = layerList[l];
Akron0b489ad2018-02-02 16:49:32 +0100224 tr = tbody.addE('tr');
Akron99713ef2017-06-28 18:19:28 +0200225 tr.setAttribute('tabindex', 0);
226 tr.addCell = addCell;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000227
Akronf2279c42017-12-21 13:48:46 +0100228 tr.addCell('th', undefined, foundry);
229 tr.addCell('th', undefined, layer);
Nils Diewald0e6992a2015-04-14 20:13:52 +0000230
Akron80055992017-12-20 16:30:52 +0100231 var key = foundry + '/' + layer + '=';
Akron80055992017-12-20 16:30:52 +0100232
Akron99713ef2017-06-28 18:19:28 +0200233 for (var v = 0; v < this.length(); v++) {
Akron80055992017-12-20 16:30:52 +0100234
235 // Get the cell value
236 var value = this.getValue(v, foundry, layer);
237
238 // Add cell to row
239 var cell = tr.addCell(
Akron99713ef2017-06-28 18:19:28 +0200240 'td',
Akronf2279c42017-12-21 13:48:46 +0100241 key,
Akron80055992017-12-20 16:30:52 +0100242 value
Akron99713ef2017-06-28 18:19:28 +0200243 );
244 };
245 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000246 };
247
Akronaeceda72018-02-02 20:44:06 +0100248 return this._element;
249 },
Nils Diewald0e6992a2015-04-14 20:13:52 +0000250 };
251});