comparison war/scripts/sti/STICore.js @ 3:cf06b77a8bbd

Committed branch of the e4D repos sti-gwt branch 16384. git-svn-id: http://dev.dariah.eu/svn/repos/eu.dariah.de/ap1/sti-gwt-dariah-geobrowser@36 f2b5be40-def6-11e0-8a09-b3c1cc336c6b
author StefanFunk <StefanFunk@f2b5be40-def6-11e0-8a09-b3c1cc336c6b>
date Tue, 17 Jul 2012 13:34:40 +0000
parents
children 517a6422d1bd
comparison
equal deleted inserted replaced
2:2897af43ccc6 3:cf06b77a8bbd
1 /**
2 * defines the core component of the Spatio Temporal Interface
3 *
4 * @constructor
5 */
6 function STICore(){
7
8 this.map;
9 this.timeplot;
10
11 this.refining;
12 this.individualDataSet;
13
14 this.takeTime;
15
16 this.history;
17 this.historyIndex;
18 this.lockScreenContainer;
19
20 this.initialize();
21 this.blocked = false;
22
23 };
24
25 STICore.prototype = {
26
27 blockUI: function(){
28 this.blocked = true;
29 fullscreen.addFullscreen(fullscreen.loaderContent());
30 },
31
32 unblockUI: function(){
33 this.blocked = false;
34 setTimeout( function(){ if( !this.blocked ){ setDefinedBounds(); } }, 150 );
35 fullscreen.removeFullscreen();
36 },
37
38 /**
39 * refines the given data by creating a new history entry
40 */
41 refine: function(){
42 if (this.refining > -2) {
43 var contains = false;
44 var newDataSets = [];
45 var oldDataSets = this.history[this.historyIndex].dataSets;
46 for (var i = 0; i < oldDataSets.length; i++) {
47 var dataSet = oldDataSets[i].copy();
48 dataSet.source = oldDataSets[i].source;
49 for (var j = 0; j < oldDataSets[i].objects.length; j++) {
50 if ( oldDataSets[i].objects[j].percentage == 1 || this.refining > -1 && this.refining != i ){
51 dataSet.addObject( oldDataSets[i].objects[j] );
52 contains = true;
53 }
54 }
55 newDataSets.push(dataSet);
56 }
57 if (contains) {
58 this.addHistoryEntry( new HistoryEntry(newDataSets) );
59 this.reset();
60 this.initElements();
61 }
62 else {
63 alert("Your Selection contains no elements!");
64 }
65 }
66 else {
67 alert("For Refining choose an Area on the map or a Range on the Timeplot!");
68 }
69 return -1;
70 },
71
72 /**
73 * refines the given data by creating a new history entry
74 */
75 refineByTime: function(minTime,maxTime){
76 var minDate = new Date(parseInt(minTime));
77 var maxDate = new Date(parseInt(maxTime));
78 if( this.timeplot.eds.minDate.getTime() == minDate.getTime() &&
79 this.timeplot.eds.maxDate.getTime() == maxDate.getTime() ){
80 return;
81 }
82 var newDataSets = [];
83 var oldDataSets = this.history[this.historyIndex].dataSets;
84 for (var i = 0; i < oldDataSets.length; i++) {
85 var dataSet = oldDataSets[i].copy();
86 dataSet.source = oldDataSets[i].source;
87 for (var j = 0; j < oldDataSets[i].objects.length; j++) {
88 var o = oldDataSets[i].objects[j];
89 if( o.inTime(minDate,maxDate) ){
90 dataSet.addObject( o );
91 }
92 }
93 newDataSets.push(dataSet);
94 }
95 this.addHistoryEntry( new HistoryEntry(newDataSets) );
96 this.reset();
97 this.initElements();
98 },
99
100 /**
101 * refines a given dataset by a given text snippet
102 */
103 refineByText: function(text,index){
104 this.reset();
105 var dataset = this.history[this.historyIndex].dataSets[index];
106 for (var i = 0; i < dataset.objects.length; i++) {
107 var e = dataset.objects[i];
108 if( e.name.toLowerCase().indexOf(text.toLowerCase()) != -1 ){
109 e.setPercentage(1);
110 }
111 }
112 this.updateMapAndTimeAndTable(index);
113 },
114
115 /**
116 * adds selected elements of a specific dataset as a new dataset
117 * @param {int} id the id of the dataset
118 */
119 storeSelected: function(id){
120 var dataSets = this.history[this.historyIndex].dataSets;
121 if( dataSets.length == 4 ){
122 alert( "The maximum number of 4 parallel datasets is reached!" );
123 }
124 else {
125 var dataSet = dataSets[id].copy();
126 var contains = false;
127 for (var j = 0; j < dataSets[id].objects.length; j++) {
128 if ( dataSets[id].objects[j].percentage == 1 ){
129 dataSet.addObject( dataSets[id].objects[j] );
130 contains = true;
131 }
132 }
133 if (contains) {
134 this.addDataSet(dataSet);
135 }
136 else {
137 alert("Your Selection contains no elements!");
138 }
139 }
140 },
141
142 /**
143 * Adds a dataset to the actual history entry
144 */
145 addDataSet: function( dataSet ){
146 var oldDataSets = this.history[this.historyIndex].dataSets;
147 var newDataSets = oldDataSets.concat(dataSet);
148 this.addHistoryEntry(new HistoryEntry(newDataSets));
149 this.initElements();
150 this.reset();
151 },
152
153 /**
154 * Sets the widgets for the core component
155 *
156 * @param {STIMap} map the javascript object of the map widget
157 * @param {STITimeplot} plot the javascript object of the timeplot widget
158 */
159 setElements: function(map, timeplot){
160 this.map = map;
161 this.timeplot = timeplot;
162 },
163
164 /**
165 * initializes the core component for the Spatio Temporal Interface.
166 * here, the handling of the search interface is defined (including undo, refine and clear selection button).
167 * furthermore, the elements (map, timeplot, tables) are instanciated.
168 */
169 initialize: function(){
170
171 var context = this;
172 this.takeTime = false;
173 this.props = new STIProps();
174
175 this.history = [];
176
177 this.history.push( new HistoryEntry([]) );
178 this.historyIndex = 0;
179
180 var Unselectable = {
181 enable: function(e){
182 var e = e ? e : window.event;
183 if (e.button != 1) {
184 if (e.target) {
185 var targer = e.target;
186 }
187 else
188 if (e.srcElement) {
189 var targer = e.srcElement;
190 }
191 if( targer.tagName == undefined ){
192 return false;
193 }
194 var targetTag = targer.tagName.toLowerCase();
195 if ((targetTag != "input") && (targetTag != "textarea")) {
196 return false;
197 }
198 }
199 },
200 disable: function(){
201 return true;
202 }
203 }
204
205 if (typeof(document.onselectstart) != "type filter textundefined") {
206 document.onselectstart = Unselectable.enable;
207 }
208 else {
209 document.onmousedown = Unselectable.enable;
210 document.onmouseup = Unselectable.disable;
211 }
212
213 this.sources = [];
214 try {
215 var jsonString = this.getFileString("datasources.json");
216 this.sources = eval('(' + jsonString + ')');
217 }
218 catch(e){
219 }
220
221 this.lockScreenContainer = document.createElement("div");
222 this.lockScreenContainer.setAttribute('class','lockScreenContainer');
223 document.getElementsByTagName("body")[0].appendChild(this.lockScreenContainer);
224
225 },
226
227 getFileString: function(url){
228 var xmlhttp = false;
229 if (!xmlhttp)
230 try {
231 xmlhttp = new XMLHttpRequest();
232 }
233 catch (e) {
234 xmlhttp = false;
235 }
236 if (typeof ActiveXObject != "undefined") {
237 if (!xmlhttp)
238 try {
239 xmlhttp = new ActiveXObject("MSXML2.XMLHTTP");
240 }
241 catch (e) {
242 xmlhttp = false;
243 }
244 if (!xmlhttp)
245 try {
246 xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
247 }
248 catch (e) {
249 xmlhttp = false;
250 }
251 }
252 xmlhttp.open('GET', url, false);
253 xmlhttp.send("");
254 return xmlhttp.responseText;
255 },
256
257 /**
258 * constructs an url to a dynamic datasource with the specific user input as attribute
259 * @param {int} ds the datasource index
260 * @param {String} input the user input
261 */
262 retrieveKml: function(ds,input){
263 var url = this.sources[ds].url;
264 // var tags = input.replace(/[^a-zA-Z0-9]/g,",");
265 // url += tags;
266 url += input;
267 this.parseKml(url,input,ds);
268 },
269
270 parseIt: function(xml,term,ds){
271 var getTimeData = function( timeString ){
272 try {
273 var bc = false;
274 if( timeString.startsWith("-") ){
275 bc = true;
276 timeString = timeString.substring(1);
277 }
278 var timeSplit = timeString.split("T");
279 var timeData = timeSplit[0].split("-");
280 for (var i = 0; i < timeData.length; i++) {
281 parseInt(timeData[i]);
282 }
283 if( bc ){
284 timeData[0] = "-"+timeData[0];
285 }
286 if (timeSplit.length == 1) {
287 return timeData;
288 }
289 var dayData;
290 if (timeSplit[1].indexOf("Z") != -1) {
291 dayData = timeSplit[1].substring(0, timeSplit[1].indexOf("Z") - 1).split(":");
292 }
293 else {
294 dayData = timeSplit[1].substring(0, timeSplit[1].indexOf("+") - 1).split(":");
295 }
296 for (var i = 0; i < timeData.length; i++) {
297 parseInt(dayData[i]);
298 }
299 return timeData.concat(dayData);
300 }
301 catch (exception) {
302 return null;
303 }
304 }
305
306 var time = SimileAjax.DateTime;
307 var newObjects = new Array();
308 var elements = xml.getElementsByTagName("Placemark");
309 var granularity = 0;
310
311 if( elements.length == 0 ){
312 this.unblockUI();
313 return;
314 }
315
316 for (var i = 0; i < elements.length; i++) {
317
318 var placemark = elements[i];
319 var name, description, place, timeData, coordinates, timeStamp, timeSpan, g;
320
321 try {
322 name = placemark.getElementsByTagName("name")[0].childNodes[0].nodeValue;
323 }
324 catch(e){
325 name = "";
326 }
327
328 try {
329 description = placemark.getElementsByTagName("description")[0].childNodes[0].nodeValue;
330 }
331 catch(e){
332 description = "";
333 }
334
335 try {
336 place = placemark.getElementsByTagName("address")[0].childNodes[0].nodeValue;
337 }
338 catch(e){
339 place = "";
340 }
341
342 var getDate = function(timeData){
343 var date;
344 if (timeData.length == 6) {
345 g = time.SECOND;
346 date = new Date(Date.UTC(timeData[0], timeData[1]-1, timeData[2], timeData[3], timeData[4], timeData[5]));
347 }
348 else if (timeData.length == 3) {
349 g = time.DAY;
350 date = new Date(Date.UTC(timeData[0], timeData[1]-1, timeData[2]));
351 }
352 else if (timeData.length == 2) {
353 g = time.MONTH;
354 date = new Date(Date.UTC(timeData[0], timeData[1]-1, 1));
355 }
356 else if (timeData.length == 1) {
357 g = time.YEAR;
358 date = new Date(Date.UTC(timeData[0], 0, 1));
359 }
360 if (granularity < g) {
361 granularity = g;
362 }
363 if( timeData[0] && timeData[0] < 100 ){
364 date.setFullYear(timeData[0]);
365 }
366 return date;
367 }
368
369 try {
370 timeData = getTimeData( placemark.getElementsByTagName("TimeStamp")[0].getElementsByTagName("when")[0].childNodes[0].nodeValue );
371 if( timeData != null ){
372 timeStamp = getDate(timeData);
373 }
374 if( timeStamp == undefined ){
375 continue;
376 }
377 }
378 catch(e){
379 try {
380 timeStamp = undefined;
381 var timeSpanTag = placemark.getElementsByTagName("TimeSpan")[0];
382 var timeDataStart = getTimeData( timeSpanTag.getElementsByTagName("begin")[0].childNodes[0].nodeValue );
383 var startTime = getDate(timeDataStart);
384 var timeDataEnd = getTimeData( timeSpanTag.getElementsByTagName("end")[0].childNodes[0].nodeValue );
385 var endTime = getDate(timeDataEnd);
386 timeSpan = { start: startTime, end: endTime };
387 }
388 catch(e){
389 continue;
390 }
391 }
392
393 try {
394 coordinates = placemark.getElementsByTagName("Point")[0].getElementsByTagName("coordinates")[0].childNodes[0].nodeValue;
395 var lonlat = coordinates.split(",");
396 if( lonlat[0] == "" || lonlat[1] == "" || isNaN(lonlat[0]) || isNaN(lonlat[1]) ){
397 continue;
398 }
399 newObjects.push(new DataObject(name, description, place, timeStamp, timeSpan, g, lonlat[0], lonlat[1]));
400 }
401 catch(e){
402 continue;
403 }
404
405 }
406 var dataset = new DataSet( newObjects, term, granularity );
407 dataset.source = ds;
408 var core = this;
409 var status = document.getElementById("statusText");
410 status.innerHTML = "Space & Time Aggregation ...";
411 setTimeout( function(){
412 core.addDataSet( dataset );
413 core.unblockUI();
414 },
415 1 );
416 },
417
418 /**
419 * parses the kml-file which includes the results for a given search request
420 * @param {File} kmlFile
421 * @param {String} term the term identifier for the resulting dataset
422 */
423 parseKml: function(kmlFile,term,ds){
424 var core = this;
425 if( this.blocked ){
426 setTimeout( function(){ core.parseKml(kmlFile,term,ds); }, 100 );
427 return;
428 }
429 core.blockUI();
430 $.ajax({
431 url: kmlFile,
432 dataType: "xml",
433 beforeSend: function(){
434 var status = document.getElementById("statusText");
435 status.innerHTML = "Retrieving Data ...";
436 },
437 success: function(xml){
438 var status = document.getElementById("statusText");
439 status.innerHTML = "Parsing Data ...";
440 setTimeout( function(){ core.parseIt(xml,term,ds); }, 1 );
441 }
442 });
443 },
444
445 /**
446 * updates the timeplot and table element.
447 * its called from the STIMap object, when objects on the map had been selected by featureSelect or polygon.
448 * @param {boolean} hover true, if there was a hover selection
449 */
450 updateTimeAndTable: function(hover){
451 updateTables(hover);
452 this.timeplot.polesBySlices();
453 this.refining = -1;
454 },
455
456 /**
457 * updates the map, timeplot and table element.
458 * its called from the STITable object, when a text selection has been done
459 */
460 updateMapAndTimeAndTable: function(index){
461 updateTables(hover);
462 this.timeplot.polesBySlices();
463 this.map.updateMap();
464 this.refining = index;
465 },
466
467 /**
468 * updates the timeplot and map element.
469 * its called from the STITable object, when objects in one of the tables had been selected.
470 */
471 updateTimeAndMap: function(){
472 this.map.updateMap();
473 this.timeplot.polesBySlices();
474 this.refining = -1;
475 },
476
477 /**
478 * updates the table and map element.
479 * its called from the STITimeplot object, when objects in the timeplot had been selected by timestamp or -range.
480 * @param {boolean} hover true, if there was a hover selection
481 */
482 updateTableAndMap: function(hover){
483 updateTables(hover);
484 this.map.updateMap();
485 this.refining = -1;
486 },
487
488 /**
489 * initializes the sti components (map, timeplot, table) depending on the top masks of the data sets.
490 * its called after a new search was performed, refining or undo button had been clicked
491 */
492 initElements: function(){
493 this.reset();
494 var dataSets = this.history[this.historyIndex].dataSets;
495 var granularity = 0;
496 for( var i=0; i<dataSets.length; i++ ){
497 if( dataSets[i].maxGranularity > granularity ){
498 granularity = dataSets[i].maxGranularity;
499 }
500 }
501 this.timeplot.initTimeplot(dataSets, granularity);
502 this.map.initObjectLayer(dataSets);
503 initTables();
504 },
505
506 /**
507 * deletes a data set with specific index
508 * @param {int} index the index of the data set to delete
509 */
510 deleteDataSet: function(index){
511 var color = colors[index];
512 colors.splice(index, 1);
513 var oldDataSets = this.history[this.historyIndex].dataSets;
514 var newDataSets = [];
515 for( var i=0; i<oldDataSets.length; i++ ){
516 if( i != index ){
517 newDataSets.push( oldDataSets[i] );
518 }
519 }
520 colors.splice( newDataSets.length, 0, color );
521 this.addHistoryEntry(new HistoryEntry(newDataSets));
522 this.initElements();
523 this.reset();
524 },
525
526 /**
527 * Switches to another history entry with the given index
528 * @param {int} index the index of the history entry to load
529 */
530 switchThroughHistory: function( index ){
531 this.historyIndex = index;
532 this.initElements();
533 },
534
535 /**
536 * Adds a new history entry containing actual datasets
537 * @param {HistoryEntry} historyEntry the history entry to add
538 */
539 addHistoryEntry: function( historyEntry ){
540 this.history = this.history.slice(0,this.historyIndex+1);
541 this.history.push(historyEntry);
542 this.historyIndex = this.history.length - 1;
543 addHistoryItem(this.historyIndex);
544 },
545
546 /**
547 * adds an element to the user individual data set
548 * @param {DataObject} object the data object to add
549 */
550 addElement: function(object){
551 if (this.individualDataSet == null) {
552 this.individualDataSet = new DataSet([], "individual", 0);
553 var oldDataSets = this.history[this.historyIndex].dataSets;
554 var newDataSets = oldDataSets.concat(this.individualDataSet);
555 this.addHistoryEntry(new HistoryEntry(newDataSets));
556 }
557 this.individualDataSet.addObject(object);
558 this.initElements();
559 this.reset();
560 },
561
562 /**
563 * resets the core within all elements and data objects to non-selection-status
564 */
565 reset: function(){
566 this.refining = -2;
567 var dataSets = this.history[this.historyIndex].dataSets;
568 for (var i = 0; i < dataSets.length; i++){
569 for (var j = 0; j < dataSets[i].objects.length; j++){
570 dataSets[i].objects[j].setPercentage(0);
571 dataSets[i].objects[j].setHover(false);
572 }
573 }
574 this.timeplot.resetTimeplot();
575 this.map.resetMap();
576 updateTables(false);
577 },
578
579 /**
580 * Security hover unselection of elements if browser events got stucked
581 */
582 undoHover: function(update){
583
584 this.map.hoverUnselect();
585 this.timeplot.hoverUnselect(update);
586 },
587
588 createLink: function(){
589 var c = this.map.openlayersMap.getCenter();
590 var map = this.map.openlayersMap.baseLayer.id;
591 var mapCenter = { lon: c.lon, lat: c.lat };
592 var mapZoom = this.map.openlayersMap.getZoom();
593 var data = [];
594 // store complete history in data --> flow of history events
595 // history event can be: loading/deleting dataset, refinement by timerange/polygon at specific zoom level/point at specific zoom level, a loaded link history (this)
596 // flag for the ability to display stored history or not
597 },
598
599 lockScreen: function(){
600 this.lockScreenContainer.style.visibility = "visible";
601 this.lockScreenContainer.style.height = getDocHeight()+"px";
602 },
603
604 lockScreenMessage: function(div){
605 this.lockScreenContainer.innerHTML = "";
606 var lockScreenDiv = document.createElement("div");
607 lockScreenDiv.setAttribute('class','lockScreen');
608 this.lockScreenContainer.appendChild(lockScreenDiv);
609 this.lockScreenContainer.appendChild(div);
610 },
611
612 unlockScreen: function(){
613 this.lockScreenContainer.style.visibility = "hidden";
614 }
615
616 };
617
618 /**
619 * defines a history entry
620 * @param {DataSet[]} dataSets the datasets of this history entry
621 *
622 * @constructor
623 */
624 function HistoryEntry( dataSets ){
625 this.dataSets = dataSets;
626 };