blob: 1a167d2cdc32a8656f7b7d27a4708567a2a5c516 [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)
55 return this._token;
56 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) {
86 var c = children[i];
87
88 // Create object on position unless it exists
89 if (this._info[this._pos] === undefined)
90 this._info[this._pos] = {};
91
92 // Store at position in foundry/layer as array
93 var found = this._info[this._pos];
94
95 // Element with title
96 if (c.nodeType === 1) {
97 if (c.getAttribute("title") &&
98 _TermRE.exec(c.getAttribute("title"))) {
99
100 // Fill position with info
101 var foundry, layer, value;
102 if (RegExp.$2) {
103 foundry = RegExp.$1;
104 layer = RegExp.$2;
105 }
106 else {
107 foundry = "base";
108 layer = RegExp.$1
109 };
110
111 value = RegExp.$3;
112
113 if (found[foundry + "/" + layer] === undefined)
114 found[foundry + "/" + layer] = [];
115
116 // Push value to foundry/layer at correct position
117 found[foundry + "/" + layer].push(RegExp.$3);
118
119 // Set foundry
120 if (this._foundry[foundry] === undefined)
121 this._foundry[foundry] = {};
122 this._foundry[foundry][layer] = 1;
123
124 // Set layer
125 if (this._layer[layer] === undefined)
126 this._layer[layer] = {};
127 this._layer[layer][foundry] = 1;
128 };
129
130 // depth search
131 if (c.hasChildNodes())
132 this._parse(c.childNodes);
133 }
134
135 // Leaf node
136 // store string on position and go to next string
137 else if (c.nodeType === 3) {
138 if (c.nodeValue.match(/[a-z0-9]/i))
139 this._token[this._pos++] = c.nodeValue;
140 };
141 };
142
143 delete this._info[this._pos];
144 },
145
146
147 /**
148 * Get HTML table view of annotations.
149 */
150 element : function () {
151 if (this._element !== undefined)
152 return this._element;
153
154 // First the legend table
155 var d = document;
156 var table = d.createElement('table');
157
158 // Single row in head
159 var tr = table.appendChild(d.createElement('thead'))
160 .appendChild(d.createElement('tr'));
161
162 // Add cell to row
163 var addCell = function (type, name) {
164 var c = this.appendChild(d.createElement(type))
165 if (name === undefined)
166 return c;
167
168 if (name instanceof Array) {
169 for (var n = 0; n < name.length; n++) {
170 c.appendChild(d.createTextNode(name[n]));
171 if (n !== name.length - 1) {
172 c.appendChild(d.createElement('br'));
173 };
174 };
175 }
176 else {
177 c.appendChild(d.createTextNode(name));
178 };
179 };
180
181 tr.addCell = addCell;
182
183 // Add header information
184 tr.addCell('th', 'Foundry');
185 tr.addCell('th', 'Layer');
186
187 // Add tokens
188 for (var i in this._token) {
189 tr.addCell('th', this.getToken(i));
190 };
191
192 var tbody = table.appendChild(
193 d.createElement('tbody')
194 );
195
196 var foundryList = Object.keys(this._foundry).sort();
197
198 for (var f = 0; f < foundryList.length; f++) {
199 var foundry = foundryList[f];
200 var layerList =
201 Object.keys(this._foundry[foundry]).sort();
202
203 for (var l = 0; l < layerList.length; l++) {
204 var layer = layerList[l];
205 tr = tbody.appendChild(
206 d.createElement('tr')
207 );
208 tr.setAttribute('tabindex', 0);
209 tr.addCell = addCell;
210
211 tr.addCell('th', foundry);
212 tr.addCell('th', layer);
213
214 for (var v = 0; v < this.length(); v++) {
215 tr.addCell(
216 'td',
217 this.getValue(v, foundry, layer)
218 );
219 };
220 };
221 };
222
223 return this._element = table;
224 }
225 };
226});