diff war/scripts/sti/STIMap.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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/war/scripts/sti/STIMap.js	Tue Jul 17 13:34:40 2012 +0000
@@ -0,0 +1,1372 @@
+/**
+ * defines the map component of the Spatio Temporal Interface.
+ * it builds a map context with the OpenLayers JavaScript Framework
+ * @param {STICore} core the sti core component, the map component has to deal with
+ * @param {String} window the div id for the window div for the container of the map widget
+ * @param {String} container the div id for the container of the map widget
+ *
+ * @constructor
+ */
+function STIMap(core,window,container){
+
+    this.core = core;
+    this.window = window;
+    this.container = container; 
+    this.openlayersMap;
+    this.baseLayers;
+    this.objectLayer;
+    this.drilldownLayer;
+    this.connectionLayer;
+    
+    this.drawPolygon;
+    this.drawCircle;
+    this.selectCountry;
+    this.dragArea;
+    this.selectFeature;
+    this.navigation;
+    
+    this.polygon;
+
+    this.selectElementsPlace;
+    this.pointToAdd;
+    this.displayPointSet;
+    
+    this.popup;
+    this.lastHovered;
+    
+    this.xShift;
+    this.yShift;
+    this.showConnections;
+    this.connections;
+    
+    this.mapMouseMove;
+    this.addCrossImage;
+    
+    this.initialize();
+    
+}
+
+STIMap.prototype = {
+
+    /**
+     * initializes the map for the Spatio Temporal Interface.
+     * it includes setting up all layers of the map and defines all map specific interaction possibilities
+     */
+    initialize: function(){
+
+        //OpenLayers.ProxyHost = "/cgi-bin/proxy.cgi?url=";
+        var map = this;
+                
+		this.pointSelected = false;
+        this.showConnections = false;
+        this.labelDivs = [];
+        this.polygons = [];
+        
+        var window = document.getElementById(this.window); 
+        
+        this.toolbar = document.createElement("div");
+        this.toolbar.setAttribute('class','mapToolbar');
+        window.appendChild(this.toolbar);
+
+        this.drag = document.createElement("div");
+        this.drag.title = "Drag Area: drag a selection area and with left mouse-button";
+        this.drag.setAttribute('class','dragRange');
+        this.toolbar.appendChild(this.drag);
+        this.drag.onclick = function(evt){
+        	if( map.activeControl == "drag" ){
+        		map.deactivate("drag");
+        	}
+        	else {
+        		map.deactivate(map.activControl);
+        		map.activate("drag");
+        	}
+        }
+        
+        var zoom = document.createElement("div");
+        zoom.title = "Zoom into selection. To undo, go a step back in the History.";
+        zoom.setAttribute('class','zoomRange');
+        this.toolbar.appendChild(zoom);
+        zoom.onclick = function(){
+        	map.core.refine();
+        }
+
+        var cancel = document.createElement("div");
+        cancel.title = "Clear Selection";
+        cancel.setAttribute('class','cancelRange');
+        this.toolbar.appendChild(cancel);
+        cancel.onclick = function(){
+        	map.core.reset();
+        }
+
+        this.controlLockDiv = document.createElement("div");
+        this.controlLockDiv.setAttribute('class','controlLock');
+        window.appendChild(this.controlLockDiv);        
+                
+        this.leftTagCloudDiv = document.createElement("div");
+        this.leftTagCloudDiv.setAttribute('class','tagCloudDiv');
+        window.appendChild(this.leftTagCloudDiv);
+                
+		this.rightTagCloudDiv = document.createElement("div");
+        this.rightTagCloudDiv.setAttribute('class','tagCloudDiv');
+        window.appendChild(this.rightTagCloudDiv);
+        
+        this.pointClickDiv = document.createElement("div");
+        this.pointClickDiv.setAttribute('class','pointClickDiv');
+        window.appendChild(this.pointClickDiv);
+        
+        var pointClickDivBackground = document.createElement("div");
+        pointClickDivBackground.setAttribute('class','pointClickDivBackground');
+        this.pointClickDiv.appendChild(pointClickDivBackground);
+        
+        this.objectLayer = new OpenLayers.Layer.Vector("Data Objects", {
+            projection: "EPSG:4326"
+        });
+        this.connectionLayer = new OpenLayers.Layer.Vector("Connections", {
+            projection: "EPSG:4326"
+        });
+        this.drilldownLayer = new OpenLayers.Layer.Vector("Drilldown", {
+            projection: "EPSG:4326"
+        });
+        this.parseBaseLayers("layers.xml");
+        
+        this.navigation = new OpenLayers.Control.Navigation({
+            zoomWheelEnabled: true
+        });
+        this.navigation.defaultDblClick = function(evt){
+            var newCenter = this.map.getLonLatFromViewPortPx(evt.xy);
+            this.map.setCenter(newCenter, this.map.zoom + 1);
+            map.drawObjectLayer(true);
+            setMapZoom(this.map.zoom/this.map.numZoomLevels);
+        }
+        this.navigation.wheelUp = function(evt){
+        	this.wheelChange(evt, 1);
+            map.drawObjectLayer(true);
+            setMapZoom(this.map.zoom/this.map.numZoomLevels);
+        }
+        this.navigation.wheelDown = function(evt){
+        	this.wheelChange(evt, -1);
+            map.drawObjectLayer(true);
+            setMapZoom(this.map.zoom/this.map.numZoomLevels);
+        }
+        
+        var options = {
+            controls: [this.navigation, new OpenLayers.Control.ScaleLine()],
+            projection: new OpenLayers.Projection("EPSG:900913"),
+            displayProjection: new OpenLayers.Projection("EPSG:4326"),
+            units: "m",
+			minZoomLevel: 1,
+			maxZoomLevel: 17,
+			numZoomLevels: 17,
+			maxResolution: 78271.51695,
+            maxExtent: new OpenLayers.Bounds(-20037508.34, -20037508.34, 20037508.34, 20037508.34)
+        };
+        this.openlayersMap = new OpenLayers.Map(this.container, options);
+        for (var i = 0; i < this.baseLayers.length; i++) 
+            this.openlayersMap.addLayers([this.baseLayers[i]]);
+        this.openlayersMap.fractionalZoom = false;
+    	this.activeControl = "navigate";
+
+        var bounds = new OpenLayers.Bounds(boundaries.minLon, boundaries.minLat, boundaries.maxLon, boundaries.maxLat);
+        var projectionBounds = bounds.transform(this.openlayersMap.displayProjection, this.openlayersMap.projection);
+		this.openlayersMap.zoomToExtent(projectionBounds);
+		this.openlayersMap.addLayers([this.connectionLayer, this.objectLayer, this.drilldownLayer]);
+		
+		// places the toolbar inside the window
+		var placeToolbar = function(){
+			map.toolbar.style.visibility = "visible";
+			var left = 0;
+			var top = 0;
+			if( map.polygons.length > 0 ){
+			    map.drag.style.visibility = "visible";		
+				for (var i = 0; i < map.polygons.length; i++){				 
+					for (var j = 0; j < map.polygons[i].components.length; j++){
+						var vertices = map.polygons[i].components[j].getVertices();
+						for (var k = 0; k < vertices.length; k++){
+							var lonlat = new OpenLayers.LonLat( vertices[k].x, vertices[k].y );
+            				var pixel = map.openlayersMap.getPixelFromLonLat(lonlat);
+            				if( pixel.x > left ){
+            					left = pixel.x;
+            					top = pixel.y;
+            				}
+						}
+					}
+				}
+			    map.toolbar.style.width = "69px";
+				map.toolbar.style.left = left+"px";
+				map.toolbar.style.top = (top-map.toolbar.offsetHeight/2)+"px";
+			}
+			else {
+			    map.drag.style.visibility = "hidden";
+			    map.toolbar.style.width = "47px";
+				map.toolbar.style.left = (map.pointClickDiv.offsetLeft + map.pointClickDiv.offsetWidth - map.toolbar.offsetWidth)+"px";
+				map.toolbar.style.top = map.pointClickDiv.offsetTop+"px";
+			}
+		}
+
+		this.openlayersMap.div.onmousedown = function(){
+        	map.toolbar.style.visibility = "hidden";
+		    map.drag.style.visibility = "hidden";		
+		}		
+		this.openlayersMap.div.onmouseup = function(){
+			if( map.polygons.length > 0 ){
+				placeToolbar();
+        	}
+		}	
+
+		// manages selection of elements if a polygon was drawn        
+        var drawnPolygonHandler = function(polygon){
+        	if( map.displayPointSet == undefined ){
+        		return;
+        	}
+        	map.polygon = polygon;
+            var polygonArea;
+            if (polygon instanceof OpenLayers.Geometry.Polygon) 
+                polygonArea = new OpenLayers.Geometry.MultiPolygon([polygon]);
+            else 
+                if (polygon instanceof OpenLayers.Geometry.MultiPolygon) 
+                    polygonArea = polygon;
+            var points = map.displayPointSet[Math.floor(map.openlayersMap.getZoom()+0.05)];
+            var polygons = polygonArea.components;
+            var innerPoints = [];
+            for (var i = 0; i < points.length; i++) 
+                for (var j = 0; j < polygons.length; j++) 
+                    if (polygons[j].containsPoint(points[i].pointFeature.geometry)) {
+                        innerPoints.push(points[i]);
+                        continue;
+                    }
+            map.updateByPlace(innerPoints, 0);
+            map.drilldownLayer.addFeatures([new OpenLayers.Feature.Vector(polygon)]);
+            map.polygons = polygons;
+            placeToolbar();
+            switchToNavigation();
+        }
+        
+		// resets the core
+        var snapper = function(){
+			map.core.reset();
+        }
+
+		if( this.core.props.polygonSelect ){        
+        this.drawPolygon = new OpenLayers.Control.DrawFeature(map.drilldownLayer, OpenLayers.Handler.Polygon, {
+            displayClass: "olControlDrawFeaturePolygon",
+            title: "Polygon Drilldown",
+            callbacks: {
+                "done": drawnPolygonHandler,
+                "create": snapper
+            }
+        });
+        this.openlayersMap.addControl(this.drawPolygon);
+        }
+
+		if( this.core.props.circleSelect ){        
+        this.drawCircle = new OpenLayers.Control.DrawFeature(map.drilldownLayer, OpenLayers.Handler.RegularPolygon, {
+            displayClass: "olControlDrawFeaturePolygon",
+            title: "Cirlce Drilldown",
+            handlerOptions: {
+                sides: 40
+            },
+            callbacks: {
+                "done": drawnPolygonHandler,
+                "create": snapper
+            }
+        });
+        this.openlayersMap.addControl(this.drawCircle);
+        }
+        
+		if( this.core.props.polygonSelect || this.core.props.circleSelect ){
+        this.dragArea = new OpenLayers.Control.DragFeature(map.drilldownLayer, {
+        	onStart: function(){
+        		map.toolbar.style.visibility = "hidden";
+        	},
+            onComplete: function(feature){
+                drawnPolygonHandler(feature.geometry);
+            }
+        });
+        this.openlayersMap.addControl(this.dragArea);
+        }
+
+		if( this.core.props.historicMaps && this.core.props.countrySelect ){
+        	this.selectCountry = new OpenLayers.Control.GetFeature({
+            	protocol: OpenLayers.Protocol.WFS.fromWMSLayer(map.openlayersMap.baseLayer)
+        	});
+        	this.selectCountry.events.register("featureselected", this, function(e){
+            	if (map.pointSelected){ 
+                	map.pointSelected = false;
+				}
+            	else {
+                	drawnPolygonHandler(e.feature.geometry);
+				}
+        	});
+        	this.selectCountry.events.register("featureunselected", this, function(e){
+            	snapper();
+        	});
+        	this.openlayersMap.addControl(this.selectCountry);
+		}
+
+		// changes selection between labels (click, hover)
+		var changeLabelSelection = function(point,label,update){
+			if( update && map.lastLabel.div == label.div ){
+				return;
+			}
+			var k = point.search;
+			var color0 = 'rgb('+colors[k].r0+','+colors[k].g0+','+colors[k].b0+')';
+			var color1 = colors[k].hex;
+			if( update ){
+				map.lastLabel.div.style.color = color0;
+				map.lastLabel.div.style.textShadow = "0 0 0.4em black, 0 0 0.4em black, 0 0 0.4em black, 0 0 0.4em "+color1;
+				map.lastLabel.div.style.textDecoration = "none";
+				map.lastLabel.selected = false;				
+			}
+			map.lastLabel = label;
+			label.selected = true;							
+			label.div.style.color = color1;
+			label.div.style.textDecoration = "underline";
+			label.div.style.textShadow = "0 0 0.1em white, 0 0 0.1em white, 0 0 0.1em white, 0 0 0.1em "+color1;
+//			label.div.style.textShadow = "0 0 0.4em black, 0 0 0.4em black, 0 0 0.4em black, 0 0 0.4em "+color1;
+			label.div.style.filter = "glow(color="+color1+", strength=3) DropShadow(Color=#292929, OffX=1, OffY=-1, Positive=1) DropShadow(Color=#292929, OffX=-1, OffY=-1, Positive=1) DropShadow(Color=#292929, OffX=1, OffY=1, Positive=1) DropShadow(Color=#292929, OffX=-1, OffY=1, Positive=1) blur(add=false, direction=0, strength=1) blur(add=false, direction=90, strength=1) blur(add=false, direction=180, strength=1) blur(add=false, direction=270, strength=1)";
+			map.updateByPlaceLabel(point,label.elements,0);
+		}
+
+		var getLevelOfDetail = function(){
+			var zoom = map.openlayersMap.getZoom();
+			if( zoom <= 1 ){
+				return 0;
+			}
+			else if( zoom <= 3 ){
+				return 1;
+			}
+			else if( zoom <= 8 ){
+				return 2;
+			}
+			else {
+				return 3;
+			}
+		}
+		
+		// calculates the tag cloud
+		var calculateTagCloud = function(){
+			var elements = map.lastHovered.elements;
+			var labels = [];
+			var levelOfDetail = getLevelOfDetail();
+			for( var i=0; i<elements.length; i++ ){
+				var found = false;
+				var label = elements[i].getPlace(levelOfDetail);
+				if( label == "" ){
+					label = "unknown";
+				}
+				for( var j=0; j<labels.length; j++ ){
+					if( labels[j].place == label ){
+						labels[j].elements.push(elements[i]);
+						found = true;
+						break;
+					}
+				}
+				if( !found ){
+					labels.push( { place: label, elements: new Array(elements[i]) } );
+				}
+			}
+            var sortBySize = function(label1, label2){
+                if (label1.elements.length > label2.elements.length){ 
+                    return -1;
+				}
+                return 1;
+            }
+			labels.sort(sortBySize);
+			if( labels.length+1 > tagCloudLabels ){
+				var c = [];
+				for( var i=tagCloudLabels-2; i<labels.length; i++ ){
+					c = c.concat(labels[i].elements);
+				}
+				labels = labels.slice(0,tagCloudLabels-2);
+				labels.push( { place: "others", elements: c } );
+			}
+			if( labels.length > 1 ){
+				labels.push( { place: "all", elements: elements } );
+			}
+			else if( labels[0].place == "unknown" ){
+				labels[0].place = "all";
+			}
+			map.labels = labels;
+
+			var k = map.lastHovered.search;
+			var color = 'rgb('+colors[k].r0+','+colors[k].g0+','+colors[k].b0+')';
+			var shadow = colors[k].hex;0
+			var clickFunction = function(point,label){
+				label.div.onclick = function(){
+					if( map.pointSelected ){
+						changeLabelSelection(point,label,true);
+					}
+				}
+				label.div.onmouseover = function(){
+					if( map.pointSelected && !label.selected ){
+						label.div.style.textShadow = "0 -1px "+shadow+", 1px 0 "+shadow+", 0 1px "+shadow+", -1px 0 "+shadow;
+						label.div.style.filter = "glow(color="+shadow+", strength=2) blur(add=false, direction=135, strength=1) blur(add=false, direction=45, strength=1)";
+						map.updateByPlaceLabel(point,label.elements,1);
+					}
+				}
+				label.div.onmouseout = function(){
+					if( map.pointSelected && !label.selected ){
+						label.div.style.textShadow = "0 0 0.4em black, 0 0 0.4em black, 0 0 0.4em black, 0 0 0.4em "+shadow;
+						label.div.style.filter = "glow(color="+shadow+", strength=3) DropShadow(Color=#292929, OffX=1, OffY=-1, Positive=1) DropShadow(Color=#292929, OffX=-1, OffY=-1, Positive=1) DropShadow(Color=#292929, OffX=1, OffY=1, Positive=1) DropShadow(Color=#292929, OffX=-1, OffY=1, Positive=1) blur(add=false, direction=0, strength=1) blur(add=false, direction=90, strength=1) blur(add=false, direction=180, strength=1) blur(add=false, direction=270, strength=1)";
+						map.updateByPlaceLabel(point,label.elements,2);
+					}
+				}
+			}
+			for( var i=0; i<map.labels.length; i++ ){
+				var l = map.labels[i];
+				l.selected = false;				
+				var div = document.createElement("div");
+				div.setAttribute('class','tagCloudItem');
+				div.style.color = color;
+				var fs = 2*l.elements.length/1000;
+				if( l.place == "all" ){
+					fs = 0;
+				}
+				if( fs > 2 ){
+
+
+					fs = 2;
+				}
+
+
+
+
+
+				window.appendChild(div);
+				div.style.fontSize = (1+fs)+"em";
+				div.style.textShadow = "0 0 0.4em black, 0 0 0.4em black, 0 0 0.4em black, 0 0 0.4em "+shadow;			
+				div.style.filter = "glow(color="+shadow+", strength=3) DropShadow(Color=#292929, OffX=1, OffY=-1, Positive=1) DropShadow(Color=#292929, OffX=-1, OffY=-1, Positive=1) DropShadow(Color=#292929, OffX=1, OffY=1, Positive=1) DropShadow(Color=#292929, OffX=-1, OffY=1, Positive=1) blur(add=false, direction=0, strength=1) blur(add=false, direction=90, strength=1) blur(add=false, direction=180, strength=1) blur(add=false, direction=270, strength=1)";
+				div.innerHTML = l.place + "<span style='font-size:"+(1-fs/(1+fs))+"em'>&nbsp;(" + l.elements.length + ")</span>";
+				l.div = div;
+				var point = map.lastHovered; 
+				clickFunction(point,l);
+			}			
+			var createDiv = function( mod, div ){
+				var height = 0;
+				var width = 0;
+				for( var i=0; i<map.labels.length; i++ ){
+					if( i%2 == mod ){ 
+						height += map.labels[i].div.offsetHeight;
+						if( map.labels[i].div.offsetWidth > width ){
+							width = map.labels[i].div.offsetWidth;
+						}
+						if( i>1 ){
+							height += 5;
+						}
+					}
+				}
+				div.style.width = width+"px";
+				div.style.height = height+"px";
+				height = 0;
+				for( var i=0; i<map.labels.length; i++ ){
+					if( i%2 == mod ){ 
+						var h = map.labels[i].div.offsetHeight;
+						div.appendChild(map.labels[i].div);
+						if( mod == 0 ){
+							map.labels[i].div.style.right = "0px";
+						}
+						else {
+							map.labels[i].div.style.left = "0px";
+						}
+						map.labels[i].div.style.top = height+"px";
+						height += h+5;
+					}
+				}
+			}
+			map.leftTagCloudDiv.innerHTML = "";
+			map.rightTagCloudDiv.innerHTML = "";
+			createDiv(0,map.leftTagCloudDiv);			
+			createDiv(1,map.rightTagCloudDiv);
+			map.placeTagCloud(map.lastHovered);
+		}
+
+		// manages hover selection of point objects
+        var hoverSelect = function(event){
+        	if( map.pointSelected ){
+        		return;
+        	}
+			map.core.undoHover(true);
+			var index = event.feature.index;
+			map.lastHovered = map.displayPointSet[Math.floor(map.openlayersMap.getZoom()+0.05)][index];
+			calculateTagCloud();
+			map.updateByPlace([map.lastHovered], 1);
+        };
+        var hoverUnselect = function(event){
+        	map.hoverUnselect();
+        };
+        var highlightCtrl = new OpenLayers.Control.SelectFeature(this.objectLayer, {
+            hover: true,
+            highlightOnly: true,
+            renderIntent: "temporary",
+            eventListeners: {
+                featurehighlighted: hoverSelect,
+                featureunhighlighted: hoverUnselect
+            }
+        });
+        this.openlayersMap.addControl(highlightCtrl);
+        highlightCtrl.activate();
+        
+        this.selectFeature = new OpenLayers.Control.SelectFeature(this.objectLayer);
+
+		// manages click selection of point objects
+        var onFeatureSelect = function(event){
+        	if( map.pointSelected ){
+        		return;
+        	}
+        	hoverUnselect();
+			map.openlayersMap.setCenter(event.feature.geometry.getBounds().getCenterLonLat());
+			var index = event.feature.index;
+            var point = map.displayPointSet[Math.floor(map.openlayersMap.getZoom()+0.05)][index];
+			map.placeTagCloud(point);
+			map.pointClickDiv.style.visibility = "visible";
+			map.polygons = [];
+			placeToolbar();
+			changeLabelSelection(point,map.labels[map.labels.length-1],false);
+        }
+        this.objectLayer.events.on({ "featureselected": onFeatureSelect });
+        this.openlayersMap.addControl(this.selectFeature);
+        this.selectFeature.activate();
+
+		if( this.core.props.addElements ){
+			this.addCrossImage = document.createElement("img");
+			this.addCrossImage.src = "images/cross.png";
+			this.addCrossImage.setAttribute('class','addCross');
+  			this.addCrossImage.style.visibility = "hidden";
+			window.appendChild(this.addCrossImage);
+
+			this.addCrossImage.onclick = function(e){
+            	var mousePos = getMousePosition(e);
+            	var pixel = new OpenLayers.Pixel( 
+            		mousePos.left - window.offsetLeft,
+            		mousePos.top - window.offsetTop
+            	);
+            	var position = map.openlayersMap.getLonLatFromPixel(pixel);
+            	var point = new OpenLayers.Geometry.Point(
+            		position.lon,	
+            		position.lat
+            	);
+            	if (map.pointToAdd != null){ 
+                	map.drilldownLayer.removeFeatures([map.pointToAdd]);
+				}
+            	map.pointToAdd = new OpenLayers.Feature.Vector(point);
+            	map.drilldownLayer.addFeatures([map.pointToAdd]);
+            	point.transform(map.openlayersMap.projection, map.openlayersMap.displayProjection);
+            	setAddElementContext(point.x,point.y,mousePos.left,mousePos.top,window.offsetWidth,window.offsetHeight);
+        	}
+		
+			// manages movement of the add cross
+        	this.mapMouseMove = function(e){
+        	    var mousePos = getMousePosition(e);
+            	var left = mousePos.left - window.offsetLeft - 7;
+            	var top = mousePos.top - window.offsetTop - 6;
+            	var visibility = map.addCrossImage.style.visibility;
+            	if( left < 0 || left+14 > window.offsetWidth || top < 0 || top+12 > window.offsetHeight ){
+            		if( visibility == "visible" ){
+            			map.addCrossImage.style.visibility = "hidden";
+            		}
+            	}
+            	else {
+            		if( visibility == "hidden" ){
+            			map.addCrossImage.style.visibility = "visible";
+            		}
+            		map.addCrossImage.style.left = left+"px";
+            		map.addCrossImage.style.top = top+"px";
+				}
+        	}        
+        }
+        
+        if( this.core.props.historicMaps ){
+        	this.setCanvas();
+        }
+        
+    },
+    
+    /**
+     * parses all base layers in a given xmlFile and initializes google and osm layers
+     * @param {String} xmlFile the name of the file to parse
+     */
+    parseBaseLayers: function(xmlFile){
+		this.baseLayers = [];
+		if( this.core.props.historicMaps ){
+        var xmlhttp = false;
+        if (!xmlhttp) 
+            try {
+                xmlhttp = new XMLHttpRequest();
+            } 
+            catch (e) {
+                xmlhttp = false;
+            }
+        if (typeof ActiveXObject != "undefined") {
+            if (!xmlhttp) 
+                try {
+                    xmlhttp = new ActiveXObject("MSXML2.XMLHTTP");
+                } 
+                catch (e) {
+                    xmlhttp = false;
+                }
+            if (!xmlhttp) 
+                try {
+                    xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
+                } 
+                catch (e) {
+                    xmlhttp = false;
+                }
+        }
+        if (!xmlhttp) 
+            try {
+                xmlhttp = createRequest();
+            } 
+            catch (e) {
+                xmlhttp = false;
+            }
+        
+        xmlhttp.open("GET", xmlFile, false);
+        xmlhttp.send("");
+        xmlDoc = xmlhttp.responseXML;
+        
+        var wmsLayers = xmlDoc.getElementsByTagName("wms");
+        for (i = 0; i < wmsLayers.length; i++) {
+            var name = wmsLayers[i].getElementsByTagName("name")[0].childNodes[0].nodeValue;
+            var server = wmsLayers[i].getElementsByTagName("server")[0].childNodes[0].nodeValue;
+            var layer = wmsLayers[i].getElementsByTagName("layer")[0].childNodes[0].nodeValue;
+            var format = wmsLayers[i].getElementsByTagName("format")[0].childNodes[0].nodeValue;
+            var transparency = wmsLayers[i].getElementsByTagName("transparency")[0].childNodes[0].nodeValue;
+            var layer = new OpenLayers.Layer.WMS(name, server, {
+                layers: layer,
+                format: format,
+                transparent: transparency
+            }, {
+                isBaseLayer: true
+            });
+            this.baseLayers.push(layer);
+        }
+		}
+		
+
+		if( this.core.props.googleMaps ){
+        this.baseLayers.push( new OpenLayers.Layer.Google("Google Physical", {type: G_PHYSICAL_MAP, 'sphericalMercator': true} ) );        
+		this.baseLayers.push( new OpenLayers.Layer.Google( 'Google Streets', { 'sphericalMercator': true } ) );
+		this.baseLayers.push( new OpenLayers.Layer.Google( 'Google Satellite', { type: G_SATELLITE_MAP, 'sphericalMercator': true } ) );
+		this.baseLayers.push( new OpenLayers.Layer.Google( 'Google Hybrid', { type: G_HYBRID_MAP, 'sphericalMercator': true } ) );
+		}
+		
+		if( this.core.props.bingMaps ){
+		this.baseLayers.push( new OpenLayers.Layer.VirtualEarth("Bing Streets", { type: VEMapStyle.Shaded, 'sphericalMercator': true } ) );
+        this.baseLayers.push( new OpenLayers.Layer.VirtualEarth("Bing Aerial", { type: VEMapStyle.Aerial, 'sphericalMercator': true } ) );
+        this.baseLayers.push( new OpenLayers.Layer.VirtualEarth("Bing Hybrid", { type: VEMapStyle.Hybrid, 'sphericalMercator': true } ) );
+        }
+        /*
+		if( this.core.props.osmMaps ){
+		this.baseLayers.push( new OpenLayers.Layer.OSM( 'Open Street Map' ) );
+		this.baseLayers.push( new OpenLayers.Layer.OSM( 'OSM Tiles@Home', 'http://tah.openstreetmap.org/Tiles/tile/${z}/${x}/${y}.png' ) );
+		}
+		*/		
+    },
+    
+    /**
+     * sets the background canvas of the map window (or resets it after resizing the browser window)
+     */
+    setCanvas: function(){
+        var mapWindow = document.getElementById(this.window);
+        var cv = document.getElementById("mapCanvas");
+        if (cv == null) {
+            cv = document.createElement("canvas");
+            cv.id = "mapCanvas";
+            mapWindow.appendChild(cv);
+        }
+        cv.width = document.getElementById(this.container).clientWidth;
+        cv.height = document.getElementById(this.container).clientHeight;
+        if (!cv.getContext && G_vmlCanvasManager) 
+            cv = G_vmlCanvasManager.initElement(cv);
+        var ctx = cv.getContext('2d');
+        var gradient = ctx.createLinearGradient(0, 0, 0, cv.height);
+        gradient.addColorStop(0, '#8bafd8');
+        gradient.addColorStop(1, '#355272');
+        ctx.fillStyle = gradient;
+        ctx.fillRect(0, 0, cv.width, cv.height);
+    },
+    
+    /**
+     * draws the object layer.
+	 * @param {boolean} zoom if there was a zoom; if not, the new boundary of the map is calculated
+     */
+    drawObjectLayer: function(zoom){
+		if( this.displayPointSet == undefined ){
+			return;
+		}
+	this.hoverUnselect();
+        this.objectLayer.removeAllFeatures();
+        if (!zoom) {
+            var minLat, maxLat, minLon, maxLon;
+            var points = this.displayPointSet[this.openlayersMap.getNumZoomLevels() - 1];
+            for (var i = 0; i < points.length; i++) {
+                var point = points[i];
+                if (!minLon || point.originX < minLon) 
+                    minLon = point.originX;
+                if (!maxLon || point.originX > maxLon) 
+                    maxLon = point.originX;
+                if (!minLat || point.originY < minLat) 
+                    minLat = point.originY;
+                if (!maxLat || point.originY > maxLat) 
+                    maxLat = point.originY;
+            }
+            if (minLon == maxLon && minLat == maxLat) {
+                this.openlayersMap.setCenter(new OpenLayers.LonLat(minLon, minLat));
+            }
+            else {
+            	var gapX = 0.1 * ( maxLon - minLon );
+            	var gapY = 0.1 * ( maxLat - minLat );
+                this.openlayersMap.zoomToExtent(new OpenLayers.Bounds(minLon-gapX, minLat-gapY, maxLon+gapX, maxLat+gapY));
+                this.openlayersMap.zoomTo(Math.floor(this.openlayersMap.getZoom()+0.05));
+            }
+            setMapZoom(this.openlayersMap.getZoom()/this.openlayersMap.numZoomLevels);
+		if( this.openlayersMap.getZoom() == this.openlayersMap.numZoomLevels - 1 ){
+		        this.openlayersMap.zoomTo(2);
+		    	setMapZoom(2/this.openlayersMap.numZoomLevels);
+		}
+        }
+
+        var points = this.displayPointSet[Math.floor(this.openlayersMap.getZoom()+0.05)];
+        for (var i = 0; i < points.length; i++) {
+        	var resolution = this.openlayersMap.getResolution();
+        	var p = points[i];
+        	var x = p.originX + resolution * p.shiftX; 
+        	var y = p.originY + resolution * p.shiftY;
+        	p.pointFeature.geometry.x = x;
+        	p.pointFeature.geometry.y = y;
+        	p.olPointFeature.geometry.x = x;
+        	p.olPointFeature.geometry.y = y;
+            this.objectLayer.addFeatures([p.pointFeature]);
+            this.objectLayer.addFeatures([p.olPointFeature]);
+        }
+        
+        var dist = function(p1,p2){
+        	return Math.sqrt( (p1.x-p2.x)*(p1.x-p2.x) + (p1.y-p2.y)*(p1.y-p2.y) );
+        }
+        
+        for (var i = 0; i < this.connections.length; i++) 
+            this.connections[i] = [];
+        var slices = this.core.timeplot.getSlices();
+        for (var i = 0; i < slices.length; i++) {
+            for (var j = 0; j < slices[i].elements.length; j++) {
+            	var e = slices[i].elements[j]; 
+                if (e.length == 0) 
+                    continue;
+                var points = [];
+                for (var k = 0; k < e.length; k++) {
+                	var point = e[k].pointobjects[Math.floor(this.openlayersMap.getZoom())].pointFeature.geometry;                	
+                	if( points.indexOf(point) == -1 ){
+               			points.push(point);
+                	}
+                }
+                var matrix = new AdjMatrix(points.length);
+                for (var k = 0; k < points.length-1; k++) {
+                	for (var l = k+1; l < points.length; l++) {
+                    	matrix.setEdge(k,l,dist(points[k],points[l]));
+                    }
+                }
+				var tree = Prim(matrix);
+				var lines = [];
+				for( var z=0; z<tree.length; z++ ){
+					lines.push(new OpenLayers.Geometry.LineString(new Array(points[tree[z].v1],points[tree[z].v2])));
+				}
+                this.connections[j].push({
+                	first: e[0].pointobjects[Math.floor(this.openlayersMap.getZoom()+0.05)].pointFeature.geometry,
+                	last: e[e.length-1].pointobjects[Math.floor(this.openlayersMap.getZoom()+0.05)].pointFeature.geometry,
+                    lines: lines,
+                    time: slices[i].date
+                });
+            }
+        }
+        this.updateMap();			
+    },
+    
+    /**
+     * initializes the object layer.
+     * all point representations for all zoom levels are calculated and initialized
+	 * @param {DataSet[]} dataSets the datasets which contain all objects to display on the map
+     */
+    initObjectLayer: function(dataSets){
+
+    	this.clearMap();
+    
+        var map = this;
+        
+        var getPointCluster = function(dataSets){
+
+       		maximumRadius = minimumRadius;
+            var zoomLevels = map.openlayersMap.getNumZoomLevels();
+			var getMaxRadius = function(size){
+                var exponent = 0;
+                while (Math.pow(classBase, exponent) < size) 
+                    exponent++;
+                return minimumRadius + exponent;
+			}
+
+			var dd = new HierarchicalClustering(-20037508.34,-20037508.34,20037508.34,20037508.34);
+            for (var i = 0; i < dataSets.length; i++){
+               	for (var j = 0; j < dataSets[i].objects.length; j++) {
+                   	var p = new OpenLayers.Geometry.Point(dataSets[i].objects[j].longitude, dataSets[i].objects[j].latitude, null);
+                   	p.transform(map.openlayersMap.displayProjection, map.openlayersMap.projection);
+                   	var point = new Vertex(Math.floor(p.x), Math.floor(p.y));
+                   	var objects = [];
+                   	for( var k=0; k<dataSets.length; k++ ){
+                   		objects.push([]);
+                   	}
+                   	objects[i].push(dataSets[i].objects[j]);
+					point.setElements(objects);
+					dd.add(point);
+               	}
+               	var r = getMaxRadius(dataSets[i].objects.length);
+               	if( r > maximumRadius ){
+               		maximumRadius = r;
+               		maximumPoints = dataSets[i].objects.length;
+               	}
+           	}
+
+            var displayPoints = [];
+            for (var i = 0; i < zoomLevels; i++) {
+                var points = [];
+                var resolution = map.openlayersMap.getResolutionForZoom(zoomLevels - i - 1);
+                dd.mergeForResolution(resolution);
+                for (var j = 0; j < dd.vertices.length; j++) {
+                	var point = dd.vertices[j];
+                	if( !point.legal ){
+                		continue;
+                	}
+                    var balls = [];
+                    for (var k = 0; k < point.elements.length; k++){                    	
+                        if (point.elements[k].length > 0){
+                            balls.push({
+                                search: k,
+                                elements: point.elements[k],
+                                radius: point.radii[k]
+                            });                        	
+                        }
+                    }
+                   	var orderBalls = function( b1, b2 ){
+                		if ( b1.radius > b2.radius ){
+                			return -1;
+                		}
+                		if ( b2.radius > b1.radius ){
+                			return 1;
+                		}
+                		return 0;
+                	}
+                    if (balls.length == 1) {
+                        points.push(new DisplayPointObject(point.x, point.y, 0, 0, balls[0].elements, balls[0].radius, balls[0].search));
+                    }
+                    else 
+                        if (balls.length == 2) {
+                            var r1 = balls[0].radius;
+                            var r2 = balls[1].radius;
+                            points.push(new DisplayPointObject(point.x, point.y, -1*r2, 0, balls[0].elements, r1, balls[0].search));
+                            points.push(new DisplayPointObject(point.x, point.y, r1, 0, balls[1].elements, r2, balls[1].search));
+                        }
+                        else 
+                            if (balls.length == 3) {
+                                var r1 = balls[0].radius;
+                                var r2 = balls[1].radius;
+                                var r3 = balls[2].radius;
+                                var d = (2 / 3 * Math.sqrt(3) - 1) / 2;
+                                points.push(new DisplayPointObject(point.x, point.y, -2*d*r1-r1, 0, balls[0].elements, r1, balls[0].search));
+                                points.push(new DisplayPointObject(point.x, point.y, r2/2, r2, balls[1].elements, r2, balls[1].search));
+                                points.push(new DisplayPointObject(point.x, point.y, r3/2, -1*r3, balls[2].elements, r3, balls[2].search));
+                            }
+                            else 
+                                if (balls.length == 4) {
+                		    balls.sort(orderBalls);                    
+                                    var r1 = balls[0].radius;
+                                    var r2 = balls[1].radius;
+                                    var r3 = balls[2].radius;
+                                    var r4 = balls[3].radius;
+                                    var d = (Math.sqrt(2) - 1)*r2;
+                                    points.push(new DisplayPointObject(point.x, point.y, -1*d-r2, 0, balls[0].elements, r1, balls[0].search));
+                                    points.push(new DisplayPointObject(point.x, point.y, r1-r2, -1*d-r4, balls[3].elements, r4, balls[3].search));
+                                    points.push(new DisplayPointObject(point.x, point.y, r1-r2, d+r3, balls[2].elements, r3, balls[2].search));
+                                    points.push(new DisplayPointObject(point.x, point.y, d+r1, 0, balls[1].elements, r2, balls[1].search));
+                                }
+                }
+                displayPoints.push(points);
+            }                        
+            return displayPoints.reverse();
+
+        }
+        
+        this.connections = [];
+        for (var i = 0; i < dataSets.length; i++) {
+           	this.connections.push([]);
+           	for (var j = 0; j < dataSets[i].objects.length; j++){ 
+               	dataSets[i].objects[j].pointobjects = [];
+            }
+        }
+
+        this.displayPointSet = getPointCluster(dataSets);
+
+    	if( this.connections.length == 0 || this.displayPointSet.length == 0 ){
+    		return;
+    	}
+            
+        for (var i = 0; i < this.displayPointSet.length; i++) 
+            for (var j = 0; j < this.displayPointSet[i].length; j++) {
+                var point = this.displayPointSet[i][j];
+                for (var k = 0; k < point.elements.length; k++) 
+                    point.elements[k].pointobjects.push(point);
+                var style = {
+                    fillColor: 'rgb(' + colors[point.search].r0 + ',' + colors[point.search].g0 + ',' + colors[point.search].b0 + ')',
+                    fillOpacity: 1,
+				strokeWidth: 1,
+				strokeColor: 'rgb(' + colors[point.search].r1 + ',' + colors[point.search].g1 + ',' + colors[point.search].b1 + ')',
+				stroke: false,
+                    pointRadius: point.radius
+                };
+                var pointGeometry = new OpenLayers.Geometry.Point(point.originX, point.originY, null);
+                var pointFeature = new OpenLayers.Feature.Vector(pointGeometry);
+                pointFeature.style = style;
+                pointFeature.index = j;
+                point.setPointFeature(pointFeature);
+                var olStyle = {
+                    fillColor: 'rgb(' + colors[point.search].r1 + ',' + colors[point.search].g1 + ',' + colors[point.search].b1 + ')',
+                    fillOpacity: 1,
+				stroke: false,
+                    pointRadius: 0
+                };
+                var olPointGeometry = new OpenLayers.Geometry.Point(point.originX, point.originY, null);
+                var olPointFeature = new OpenLayers.Feature.Vector(olPointGeometry);
+                olPointFeature.style = olStyle;
+                olPointFeature.index = j;
+                point.setOlPointFeature(olPointFeature);
+            }
+    	
+        this.drawObjectLayer(false);
+        
+    },
+
+    /**
+     * hides all tagCloud and pointclick divs
+     */
+	setVisibility: function(visibility){
+        this.toolbar.style.visibility = visibility;
+       	this.leftTagCloudDiv.style.visibility = visibility;
+       	this.rightTagCloudDiv.style.visibility = visibility;
+		this.pointClickDiv.style.visibility = visibility;       	
+	},
+    
+    /**
+     * resets the map by destroying all additional elements except the point objects, which are replaced
+     */
+    resetMap: function(){
+        this.connectionLayer.destroyFeatures();
+        this.drilldownLayer.destroyFeatures();
+		this.controlLockDiv.style.visibility = "hidden";
+		this.selectFeature.unselectAll();
+        this.resetPoints();
+  		this.deactivate("drag");
+	    this.drag.style.visibility = "hidden";		
+		this.setVisibility("hidden");
+		this.pointSelected = false;
+		this.polygons = [];
+    },
+    
+    /**
+     * resets the map by destroying all elements
+     */
+    clearMap: function(){
+        this.connectionLayer.destroyFeatures();
+        this.drilldownLayer.destroyFeatures();
+        this.objectLayer.destroyFeatures();
+		delete this.displayPointSet;
+        this.displayPointSet = undefined;
+    },
+    
+    /**
+     * updates the proportional selection status of a point object
+     * @param {PointObject} point the point to update
+     * @param {OpenLayers.Geometry.Polygon} polygon the actual displayed map polygon
+     */
+    updatePoint: function(point,polygon){
+		var pFull = 0;
+		var pRest = 0;
+		for (var j = 0; j < point.elements.length; j++) {
+			var o = point.elements[j];
+			if (o.percentage == 1 || ( o.hoverSelect && this.lastHovered == undefined ) ) {
+				pFull++;
+			}
+			else {
+				pRest += o.percentage;
+			}
+		}
+		var drawOl = false;
+		var draw = false;
+		var pf = point.pointFeature;
+		var olf = point.olPointFeature;
+		if (pFull == 0 && olf.style.pointRadius != 0) {
+			olf.style.pointRadius = 0;
+			drawOl = true;
+		}
+		else if (pFull > 0) {
+			/*
+			var noer = pf.style.pointRadius - minimumRadius;
+			var olpr = Math.floor(pFull / point.elements.length * noer) + minimumRadius;
+			if (olpr != olf.style.pointRadius) {
+				olf.style.pointRadius = olpr;
+				drawOl = true;
+			}
+			*/
+			olf.style.pointRadius = getRadius(pFull);
+			drawOl = true;
+		}
+		if (point.percentage != pRest) {
+			point.percentage = pRest;
+			draw = true;
+			var p;
+			if (pRest == 0){
+				p = 0;
+			}
+			else { 
+				p = pRest / (point.elements.length - pFull);
+			}
+			var s = point.search;
+			var r = colors[s].r0 + Math.round(p * (colors[s].r1 - colors[s].r0));
+			var g = colors[s].g0 + Math.round(p * (colors[s].g1 - colors[s].g0));
+			var b = colors[s].b0 + Math.round(p * (colors[s].b1 - colors[s].b0));
+			point.pointFeature.style.fillColor = 'rgb(' + r + ',' + g + ',' + b + ')';
+		}
+		if (polygon.containsPoint(point.pointFeature.geometry)) {
+			if (draw || drawOl) {
+				this.objectLayer.drawFeature(point.pointFeature);
+				this.objectLayer.drawFeature(point.olPointFeature);
+			}
+		}
+    },
+    
+    /**
+     * updates the the object layer of the map after selections had been executed in timeplot or table or zoom level has changed
+     */
+    updateMap: function(){
+        var points = this.displayPointSet[Math.floor(this.openlayersMap.getZoom()+0.05)];
+        var polygon = this.openlayersMap.getExtent().toGeometry();
+        for (var i = 0; i < points.length; i++) {
+        	this.updatePoint(points[i],polygon);
+        }
+        this.displayConnections();
+    },
+    
+    /**
+     * resets the point objects depending on the actual zoom level in basic style
+     */
+    resetPoints: function(){    	
+    	if( this.displayPointSet != undefined ){
+    		if( this.displayPointSet.length == 0 ){
+    			return;
+    		}
+        	var points = this.displayPointSet[Math.floor(this.openlayersMap.getZoom()+0.05)];
+        	for (var i = 0; i < points.length; i++) {
+            	var j = points[i].search;
+            	points[i].pointFeature.style.fillColor = 'rgb(' + colors[j].r0 + ',' + colors[j].g0 + ',' + colors[j].b0 + ')';
+            	points[i].olPointFeature.style.pointRadius = 0;
+        	}
+        	this.objectLayer.redraw();        	
+       	}       	
+    },
+    
+    /**
+     * updates the data objects percentages after a selection on the map had been performed
+     * @param {PointObject[]} pointObjects the point objects that corresponds to the selection
+     * @param {boolean} hover if it was a hover selection
+     */
+    updateByPlace: function(pointObjects, hover){
+        if (hover == 0) {
+            this.core.reset();
+        }
+        for (var i = 0; i < pointObjects.length; i++) {
+            var s = pointObjects[i].search;
+            var c = colors[s].hex;
+            if (hover == 1) {
+                pointObjects[i].pointFeature.style.stroke = true;
+                for (var j = 0; j < pointObjects[i].elements.length; j++) {
+                    pointObjects[i].elements[j].setHover(true);
+                }
+            }
+            else 
+                if (hover == 2) {
+                    pointObjects[i].pointFeature.style.stroke = false;
+                    for (var j = 0; j < pointObjects[i].elements.length; j++) {
+                        pointObjects[i].elements[j].setHover(false);
+                    }
+                }
+                else {
+                    pointObjects[i].pointFeature.style.fillColor = c;
+                    pointObjects[i].pointFeature.style.stroke = false;
+                    for (var j = 0; j < pointObjects[i].elements.length; j++) {
+                        pointObjects[i].elements[j].setHover(false);
+                        pointObjects[i].elements[j].setPercentage(1);
+                    }
+                }
+            this.objectLayer.drawFeature(pointObjects[i].pointFeature);
+            this.objectLayer.drawFeature(pointObjects[i].olPointFeature);
+        }
+        if( hover == 0 ){
+        	this.core.updateTimeAndTable(false);
+        }
+        else {
+        	this.core.updateTimeAndTable(true);
+        }
+    },
+    
+    /**
+     * updates the data objects percentages after a selection on the map by clicking on a place label
+     * @param {PointObject} point the point object that corresponds to the label selection
+     * @param {DataObject[]} elements the data objects corresponding to the selected label
+     * @param {boolean} hover if it was a hover selection
+     */
+    updateByPlaceLabel: function(point,elements,hover){
+    	if( hover == 0 ){
+			this.core.reset();
+		}
+		this.controlLockDiv.style.visibility = "visible";
+		for (var j = 0; j < elements.length; j++) {
+			if( hover == 0 ){
+				elements[j].setPercentage(1);
+			}
+			else if( hover == 1 ){
+				elements[j].hoverSelect = true;
+			} 
+			else if( hover == 2 ){
+				elements[j].hoverSelect = false;
+			} 
+		}
+		this.setVisibility("visible");
+		this.pointSelected = true;
+		this.updatePoint(point,this.openlayersMap.getExtent().toGeometry());
+        if( hover == 0 ){
+        	this.core.updateTimeAndTable(false);
+        }
+        else {
+        	this.core.updateTimeAndTable(true);
+        }
+    },    
+    
+    /**
+     * displays connections between data objects
+     */
+    displayConnections: function(){
+        var ltm = this.core.timeplot.leftFlagTime;
+        var rtm = this.core.timeplot.rightFlagTime;
+        if (ltm == undefined || ltm == null){
+            return;
+		}
+        else {
+            ltm = ltm.getTime();
+            rtm = rtm.getTime();
+        }
+        this.connectionLayer.destroyFeatures();
+        if (this.showConnections) {
+            for (var i = 0; i < this.connections.length; i++) {
+                var c = colors[i];
+                var style = {
+                    strokeColor: 'rgb(' + c.r1 + ',' + c.g1 + ',' + c.b1 + ')',
+                    strokeOpacity: 0.5,
+                    strokeWidth: 3	
+                };
+                var pointsToConnect = [];
+                var last = undefined;
+                for (var j = 0; j < this.connections[i].length; j++) {
+                	var c = this.connections[i][j];
+                    var ct = c.time.getTime();
+					if (ct >= ltm && ct <= rtm) {
+						if( last != undefined ){
+                			var line = new OpenLayers.Geometry.LineString(new Array(last,c.first));
+                			this.connectionLayer.addFeatures([new OpenLayers.Feature.Vector(line, null, style)]);
+						}
+						for( var k=0; k<c.lines.length; k++ ){
+                			this.connectionLayer.addFeatures([new OpenLayers.Feature.Vector(c.lines[k], null, style)]);							
+						}
+						last = c.last;
+                    }
+                }
+            }
+            this.connectionLayer.redraw();
+        }
+    },
+
+    /**
+     * causes deselection of a hovered point object
+     */
+	hoverUnselect: function(){
+        if( this.pointSelected ){
+        	return;
+        }
+		if (this.lastHovered != undefined) {
+        	this.leftTagCloudDiv.style.visibility = "hidden";
+        	this.rightTagCloudDiv.style.visibility = "hidden";
+			this.updateByPlace([this.lastHovered], 2);
+            this.lastHovered = undefined;
+		}
+	},
+	
+    /**
+     * places the tagCloud divs inside the map window
+     * @param {PointObject} point the point object that corresponds to the tagCloud
+     */
+	placeTagCloud: function( point ){
+		var lonlat = new OpenLayers.LonLat( point.pointFeature.geometry.x, point.pointFeature.geometry.y );
+		var pixel = this.openlayersMap.getPixelFromLonLat(lonlat);
+		var radius = point.pointFeature.style.pointRadius;
+		var window = document.getElementById(this.window);			
+		var lw = this.leftTagCloudDiv.offsetWidth;
+		var rw = this.rightTagCloudDiv.offsetWidth;
+		var lp = false;
+		var rp = false;		
+		if( pixel.x - radius - lw -5 < 0 ){
+			lp = true;
+			if( pixel.x + radius + lw + rw + 10 > window.offsetWidth ){
+				rp = true;
+			}
+		}
+		else if( pixel.x + radius + rw + 5 > window.offsetWidth ){
+			rp = true;
+			if( pixel.x - radius - lw - rw - 10 < 0 ){
+				lp = true;
+			}
+		}			
+		if( !lp && !rp ){
+			this.leftTagCloudDiv.style.left = (pixel.x-radius-lw-5)+"px";
+			this.rightTagCloudDiv.style.left = (pixel.x+radius+5)+"px";
+		}
+		else if( lp && !rp ){
+			this.leftTagCloudDiv.style.left = (pixel.x+radius+5)+"px";
+			this.rightTagCloudDiv.style.left = (pixel.x+radius+lw+10)+"px";
+		}
+		else if( !lp && rp ){
+			this.leftTagCloudDiv.style.left = (pixel.x-radius-lw-rw-10)+"px";
+			this.rightTagCloudDiv.style.left = (pixel.x-radius-rw-5)+"px";
+		}
+		var lh = this.leftTagCloudDiv.offsetHeight;
+		var rh = this.rightTagCloudDiv.offsetHeight;
+		var lt = pixel.y - lh/2; 
+		var rt = pixel.y - rh/2;
+		if( lt < 0 ){
+			lt = 0;
+		}
+		else if( lt + lh > window.offsetHeight ){
+			lt = window.offsetHeight - lh;
+		}
+		if( rt < 0 ){
+			rt = 0;
+		}
+		else if( rt + rh > window.offsetHeight ){
+			rt = window.offsetHeight - rh;
+		}
+		this.leftTagCloudDiv.style.top = lt+"px";
+		this.rightTagCloudDiv.style.top = rt+"px";
+		this.leftTagCloudDiv.style.visibility = "visible";
+		this.rightTagCloudDiv.style.visibility = "visible";
+		
+		this.pointClickDiv.style.height = (lh+45)+"px";
+		this.pointClickDiv.style.width = (lw+rw+2*radius+70)+"px"; 
+		this.pointClickDiv.style.left = (this.leftTagCloudDiv.offsetLeft-30)+"px";
+		this.pointClickDiv.style.top = (lt-30)+"px"; 
+	},
+	
+    /**
+     * activates a specific map control
+     * @param {String} status the identifier of the control to activate
+     */
+    activate: function(status){
+    	this.activeControl = status;
+   		if( status == "drag" ){
+			this.dragArea.activate();
+			this.drilldownLayer.setZIndex(parseInt(this.objectLayer.getZIndex())+1);
+       		this.drag.style.backgroundImage = "url(images/dragger-click.png)";
+		}
+		else if( status == "polygon" ){
+			this.drawPolygon.activate();
+		}
+		else if( status == "circle" ){
+			this.drawCircle.activate();
+		}
+		else if( status == "country" ){
+			this.selectCountry.activate();
+		}
+		else if( status == "add" ){
+			document.onmousemove = this.mapMouseMove;
+		}
+	},
+    
+    /**
+     * deactivates a specific map control
+     * @param {String} status the identifier of the control to deactivate
+     */
+    deactivate: function(status){
+		if( status == "drag" ){
+			this.dragArea.deactivate();
+			this.drilldownLayer.setZIndex(parseInt(this.objectLayer.getZIndex())-1);
+       		this.drag.style.backgroundImage = "url(images/dragger.png)";
+		}
+		else if( status == "polygon" ){
+			this.drawPolygon.deactivate();
+		}
+		else if( status == "circle" ){
+			this.drawCircle.deactivate();
+		}
+		else if( status == "country" ){
+			this.selectCountry.deactivate();
+		}
+		else if( status == "add" ){
+			document.onmousemove = null;
+			this.addCrossImage.style.visibility = "hidden";		
+		}
+	},
+	
+    /**
+     * inverts the show connection status
+     * @return boolean value if connections are enabled or not
+     */
+	connectionsClick: function(){
+		this.showConnections = !this.showConnections;
+		this.displayConnections();
+		return this.showConnections;
+	},
+	
+    /**
+     * performs a zoom on the map
+     * @param {int} delta the change of zoom levels
+     */
+	zoom: function( delta ){
+		if( this.pointSelected ){
+			return false;
+		}
+		var zoom = delta*this.openlayersMap.numZoomLevels;
+		if( this.openlayersMap.baseLayer instanceof OpenLayers.Layer.WMS ){
+			this.openlayersMap.zoomTo(zoom);	
+		}
+		else {
+			this.openlayersMap.zoomTo(Math.round(zoom));
+			
+		}
+		this.drawObjectLayer(true);
+		return true;
+	},
+	
+	setMap: function(index){
+		if (this.baseLayers[index] instanceof OpenLayers.Layer.WMS) {
+			this.openlayersMap.fractionalZoom = true;
+			this.selectCountry.protocol = OpenLayers.Protocol.WFS.fromWMSLayer(this.baseLayers[index]);
+		}
+		else {
+			this.openlayersMap.fractionalZoom = false;
+		}
+		this.openlayersMap.zoomTo(Math.floor(this.openlayersMap.getZoom()+0.05));
+		this.openlayersMap.setBaseLayer(this.baseLayers[index]);
+	},
+
+	configure: function(zoom,cLon,cLat,mapId){
+		this.openlayersMap.zoomTo(zoom);
+		this.drawObjectLayer(true);
+		this.setMap(mapId);
+		this.openlayersMap.setCenter(new OpenLayers.LonLat(cLon,cLat));
+		setMapZoom(this.openlayersMap.zoom/this.openlayersMap.numZoomLevels);
+	}
+
+}