view war/scripts/sti/STIMap.js @ 61:eac73bf1ce6e CellTable

add overlay functionality (beta)
author Sebastian Kruse <skruse@mpiwg-berlin.mpg.de>
date Fri, 14 Dec 2012 16:33:36 +0100
parents 5ef409e34638
children d69066d16e45
line wrap: on
line source

/**
 * 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.overlayLayers;
    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(){
    	
    	this.overlayLayers = new Array();

        //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: google.maps.MapTypeId.TERRAIN, 'sphericalMercator': true} ) );        
		this.baseLayers.push( new OpenLayers.Layer.Google( 'Google Streets', { 'sphericalMercator': true } ) );
		this.baseLayers.push( new OpenLayers.Layer.Google( 'Google Satellite', { type: google.maps.MapTypeId.SATELLITE, 'sphericalMercator': true } ) );
		this.baseLayers.push( new OpenLayers.Layer.Google( 'Google Hybrid', { type: google.maps.MapTypeId.HYBRID, '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 } ) );
        }
		/* Was commented out, no idea, why? */
		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";
            cv.className = "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);
        /* OLD GRADIENTS */
        /* gradient.addColorStop(0, '#8bafd8');
         * gradient.addColorStop(1, '#355272');
         */
        /* new gradients: dark DARIAH theme (2012-07-19 SUBGOE Stefan E. Funk) */
        gradient.addColorStop(0, '#68635d');                                            
        gradient.addColorStop(1, '#46413a');  
        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]);
	},
	
	setOverlay: function(index){

		if (this.overlayLayers[index] instanceof OpenLayers.Layer.Vector) {

			this.openlayersMap.removeLayer(this.overlayLayers[index]);
			this.overlayLayers[index] = null;
			
		} else {
			
			var limesLayer = new OpenLayers.Layer.Vector("KML", {
				projection: this.openlayersMap.displayProjection,
	            strategies: [new OpenLayers.Strategy.Fixed()],
	            protocol: new OpenLayers.Protocol.HTTP({
	                url: "data/overlay/limes.kml",
	                format: new OpenLayers.Format.KML({
	                    extractStyles: true,
	                    extractAttributes: true
	                })
	            })
	        });
	        this.openlayersMap.addLayer(limesLayer);
	        
	        this.overlayLayers[index] = limesLayer;
	        
	        //limesLayer.setVisibility(true);
		}
	},		

	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);
	}

}