0
|
1 /*
|
|
2 * TableWidget.js
|
|
3 *
|
|
4 * Copyright (c) 2012, Stefan Jänicke. All rights reserved.
|
|
5 *
|
|
6 * This library is free software; you can redistribute it and/or
|
|
7 * modify it under the terms of the GNU Lesser General Public
|
|
8 * License as published by the Free Software Foundation; either
|
|
9 * version 3 of the License, or (at your option) any later version.
|
|
10 *
|
|
11 * This library is distributed in the hope that it will be useful,
|
|
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
14 * Lesser General Public License for more details.
|
|
15 *
|
|
16 * You should have received a copy of the GNU Lesser General Public
|
|
17 * License along with this library; if not, write to the Free Software
|
|
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
19 * MA 02110-1301 USA
|
|
20 */
|
|
21
|
|
22 /**
|
|
23 * @class TableWidget
|
|
24 * TableWidget Implementation
|
|
25 * @author Stefan Jänicke (stjaenicke@informatik.uni-leipzig.de)
|
|
26 * @release 1.0
|
|
27 * @release date: 2012-07-27
|
|
28 * @version date: 2012-07-27
|
|
29 *
|
|
30 * @param {TableWrapper} core wrapper for interaction to other widgets
|
|
31 * @param {HTML object} div parent div to append the table widget div
|
|
32 * @param {JSON} options user specified configuration that overwrites options in TableConfig.js
|
|
33 */
|
|
34 TableWidget = function(core, div, options) {
|
|
35
|
|
36 this.core = core;
|
|
37 this.core.setWidget(this);
|
|
38 this.tables = [];
|
|
39 this.tableTabs = [];
|
|
40 this.tableElements = [];
|
|
41 this.tableHash = [];
|
|
42
|
|
43 this.options = (new TableConfig(options)).options;
|
|
44 this.gui = new TableGui(this, div, this.options);
|
|
45 this.filterBar = new FilterBar(this);
|
|
46
|
|
47 }
|
|
48
|
|
49 TableWidget.prototype = {
|
|
50
|
|
51 initWidget : function(data) {
|
|
52 this.datasets = data;
|
|
53
|
|
54 $(this.gui.tabs).empty();
|
|
55 $(this.gui.input).empty();
|
|
56 this.activeTable = undefined;
|
|
57 this.tables = [];
|
|
58 this.tableTabs = [];
|
|
59 this.tableElements = [];
|
|
60 this.tableHash = [];
|
|
61 this.selection = new Selection();
|
|
62 this.filterBar.reset(false);
|
|
63
|
|
64 var tableWidget = this;
|
|
65 var addTab = function(name, index) {
|
|
66 var dataSet = GeoTemConfig.datasets[index];
|
|
67 var tableTab = document.createElement('div');
|
|
68 var tableTabTable = document.createElement('table');
|
|
69 $(tableTab).append(tableTabTable);
|
|
70 var tableTabTableRow = document.createElement('tr');
|
|
71 $(tableTabTable).append(tableTabTableRow);
|
|
72 tableTab.setAttribute('class', 'tableTab');
|
|
73 var c = GeoTemConfig.getColor(index);
|
|
74 tableTab.style.backgroundColor = 'rgb(' + c.r0 + ',' + c.g0 + ',' + c.b0 + ')';
|
|
75 tableTab.onclick = function() {
|
|
76 tableWidget.selectTable(index);
|
|
77 }
|
|
78 var tableNameDiv = document.createElement('div');
|
|
79 $(tableNameDiv).append(name);
|
|
80
|
|
81 if (typeof dataSet.url !== "undefined"){
|
|
82 var tableLinkDiv = document.createElement('a');
|
|
83 tableLinkDiv.title = dataSet.url;
|
|
84 tableLinkDiv.href = dataSet.url;
|
|
85 tableLinkDiv.target = '_';
|
|
86 tableLinkDiv.setAttribute('class', 'externalLink');
|
|
87 $(tableNameDiv).append(tableLinkDiv);
|
|
88 }
|
|
89 $(tableTabTableRow).append($(document.createElement('td')).append(tableNameDiv));
|
|
90
|
|
91 var removeTabDiv = document.createElement('div');
|
|
92 removeTabDiv.setAttribute('class', 'smallButton removeDataset');
|
|
93 removeTabDiv.title = GeoTemConfig.getString('removeDatasetHelp');
|
|
94 removeTabDiv.onclick = $.proxy(function(e) {
|
|
95 GeoTemConfig.removeDataset(index);
|
|
96 //don't let the event propagate to the DIV above
|
|
97 e.stopPropagation();
|
|
98 //discard link click
|
|
99 return(false);
|
|
100 },{index:index});
|
|
101 $(tableTabTableRow).append($(document.createElement('td')).append(removeTabDiv));
|
|
102
|
|
103 if (GeoTemConfig.tableExportDataset){
|
|
104 var exportTabDiv = document.createElement('div');
|
|
105 exportTabDiv.setAttribute('class', 'smallButton exportDataset');
|
|
106 exportTabDiv.title = GeoTemConfig.getString('exportDatasetHelp');
|
|
107 var exportTabForm = document.createElement('form');
|
|
108 //TODO: make this configurable
|
|
109 exportTabForm.action = 'php/download.php';
|
|
110 exportTabForm.method = 'post';
|
|
111 var exportTabHiddenValue = document.createElement('input');
|
|
112 exportTabHiddenValue.name = 'file';
|
|
113 exportTabHiddenValue.type = 'hidden';
|
|
114 exportTabForm.appendChild(exportTabHiddenValue);
|
|
115 exportTabDiv.onclick = $.proxy(function(e) {
|
|
116 $(exportTabHiddenValue).val(GeoTemConfig.createKMLfromDataset(index));
|
|
117 $(exportTabForm).submit();
|
|
118 //don't let the event propagate to the DIV
|
|
119 e.stopPropagation();
|
|
120 //discard link click
|
|
121 return(false);
|
|
122 },{index:index});
|
|
123 exportTabDiv.appendChild(exportTabForm);
|
|
124 $(tableTabTableRow).append($(document.createElement('td')).append(exportTabDiv));
|
|
125 }
|
|
126
|
|
127 if (GeoTemConfig.allowUserShapeAndColorChange){
|
|
128 var dataset = GeoTemConfig.datasets[index];
|
|
129
|
|
130 var changeColorShapeSelect = $("<select></select>");
|
|
131 changeColorShapeSelect.attr("title", GeoTemConfig.getString("colorShapeDatasetHelp"));
|
|
132 changeColorShapeSelect.css("font-size","1.5em");
|
|
133
|
|
134 var currentOptgroup = $("<optgroup label='Current'></optgroup>");
|
|
135 var currentOption = $("<option value='current'></option>");
|
|
136 var color = GeoTemConfig.getColor(index);
|
|
137 currentOption.css("color","rgb("+color.r1+","+color.g1+","+color.b1+")");
|
|
138 currentOption.data("color",{r1:color.r1,g1:color.g1,b1:color.b1,r0:color.r0,g0:color.g0,b0:color.b0});
|
|
139 if (dataset.graphic.shape=="circle"){
|
|
140 currentOption.append("●");
|
|
141 } else if (dataset.graphic.shape=="triangel"){
|
|
142 currentOption.append("▲");
|
|
143 } else if (dataset.graphic.shape=="square"){
|
|
144 if (dataset.graphic.rotation===0){
|
|
145 currentOption.append("■");
|
|
146 } else {
|
|
147 currentOption.append("◆");
|
|
148 }
|
|
149 }
|
|
150 currentOptgroup.append(currentOption);
|
|
151 changeColorShapeSelect.append(currentOptgroup);
|
|
152
|
|
153 var defaultOptgroup = $("<optgroup label='Default'></optgroup>");
|
|
154 var defaultOption = $("<option value='default'></option>");
|
|
155 var color = GeoTemConfig.colors[index];
|
|
156 defaultOption.css("color","rgb("+color.r1+","+color.g1+","+color.b1+")");
|
|
157 defaultOption.data("color",{r1:color.r1,g1:color.g1,b1:color.b1,r0:color.r0,g0:color.g0,b0:color.b0});
|
|
158 defaultOption.append("●");
|
|
159 defaultOptgroup.append(defaultOption);
|
|
160 changeColorShapeSelect.append(defaultOptgroup);
|
|
161
|
|
162 var shapeOptgroup = $("<optgroup label='Shapes'></optgroup>");
|
|
163 shapeOptgroup.append("<option>○</option>");
|
|
164 shapeOptgroup.append("<option>□</option>");
|
|
165 shapeOptgroup.append("<option>◇</option>");
|
|
166 shapeOptgroup.append("<option>△</option>");
|
|
167 changeColorShapeSelect.append(shapeOptgroup);
|
|
168
|
|
169 var colorOptgroup = $("<optgroup label='Colors'></optgroup>");
|
|
170 var red = $("<option style='color:red'>■</option>");
|
|
171 red.data("color",{r1:255,g1:0,b1:0});
|
|
172 colorOptgroup.append(red);
|
|
173 var green = $("<option style='color:green'>■</option>");
|
|
174 green.data("color",{r1:0,g1:255,b1:0});
|
|
175 colorOptgroup.append(green);
|
|
176 var blue = $("<option style='color:blue'>■</option>");
|
|
177 blue.data("color",{r1:0,g1:0,b1:255});
|
|
178 colorOptgroup.append(blue);
|
|
179 var yellow = $("<option style='color:yellow'>■</option>");
|
|
180 yellow.data("color",{r1:255,g1:255,b1:0});
|
|
181 colorOptgroup.append(yellow);
|
|
182 changeColorShapeSelect.append(colorOptgroup);
|
|
183
|
|
184 changeColorShapeSelect.change($.proxy(function(e) {
|
|
185 var selected = changeColorShapeSelect.find("option:selected");
|
|
186
|
|
187 //credits: Pimp Trizkit @ http://stackoverflow.com/a/13542669
|
|
188 function shadeRGBColor(color, percent) {
|
|
189 var f=color.split(","),t=percent<0?0:255,p=percent<0?percent*-1:percent,R=parseInt(f[0].slice(4)),G=parseInt(f[1]),B=parseInt(f[2]);
|
|
190 return "rgb("+(Math.round((t-R)*p)+R)+","+(Math.round((t-G)*p)+G)+","+(Math.round((t-B)*p)+B)+")";
|
|
191 }
|
|
192
|
|
193 var color = selected.data("color");
|
|
194
|
|
195 if (typeof color !== "undefined"){
|
|
196 if ( (typeof color.r0 === "undefined") ||
|
|
197 (typeof color.g0 === "undefined") ||
|
|
198 (typeof color.b0 === "undefined") ){
|
|
199 var shadedrgb = shadeRGBColor("rgb("+color.r1+","+color.g1+","+color.b1+")",0.7);
|
|
200 shadedrgb = shadedrgb.replace("rgb(","").replace(")","");
|
|
201 shadedrgb = shadedrgb.split(",");
|
|
202
|
|
203 color.r0 = parseInt(shadedrgb[0]);
|
|
204 color.g0 = parseInt(shadedrgb[1]);
|
|
205 color.b0 = parseInt(shadedrgb[2]);
|
|
206 }
|
|
207 }
|
|
208
|
|
209 var shapeText = selected.text();
|
|
210 var graphic;
|
|
211 if ((shapeText=="■") || (shapeText=="□")){
|
|
212 graphic = {
|
|
213 shape: "square",
|
|
214 rotation: 0
|
|
215 };
|
|
216 } else if ((shapeText=="●") || (shapeText=="○")){
|
|
217 graphic = {
|
|
218 shape: "circle",
|
|
219 rotation: 0
|
|
220 };
|
|
221 } else if ((shapeText=="◆") || (shapeText=="◇")){
|
|
222 graphic = {
|
|
223 shape: "square",
|
|
224 rotation: 45
|
|
225 };
|
|
226 } else if ((shapeText=="▲") || (shapeText=="△")){
|
|
227 graphic = {
|
|
228 shape: "triangle",
|
|
229 rotation: 0
|
|
230 };
|
|
231 }
|
|
232
|
|
233 if (shapeOptgroup.has(selected).length>0){
|
|
234 //shape change
|
|
235 dataset.graphic = graphic;
|
|
236 } else if (colorOptgroup.has(selected).length>0){
|
|
237 //color changed
|
|
238 dataset.color = color;
|
|
239 } else {
|
|
240 //back to default
|
|
241 dataset.graphic = graphic;
|
|
242 dataset.color = color;
|
|
243 }
|
|
244
|
|
245 //reload data
|
|
246 Publisher.Publish('filterData', GeoTemConfig.datasets, null);
|
|
247
|
|
248 //don't let the event propagate to the DIV
|
|
249 e.stopPropagation();
|
|
250 //discard link click
|
|
251 return(false);
|
|
252 },{index:index}));
|
|
253 $(tableTabTableRow).append($(document.createElement('td')).append(changeColorShapeSelect));
|
|
254 }
|
|
255
|
|
256 return tableTab;
|
|
257 }
|
|
258 tableWidget.addTab = addTab;
|
|
259
|
|
260 for (var i in data ) {
|
|
261 this.tableHash.push([]);
|
|
262 var tableTab = addTab(data[i].label, i);
|
|
263 this.gui.tabs.appendChild(tableTab);
|
|
264 this.tableTabs.push(tableTab);
|
|
265 var elements = [];
|
|
266 for (var j in data[i].objects ) {
|
|
267 elements.push(new TableElement(data[i].objects[j]));
|
|
268 this.tableHash[i][data[i].objects[j].index] = elements[elements.length - 1];
|
|
269 }
|
|
270 var table = new Table(elements, this, i);
|
|
271 this.tables.push(table);
|
|
272 this.tableElements.push(elements);
|
|
273 }
|
|
274
|
|
275 if (data.length > 0) {
|
|
276 this.selectTable(0);
|
|
277 }
|
|
278
|
|
279 },
|
|
280
|
|
281 getHeight : function() {
|
|
282 if (this.options.tableHeight) {
|
|
283 return this.gui.tableContainer.offsetHeight - this.gui.tabs.offsetHeight;
|
|
284 }
|
|
285 return false;
|
|
286 },
|
|
287
|
|
288 selectTable : function(index) {
|
|
289 if (this.activeTable != index) {
|
|
290 if ( typeof this.activeTable != 'undefined') {
|
|
291 this.tables[this.activeTable].hide();
|
|
292 var c = GeoTemConfig.getColor(this.activeTable);
|
|
293 this.tableTabs[this.activeTable].style.backgroundColor = 'rgb(' + c.r0 + ',' + c.g0 + ',' + c.b0 + ')';
|
|
294 }
|
|
295 this.activeTable = index;
|
|
296 this.tables[this.activeTable].show();
|
|
297 var c = GeoTemConfig.getColor(this.activeTable);
|
|
298 this.tableTabs[this.activeTable].style.backgroundColor = 'rgb(' + c.r1 + ',' + c.g1 + ',' + c.b1 + ')';
|
|
299 this.core.triggerRise(index);
|
|
300 }
|
|
301
|
|
302 },
|
|
303
|
|
304 highlightChanged : function(objects) {
|
|
305 if( !GeoTemConfig.highlightEvents || (typeof this.tables[this.activeTable] === "undefined")){
|
|
306 return;
|
|
307 }
|
|
308 if( this.tables.length > 0 ){
|
|
309 return;
|
|
310 }
|
|
311 for (var i = 0; i < this.tableElements.length; i++) {
|
|
312 for (var j = 0; j < this.tableElements[i].length; j++) {
|
|
313 this.tableElements[i][j].highlighted = false;
|
|
314 }
|
|
315 }
|
|
316 for (var i = 0; i < objects.length; i++) {
|
|
317 for (var j = 0; j < objects[i].length; j++) {
|
|
318 this.tableHash[i][objects[i][j].index].highlighted = true;
|
|
319 }
|
|
320 }
|
|
321 this.tables[this.activeTable].update();
|
|
322 },
|
|
323
|
|
324 selectionChanged : function(selection) {
|
|
325 if( !GeoTemConfig.selectionEvents || (typeof this.tables[this.activeTable] === "undefined")){
|
|
326 return;
|
|
327 }
|
|
328 this.reset();
|
|
329 if( this.tables.length == 0 ){
|
|
330 return;
|
|
331 }
|
|
332 this.selection = selection;
|
|
333 for (var i = 0; i < this.tableElements.length; i++) {
|
|
334 for (var j = 0; j < this.tableElements[i].length; j++) {
|
|
335 this.tableElements[i][j].selected = false;
|
|
336 this.tableElements[i][j].highlighted = false;
|
|
337 }
|
|
338 }
|
|
339 var objects = selection.getObjects(this);
|
|
340 for (var i = 0; i < objects.length; i++) {
|
|
341 for (var j = 0; j < objects[i].length; j++) {
|
|
342 this.tableHash[i][objects[i][j].index].selected = true;
|
|
343 }
|
|
344 }
|
|
345 this.tables[this.activeTable].reset();
|
|
346 this.tables[this.activeTable].update();
|
|
347 },
|
|
348
|
|
349 triggerHighlight : function(item) {
|
|
350 var selectedObjects = [];
|
|
351 for (var i = 0; i < GeoTemConfig.datasets.length; i++) {
|
|
352 selectedObjects.push([]);
|
|
353 }
|
|
354 if ( typeof item != 'undefined') {
|
|
355 selectedObjects[this.activeTable].push(item);
|
|
356 }
|
|
357 this.core.triggerHighlight(selectedObjects);
|
|
358 },
|
|
359
|
|
360 tableSelection : function() {
|
|
361 var selectedObjects = [];
|
|
362 for (var i = 0; i < GeoTemConfig.datasets.length; i++) {
|
|
363 selectedObjects.push([]);
|
|
364 }
|
|
365 var valid = false;
|
|
366 for (var i = 0; i < this.tableElements.length; i++) {
|
|
367 for (var j = 0; j < this.tableElements[i].length; j++) {
|
|
368 var e = this.tableElements[i][j];
|
|
369 if (e.selected) {
|
|
370 selectedObjects[i].push(e.object);
|
|
371 valid = true;
|
|
372 }
|
|
373 }
|
|
374 }
|
|
375 this.selection = new Selection();
|
|
376 if (valid) {
|
|
377 this.selection = new Selection(selectedObjects, this);
|
|
378 }
|
|
379 this.core.triggerSelection(this.selection);
|
|
380 this.filterBar.reset(true);
|
|
381 },
|
|
382
|
|
383 deselection : function() {
|
|
384 this.reset();
|
|
385 this.selection = new Selection();
|
|
386 this.core.triggerSelection(this.selection);
|
|
387 },
|
|
388
|
|
389 filtering : function() {
|
|
390 for (var i = 0; i < this.datasets.length; i++) {
|
|
391 this.datasets[i].objects = this.selection.objects[i];
|
|
392 }
|
|
393 this.core.triggerRefining(this.datasets);
|
|
394 },
|
|
395
|
|
396 inverseFiltering : function() {
|
|
397 var selectedObjects = [];
|
|
398 for (var i = 0; i < GeoTemConfig.datasets.length; i++) {
|
|
399 selectedObjects.push([]);
|
|
400 }
|
|
401 var valid = false;
|
|
402 for (var i = 0; i < this.tableElements.length; i++) {
|
|
403 for (var j = 0; j < this.tableElements[i].length; j++) {
|
|
404 var e = this.tableElements[i][j];
|
|
405 if (!e.selected) {
|
|
406 selectedObjects[i].push(e.object);
|
|
407 valid = true;
|
|
408 }
|
|
409 }
|
|
410 }
|
|
411 this.selection = new Selection();
|
|
412 if (valid) {
|
|
413 this.selection = new Selection(selectedObjects, this);
|
|
414 }
|
|
415 this.filtering();
|
|
416 },
|
|
417
|
|
418 triggerRefining : function() {
|
|
419 this.core.triggerRefining(this.selection.objects);
|
|
420 },
|
|
421
|
|
422 reset : function() {
|
|
423 this.filterBar.reset(false);
|
|
424 if( this.tables.length > 0 ){
|
|
425 this.tables[this.activeTable].resetElements();
|
|
426 this.tables[this.activeTable].reset();
|
|
427 this.tables[this.activeTable].update();
|
|
428 }
|
|
429 }
|
|
430 }
|