Mercurial > hg > extraction-interface
comparison geotemco/js/GeoTemConfig.js @ 0:b12c99b7c3f0
commit for previous development
author | Zoe Hong <zhong@mpiwg-berlin.mpg.de> |
---|---|
date | Mon, 19 Jan 2015 17:13:49 +0100 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:b12c99b7c3f0 |
---|---|
1 /* | |
2 * GeoTemConfig.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 GeoTemConfig | |
24 * Global GeoTemCo Configuration File | |
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 | |
31 | |
32 // credits: user76888, The Digital Gabeg (http://stackoverflow.com/questions/1539367) | |
33 $.fn.cleanWhitespace = function() { | |
34 textNodes = this.contents().filter( function() { | |
35 return (this.nodeType == 3 && !/\S/.test(this.nodeValue)); | |
36 }).remove(); | |
37 return this; | |
38 }; | |
39 | |
40 GeoTemConfig = { | |
41 debug : false, //show debug output (esp. regarding corrupt datasets) | |
42 incompleteData : true, // show/hide data with either temporal or spatial metadata | |
43 inverseFilter : true, // if inverse filtering is offered | |
44 mouseWheelZoom : true, // enable/disable zoom with mouse wheel on map & timeplot | |
45 language : 'en', // default language of GeoTemCo | |
46 allowFilter : true, // if filtering should be allowed | |
47 highlightEvents : true, // if updates after highlight events | |
48 selectionEvents : true, // if updates after selection events | |
49 tableExportDataset : true, // export dataset to KML | |
50 allowCustomColoring : false, // if DataObjects can have an own color (useful for weighted coloring) | |
51 allowUserShapeAndColorChange: false, // if the user can change the shapes and color of datasets | |
52 // this turns MapConfig.useGraphics auto-on, but uses circles as default | |
53 loadColorFromDataset : false, // if DataObject color should be loaded automatically (from column "color") | |
54 allowColumnRenaming : true, | |
55 //proxy : 'php/proxy.php?address=', //set this if a HTTP proxy shall be used (e.g. to bypass X-Domain problems) | |
56 //colors for several datasets; rgb1 will be used for selected objects, rgb0 for unselected | |
57 colors : [{ | |
58 r1 : 255, | |
59 g1 : 101, | |
60 b1 : 0, | |
61 r0 : 253, | |
62 g0 : 229, | |
63 b0 : 205 | |
64 }, { | |
65 r1 : 144, | |
66 g1 : 26, | |
67 b1 : 255, | |
68 r0 : 230, | |
69 g0 : 225, | |
70 b0 : 255 | |
71 }, { | |
72 r1 : 0, | |
73 g1 : 217, | |
74 b1 : 0, | |
75 r0 : 213, | |
76 g0 : 255, | |
77 b0 : 213 | |
78 }, { | |
79 r1 : 240, | |
80 g1 : 220, | |
81 b1 : 0, | |
82 r0 : 247, | |
83 g0 : 244, | |
84 b0 : 197 | |
85 }] | |
86 | |
87 } | |
88 | |
89 GeoTemConfig.ie = false; | |
90 GeoTemConfig.ie8 = false; | |
91 | |
92 GeoTemConfig.independentMapId = 0; | |
93 GeoTemConfig.independentTimeId = 0; | |
94 | |
95 if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) { | |
96 GeoTemConfig.ie = true; | |
97 var ieversion = new Number(RegExp.$1); | |
98 if (ieversion == 8) { | |
99 GeoTemConfig.ie8 = true; | |
100 } | |
101 } | |
102 | |
103 GeoTemConfig.getIndependentId = function(target){ | |
104 if( target == 'map' ){ | |
105 return ++GeoTemConfig.independentMapId; | |
106 } | |
107 if( target == 'time' ){ | |
108 return ++GeoTemConfig.independentTimeId; | |
109 } | |
110 return 0; | |
111 }; | |
112 | |
113 GeoTemConfig.setHexColor = function(hex,index,fill){ | |
114 var result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex); | |
115 if( fill ){ | |
116 GeoTemConfig.colors[index].r0 = parseInt(result[1], 16); | |
117 GeoTemConfig.colors[index].g0 = parseInt(result[2], 16); | |
118 GeoTemConfig.colors[index].b0 = parseInt(result[3], 16); | |
119 } | |
120 else { | |
121 GeoTemConfig.colors[index].r1 = parseInt(result[1], 16); | |
122 GeoTemConfig.colors[index].g1 = parseInt(result[2], 16); | |
123 GeoTemConfig.colors[index].b1 = parseInt(result[3], 16); | |
124 } | |
125 } | |
126 | |
127 GeoTemConfig.setRgbColor = function(r,g,b,index,fill){ | |
128 if( fill ){ | |
129 GeoTemConfig.colors[index].r0 = r; | |
130 GeoTemConfig.colors[index].g0 = g; | |
131 GeoTemConfig.colors[index].b0 = b; | |
132 } | |
133 else { | |
134 GeoTemConfig.colors[index].r1 = r; | |
135 GeoTemConfig.colors[index].g1 = g; | |
136 GeoTemConfig.colors[index].b1 = b; | |
137 } | |
138 } | |
139 | |
140 GeoTemConfig.configure = function(urlPrefix) { | |
141 GeoTemConfig.urlPrefix = urlPrefix; | |
142 GeoTemConfig.path = GeoTemConfig.urlPrefix + "images/"; | |
143 } | |
144 | |
145 GeoTemConfig.applySettings = function(settings) { | |
146 $.extend(this, settings); | |
147 }; | |
148 | |
149 //Keeps track of how many colors where assigned yet. | |
150 GeoTemConfig.assignedColorCount = 0; | |
151 GeoTemConfig.getColor = function(id){ | |
152 if (typeof GeoTemConfig.datasets[id].color === "undefined"){ | |
153 var color; | |
154 | |
155 while (true){ | |
156 if( GeoTemConfig.colors.length <= GeoTemConfig.assignedColorCount ){ | |
157 color = { | |
158 r1 : Math.floor((Math.random()*255)+1), | |
159 g1 : Math.floor((Math.random()*255)+1), | |
160 b1 : Math.floor((Math.random()*255)+1), | |
161 r0 : 230, | |
162 g0 : 230, | |
163 b0 : 230 | |
164 }; | |
165 } else | |
166 color = GeoTemConfig.colors[GeoTemConfig.assignedColorCount]; | |
167 | |
168 //make sure that no other dataset has this color | |
169 //TODO: one could also check that they are not too much alike | |
170 var found = false; | |
171 for (var i = 0; i < GeoTemConfig.datasets.length; i++){ | |
172 var dataset = GeoTemConfig.datasets[i]; | |
173 | |
174 if (typeof dataset.color === "undefined") | |
175 continue; | |
176 | |
177 if ( (dataset.color.r1 == color.r1) && | |
178 (dataset.color.g1 == color.g1) && | |
179 (dataset.color.b1 == color.b1) ){ | |
180 found = true; | |
181 break; | |
182 } | |
183 } | |
184 if (found === true){ | |
185 if( GeoTemConfig.colors.length <= GeoTemConfig.assignedColorCount ){ | |
186 //next time skip over this color | |
187 GeoTemConfig.assignedColorCount++; | |
188 } | |
189 continue; | |
190 } else { | |
191 GeoTemConfig.colors.push(color); | |
192 break; | |
193 } | |
194 } | |
195 GeoTemConfig.datasets[id].color = color; | |
196 | |
197 GeoTemConfig.assignedColorCount++; | |
198 } | |
199 return GeoTemConfig.datasets[id].color; | |
200 }; | |
201 | |
202 GeoTemConfig.getAverageDatasetColor = function(id, objects){ | |
203 var c = new Object(); | |
204 var datasetColor = GeoTemConfig.getColor(id); | |
205 c.r0 = datasetColor.r0; | |
206 c.g0 = datasetColor.g0; | |
207 c.b0 = datasetColor.b0; | |
208 c.r1 = datasetColor.r1; | |
209 c.g1 = datasetColor.g1; | |
210 c.b1 = datasetColor.b1; | |
211 if (!GeoTemConfig.allowCustomColoring) | |
212 return c; | |
213 if (objects.length == 0) | |
214 return c; | |
215 var avgColor = new Object(); | |
216 avgColor.r0 = 0; | |
217 avgColor.g0 = 0; | |
218 avgColor.b0 = 0; | |
219 avgColor.r1 = 0; | |
220 avgColor.g1 = 0; | |
221 avgColor.b1 = 0; | |
222 | |
223 $(objects).each(function(){ | |
224 if (this.hasColorInformation){ | |
225 avgColor.r0 += this.color.r0; | |
226 avgColor.g0 += this.color.g0; | |
227 avgColor.b0 += this.color.b0; | |
228 avgColor.r1 += this.color.r1; | |
229 avgColor.g1 += this.color.g1; | |
230 avgColor.b1 += this.color.b1; | |
231 } else { | |
232 avgColor.r0 += datasetColor.r0; | |
233 avgColor.g0 += datasetColor.g0; | |
234 avgColor.b0 += datasetColor.b0; | |
235 avgColor.r1 += datasetColor.r1; | |
236 avgColor.g1 += datasetColor.g1; | |
237 avgColor.b1 += datasetColor.b1; | |
238 } | |
239 }); | |
240 | |
241 c.r0 = Math.floor(avgColor.r0/objects.length); | |
242 c.g0 = Math.floor(avgColor.g0/objects.length); | |
243 c.b0 = Math.floor(avgColor.b0/objects.length); | |
244 c.r1 = Math.floor(avgColor.r1/objects.length); | |
245 c.g1 = Math.floor(avgColor.g1/objects.length); | |
246 c.b1 = Math.floor(avgColor.b1/objects.length); | |
247 | |
248 return c; | |
249 }; | |
250 | |
251 GeoTemConfig.getString = function(field) { | |
252 if ( typeof Tooltips[GeoTemConfig.language] == 'undefined') { | |
253 GeoTemConfig.language = 'en'; | |
254 } | |
255 return Tooltips[GeoTemConfig.language][field]; | |
256 } | |
257 /** | |
258 * returns the actual mouse position | |
259 * @param {Event} e the mouseevent | |
260 * @return the top and left position on the screen | |
261 */ | |
262 GeoTemConfig.getMousePosition = function(e) { | |
263 if (!e) { | |
264 e = window.event; | |
265 } | |
266 var body = (window.document.compatMode && window.document.compatMode == "CSS1Compat") ? window.document.documentElement : window.document.body; | |
267 return { | |
268 top : e.pageY ? e.pageY : e.clientY, | |
269 left : e.pageX ? e.pageX : e.clientX | |
270 }; | |
271 } | |
272 /** | |
273 * returns the json object of the file from the given url | |
274 * @param {String} url the url of the file to load | |
275 * @return json object of given file | |
276 */ | |
277 GeoTemConfig.getJson = function(url) { | |
278 var data; | |
279 $.ajax({ | |
280 url : url, | |
281 async : false, | |
282 dataType : 'json', | |
283 success : function(json) { | |
284 data = json; | |
285 } | |
286 }); | |
287 return data; | |
288 } | |
289 | |
290 GeoTemConfig.mergeObjects = function(set1, set2) { | |
291 var inside = []; | |
292 var newSet = []; | |
293 for (var i = 0; i < GeoTemConfig.datasets.length; i++){ | |
294 inside.push([]); | |
295 newSet.push([]); | |
296 } | |
297 for (var i = 0; i < set1.length; i++) { | |
298 for (var j = 0; j < set1[i].length; j++) { | |
299 inside[i][set1[i][j].index] = true; | |
300 newSet[i].push(set1[i][j]); | |
301 } | |
302 } | |
303 for (var i = 0; i < set2.length; i++) { | |
304 for (var j = 0; j < set2[i].length; j++) { | |
305 if (!inside[i][set2[i][j].index]) { | |
306 newSet[i].push(set2[i][j]); | |
307 } | |
308 } | |
309 } | |
310 return newSet; | |
311 }; | |
312 | |
313 GeoTemConfig.datasets = []; | |
314 | |
315 GeoTemConfig.addDataset = function(newDataset){ | |
316 GeoTemConfig.datasets.push(newDataset); | |
317 Publisher.Publish('filterData', GeoTemConfig.datasets, null); | |
318 }; | |
319 | |
320 GeoTemConfig.addDatasets = function(newDatasets){ | |
321 $(newDatasets).each(function(){ | |
322 GeoTemConfig.datasets.push(this); | |
323 }); | |
324 Publisher.Publish('filterData', GeoTemConfig.datasets, null); | |
325 }; | |
326 | |
327 GeoTemConfig.removeDataset = function(index){ | |
328 GeoTemConfig.datasets.splice(index,1); | |
329 Publisher.Publish('filterData', GeoTemConfig.datasets, null); | |
330 }; | |
331 | |
332 /** | |
333 * converts the csv-file into json-format | |
334 * | |
335 * @param {String} | |
336 * text | |
337 */ | |
338 GeoTemConfig.convertCsv = function(text){ | |
339 /* convert here from CSV to JSON */ | |
340 var json = []; | |
341 /* define expected csv table headers (first line) */ | |
342 var expectedHeaders = new Array("Name","Address","Description","Longitude","Latitude","TimeStamp","TimeSpan:begin","TimeSpan:end","weight"); | |
343 /* convert csv string to array of arrays using ucsv library */ | |
344 var csvArray = CSV.csvToArray(text); | |
345 /* get real used table headers from csv file (first line) */ | |
346 var usedHeaders = csvArray[0]; | |
347 /* loop outer array, begin with second line */ | |
348 for (var i = 1; i < csvArray.length; i++) { | |
349 var innerArray = csvArray[i]; | |
350 var dataObject = new Object(); | |
351 var tableContent = new Object(); | |
352 /* exclude lines with no content */ | |
353 var hasContent = false; | |
354 for (var j = 0; j < innerArray.length; j++) { | |
355 if (typeof innerArray[j] !== "undefined"){ | |
356 if (typeof innerArray[j] === "string"){ | |
357 if (innerArray[j].length > 0) | |
358 hasContent = true; | |
359 } else { | |
360 hasContent = true; | |
361 } | |
362 } | |
363 | |
364 if (hasContent === true) | |
365 break; | |
366 } | |
367 if (hasContent === false) | |
368 continue; | |
369 /* loop inner array */ | |
370 for (var j = 0; j < innerArray.length; j++) { | |
371 /* Name */ | |
372 if (usedHeaders[j] == expectedHeaders[0]) { | |
373 dataObject["name"] = ""+innerArray[j]; | |
374 tableContent["name"] = ""+innerArray[j]; | |
375 } | |
376 /* Address */ | |
377 else if (usedHeaders[j] == expectedHeaders[1]) { | |
378 dataObject["place"] = ""+innerArray[j]; | |
379 tableContent["place"] = ""+innerArray[j]; | |
380 } | |
381 /* Description */ | |
382 else if (usedHeaders[j] == expectedHeaders[2]) { | |
383 dataObject["description"] = ""+innerArray[j]; | |
384 tableContent["description"] = ""+innerArray[j]; | |
385 } | |
386 /* TimeStamp */ | |
387 else if (usedHeaders[j] == expectedHeaders[5]) { | |
388 dataObject["time"] = ""+innerArray[j]; | |
389 } | |
390 /* TimeSpan:begin */ | |
391 else if (usedHeaders[j] == expectedHeaders[6]) { | |
392 tableContent["TimeSpan:begin"] = ""+innerArray[j]; | |
393 } | |
394 /* TimeSpan:end */ | |
395 else if (usedHeaders[j] == expectedHeaders[7]) { | |
396 tableContent["TimeSpan:end"] = ""+innerArray[j]; | |
397 } | |
398 /* weight */ | |
399 else if (usedHeaders[j] == expectedHeaders[8]) { | |
400 dataObject["weight"] = ""+innerArray[j]; | |
401 } | |
402 /* Longitude */ | |
403 else if (usedHeaders[j] == expectedHeaders[3]) { | |
404 dataObject["lon"] = parseFloat(innerArray[j]); | |
405 } | |
406 /* Latitude */ | |
407 else if (usedHeaders[j] == expectedHeaders[4]) { | |
408 dataObject["lat"] = parseFloat(innerArray[j]); | |
409 } | |
410 else { | |
411 var header = new String(usedHeaders[j]); | |
412 //remove leading and trailing Whitespace | |
413 header = $.trim(header); | |
414 tableContent[header] = ""+innerArray[j]; | |
415 } | |
416 } | |
417 | |
418 dataObject["tableContent"] = tableContent; | |
419 | |
420 json.push(dataObject); | |
421 } | |
422 | |
423 return json; | |
424 }; | |
425 | |
426 /** | |
427 * returns the xml dom object of the file from the given url | |
428 * @param {String} url the url of the file to load | |
429 * @return xml dom object of given file | |
430 */ | |
431 GeoTemConfig.getKml = function(url,asyncFunc) { | |
432 var data; | |
433 var async = false; | |
434 if( asyncFunc ){ | |
435 async = true; | |
436 } | |
437 $.ajax({ | |
438 url : url, | |
439 async : async, | |
440 dataType : 'xml', | |
441 success : function(xml) { | |
442 if( asyncFunc ){ | |
443 asyncFunc(xml); | |
444 } | |
445 else { | |
446 data = xml; | |
447 } | |
448 } | |
449 }); | |
450 if( !async ){ | |
451 return data; | |
452 } | |
453 } | |
454 | |
455 /** | |
456 * returns an array of all xml dom object of the kmls | |
457 * found in the zip file from the given url | |
458 * | |
459 * can only be used with asyncFunc (because of browser | |
460 * constraints regarding arraybuffer) | |
461 * | |
462 * @param {String} url the url of the file to load | |
463 * @return xml dom object of given file | |
464 */ | |
465 GeoTemConfig.getKmz = function(url,asyncFunc) { | |
466 var kmlDom = new Array(); | |
467 | |
468 var async = true; | |
469 if( !asyncFunc ){ | |
470 //if no asyncFunc is given return an empty array | |
471 return kmlDom; | |
472 } | |
473 | |
474 //use XMLHttpRequest as "arraybuffer" is not | |
475 //supported in jQuery native $.get | |
476 var req = new XMLHttpRequest(); | |
477 req.open("GET",url,async); | |
478 req.responseType = "arraybuffer"; | |
479 req.onload = function() { | |
480 var zip = new JSZip(); | |
481 zip.load(req.response, {base64:false}); | |
482 var kmlFiles = zip.file(new RegExp("kml$")); | |
483 | |
484 $(kmlFiles).each(function(){ | |
485 var kml = this; | |
486 if (kml.data != null) { | |
487 kmlDom.push($.parseXML(kml.data)); | |
488 } | |
489 }); | |
490 | |
491 asyncFunc(kmlDom); | |
492 }; | |
493 req.send(); | |
494 }; | |
495 | |
496 /** | |
497 * returns the JSON "object" | |
498 * from the csv file from the given url | |
499 * @param {String} url the url of the file to load | |
500 * @return xml dom object of given file | |
501 */ | |
502 GeoTemConfig.getCsv = function(url,asyncFunc) { | |
503 var async = false; | |
504 if( asyncFunc ){ | |
505 async = true; | |
506 } | |
507 | |
508 //use XMLHttpRequest as synchronous behaviour | |
509 //is not supported in jQuery native $.get | |
510 var req = new XMLHttpRequest(); | |
511 req.open("GET",url,async); | |
512 //can only be set on asynchronous now | |
513 //req.responseType = "text"; | |
514 var json; | |
515 req.onload = function() { | |
516 json = GeoTemConfig.convertCsv(req.response); | |
517 if( asyncFunc ) | |
518 asyncFunc(json); | |
519 }; | |
520 req.send(); | |
521 | |
522 if( !async ){ | |
523 return json; | |
524 } | |
525 }; | |
526 | |
527 /** | |
528 * returns a Date and a SimileAjax.DateTime granularity value for a given XML time | |
529 * @param {String} xmlTime the XML time as String | |
530 * @return JSON object with a Date and a SimileAjax.DateTime granularity | |
531 */ | |
532 GeoTemConfig.getTimeData = function(xmlTime) { | |
533 if (!xmlTime) | |
534 return; | |
535 var dateData; | |
536 try { | |
537 var bc = false; | |
538 if (xmlTime.startsWith("-")) { | |
539 bc = true; | |
540 xmlTime = xmlTime.substring(1); | |
541 } | |
542 var timeSplit = xmlTime.split("T"); | |
543 var timeData = timeSplit[0].split("-"); | |
544 for (var i = 0; i < timeData.length; i++) { | |
545 parseInt(timeData[i]); | |
546 } | |
547 if (bc) { | |
548 timeData[0] = "-" + timeData[0]; | |
549 } | |
550 if (timeSplit.length == 1) { | |
551 dateData = timeData; | |
552 } else { | |
553 var dayData; | |
554 if (timeSplit[1].indexOf("Z") != -1) { | |
555 dayData = timeSplit[1].substring(0, timeSplit[1].indexOf("Z") - 1).split(":"); | |
556 } else { | |
557 dayData = timeSplit[1].substring(0, timeSplit[1].indexOf("+") - 1).split(":"); | |
558 } | |
559 for (var i = 0; i < timeData.length; i++) { | |
560 parseInt(dayData[i]); | |
561 } | |
562 dateData = timeData.concat(dayData); | |
563 } | |
564 } catch (exception) { | |
565 return null; | |
566 } | |
567 var date, granularity; | |
568 if (dateData.length == 6) { | |
569 granularity = SimileAjax.DateTime.SECOND; | |
570 date = new Date(Date.UTC(dateData[0], dateData[1] - 1, dateData[2], dateData[3], dateData[4], dateData[5])); | |
571 } else if (dateData.length == 3) { | |
572 granularity = SimileAjax.DateTime.DAY; | |
573 date = new Date(Date.UTC(dateData[0], dateData[1] - 1, dateData[2])); | |
574 } else if (dateData.length == 2) { | |
575 granularity = SimileAjax.DateTime.MONTH; | |
576 date = new Date(Date.UTC(dateData[0], dateData[1] - 1, 1)); | |
577 } else if (dateData.length == 1) { | |
578 granularity = SimileAjax.DateTime.YEAR; | |
579 date = new Date(Date.UTC(dateData[0], 0, 1)); | |
580 } | |
581 if (timeData[0] && timeData[0] < 100) { | |
582 date.setFullYear(timeData[0]); | |
583 } | |
584 | |
585 //check data validity; | |
586 var isValidDate = true; | |
587 if ( date instanceof Date ) { | |
588 if ( isNaN( date.getTime() ) ) | |
589 isValidDate = false; | |
590 } else | |
591 isValidDate = false; | |
592 | |
593 if (!isValidDate){ | |
594 if ((GeoTemConfig.debug)&&(typeof console !== "undefined")) | |
595 console.error(xmlTime + " is no valid time format"); | |
596 return null; | |
597 } | |
598 | |
599 return { | |
600 date : date, | |
601 granularity : granularity | |
602 }; | |
603 } | |
604 /** | |
605 * converts a JSON array into an array of data objects | |
606 * @param {JSON} JSON a JSON array of data items | |
607 * @return an array of data objects | |
608 */ | |
609 GeoTemConfig.loadJson = function(JSON) { | |
610 var mapTimeObjects = []; | |
611 var runningIndex = 0; | |
612 for (var i in JSON ) { | |
613 try { | |
614 var item = JSON[i]; | |
615 var index = item.index || item.id || runningIndex++; | |
616 var name = item.name || ""; | |
617 var description = item.description || ""; | |
618 var tableContent = item.tableContent || []; | |
619 var locations = []; | |
620 if (item.location instanceof Array) { | |
621 for (var j = 0; j < item.location.length; j++) { | |
622 var place = item.location[j].place || "unknown"; | |
623 var lon = item.location[j].lon; | |
624 var lat = item.location[j].lat; | |
625 if ((typeof lon === "undefined" || typeof lat === "undefined" || isNaN(lon) || isNaN(lat) ) && !GeoTemConfig.incompleteData) { | |
626 throw "e"; | |
627 } | |
628 locations.push({ | |
629 longitude : lon, | |
630 latitude : lat, | |
631 place : place | |
632 }); | |
633 } | |
634 } else { | |
635 var place = item.place || "unknown"; | |
636 var lon = item.lon; | |
637 var lat = item.lat; | |
638 if ((typeof lon === "undefined" || typeof lat === "undefined" || isNaN(lon) || isNaN(lat) ) && !GeoTemConfig.incompleteData) { | |
639 throw "e"; | |
640 } | |
641 locations.push({ | |
642 longitude : lon, | |
643 latitude : lat, | |
644 place : place | |
645 }); | |
646 } | |
647 var dates = []; | |
648 if (item.time instanceof Array) { | |
649 for (var j = 0; j < item.time.length; j++) { | |
650 var time = GeoTemConfig.getTimeData(item.time[j]); | |
651 if (time == null && !GeoTemConfig.incompleteData) { | |
652 throw "e"; | |
653 } | |
654 dates.push(time); | |
655 } | |
656 } else { | |
657 var time = GeoTemConfig.getTimeData(item.time); | |
658 if (time == null && !GeoTemConfig.incompleteData) { | |
659 throw "e"; | |
660 } | |
661 if (time != null) { | |
662 dates.push(time); | |
663 } | |
664 } | |
665 var weight = parseInt(item.weight) || 1; | |
666 //add all "other" attributes to table data | |
667 //this is a hack to allow "invalid" JSONs | |
668 var specialAttributes = ["id", "name", "description", "lon", "lat", "place", "time", | |
669 "tableContent", "location", "time"]; | |
670 for (var attribute in item){ | |
671 if ($.inArray(attribute, specialAttributes) == -1){ | |
672 tableContent[attribute] = item[attribute]; | |
673 } | |
674 } | |
675 | |
676 var mapTimeObject = new DataObject(name, description, locations, dates, weight, tableContent); | |
677 mapTimeObject.setIndex(index); | |
678 mapTimeObjects.push(mapTimeObject); | |
679 } catch(e) { | |
680 continue; | |
681 } | |
682 } | |
683 | |
684 if (GeoTemConfig.loadColorFromDataset) | |
685 GeoTemConfig.loadDataObjectColoring(mapTimeObjects); | |
686 | |
687 return mapTimeObjects; | |
688 } | |
689 /** | |
690 * converts a KML dom into an array of data objects | |
691 * @param {XML dom} kml the XML dom for the KML file | |
692 * @return an array of data objects | |
693 */ | |
694 GeoTemConfig.loadKml = function(kml) { | |
695 var mapObjects = []; | |
696 var elements = kml.getElementsByTagName("Placemark"); | |
697 if (elements.length == 0) { | |
698 return []; | |
699 } | |
700 var index = 0; | |
701 var descriptionTableHeaders = []; | |
702 var xmlSerializer = new XMLSerializer(); | |
703 | |
704 for (var i = 0; i < elements.length; i++) { | |
705 var placemark = elements[i]; | |
706 var name, description, place, granularity, lon, lat, tableContent = [], time = [], location = []; | |
707 var weight = 1; | |
708 var timeData = false, mapData = false; | |
709 | |
710 try { | |
711 description = placemark.getElementsByTagName("description")[0].childNodes[0].nodeValue; | |
712 | |
713 //cleanWhitespace removes non-sense text-nodes (space, tab) | |
714 //and is an addition to jquery defined above | |
715 try { | |
716 var descriptionDocument = $($.parseXML(description)).cleanWhitespace(); | |
717 | |
718 //check whether the description element contains a table | |
719 //if yes, this data will be loaded as separate columns | |
720 $(descriptionDocument).find("table").each(function(){ | |
721 $(this).find("tr").each( | |
722 function() { | |
723 var isHeader = true; | |
724 var lastHeader = ""; | |
725 | |
726 $(this).find("td").each( | |
727 function() { | |
728 if (isHeader) { | |
729 lastHeader = $.trim($(this).text()); | |
730 isHeader = false; | |
731 } else { | |
732 var value = ""; | |
733 | |
734 //if this td contains HTML, serialize all | |
735 //it's children (the "content"!) | |
736 $(this).children().each( | |
737 function() { | |
738 value += xmlSerializer.serializeToString(this); | |
739 } | |
740 ); | |
741 | |
742 //no HTML content (or no content at all) | |
743 if (value.length == 0) | |
744 value = $(this).text(); | |
745 if (typeof value === "undefined") | |
746 value = ""; | |
747 | |
748 if ($.inArray(lastHeader, descriptionTableHeaders) === -1) | |
749 descriptionTableHeaders.push(lastHeader); | |
750 | |
751 if (tableContent[lastHeader] != null) | |
752 //append if a field occures more than once | |
753 tableContent[lastHeader] += "\n" + value; | |
754 else | |
755 tableContent[lastHeader] = value; | |
756 | |
757 isHeader = true; | |
758 } | |
759 } | |
760 ); | |
761 } | |
762 ); | |
763 }); | |
764 } catch(e) { | |
765 //couldn't be parsed, so it contains no html table | |
766 //or is not in valid XHTML syntax | |
767 } | |
768 | |
769 //check whether the description element contains content in the form of equations | |
770 //e.g. someDescriptor = someValue, where these eqations are separated by <br/> | |
771 //if yes, this data will be loaded as separate columns | |
772 var descriptionRows = description.replace(/<\s*br\s*[\/]*\s*>/g,"<br/>"); | |
773 $(descriptionRows.split("<br/>")).each(function(){ | |
774 var row = this; | |
775 | |
776 if (typeof row === "undefined") | |
777 return; | |
778 | |
779 var headerAndValue = row.split("="); | |
780 if (headerAndValue.length != 2) | |
781 return; | |
782 | |
783 var header = $.trim(headerAndValue[0]); | |
784 var value = $.trim(headerAndValue[1]); | |
785 | |
786 if ($.inArray(header, descriptionTableHeaders) === -1) | |
787 descriptionTableHeaders.push(header); | |
788 | |
789 if (tableContent[header] != null) | |
790 //append if a field occures more than once | |
791 tableContent[header] += "\n" + value; | |
792 else | |
793 tableContent[header] = value; | |
794 }); | |
795 | |
796 tableContent["description"] = description; | |
797 } catch(e) { | |
798 description = ""; | |
799 } | |
800 | |
801 try { | |
802 name = placemark.getElementsByTagName("name")[0].childNodes[0].nodeValue; | |
803 tableContent["name"] = name; | |
804 } catch(e) { | |
805 if (typeof tableContent["name"] !== "undefined") | |
806 name = tableContent["name"]; | |
807 else | |
808 name = ""; | |
809 } | |
810 | |
811 try { | |
812 place = placemark.getElementsByTagName("address")[0].childNodes[0].nodeValue; | |
813 tableContent["place"] = place; | |
814 } catch(e) { | |
815 if (typeof tableContent["place"] !== "undefined") | |
816 place = tableContent["place"]; | |
817 else | |
818 place = ""; | |
819 } | |
820 | |
821 try { | |
822 var coordinates = placemark.getElementsByTagName("Point")[0].getElementsByTagName("coordinates")[0].childNodes[0].nodeValue; | |
823 var lonlat = coordinates.split(","); | |
824 lon = lonlat[0]; | |
825 lat = lonlat[1]; | |
826 if (lon == "" || lat == "" || isNaN(lon) || isNaN(lat)) { | |
827 throw "e"; | |
828 } | |
829 location.push({ | |
830 longitude : lon, | |
831 latitude : lat, | |
832 place : place | |
833 }); | |
834 } catch(e) { | |
835 if (!GeoTemConfig.incompleteData) { | |
836 continue; | |
837 } | |
838 } | |
839 | |
840 try { | |
841 var tuple = GeoTemConfig.getTimeData(placemark.getElementsByTagName("TimeStamp")[0].getElementsByTagName("when")[0].childNodes[0].nodeValue); | |
842 if (tuple != null) { | |
843 time.push(tuple); | |
844 timeData = true; | |
845 } else if (!GeoTemConfig.incompleteData) { | |
846 continue; | |
847 } | |
848 } catch(e) { | |
849 try { | |
850 if ( (typeof tableContent["TimeSpan:begin"] === "undefined") && | |
851 (typeof tableContent["TimeSpan:end"] === "undefined") ){ | |
852 var timeStart = $(placemark).find("TimeSpan begin").text(); | |
853 var timeEnd = $(placemark).find("TimeSpan end").text(); | |
854 | |
855 if ( (timeStart != "") && (timeStart != "") ){ | |
856 tableContent["TimeSpan:begin"] = timeStart; | |
857 tableContent["TimeSpan:end"] = timeEnd; | |
858 | |
859 timeData = true; | |
860 } | |
861 } | |
862 } catch(e) { | |
863 if (!GeoTemConfig.incompleteData) { | |
864 continue; | |
865 } | |
866 } | |
867 } | |
868 var object = new DataObject(name, description, location, time, 1, tableContent); | |
869 object.setIndex(index); | |
870 index++; | |
871 mapObjects.push(object); | |
872 } | |
873 | |
874 //make sure that all "description table" columns exists in all rows | |
875 if (descriptionTableHeaders.length > 0){ | |
876 $(mapObjects).each(function(){ | |
877 var object = this; | |
878 $(descriptionTableHeaders).each(function(){ | |
879 if (typeof object.tableContent[this] === "undefined") | |
880 object.tableContent[this] = ""; | |
881 }); | |
882 }); | |
883 } | |
884 | |
885 if (GeoTemConfig.loadColorFromDataset) | |
886 GeoTemConfig.loadDataObjectColoring(mapObjects); | |
887 | |
888 return mapObjects; | |
889 }; | |
890 | |
891 GeoTemConfig.createKMLfromDataset = function(index){ | |
892 var kmlContent = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><kml xmlns=\"http://www.opengis.net/kml/2.2\"><Document>"; | |
893 | |
894 //credits: Anatoly Mironov, http://stackoverflow.com/questions/2573521/how-do-i-output-an-iso-8601-formatted-string-in-javascript | |
895 function pad(number) { | |
896 var r = String(number); | |
897 if ( r.length === 1 ) { | |
898 r = '0' + r; | |
899 } | |
900 return r; | |
901 } | |
902 | |
903 var dateToISOString = function(date, granularity) { | |
904 var ISOString = date.getFullYear(); | |
905 | |
906 if (granularity <= SimileAjax.DateTime.MONTH) | |
907 ISOString += '-' + pad( date.getMonth() + 1 ); | |
908 if (granularity <= SimileAjax.DateTime.DAY) | |
909 ISOString += '-' + pad( date.getDate() ); | |
910 if (granularity <= SimileAjax.DateTime.HOUR){ | |
911 ISOString += 'T' + pad( date.getHours() ); | |
912 if (granularity <= SimileAjax.DateTime.MINUTE) | |
913 ISOString += ':' + pad( date.getMinutes() ); | |
914 if (granularity <= SimileAjax.DateTime.SECOND) | |
915 ISOString += ':' + pad( date.getSeconds() ); | |
916 if (granularity <= SimileAjax.DateTime.MILLISECOND) | |
917 ISOString += '.' + String( (date.getMilliseconds()/1000).toFixed(3) ).slice( 2, 5 ); | |
918 ISOString += 'Z'; | |
919 } | |
920 | |
921 return ISOString; | |
922 }; | |
923 | |
924 $(GeoTemConfig.datasets[index].objects).each(function(){ | |
925 var name = this.name; | |
926 var description = this.description; | |
927 //TODO: allow multiple time/date | |
928 var place = this.getPlace(0,0); | |
929 var lat = this.getLatitude(0); | |
930 var lon = this.getLongitude(0); | |
931 | |
932 var kmlEntry = "<Placemark>"; | |
933 | |
934 kmlEntry += "<name><![CDATA[" + name + "]]></name>"; | |
935 kmlEntry += "<address><![CDATA[" + place + "]]></address>"; | |
936 kmlEntry += "<description><![CDATA[" + description + "]]></description>"; | |
937 kmlEntry += "<Point><coordinates>" + lon + "," + lat + "</coordinates></Point>"; | |
938 | |
939 if (this.isTemporal){ | |
940 kmlEntry += "<TimeStamp><when>" + dateToISOString(this.getDate(0), this.getTimeGranularity(0)) + "</when></TimeStamp>"; | |
941 } else if (this.isFuzzyTemporal){ | |
942 kmlEntry += "<TimeSpan>"+ | |
943 "<begin>" + dateToISOString(this.TimeSpanBegin.utc().toDate(), this.TimeSpanBeginGranularity) + "</begin>" + | |
944 "<end>" + dateToISOString(this.TimeSpanEnd.utc().toDate(), this.TimeSpanEndGranularity) + "</end>" + | |
945 "</TimeSpan>"; | |
946 } | |
947 | |
948 kmlEntry += "</Placemark>"; | |
949 | |
950 kmlContent += kmlEntry; | |
951 }); | |
952 | |
953 kmlContent += "</Document></kml>"; | |
954 | |
955 return(kmlContent); | |
956 }; | |
957 | |
958 GeoTemConfig.createCSVfromDataset = function(index){ | |
959 var csvContent = ""; | |
960 var header = ["name", "description", "weight"]; | |
961 var tableContent = []; | |
962 | |
963 var firstDataObject = GeoTemConfig.datasets[index].objects[0]; | |
964 | |
965 for(var key in firstDataObject.tableContent){ | |
966 var found = false; | |
967 $(header).each(function(index,val){ | |
968 if (val === key){ | |
969 found = true; | |
970 return false; | |
971 } | |
972 }); | |
973 if (found === true) | |
974 continue; | |
975 else | |
976 tableContent.push(key); | |
977 } | |
978 | |
979 var isFirst = true; | |
980 $(header).each(function(key,val){ | |
981 if (isFirst){ | |
982 isFirst = false; | |
983 } else { | |
984 csvContent += ","; | |
985 } | |
986 | |
987 //Rename according to CSV import definition | |
988 if (val === "name") | |
989 val = "Name"; | |
990 else if (val === "description") | |
991 val = "Description"; | |
992 csvContent += "\""+val+"\""; | |
993 }); | |
994 $(tableContent).each(function(key,val){ | |
995 if (isFirst){ | |
996 isFirst = false; | |
997 } else { | |
998 csvContent += ","; | |
999 } | |
1000 csvContent += "\""+val+"\""; | |
1001 }); | |
1002 //Names according to CSV import definition | |
1003 csvContent += ",\"Address\",\"Latitude\",\"Longitude\",\"TimeStamp\""; | |
1004 csvContent += "\n"; | |
1005 | |
1006 var isFirstRow = true; | |
1007 $(GeoTemConfig.datasets[index].objects).each(function(){ | |
1008 var elem = this; | |
1009 | |
1010 if (isFirstRow){ | |
1011 isFirstRow = false; | |
1012 } else { | |
1013 csvContent += "\n"; | |
1014 } | |
1015 | |
1016 var isFirst = true; | |
1017 $(header).each(function(key,val){ | |
1018 if (isFirst){ | |
1019 isFirst = false; | |
1020 } else { | |
1021 csvContent += ","; | |
1022 } | |
1023 csvContent += "\""+elem[val]+"\""; | |
1024 }); | |
1025 $(tableContent).each(function(key,val){ | |
1026 if (isFirst){ | |
1027 isFirst = false; | |
1028 } else { | |
1029 csvContent += ","; | |
1030 } | |
1031 csvContent += "\""+elem.tableContent[val]+"\""; | |
1032 }); | |
1033 | |
1034 csvContent += ","; | |
1035 csvContent += "\""; | |
1036 if (elem.isGeospatial){ | |
1037 csvContent += elem.locations[0].place; | |
1038 } | |
1039 csvContent += "\""; | |
1040 | |
1041 csvContent += ","; | |
1042 csvContent += "\""; | |
1043 if ( (elem.isGeospatial) && (typeof elem.getLatitude(0) !== "undefined") ){ | |
1044 csvContent += elem.getLatitude(0); | |
1045 } | |
1046 csvContent += "\""; | |
1047 | |
1048 csvContent += ","; | |
1049 csvContent += "\""; | |
1050 if ( (elem.isGeospatial) && (typeof elem.getLongitude(0) !== "undefined") ){ | |
1051 csvContent += elem.getLongitude(0); | |
1052 } | |
1053 csvContent += "\""; | |
1054 | |
1055 csvContent += ","; | |
1056 csvContent += "\""; | |
1057 if ( (elem.isTemporal) && (typeof elem.getDate(0) !== "undefined") ){ | |
1058 //TODO: not supported in IE8 switch to moment.js | |
1059 csvContent += elem.getDate(0).toISOString(); | |
1060 } | |
1061 csvContent += "\""; | |
1062 }); | |
1063 | |
1064 return(csvContent); | |
1065 }; | |
1066 /** | |
1067 * iterates over Datasets/DataObjects and loads color values | |
1068 * from the "color0" and "color1" elements, which contains RGB | |
1069 * values in hex (CSS style #RRGGBB) | |
1070 * @param {dataObjects} array of DataObjects | |
1071 */ | |
1072 GeoTemConfig.loadDataObjectColoring = function(dataObjects) { | |
1073 $(dataObjects).each(function(){ | |
1074 var r0,g0,b0,r1,g1,b1; | |
1075 if ( (typeof this.tableContent !== "undefined") && | |
1076 (typeof this.tableContent["color0"] !== "undefined") ){ | |
1077 var color = this.tableContent["color0"]; | |
1078 if ( (color.indexOf("#") == 0) && (color.length == 7) ){ | |
1079 r0 = parseInt("0x"+color.substr(1,2)); | |
1080 g0 = parseInt("0x"+color.substr(3,2)); | |
1081 b0 = parseInt("0x"+color.substr(5,2)); | |
1082 } | |
1083 } | |
1084 if ( (typeof this.tableContent !== "undefined") && | |
1085 (typeof this.tableContent["color1"] !== "undefined") ){ | |
1086 var color = this.tableContent["color1"]; | |
1087 if ( (color.indexOf("#") == 0) && (color.length == 7) ){ | |
1088 r1 = parseInt("0x"+color.substr(1,2)); | |
1089 g1 = parseInt("0x"+color.substr(3,2)); | |
1090 b1 = parseInt("0x"+color.substr(5,2)); | |
1091 } | |
1092 } | |
1093 | |
1094 if ( (typeof r0 !== "undefined") && (typeof g0 !== "undefined") && (typeof b0 !== "undefined") && | |
1095 (typeof r1 !== "undefined") && (typeof g1 !== "undefined") && (typeof b1 !== "undefined") ){ | |
1096 this.setColor(r0,g0,b0,r1,g1,b1); | |
1097 delete this.tableContent["color0"]; | |
1098 delete this.tableContent["color1"]; | |
1099 } else { | |
1100 if ((GeoTemConfig.debug)&&(typeof console !== undefined)) | |
1101 console.error("Object '" + this.name + "' has invalid color information"); | |
1102 } | |
1103 }); | |
1104 }; | |
1105 | |
1106 /** | |
1107 * renames (or copies, see below) a column of each DataObject in a Dataset | |
1108 * @param {Dataset} dataset the dataset where the rename should take place | |
1109 * @param {String} oldColumn name of column that will be renamed | |
1110 * @param {String} newColumn new name of column | |
1111 * @param {Boolean} keepOld keep old column (copy mode) | |
1112 * @return an array of data objects | |
1113 */ | |
1114 GeoTemConfig.renameColumns = function(dataset, renames){ | |
1115 if (renames.length===0){ | |
1116 return; | |
1117 } | |
1118 for (var renCnt = 0; renCnt < renames.length; renCnt++){ | |
1119 var oldColumn = renames[renCnt].oldColumn; | |
1120 var newColumn = renames[renCnt].newColumn; | |
1121 | |
1122 var keepOld = renames[renCnt].keepOld; | |
1123 if (typeof keepOld === "undefined"){ | |
1124 keepOld = true; | |
1125 } | |
1126 var oldColumObject = {}; | |
1127 if (oldColumn.indexOf("[") != -1){ | |
1128 oldColumObject.columnName = oldColumn.split("[")[0]; | |
1129 var IndexAndAttribute = oldColumn.split("[")[1]; | |
1130 if (IndexAndAttribute.indexOf("]") != -1){ | |
1131 oldColumObject.type = 2; | |
1132 oldColumObject.arrayIndex = IndexAndAttribute.split("]")[0]; | |
1133 var attribute = IndexAndAttribute.split("]")[1]; | |
1134 if (attribute.length > 0){ | |
1135 oldColumObject.type = 3; | |
1136 oldColumObject.attribute = attribute.split(".")[1]; | |
1137 } | |
1138 } | |
1139 } else { | |
1140 oldColumObject.type = 1; | |
1141 oldColumObject.name = oldColumn; | |
1142 } | |
1143 | |
1144 var newColumObject = {}; | |
1145 if (newColumn.indexOf("[") != -1){ | |
1146 newColumObject.name = newColumn.split("[")[0]; | |
1147 var IndexAndAttribute = newColumn.split("[")[1]; | |
1148 if (IndexAndAttribute.indexOf("]") != -1){ | |
1149 newColumObject.type = 2; | |
1150 newColumObject.arrayIndex = IndexAndAttribute.split("]")[0]; | |
1151 var attribute = IndexAndAttribute.split("]")[1]; | |
1152 if (attribute.length > 0){ | |
1153 newColumObject.type = 3; | |
1154 newColumObject.attribute = attribute.split(".")[1]; | |
1155 } | |
1156 } | |
1157 } else { | |
1158 newColumObject.type = 1; | |
1159 newColumObject.name = newColumn; | |
1160 } | |
1161 | |
1162 for (var i = 0; i < dataset.objects.length; i++){ | |
1163 var dataObject = dataset.objects[i]; | |
1164 | |
1165 //get value from old column name | |
1166 var value; | |
1167 if (oldColumObject.type == 1){ | |
1168 value = dataObject[oldColumObject.name]; | |
1169 if (typeof value === "undefined"){ | |
1170 value = dataObject.tableContent[oldColumObject.name]; | |
1171 } | |
1172 if (!keepOld){ | |
1173 delete dataObject.tableContent[oldColumObject.name]; | |
1174 delete dataObject[oldColumObject.name]; | |
1175 } | |
1176 } else if (oldColumObject.type == 2){ | |
1177 value = dataObject[oldColumObject.name][oldColumObject.arrayIndex]; | |
1178 if (!keepOld){ | |
1179 delete dataObject[oldColumObject.name][oldColumObject.arrayIndex]; | |
1180 } | |
1181 } else if (oldColumObject.type == 3){ | |
1182 value = dataObject[oldColumObject.name][oldColumObject.arrayIndex][oldColumObject.attribute]; | |
1183 if (!keepOld){ | |
1184 delete dataObject[oldColumObject.name][oldColumObject.arrayIndex][oldColumObject.attribute]; | |
1185 } | |
1186 } | |
1187 | |
1188 //create new column | |
1189 if (newColumObject.type == 1){ | |
1190 dataObject[newColumObject.name] = value; | |
1191 dataObject.tableContent[newColumObject.name] = value; | |
1192 } else if (newColumObject.type == 2){ | |
1193 if (typeof dataObject[newColumObject.name] == "undefined"){ | |
1194 dataObject[newColumObject.name] = []; | |
1195 } | |
1196 dataObject[newColumObject.name][newColumObject.arrayIndex] = value; | |
1197 } else if (newColumObject.type == 3){ | |
1198 if (typeof dataObject[newColumObject.name] == "undefined"){ | |
1199 dataObject[newColumObject.name] = []; | |
1200 } | |
1201 if (typeof dataObject[newColumObject.name][newColumObject.arrayIndex] == "undefined"){ | |
1202 dataObject[newColumObject.name][newColumObject.arrayIndex] = {}; | |
1203 } | |
1204 dataObject[newColumObject.name][newColumObject.arrayIndex][newColumObject.attribute] = value; | |
1205 } | |
1206 } | |
1207 } | |
1208 | |
1209 //actually create new dataObjects | |
1210 for (var i = 0; i < dataset.objects.length; i++){ | |
1211 var dataObject = dataset.objects[i]; | |
1212 //save index | |
1213 var index = dataObject.index; | |
1214 | |
1215 dataset.objects[i] = new DataObject(dataObject.name, dataObject.description, dataObject.locations, | |
1216 dataObject.dates, dataObject.weight, dataObject.tableContent, dataObject.projection); | |
1217 //set index | |
1218 dataset.objects[i].setIndex(index); | |
1219 } | |
1220 }; |