function progressMapInitialise() {

	// Set up map to cover all points
	pmap_bounds = new OpenLayers.Bounds();
	pmap_bounds.extend(new OpenLayers.LonLat(minLon, minLat));
	pmap_bounds.extend(new OpenLayers.LonLat(maxLon, maxLat));

	pmap_mapObj = new OpenLayers.Map("progressMapOSMap", {
		controls:[
			new OpenLayers.Control.Navigation()
		],
		maxExtent: pmap_bounds,
		maxResolution: 156543.0399,
		numZoomLevels: 24,
		units: 'm',
		projection: new OpenLayers.Projection("EPSG:900913"),
		displayProjection: new OpenLayers.Projection("EPSG:4326")
	});

	// Add pan and zoom control separately since we need a reference to it
	// so as to be able to remove it before resizing
	pmap_panZoomControl = new OpenLayers.Control.PanZoom();
	pmap_mapObj.addControl(pmap_panZoomControl);

	// Add Mapnik layer (this will show the actual map)
	layerMapnik = new OpenLayers.Layer.OSM.Mapnik("Mapnik");
	pmap_mapObj.addLayer(layerMapnik);

	// Set up track layer
	var pmap_trackLayer = new OpenLayers.Layer.Vector("GPX track", {style: pmap_trackLayerStyle});
	pmap_mapObj.addLayer(pmap_trackLayer);

	// Set up styles for track
	var pmap_trackLayerStyle = OpenLayers.Util.extend({}, OpenLayers.Feature.Vector.style['default']);
	var pmap_trackFeatureStyle = {
		strokeColor: "#FF0000",
		strokeWidth: 4,
		strokeOpacity: 0.6
	};

	// Fetch track and draw
	jQuery.get("/cycletrip2009/wp-content/themes/hitsfaethedam-ontour/getgpxpoints.php",
	function(data){
		jQuery(data).find("trkseg").each(function(){
			var pointList = [];
			jQuery(this).find("trkpt").each(function(){
				lat = jQuery(this).attr("lat");
				lon = jQuery(this).attr("lon");
				var point = new OpenLayers.Geometry.Point(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), pmap_mapObj.getProjectionObject());
				pointList.push(point);
			});
			var pmap_trackFeature = new OpenLayers.Feature.Vector(
					new OpenLayers.Geometry.LineString(pointList),
					null, pmap_trackFeatureStyle);
			pmap_trackLayer.addFeatures([pmap_trackFeature]);
		});
	},"xml");

	// Add markers layer
	var postMarkers = new OpenLayers.Layer.Markers( "Markers" );
	pmap_mapObj.addLayer(postMarkers);

	// Set up icon for markers
	var size = new OpenLayers.Size(7, 13);
	var offset = new OpenLayers.Pixel(-(size.w/2), -size.h);
	pmap_markerIcon = new OpenLayers.Icon('/cycletrip2009/wp-content/themes/hitsfaethedam-ontour/images/mapmarker.png', size, offset);

	// Set up markers (asynchronously using AJAX to avoid slowing things down)
	jQuery.get("/cycletrip2009/wp-content/themes/hitsfaethedam-ontour/getprogressmapmarkers.php", {},
		function(xml){
			var markers = jQuery(xml).find("marker");
			var total_markers = markers.size();
			markers.each(function(){
				var lat = jQuery(this).attr("lat");
				var lon = jQuery(this).attr("lon");
				var title = jQuery(this).find("title").text();
				var summary = jQuery(this).find("summary").text();
				var url = jQuery(this).find("url").text();

				var marker = new OpenLayers.Marker(new OpenLayers.LonLat(lon, lat).transform(new OpenLayers.Projection("EPSG:4326"), pmap_mapObj.getProjectionObject()), pmap_markerIcon.clone());
				marker.title = title;
				marker.url = url;
				marker.summary = summary;
				marker.events.register('mouseover', marker, function(evt) {
					if (pmap_popup) pmap_mapObj.removePopup(pmap_popup);
					pmap_popup = new OpenLayers.Popup.FramedCloud("post",
						this.lonlat,
						null,
						"<div class='progressMapPopupTitle'><a href='"+this.url+"' title='"+this.title+"'>"+this.title+"</a></div><div class='progressMapPopupSummary'>"+this.summary+"</div>",
						null, true, null);
					pmap_mapObj.addPopup(pmap_popup);
					OpenLayers.Event.stop(evt);
				});
				postMarkers.addMarker(marker);
			});
		}
	);

	// Zoom and centre to match bounds of points
	progressMapZoomAndCentre();
}

function progressMapZoomAndCentre() {
	var lonLat = pmap_bounds.getCenterLonLat().transform(new OpenLayers.Projection("EPSG:4326"), pmap_mapObj.getProjectionObject());
	var zoom = pmap_mapObj.getZoomForExtent(pmap_bounds.transform(new OpenLayers.Projection("EPSG:4326"), pmap_mapObj.getProjectionObject()), false);
	pmap_mapObj.setCenter(lonLat, zoom);
}

function progressMapExpandOrContract() {
	if (pmap_animating) return; // Prevent re-entrancy
	pmap_animating = true;
	pmap_mapObj.removeControl(pmap_panZoomControl); // Must remove and add again after resize
	if (pmap_popup) pmap_mapObj.removePopup(pmap_popup);
	jQuery("#progressMapOSMap").hide();
	jQuery("#progressMap").css({
		"opacity" : "0.5",
		"filter" : "alpha(opacity=50)",
		"background-color" : "black"
	});

	// Collapsed - expand
	if (jQuery("#progressMap").width() == pmap_collapsedWidth && jQuery("#progressMap").height() == pmap_collapsedHeight) {

		jQuery("#progressMapContentSpacer").slideDown(1000);
		jQuery("#progressMapSidebarSpacer2").slideDown(1000);

		progressMapExpandOrContractAnimate(pmap_maxWidth, pmap_maxHeight, function() {
			pmap_mapObj.zoomTo(pmap_mapObj.getZoom() + 1);
			pmap_animating = false;
		});
		jQuery("#progressMapDragMessageText").text("click to collapse");

	// Expanded - collapse
	} else {

		jQuery("#progressMapContentSpacer").slideUp(1000);
		jQuery("#progressMapSidebarSpacer2").slideUp(1000);

		progressMapExpandOrContractAnimate(pmap_collapsedWidth, pmap_collapsedHeight, function() {
			pmap_mapObj.zoomTo(pmap_mapObj.getZoom() - 1);
			pmap_animating = false;
		});
		jQuery("#progressMapDragMessageText").text("click to expand");
	}
}

function progressMapExpandOrContractAnimate(endWidth, endHeight, finishedCallback) {
	pmap_animEndWidth = endWidth;
	pmap_animEndHeight = endHeight;
	pmap_animFinishedCallback = finishedCallback;
	jQuery("#progressMap").animate({
		width: pmap_animEndWidth,
		height: pmap_animEndHeight
	}, 1000, "linear", function() {

			jQuery("#progressMapOSMap").width(pmap_animEndWidth);
			jQuery("#progressMapOSMap").height(pmap_animEndHeight);

			// Remove opacity
			jQuery("#progressMap").css({
				"opacity" : "",
				"filter" : "",
				"background-color" : "white"
			});
			jQuery("#progressMapOSMap").show();

			pmap_mapObj.updateSize();
			pmap_panZoomControl = new OpenLayers.Control.PanZoom();
			pmap_mapObj.addControl(pmap_panZoomControl);

			pmap_animFinishedCallback();
		}
	);
}

