  var ICON_IMAGE_TYPE1 = "images/mm_20_silver.png";
  var ICON_IMAGE_TYPE2 = "images/mm_20_orange.png";
  var ICON_IMAGE_TYPE1_2 = "images/mm_20_red.png";
  var ICON_IMAGE_SHADOW = "images/mm_20_shadow.png";

  var detLocType = function(inst, type) {
     if (inst.type != undefined) {
	for ( var i in inst.type) {
		if (inst.type[i] == type) {
			return true;
		}
	}
     }
     return false;
  };
  

  //the google map div
  var mapframe;
  var map;
  var mapbox;
  var mapinfowindow;
  
  var scrollMap = function(){
      //if (mapbox.style.position == 'relative') {
           var bt = document.body.scrollTop;
		   var et = document.documentElement ? document.documentElement.scrollTop :	null;
		
           var top = (bt || et) - 185; 
           mapbox.style.top = (top > 0 ? top : 0) + 'px';
      //}
  }; 
  
  var initDiv = function(){
      mapframe = document.getElementById('mapframe');
      mapframe.style.height = mapframe.parentNode.scrollHeight+'px';
      mapframe.style.display = 'block';
      
      mapbox = document.getElementById("mapbox");
      
      mapframe.style.position="relative";
      mapbox.style.position="relative";
      
      window.onscroll = scrollMap; 
  };
 
  
  //initialize the map
  var initialize = function() {
    
    initDiv();
    
	var styleWhite = [
	   {
	     featureType: "all",
	     elementType: "all",
	     stylers: [
	       { visibility: "off" }
	     ]
	   },{
	     featureType: "water",
	     elementType: "all",
	     stylers: [
	       { visibility: "simplified" }
	     ]
	   },{
	     featureType: "administrative.country",
	     elementType: "all",
	     stylers: [
	       { visibility: "simplified" }
	     ]
	   },{
	     featureType: "all",
	     elementType: "all",
	     stylers: [

	     ]
	   }
	 ];
	
	var styleGreen = [
	                  {
	                	    featureType: "all",
	                	    elementType: "all",
	                	    stylers: [
	                	      { visibility: "off" },
	                	      { hue: "#08ff00" },
	                	      { saturation: 100 }
	                	    ]
	                	  },{
	                	    featureType: "water",
	                	    elementType: "all",
	                	    stylers: [
	                	      { visibility: "simplified" },
	                	      { hue: "#0019ff" },
	                	      { saturation: 99 },
	                	      { lightness: -49 }
	                	    ]
	                	  },{
	                	    featureType: "administrative.locality",
	                	    elementType: "all",
	                	    stylers: [
	                	      { visibility: "on" },
	                	      { saturation: -100 },
	                	      { gamma: 4.41 },
	                	      { lightness: 70 }
	                	    ]
	                	  },{
	                	    featureType: "administrative.country",
	                	    elementType: "all",
	                	    stylers: [
	                	      { visibility: "simplified" },
	                	      { hue: "#6600ff" },
	                	      { saturation: -78 }
	                	    ]
	                	  }
	                	];
	           	

	// get container
	var latlng = new google.maps.LatLng(51, 9.5);
	var myOptions = {
		zoom : 5,
		center : latlng,
		mapTypeControlOptions : {
			mapTypeIds : [ google.maps.MapTypeId.ROADMAP, google.maps.MapTypeId.HYBRID, google.maps.MapTypeId.TERRAIN, google.maps.MapTypeId.SATELLITE, 'relief', 'white', 'green']
		}
	};
	map = new google.maps.Map(document.getElementById("googlemap"),
			myOptions);

	
	var whiteMap = new google.maps.StyledMapType(styleWhite, {name : "White"});
	map.mapTypes.set('white', whiteMap);

	var whiteMap = new google.maps.StyledMapType(styleGreen, {name : "Green"});
	map.mapTypes.set('green', whiteMap);
	
	var reliefMap = new google.maps.ImageMapType({
		    getTileUrl: function(a,b) {return "http://maps-for-free.com/layer/relief/z" + b + "/row" + a.y + "/" + b + "_" + a.x + "-" + a.y + ".jpg"; },
		    maxZoom: 12,
		    minZoom: 0,
		    name: "Relief",
		    tileSize: new google.maps.Size(256, 256),
		    isPng: false
	});

    map.mapTypes.set('relief', reliefMap);
    
	map.setMapTypeId(google.maps.MapTypeId.ROADMAP);
	
	//license info for relief layer
	var reliefLicense = document.createElement('DIV');
	reliefLicense.innerHTML = "<a style='color:#7777CC; font:12px Arial,sans-serif' href='http://www.maps-for-free.com/html/about.html' target='_blank'>Relief Licence</a>";
	map.controls[google.maps.ControlPosition.RIGHT_BOTTOM].push(reliefLicense);
	
	// geocoder
	var geocoder = new google.maps.Geocoder();

	// number of the geocoded institutes
	var numGeocoded = 0;

	// number of tries to geocode an institute's address
	var repeat = 0;
	
	// add project
	var addInst = function() {
		if (numGeocoded < institutes.length && institutes[numGeocoded]) {
			var current_inst = institutes[numGeocoded];

			// coordinate of the institute is known, add a marker into map
			if (current_inst.latitude != null && current_inst.longitude != null
					&& current_inst.latitude != ""
					&& current_inst.longitude != "") {
				// add a marker
				var LatLng = new google.maps.LatLng(current_inst.latitude, current_inst.longitude);
				addMarker(LatLng, current_inst);

				// next institute
				numGeocoded++;
				addInst();

			} else {// coordinate of the institute is unknown, call google
				// geocoding service
				// failed 2 times, geocode the city only
				var address = repeat >= 2 ? (current_inst.city + "," + current_inst.country) : (current_inst.street + "," + current_inst.city + "," + current_inst.country);
				geocoder.geocode({'address' : address}, function(results, status) {
					var delay = 0;
					if (status == google.maps.GeocoderStatus.OK) {
						repeat = 0;
						current_inst.latitude = results[0].geometry.location.lat();
						current_inst.longitude = results[0].geometry.location.lng();
					} else if (repeat < 4) {
						repeat++;
						delay = 200;
					} else {// failed 5 times, ignore it, try next institute
						numGeocoded++;
						repeat = 0;
					}
					// pause, then Geocoding
					setTimeout(addInst, delay);
				});
			}
		}
	};

	var allLinks = document.getElementById("contentbox").getElementsByTagName("a");
        
        google.maps.event.addListener(map, 'click', function() {
                if (mapinfowindow){
		      	    mapinfowindow.close();
		      	    mapinfowindow = null;
		        }
        });

	// add marker
	var addMarker = function(LatLng, inst) {
		
		var isType1 = detLocType(inst, 1);
		var isType2 = detLocType(inst, 2);

		var image = ICON_IMAGE_TYPE1_2;
		if (isType1 && isType2) {
			image = ICON_IMAGE_TYPE1_2;
		} else if (isType1) {
			image = ICON_IMAGE_TYPE1;
		} else if (isType2) {
			image = ICON_IMAGE_TYPE2;
        }
		//HTML code of the popup info window
        var info = "<p style='font-weight: bold; width:200px;'><a href = '"+ inst.www + "'>" + inst.university + "</a></p>" +
                       "<a href = 'javascript:map.setCenter(new google.maps.LatLng"+LatLng.toString()+");map.setZoom(15);'>" +
                       inst.street + "<br>" +
                       inst.postcode + ", " + inst.city + ", " + inst.country + "</a>";

		var marker = new google.maps.Marker({
      		       position: LatLng,
      		       map: map,
      		       icon: image
  		});

		google.maps.event.addListener(marker, 'click', function() {
		           if (mapinfowindow){
		      	        mapinfowindow.close();
		      	        mapinfowindow = null;
		           }
                   mapinfowindow = new google.maps.InfoWindow({
    			        content: info
		           });
		       
		           mapinfowindow.open(map,marker);
        });

		var www = inst.www.replace(/^\s*(http:\/\/)?(www\.)?|\/?\s*$/g, '');
		//add mouseover event to links in div contentbox
        for (var k in allLinks){
             if (www && typeof allLinks[k].href == 'string' && allLinks[k].href.replace(/^\s*(http:\/\/)?(www\.)?|\/?\s*$/g, '') == www){
                   //add mouse evente to the institute links
                   google.maps.event.addDomListener(allLinks[k], "mouseover", function(){
                        google.maps.event.trigger(marker, 'click');
                    });
                   google.maps.event.addDomListener(allLinks[k], "mouseout", function(){
                        mapinfowindow.close();
                        mapinfowindow = null;
                    });
             }
        }
	};
	
	addInst();
  };
  
  //load google map
  google.maps.event.addDomListener(window, 'load', initialize);
  
  //pop out
  var move=function(title) {
        //unlock
        mapframe.style.position="absolute";
        mapbox.style.position="absolute";
        //enlarge
        mapbox.style.left="0px";
        //var top = document.body.scrollTop-100;
        //mapbox.style.top=(top > 0 ? top : 0) + "px";
        mapbox.style.width="595px";
        mapbox.style.height="450px";
        //refresh
        var center = map.getCenter();
        //map.checkResize();
        google.maps.event.trigger(map, 'resize');
        map.setCenter(center);
        //set event handle
        title.onclick = function(){restore(title);};
        title.innerHTML= "↙Pop-in"; 
        mapbox.className= "floating"; 
  };
  
  //pop in
  var restore=function(title) {
        //lock
        mapframe.style.position="relative";
        mapbox.style.position="relative";
        mapbox.style.left="";
        mapbox.style.top="";
        //restore
        mapbox.style.width="250px";
        mapbox.style.height="415px";
        //refresh
        var center = map.getCenter();
        //map.checkResize();
        google.maps.event.trigger(map, 'resize');
        map.setCenter(center);
        //set event handle
        title.onclick = function(){move(title);};
        title.innerHTML= "↖Pop-out";
        mapbox.className= "anchored"; 
        scrollMap();        
  };
  //move or resize by mouse drag and drop
  var drag=function(element,event,direction){
        //is mapbox locked
        if ("absolute" != element.style.position)
           return null;
        
        //is bubble event
        if (event.eventPhase == 3) 
           return null;
        else if(!event.eventPhase && event.srcElement.parentNode != element)//IE
           return null;
        //get the current position and size
        var width = parseInt(element.style.width); 
        var height = parseInt(element.style.height);
        var left = parseInt(element.style.left);
        var top = parseInt(element.style.top);
        var X = event.clientX;
        var Y = event.clientY;
        var deltaX = left-X;
        var deltaY = top-Y;
        var deltaW = width-X;
        var deltaH = height-Y;
        var sumW = width+X;
        var sumH = height+Y;
        
        //create a new temp dragable div
        var dragDiv =document.createElement("div");
        dragDiv.style.position="absolute";
        dragDiv.style.left=(left)+"px";
        dragDiv.style.top=(top)+"px";
        dragDiv.style.height=(height)+"px";
        dragDiv.style.width=(width)+"px";
        dragDiv.style.border="1px dotted red";
        dragDiv.style.zIndex="50";
        element.parentNode.appendChild(dragDiv);
       
        //add level 2 event listener
        if(document.addEventListener){
            //add mousemove listener for moving and resizing the mapbox
            eval('document.addEventListener("mousemove",handler'+direction+',true)');
            //add mouseup listener for deleting the level 2 event listener
            document.addEventListener("mouseup",upHandler,true);
        }else{//IE
            eval('document.attachEvent("onmousemove",handler'+direction+')');
            document.attachEvent("onmouseup",upHandler);
        }
        
        //prevent default events
        if(event.preventDefault){
            event.preventDefault();
            event.stopPropagation();
        }else if(event.returnValue){//IE6
            event.returnValue=false;
            event.cancelBubble=true;
        }else{//IE7
            event.preventDefault();
            event.cancelBubble=true;
        }
        
        //mousemove event handle move
        function handlerMV(e){
            if(!e){//IE
                e=window.event;
            }
            dragDiv.style.left=(e.clientX+deltaX)+"px";
            dragDiv.style.top=(e.clientY+deltaY)+"px";
            
            if(e.stopPropagation){
                e.stopPropagation();
            }else{//IE
                e.cancelBubble=true;
            }
        }
        
        //mousemove event handle resize northwest
        function handlerNW(e){
            if(!e){//IE
                e=window.event;
            }
            dragDiv.style.left=(e.clientX+deltaX)+"px";
            dragDiv.style.top=(e.clientY+deltaY)+"px";
            dragDiv.style.width= (sumW-e.clientX)+"px";
            dragDiv.style.height= (sumH-e.clientY)+"px";
           
            if(e.stopPropagation){
                e.stopPropagation();
            }else{//IE
                e.cancelBubble=true;
            }
        }
        
        //mousemove event handle resize north
        function handlerN(e){
            if(!e){//IE
                e=window.event;
            }
            dragDiv.style.top=(e.clientY+deltaY)+"px";
            dragDiv.style.height= (sumH-e.clientY)+"px";
            
            if(e.stopPropagation){
                e.stopPropagation();
            }else{//IE
                e.cancelBubble=true;
            }
        }
        
        //mousemove event handle resize northeast
        function handlerNE(e){
            if(!e){//IE
                e=window.event;
            }
            dragDiv.style.top=(e.clientY+deltaY)+"px";
            dragDiv.style.width= (e.clientX+deltaW)+"px";
            dragDiv.style.height= (sumH-e.clientY)+"px";
            
            if(e.stopPropagation){
                e.stopPropagation();
            }else{//IE
                e.cancelBubble=true;
            }
        }
        
        //mousemove event handle resize west
        function handlerW(e){
            if(!e){//IE
                e=window.event;
            }
            dragDiv.style.left=(e.clientX+deltaX)+"px";
            dragDiv.style.width= (sumW-e.clientX)+"px";
            
            if(e.stopPropagation){
                e.stopPropagation();
            }else{//IE
                e.cancelBubble=true;
            }
        }
        
        //mousemove event handle resize east
        function handlerE(e){
            if(!e){//IE
                e=window.event;
            }
            dragDiv.style.width= (e.clientX+deltaW)+"px";
            
            if(e.stopPropagation){
                e.stopPropagation();
            }else{//IE
                e.cancelBubble=true;
            }
        }
        
        //mousemove event handle resize southwest
        function handlerSW(e){
            if(!e){//IE
                e=window.event;
            }
            dragDiv.style.left=(e.clientX+deltaX)+"px";
            dragDiv.style.width= (sumW-e.clientX)+"px";
            dragDiv.style.height= (e.clientY+deltaH)+"px";
            
            if(e.stopPropagation){
                e.stopPropagation();
            }else{//IE
                e.cancelBubble=true;
            }
        }
        
        //mousemove event handle resize south
        function handlerS(e){
            if(!e){//IE
                e=window.event;
            }
            dragDiv.style.height= (e.clientY+deltaH)+"px";
            
            if(e.stopPropagation){
                e.stopPropagation();
            }else{//IE
                e.cancelBubble=true;
            }
        }
        
        //mousemove event handle resize southeast
        function handlerSE(e){
            if(!e){//IE
                e=window.event;
            }
            dragDiv.style.width= (e.clientX+deltaW)+"px";
            dragDiv.style.height= (e.clientY+deltaH)+"px";
            
            if(e.stopPropagation){
                e.stopPropagation();
            }else{//IE
                e.cancelBubble=true;
            }
        }
        
        //mouseup event handle
        function upHandler(e){
            if(!e){
                e=window.event;
            }
            //move or resize mapbox
            element.style.height=dragDiv.style.height;
            element.style.width=dragDiv.style.width;
            element.style.left=(parseInt(dragDiv.style.left))+"px";
            element.style.top=(parseInt(dragDiv.style.top))+"px";
            
            //refresh google map
            var center = map.getCenter();
            //map.checkResize();
            google.maps.event.trigger(map, 'resize');
            map.setCenter(center);
            //delete the temp dragable div
            dragDiv.parentNode.removeChild(dragDiv);
            if(document.removeEventListener){
                document.removeEventListener("mouseup",upHandler,true);
                eval('document.removeEventListener("mousemove",handler'+direction+',true)');
            }else{//IE
                document.detachEvent("onmouseup",upHandler);
                eval('document.detachEvent("onmousemove",handler'+direction+')');
            }
            if(e.stopPropagation){
                e.stopPropagation();
            }else{//IE
                e.cancelBubble=true;
            }
        }
    };
    
  var autoScroll=function(element,event,direction){ 
  };

