blob: 45f24f55418868761f3a2b4c19a02d0b1aebab91 [file] [log] [blame]
Nils Diewalde8518f82015-03-18 22:41:49 +00001/**
2 * Make annotations visible.
3 *
4 * @author Nils Diewald
5 */
6/*
7 - Scroll with a static left legend.
8 - Highlight (at least mark as bold) the match
9 - Scroll to match vertically per default
10 */
11var KorAP = KorAP || {};
12
13(function (KorAP) {
14 "use strict";
15
16 KorAP._AvailableRE = new RegExp("^([^\/]+?)\/([^=]+?)(?:=(spans|rels|tokens))?$");
17 KorAP._TermRE = new RegExp("^([^\/]+?)(?:\/([^:]+?))?:(.+?)$");
18 KorAP._matchTerms = ["corpusID", "docID", "textID"];
19
20 // API requests
21 KorAP.API = KorAP.API || {};
Nils Diewald8bc7e412015-03-19 22:08:27 +000022 // TODO: Make this async
Nils Diewalde8518f82015-03-18 22:41:49 +000023 KorAP.API.getMatchInfo = KorAP.API.getMatchInfo || function () { return {} };
24
25 KorAP.MatchInfo = {
26
27 /**
28 * Create a new annotation object.
29 * Expects an array of available foundry/layer=type terms.
30 * Supported types are 'spans', 'tokens' and 'rels'.
31 */
32 create : function (match, available) {
33 if (arguments.length < 2)
34 throw new Error("Missing parameters");
35
36 return Object.create(KorAP.MatchInfo)._init(match, available);
37 },
38
39 _init : function (match, available) {
40 this._match = KorAP.Match.create(match);
41 this._available = {
42 tokens : [],
43 spans : [],
44 rels : []
45 };
46 for (var i = 0; i < available.length; i++) {
47 var term = available[i];
48 // Create info layer objects
49 try {
50 var layer = KorAP.InfoLayer.create(term);
51 this._available[layer.type].push(layer);
52 }
53 catch (e) {
54 continue;
55 };
56 };
57 return this;
58 },
59
60
61 /**
62 * Return a list of parseable tree annotations.
63 */
64 getSpans : function () {
65 return this._available.spans;
66 },
67
68
69 /**
70 * Return a list of parseable token annotations.
71 */
72 getTokens : function () {
73 return this._available.tokens;
74 },
75
76
77 /**
78 * Return a list of parseable relation annotations.
79 */
80 getRels : function () {
81 return this._available.rels;
82 },
83
84
Nils Diewald8bc7e412015-03-19 22:08:27 +000085 /**
86 * Get table object.
87 */
Nils Diewalde8518f82015-03-18 22:41:49 +000088 getTable : function (tokens) {
89 var focus = [];
90
91 // Get all tokens
92 if (tokens === undefined) {
93 focus = this.getTokens();
94 }
95
96 // Get only some tokens
97 else {
98
99 // Push newly to focus array
100 for (var i = 0; i < tokens.length; i++) {
101 var term = tokens[i];
102 try {
103 // Create info layer objects
104 var layer = KorAP.InfoLayer.create(term);
105 layer.type = "tokens";
106 focus.push(layer);
107 }
108 catch (e) {
109 continue;
110 };
111 };
112 };
113
114 // No tokens chosen
115 if (focus.length == 0)
116 return;
117
118 // Get info (may be cached)
119 var matchResponse = KorAP.API.getMatchInfo(
120 this._match,
121 { 'spans' : true, 'layer' : focus }
122 );
123
124 // Get snippet from match info
125 if (matchResponse["snippet"] !== undefined) {
Nils Diewald8bc7e412015-03-19 22:08:27 +0000126 this._table = KorAP.MatchTable.create(matchResponse["snippet"]);
Nils Diewalde8518f82015-03-18 22:41:49 +0000127 return this._table;
128 };
129
130 return null;
131 }
132
133 /*
134 // Parse snippet for table visualization
135 getTree : function (foundry, layer) {
Nils Diewald8bc7e412015-03-19 22:08:27 +0000136 }
Nils Diewalde8518f82015-03-18 22:41:49 +0000137 */
138 };
139
140 KorAP.Match = {
141 create : function (match) {
142 return Object.create(KorAP.Match)._init(match);
143 },
144 _init : function (match) {
145 for (var i in KorAP._matchTerms) {
146 var term = KorAP._matchTerms[i];
147 if (match[term] !== undefined) {
148 this[term] = match[term];
149 }
150 else {
151 this[term] = undefined;
152 }
153 };
154 return this;
155 },
156 };
157
158 /**
159 *
160 * Alternatively pass a string as <tt>base/s=span</tt>
161 *
162 * @param foundry
163 */
164 KorAP.InfoLayer = {
165 create : function (foundry, layer, type) {
166 return Object.create(KorAP.InfoLayer)._init(foundry, layer, type);
167 },
168 _init : function (foundry, layer, type) {
169 if (foundry === undefined)
170 throw new Error("Missing parameters");
171
172 if (layer === undefined) {
173 if (KorAP._AvailableRE.exec(foundry)) {
174 this.foundry = RegExp.$1;
175 this.layer = RegExp.$2;
176 this.type = RegExp.$3;
177 }
178 else {
179 throw new Error("Missing parameters");
180 };
181 }
182 else {
183 this.foundry = foundry;
184 this.layer = layer;
185 this.type = type;
186 };
187
188 if (this.type === undefined)
189 this.type = 'tokens';
190
191 return this;
192 }
193 };
194
195
Nils Diewald8bc7e412015-03-19 22:08:27 +0000196 KorAP.MatchTable = {
Nils Diewalde8518f82015-03-18 22:41:49 +0000197 create : function (snippet) {
Nils Diewald8bc7e412015-03-19 22:08:27 +0000198 return Object.create(KorAP.MatchTable)._init(snippet);
Nils Diewalde8518f82015-03-18 22:41:49 +0000199 },
200 _init : function (snippet) {
201 // Create html for traversal
202 var html = document.createElement("div");
203 html.innerHTML = snippet;
204
205 this._pos = 0;
206 this._token = [];
207 this._info = [];
Nils Diewald8bc7e412015-03-19 22:08:27 +0000208 this._foundry = {};
209 this._layer = {};
Nils Diewalde8518f82015-03-18 22:41:49 +0000210
211 // Parse the snippet
212 this._parse(html.childNodes);
213
Nils Diewalde8518f82015-03-18 22:41:49 +0000214 html.innerHTML = '';
215 return this;
216 },
217
218 length : function () {
219 return this._pos;
220 },
221
222 getToken : function (pos) {
223 if (pos === undefined)
224 return this._token;
225 return this._token[pos];
226 },
227
228 getValue : function (pos, foundry, layer) {
229 return this._info[pos][foundry + '/' + layer]
230 },
231
232 getLayerPerFoundry : function (foundry) {
233 return this._foundry[foundry]
234 },
235
236 getFoundryPerLayer : function (layer) {
237 return this._layer[layer];
238 },
239
240 // Parse the snippet
241 _parse : function (children) {
242
243 // Get all children
244 for (var i in children) {
245 var c = children[i];
246
247 // Create object on position unless it exists
248 if (this._info[this._pos] === undefined)
249 this._info[this._pos] = {};
250
251 // Store at position in foundry/layer as array
252 var found = this._info[this._pos];
253
254 // Element with title
255 if (c.nodeType === 1) {
256 if (c.getAttribute("title") &&
257 KorAP._TermRE.exec(c.getAttribute("title"))) {
258
259 // Fill position with info
260 var foundry, layer, value;
261 if (RegExp.$2) {
262 foundry = RegExp.$1;
263 layer = RegExp.$2;
264 }
265 else {
266 foundry = "base";
267 layer = RegExp.$1
268 };
269
270 value = RegExp.$3;
271
272 if (found[foundry + "/" + layer] === undefined)
273 found[foundry + "/" + layer] = [];
274
275 // Push value to foundry/layer at correct position
276 found[foundry + "/" + layer].push(RegExp.$3);
277
278 // Set foundry
Nils Diewald8bc7e412015-03-19 22:08:27 +0000279 if (this._foundry[foundry] === undefined)
Nils Diewalde8518f82015-03-18 22:41:49 +0000280 this._foundry[foundry] = {};
281 this._foundry[foundry][layer] = 1;
282
283 // Set layer
Nils Diewald8bc7e412015-03-19 22:08:27 +0000284 if (this._layer[layer] === undefined)
Nils Diewalde8518f82015-03-18 22:41:49 +0000285 this._layer[layer] = {};
286 this._layer[layer][foundry] = 1;
287 };
288
289 // depth search
290 if (c.hasChildNodes())
291 this._parse(c.childNodes);
292 }
293
Nils Diewald8bc7e412015-03-19 22:08:27 +0000294 // Leaf node
295 // store string on position and go to next string
Nils Diewalde8518f82015-03-18 22:41:49 +0000296 else if (c.nodeType === 3) {
297 if (c.nodeValue.match(/[a-z0-9]/i))
298 this._token[this._pos++] = c.nodeValue;
299 };
300 };
301
302 delete this._info[this._pos];
303 },
304 element : function () {
Nils Diewalde8518f82015-03-18 22:41:49 +0000305 // First the legend table
Nils Diewald8bc7e412015-03-19 22:08:27 +0000306 var d = document;
307 var table = d.createElement('table');
308 var tr = table.appendChild(d.createElement('thead'))
309 .appendChild(
310 d.createElement('tr')
311 );
312
313 var addCell = function (type, name) {
314 var c = this.appendChild(d.createElement(type))
315 if (name === undefined)
316 return c;
317
318 if (name instanceof Array) {
319 for (var n = 0; n < name.length; n++) {
320 c.appendChild(d.createTextNode(name[n]));
321 if (n !== name.length - 1) {
322 c.appendChild(d.createElement('br'));
323 };
324 };
325 }
326 else {
327 c.appendChild(d.createTextNode(name));
328 };
329 };
330
331 tr.addCell = addCell;
332
333 // Add header information
334 tr.addCell('th', 'Foundry');
335 tr.addCell('th', 'Layer');
336
337 // Add tokens
338 for (var i in this._token) {
339 tr.addCell('th', this.getToken(i));
340 };
341
342 var tbody = table.appendChild(
343 d.createElement('tbody')
344 );
345
346 var foundryList = Object.keys(this._foundry).sort();
347
348 for (var f = 0; f < foundryList.length; f++) {
349 var foundry = foundryList[f];
350 var layerList =
351 Object.keys(this._foundry[foundry]).sort();
352
353 for (var l = 0; l < layerList.length; l++) {
354 var layer = layerList[l];
355 tr = tbody.appendChild(
356 d.createElement('tr')
357 );
358 tr.setAttribute('tabindex', 0);
359 tr.addCell = addCell;
360
361 tr.addCell('th', foundry);
362 tr.addCell('th', layer);
363
364 for (var v = 0; v < this.length(); v++) {
365 tr.addCell(
366 'td',
367 this.getValue(v, foundry, layer)
368 );
369 };
370 };
371 };
372
373 return table;
Nils Diewalde8518f82015-03-18 22:41:49 +0000374 }
375 };
376
377
378 /*
379 KorAP.InfoFoundryLayer = {};
380 KorAP.InfoTree = {};
Nils Diewald8bc7e412015-03-19 22:08:27 +0000381 KorAP.MatchTable = {};
Nils Diewalde8518f82015-03-18 22:41:49 +0000382 */
383}(this.KorAP));