blob: da56e2990a442f062cfdd48b2c6a391bbe336c8f [file] [log] [blame]
Nils Diewald7148c6f2015-05-04 15:07:53 +00001/**
2 * Table representation of morphological
3 * annotations of a match.
4 */
Nils Diewald0e6992a2015-04-14 20:13:52 +00005define(function () {
6 var _TermRE = new RegExp("^(?:([^\/]+?)\/)?([^:]+?):(.+?)$");
7
8 return {
Nils Diewald7148c6f2015-05-04 15:07:53 +00009
10 /**
11 * Create new table view for a match
12 * based on a snippet string.
13 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000014 create : function (snippet) {
15 return Object.create(this)._init(snippet);
16 },
Nils Diewald7148c6f2015-05-04 15:07:53 +000017
18 // Initialize table based on snippet
Nils Diewald0e6992a2015-04-14 20:13:52 +000019 _init : function (snippet) {
20 // Create html for traversal
21 var html = document.createElement("div");
22 html.innerHTML = snippet;
23
24 this._pos = 0;
25 this._token = [];
26 this._info = [];
27 this._foundry = {};
28 this._layer = {};
29
30 // Parse the snippet
31 this._parse(html.childNodes);
32
33 html.innerHTML = '';
34 return this;
35 },
36
Nils Diewald7148c6f2015-05-04 15:07:53 +000037
38 /**
39 * Length of the table (columns),
40 * aka the number of tokens
41 * in the snippet.
42 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000043 length : function () {
44 return this._pos;
45 },
46
Nils Diewald7148c6f2015-05-04 15:07:53 +000047 /**
48 * Get the token in the snippet
49 * At a given position.
50 *
51 * @param pos
52 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000053 getToken : function (pos) {
54 if (pos === undefined)
Akron916ec252016-11-10 17:06:32 +010055 return this._token;
Nils Diewald0e6992a2015-04-14 20:13:52 +000056 return this._token[pos];
57 },
Nils Diewald7148c6f2015-05-04 15:07:53 +000058
59 /**
60 * Get the annotation of a token
61 * in the snippet based on the position,
62 * the foundry, and the layer.
63 *
64 * @param pos
65 * @param foundry
66 * @param layer
67 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000068 getValue : function (pos, foundry, layer) {
69 return this._info[pos][foundry + '/' + layer]
70 },
71
Nils Diewald7148c6f2015-05-04 15:07:53 +000072 /*
73 getLayerPerFoundry : function (foundry) {
74 return this._foundry[foundry]
75 },
76 getFoundryPerLayer : function (layer) {
77 return this._layer[layer];
78 },
79 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000080
81 // Parse the snippet
82 _parse : function (children) {
83
84 // Get all children
85 for (var i in children) {
Akron916ec252016-11-10 17:06:32 +010086 var c = children[i];
Nils Diewald0e6992a2015-04-14 20:13:52 +000087
Akron916ec252016-11-10 17:06:32 +010088 // Create object on position unless it exists
89 if (this._info[this._pos] === undefined) {
90 this._info[this._pos] = {};
91 };
Nils Diewald0e6992a2015-04-14 20:13:52 +000092
Akron916ec252016-11-10 17:06:32 +010093 // Store at position in foundry/layer as array
94 var found = this._info[this._pos];
Nils Diewald0e6992a2015-04-14 20:13:52 +000095
Akron916ec252016-11-10 17:06:32 +010096 // Element with title
97 if (c.nodeType === 1) {
98 if (c.getAttribute("title") &&
99 _TermRE.exec(c.getAttribute("title"))) {
Nils Diewald0e6992a2015-04-14 20:13:52 +0000100
Akron916ec252016-11-10 17:06:32 +0100101 // Fill position with info
102 var foundry, layer, value;
103 if (RegExp.$2) {
104 foundry = RegExp.$1;
105 layer = RegExp.$2;
106 }
107 else {
108 foundry = "base";
109 layer = RegExp.$1
110 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000111
Akron916ec252016-11-10 17:06:32 +0100112 value = RegExp.$3;
113
114 if (found[foundry + "/" + layer] === undefined) {
115 found[foundry + "/" + layer] = [value];
116 }
117 else {
118 if (found[foundry + "/" + layer].indexOf(value) === -1) {
119 // Push value to foundry/layer at correct position
120 found[foundry + "/" + layer].push(value);
121 };
122 }
Nils Diewald0e6992a2015-04-14 20:13:52 +0000123
Akron916ec252016-11-10 17:06:32 +0100124 // Set foundry
125 if (this._foundry[foundry] === undefined)
126 this._foundry[foundry] = {};
127 this._foundry[foundry][layer] = 1;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000128
Akron916ec252016-11-10 17:06:32 +0100129 // Set layer
130 if (this._layer[layer] === undefined)
131 this._layer[layer] = {};
132 this._layer[layer][foundry] = 1;
133 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000134
Akron916ec252016-11-10 17:06:32 +0100135 // depth search
136 if (c.hasChildNodes())
137 this._parse(c.childNodes);
138 }
Nils Diewald0e6992a2015-04-14 20:13:52 +0000139
Akron916ec252016-11-10 17:06:32 +0100140 // Leaf node
141 // store string on position and go to next string
142 else if (c.nodeType === 3) {
143 if (c.nodeValue.match(/[a-z0-9]/i))
144 this._token[this._pos++] = c.nodeValue;
145 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000146 };
147
148 delete this._info[this._pos];
149 },
150
151
152 /**
153 * Get HTML table view of annotations.
154 */
155 element : function () {
156 if (this._element !== undefined)
Akron916ec252016-11-10 17:06:32 +0100157 return this._element;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000158
159 // First the legend table
160 var d = document;
161 var table = d.createElement('table');
162
163 // Single row in head
164 var tr = table.appendChild(d.createElement('thead'))
Akron916ec252016-11-10 17:06:32 +0100165 .appendChild(d.createElement('tr'));
Nils Diewald0e6992a2015-04-14 20:13:52 +0000166
167 // Add cell to row
168 var addCell = function (type, name) {
Akron916ec252016-11-10 17:06:32 +0100169 var c = this.appendChild(d.createElement(type))
170 if (name === undefined)
171 return c;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000172
Akron916ec252016-11-10 17:06:32 +0100173 if (name instanceof Array) {
174 for (var n = 0; n < name.length; n++) {
175 c.appendChild(d.createTextNode(name[n]));
176 if (n !== name.length - 1) {
177 c.appendChild(d.createElement('br'));
178 };
179 };
180 }
181 else {
182 c.appendChild(d.createTextNode(name));
183 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000184 };
185
186 tr.addCell = addCell;
187
188 // Add header information
189 tr.addCell('th', 'Foundry');
190 tr.addCell('th', 'Layer');
191
192 // Add tokens
193 for (var i in this._token) {
Akron916ec252016-11-10 17:06:32 +0100194 tr.addCell('th', this.getToken(i));
Nils Diewald0e6992a2015-04-14 20:13:52 +0000195 };
Akron916ec252016-11-10 17:06:32 +0100196
Nils Diewald0e6992a2015-04-14 20:13:52 +0000197 var tbody = table.appendChild(
Akron916ec252016-11-10 17:06:32 +0100198 d.createElement('tbody')
Nils Diewald0e6992a2015-04-14 20:13:52 +0000199 );
200
201 var foundryList = Object.keys(this._foundry).sort();
202
203 for (var f = 0; f < foundryList.length; f++) {
Akron99713ef2017-06-28 18:19:28 +0200204 var foundry = foundryList[f];
205 var layerList =
206 Object.keys(this._foundry[foundry]).sort();
Nils Diewald0e6992a2015-04-14 20:13:52 +0000207
Akron99713ef2017-06-28 18:19:28 +0200208 for (var l = 0; l < layerList.length; l++) {
209 var layer = layerList[l];
210 tr = tbody.appendChild(
211 d.createElement('tr')
212 );
213 tr.setAttribute('tabindex', 0);
214 tr.addCell = addCell;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000215
Akron99713ef2017-06-28 18:19:28 +0200216 tr.addCell('th', foundry);
217 tr.addCell('th', layer);
Nils Diewald0e6992a2015-04-14 20:13:52 +0000218
Akron99713ef2017-06-28 18:19:28 +0200219 for (var v = 0; v < this.length(); v++) {
220 tr.addCell(
221 'td',
222 this.getValue(v, foundry, layer)
223 );
224 };
225 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000226 };
227
228 return this._element = table;
229 }
230 };
231});