blob: f55dc6f8cd67158fb6aabed15e082149971b0973 [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 },
Nils Diewald0e6992a2015-04-14 20:13:52 +000071
72 // Parse the snippet
73 _parse : function (children) {
74
75 // Get all children
76 for (var i in children) {
Akron916ec252016-11-10 17:06:32 +010077 var c = children[i];
Nils Diewald0e6992a2015-04-14 20:13:52 +000078
Akron916ec252016-11-10 17:06:32 +010079 // Create object on position unless it exists
80 if (this._info[this._pos] === undefined) {
81 this._info[this._pos] = {};
82 };
Nils Diewald0e6992a2015-04-14 20:13:52 +000083
Akron916ec252016-11-10 17:06:32 +010084 // Store at position in foundry/layer as array
85 var found = this._info[this._pos];
Nils Diewald0e6992a2015-04-14 20:13:52 +000086
Akron916ec252016-11-10 17:06:32 +010087 // Element with title
88 if (c.nodeType === 1) {
89 if (c.getAttribute("title") &&
90 _TermRE.exec(c.getAttribute("title"))) {
Nils Diewald0e6992a2015-04-14 20:13:52 +000091
Akron916ec252016-11-10 17:06:32 +010092 // Fill position with info
93 var foundry, layer, value;
94 if (RegExp.$2) {
95 foundry = RegExp.$1;
96 layer = RegExp.$2;
97 }
98 else {
99 foundry = "base";
100 layer = RegExp.$1
101 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000102
Akron916ec252016-11-10 17:06:32 +0100103 value = RegExp.$3;
104
105 if (found[foundry + "/" + layer] === undefined) {
106 found[foundry + "/" + layer] = [value];
107 }
108 else {
109 if (found[foundry + "/" + layer].indexOf(value) === -1) {
110 // Push value to foundry/layer at correct position
111 found[foundry + "/" + layer].push(value);
112 };
113 }
Nils Diewald0e6992a2015-04-14 20:13:52 +0000114
Akron916ec252016-11-10 17:06:32 +0100115 // Set foundry
116 if (this._foundry[foundry] === undefined)
117 this._foundry[foundry] = {};
118 this._foundry[foundry][layer] = 1;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000119
Akron916ec252016-11-10 17:06:32 +0100120 // Set layer
121 if (this._layer[layer] === undefined)
122 this._layer[layer] = {};
123 this._layer[layer][foundry] = 1;
124 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000125
Akron916ec252016-11-10 17:06:32 +0100126 // depth search
127 if (c.hasChildNodes())
128 this._parse(c.childNodes);
129 }
Nils Diewald0e6992a2015-04-14 20:13:52 +0000130
Akron916ec252016-11-10 17:06:32 +0100131 // Leaf node
132 // store string on position and go to next string
133 else if (c.nodeType === 3) {
134 if (c.nodeValue.match(/[a-z0-9]/i))
135 this._token[this._pos++] = c.nodeValue;
136 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000137 };
138
139 delete this._info[this._pos];
140 },
141
142
143 /**
144 * Get HTML table view of annotations.
145 */
146 element : function () {
147 if (this._element !== undefined)
Akron916ec252016-11-10 17:06:32 +0100148 return this._element;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000149
150 // First the legend table
151 var d = document;
152 var table = d.createElement('table');
153
154 // Single row in head
155 var tr = table.appendChild(d.createElement('thead'))
Akron916ec252016-11-10 17:06:32 +0100156 .appendChild(d.createElement('tr'));
Nils Diewald0e6992a2015-04-14 20:13:52 +0000157
158 // Add cell to row
159 var addCell = function (type, name) {
Akron916ec252016-11-10 17:06:32 +0100160 var c = this.appendChild(d.createElement(type))
161 if (name === undefined)
162 return c;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000163
Akron4e47d0b2017-07-03 17:58:37 +0200164 if (name instanceof Array && name[1] !== undefined) {
165
166 // There are multiple values to add
Akron856af1e2017-07-03 19:57:46 +0200167 c.classList.add('matchkeyvalues');
168 for (var n = 0; n < name.length; n++) {
169 var text = d.createTextNode(name[n]);
170 var e = c.appendChild(d.createElement('div'));
171 e.appendChild(text);
172 };
Akron4e47d0b2017-07-03 17:58:37 +0200173
174 // These are andgroups
Akron856af1e2017-07-03 19:57:46 +0200175 /*
Akron4e47d0b2017-07-03 17:58:37 +0200176 if (name.some(function (item) { return item.indexOf(':') == -1 ? false : true})) {
177 c.classList.add('matchkeyvalues');
178 for (var n = 0; n < name.length; n++) {
179 var text = d.createTextNode(name[n]);
180 var e = c.appendChild(d.createElement('div'));
181 e.appendChild(text);
182 };
183 }
184
185 // Add alternatives
186 else {
187 for (var n = 0; n < name.length; n++) {
188 c.appendChild(d.createTextNode(name[n]));
189 if (n !== name.length - 1) {
190 c.appendChild(d.createElement('br'));
191 };
Akron916ec252016-11-10 17:06:32 +0100192 };
193 };
Akron856af1e2017-07-03 19:57:46 +0200194 */
Akron916ec252016-11-10 17:06:32 +0100195 }
196 else {
197 c.appendChild(d.createTextNode(name));
198 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000199 };
200
201 tr.addCell = addCell;
202
203 // Add header information
204 tr.addCell('th', 'Foundry');
205 tr.addCell('th', 'Layer');
206
207 // Add tokens
208 for (var i in this._token) {
Akron916ec252016-11-10 17:06:32 +0100209 tr.addCell('th', this.getToken(i));
Nils Diewald0e6992a2015-04-14 20:13:52 +0000210 };
Akron916ec252016-11-10 17:06:32 +0100211
Nils Diewald0e6992a2015-04-14 20:13:52 +0000212 var tbody = table.appendChild(
Akron916ec252016-11-10 17:06:32 +0100213 d.createElement('tbody')
Nils Diewald0e6992a2015-04-14 20:13:52 +0000214 );
215
216 var foundryList = Object.keys(this._foundry).sort();
217
218 for (var f = 0; f < foundryList.length; f++) {
Akron99713ef2017-06-28 18:19:28 +0200219 var foundry = foundryList[f];
220 var layerList =
221 Object.keys(this._foundry[foundry]).sort();
Nils Diewald0e6992a2015-04-14 20:13:52 +0000222
Akron99713ef2017-06-28 18:19:28 +0200223 for (var l = 0; l < layerList.length; l++) {
224 var layer = layerList[l];
225 tr = tbody.appendChild(
226 d.createElement('tr')
227 );
228 tr.setAttribute('tabindex', 0);
229 tr.addCell = addCell;
Nils Diewald0e6992a2015-04-14 20:13:52 +0000230
Akron99713ef2017-06-28 18:19:28 +0200231 tr.addCell('th', foundry);
232 tr.addCell('th', layer);
Nils Diewald0e6992a2015-04-14 20:13:52 +0000233
Akron99713ef2017-06-28 18:19:28 +0200234 for (var v = 0; v < this.length(); v++) {
235 tr.addCell(
236 'td',
237 this.getValue(v, foundry, layer)
238 );
239 };
240 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000241 };
242
243 return this._element = table;
244 }
245 };
246});