var MAP_MAX_ZINDEX = 500;
var MAP_CONTROL_INDEX = 1000;
var MAP_DRAWING_INDEX = 900;
var MAP_POPUP_ZINDEX = 5000;


var GMAP_INSTANCE = 0;

var MAP_LOAD_IMAGE = 0;
var MAP_LOAD_DATA = 1;
var MAP_LOAD_LEGEND = 2;

function GMap (EventManager) {
	var MySelf = this;
	var MapId = 'Map'+GMAP_INSTANCE+'-';
	var LayerId = MapId+'Layer-';
	GMAP_INSTANCE++;


	var MapParentId;
	var ImageParentId = MapId+'ImageParent';

	var ScaleFactor = 1;
	var MapReference = null; 

	var CoordinateObjectId = null;
	
	var ImageControlId;
	var ImageMapControlId;

	var ReferenceIndicatorId = MapId+'ReferenceIndicator';
	var DrawBoxId = MapId+'DrawBox';

	var PopupMenuId = MapId+'PopupMenu';
	
	var ImageControlCanvasId = MapId+'Canvas'

	var FunctionOffset = new Point();
	var FunctionSemaphore = false;

	var DrawnPoints = new Array();
	var PreviousViews = new Array();

	function refreshDrawBox() {
		var DrawBox = document.getElementById(DrawBoxId);

		if(!DrawBox) {
			DrawBox = document.createElement('div');
		}
		if(!DrawBox.parentNode) {
			document.getElementById(MapParentId).appendChild(DrawBox);
		}

		DrawBox.setAttribute('id', DrawBoxId);
		DrawBox.style.position = 'absolute';
		DrawBox.style.border = 'solid 2px red';
		DrawBox.style.zIndex = MAP_DRAWING_INDEX;
		DrawBox.style.visibility = 'hidden';
		DrawBox.style.overflow = 'hidden';
		DrawBox.style.width = '1px';
		DrawBox.style.height = '1px';

		DrawBox = null;
	}

	var MapCenterPoint = new Point(576000, 157909.5);
	var MapScale = 25;


	var LayerURLs = new Array();
	var LayerLoadData = new Array();	/* Stores whether data should be loaded for the layer or not */
	var LayerLegends = new Array();
	var LayerImages = new Array();
	var LayerParameters = new Array();

	var min_z_index = MAP_MAX_ZINDEX;

	var VisibilityState = 'visible';
	function setVisibility(state) {
		for(var t in LayerImages) {
			var img = document.getElementById(LayerId+l);
			img.style.visibility = state;
			img = null;
		}
		VisibilityState = state;
	}

	this.setVisibility = setVisibility;

	this.hideMap = function() {
		setVisibility('hidden');
	}

	this.showMap = function() {
		setVisibility('visible');
	}

	this.setCoordinateObject = function(objId) {
		CoordinateObjectId = objId;
	}


	this.setScaleFactor = function(scF) {
		ScaleFactor = scF;
	}
	
	this.setMapReference = function(m) {
		MapReference = m;
	}

	this.changePointScale = function(point,scale) {
		var circ = new Circle(point,scale);
		PreviousViews[PreviousViews.length] = circ;
		MapScale = scale;
		MapCenterPoint = point;
	}

	var LastActionTime = 0;

	this.setLastActionTime = function() {
		var d = new Date();
		LastActionTime = d.getTime();
		return LastActionTime;
	}

	this.getLastActionTime = function() {
		return LastActionTime;
	}


	/*
	 * This will refresh the map when a coordinate change happens
	 */
	var MapViewSet = false;
	var MAP_MARKUP_RADIUS = 25;
	this.onChangePointScale = function(psc) {
		if(MapReference && !REFERENCE_MAP_DYNAMIC && MapViewSet) {
			return true;
		}
		MapViewSet = true;
		MySelf.clearDrawingArea();
		if(psc.Markup) {
			var imageControlCanvas = document.getElementById(ImageControlCanvasId);
			var ctx = imageControlCanvas.getContext("2d");

			var mSize = MySelf.getMapSize();
			ctx.save();
				ctx.beginPath();
					ctx.strokeStyle = "rgba(255,0,0,.75)";
					ctx.lineWidth = 1;


					ctx.moveTo(mSize.x/2,mSize.y/2 - MAP_MARKUP_RADIUS);
					ctx.lineTo(mSize.x/2,mSize.y/2 + MAP_MARKUP_RADIUS);
					ctx.stroke();
					ctx.moveTo(mSize.x/2-MAP_MARKUP_RADIUS, mSize.y/2);
					ctx.lineTo(mSize.x/2+MAP_MARKUP_RADIUS, mSize.y/2);
					ctx.stroke();
				ctx.closePath();
			ctx.restore();

		//	ctx.lineWidth = 3;
			ctx.save();
				ctx.beginPath();
				ctx.strokeStyle = 'rgba(255,0,0,.75)';
				ctx.lineWidth = 3;
				ctx.arc(mSize.x/2, mSize.y/2, MAP_MARKUP_RADIUS, 0, Math.PI*2,true);
				ctx.stroke();
				ctx.closePath();
			ctx.restore();
/*			ctx.save();
				ctx.strokeStyle = "red";
				ctx.fillStyle = "red";
				ctx.arc(ZoomPoint.x, ZoomPoint.y, 3, 0, Math.PI * 2, true);
				ctx.fill();
				ctx.closePath();
			ctx.restore();*/

		}
		PreviousViews[PreviousViews.length] = psc;
		MapScale = psc.Radius * ScaleFactor;
		MapCenterPoint = psc.Center;

		MySelf.refreshLayers();
	}

	/* Drawing Tools! */

	var DrawingShape = 'point';

	function startDrawing(event) {
		if(window.event) { event = window.event; event.which = event.button; }
		if(event.which != 1) { return false; }
		FunctionOffset = objectClientPosition(document.getElementById(ImageControlId));
		DrawnPoints = new Array();
		attachEvent(document, 'mouseup',stopDrawing);

		if(DrawingShape == 'box' || DrawingShape=='evenbox' || DrawingShape=='scalebox') {
			DrawnPoints[0] = new Point(event.clientX-FunctionOffset.x, event.clientY-FunctionOffset.y);
		} else {
			MySelf.drawPoint(event.clientX-FunctionOffset.x, event.clientY-FunctionOffset.y);
		}
		FunctionSemaphore = true;
	}

	function whileDrawing(event) {
		if(window.event) { event = window.event; }
		if(FunctionSemaphore) {
			MySelf.drawPoint(event.clientX-FunctionOffset.x, event.clientY-FunctionOffset.y);
		}
	}

	function whileDrawingBox(event) {
		if(window.event) { event = window.event; }
		if(FunctionSemaphore) {
			var DrawBox = document.getElementById(DrawBoxId);
			DrawBox.style.visibility = 'visible';

			var currentPoint = new Point(event.clientX-FunctionOffset.x, event.clientY-FunctionOffset.y);
			var left = DrawnPoints[0].x - 2;
			var width = currentPoint.x - left;
			var top = DrawnPoints[0].y - 2;
			var height = currentPoint.y - top;

			var mSize = MySelf.getMapSize();
			var perspective = mSize.x / mSize.y;

			if(DrawingShape == 'evenbox') {
				perspective = 1;
			}

			if(DrawingShape =='scalebox' || DrawingShape == 'evenbox') {
				if(width > height) { width = Math.abs(height * perspective) * width / Math.abs(width); }
				else { height = Math.abs(width * 1/perspective) * height / Math.abs(height); }
			}

			if(width < 0) {
				left = left + width;
				width = Math.abs(width);
			}

			if(height < 0) {
				top = top + height;
				height = Math.abs(height);
			}
			/* These are here because they keep IE happy and FF doesn't care.
			 * I would love for someone to explain why this is necessary.
			 */
			width = width;
			height = height;

			DrawBox.style.top = top+'px';
			DrawBox.style.left = left+'px';
			DrawBox.style.height = height+'px';
			DrawBox.style.width = width+'px';

			DrawBox = null;
		}
	}
	function cancelDrawing() {
		if (document.all) {
			document.detachEvent("onmouseup",   stopDrawing);
		} else {
			document.removeEventListener("mouseup",   stopDrawing, true);
		}
		if(FunctionSemaphore) {
			FunctionSemaphore = false;
			var DrawBox = document.getElementById(DrawBoxId);
			DrawBox.style.visibility = 'hidden';
			DrawBox.style.left = '0px';
			DrawBox.style.top = '0px';
			DrawBox.style.height = '1px';
			DrawBox.style.width = '1px';
			var divPoints = document.getElementById(MapParentId).getElementsByTagName('div');
			for(var i = divPoints.length; i >= 0; i--) {
				if(divPoints[i] && divPoints[i].parentNode && divPoints[i].className == 'DrawnPoint') {
					var p = divPoints[i].parentNode;
					p.removeChild(divPoints[i]);
				}
			}
		}

	}
	function stopDrawing() {
		if (document.all) {
			document.detachEvent("onmouseup",   stopDrawing);
		} else {
			document.removeEventListener("mouseup",   stopDrawing, true);
		}

		if(FunctionSemaphore) {
			FunctionSemaphore = false;
			/* Convert Drawn Points into Ground Units */
			var GroundUnits = new Array();
			for(var i = 0; i < DrawnPoints.length; i++) {
				GroundUnits[i] = MySelf.pointToGroundUnits(new Point(DrawnPoints[i].x,DrawnPoints[i].y));
			}
			EventManager.triggerEvent('finishdrawing', GroundUnits);

			var DrawBox = document.getElementById(DrawBoxId);
			DrawBox.style.visibility = 'hidden';
			DrawBox.style.left = '0px';
			DrawBox.style.top = '0px';
			DrawBox.style.height = '1px';
			DrawBox.style.width = '1px';
			DrawBox = null;

			var divPoints = document.getElementById(MapParentId).getElementsByTagName('div');
			for(var i = divPoints.length; i >= 0; i--) {
				if(divPoints[i] && divPoints[i].parentNode && divPoints[i].className == 'DrawnPoint') {
					var p = divPoints[i].parentNode;
					p.removeChild(divPoints[i]);
				}
			}

		}
	}

	this.mapStats = function() {
		logDebugMessage('Map Statistics', false, MapCenterPoint.toString(",")+' '+MapScale);
	}
	
	this.pointToGroundUnits = function(p) {
		var ImageControl = document.getElementById(ImageControlId);
		MapCenterPoint.clean();
		p.x = (MapCenterPoint.x - (ImageControl.offsetWidth / 2 - p.x) * MapScale);
		p.y = (MapCenterPoint.y - (p.y - ImageControl.offsetHeight / 2) * MapScale);
		ImageControl = null;
		return p;
		
	}

	this.pointDrawTool = function(callFn) {
		this.loadDrawTool('poly', true);
	}

	var DrawingArea = new Array();

	this.polyDrawTool = function(shape, title) {
		this.loadDrawTool(shape,true); // measurearea = poly
		this.setMapCursor(CURSOR_DRAW);
		EventManager.addEventListener('changetool', 'MapZoomTool', function () {
			EventManager.removeEventListener('changetool','MapZoomTool');
			EventManager.removeEventListener('finishdrawing','MapZoomTool');
		});
		EventManager.addEventListener('finishdrawing', 'MapZoomTool', function () { 
			if(shape == 'measurearea') { shape = 'poly'; }
			/* Ground Unit String is in WKT/GML Format */
			var groundUnitString = '';
			for(var i = 0; i < DrawnPoints.length; i++) {
				var p = new Point(DrawnPoints[i].x,DrawnPoints[i].y);
				groundUnitString = groundUnitString + MySelf.pointToGroundUnits(p).toString(",") + ' ';
			}

			/* Close the polygon */
			if(shape == 'poly' || shape == 'circle') {
				groundUnitString = groundUnitString + MySelf.pointToGroundUnits(new Point(DrawnPoints[0].x,DrawnPoints[0].y)).toString(",");
			}
			/*logDebugMessage('Points', false, groundUnitString);*/

			var pass = false;
			if(!title) {
				var msg = '';
				while(!pass) {
					title = prompt(msg+"Name for the object?", "Title");
					pass = true;
					if(LayerImages[title]) {
						pass = false;
						msg  = 'LAYER ALREADY EXISTS --';
					}
				}
				
			}

			if(title) {
				var bufferSize = prompt('Buffer Size?','0');
				if(!bufferSize) { bufferSize = 0; }
				
				/*var saveDrawingURL = '/mapscript/cgi-bin/saveDrawing.pl?coords=%COORDS%&shape=%SHAPE%&buffer=%BUFFER%&title=%TITLE%';*/
				var saveDrawingURL = DRAWING_URL;
				saveDrawingURL = saveDrawingURL.replace('%COORDS%', groundUnitString);
				saveDrawingURL = saveDrawingURL.replace('%SHAPE%', shape);
				saveDrawingURL = saveDrawingURL.replace('%BUFFER%', bufferSize);
				saveDrawingURL = saveDrawingURL.replace('%TITLE%', title);

				var DrawingMethod = 'GET';
				var DrawingPostInfo = true;
				if(saveDrawingURL.length > 1000) {
					DrawingMethod = 'POST';
					var saveDrawingArr = saveDrawingURL.split('?');
					saveDrawingURL = saveDrawingArr[0];
					DrawingPostInfo = saveDrawingArr[1];
				}

				var titleCopy = title;

				var saveDrawingControl = getHTTPObject();
				logDebugMessage('Drawing URL', false, saveDrawingURL);
				saveDrawingControl.open(DrawingMethod, saveDrawingURL, true);
				if(DrawingMethod == 'POST') {
					saveDrawingControl.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
				}


				saveDrawingControl.onreadystatechange = function() {
					if(saveDrawingControl.readyState == 4) {
						if(saveDrawingControl.responseXML) {
							loadDefaultsFromMapBook(saveDrawingControl.responseXML, null, EventManager);
							var selection = saveDrawingControl.responseXML.getElementsByTagName('selection');
							for(var s = 0; s < selection.length; s++) {
								DrawingArea[selection[s].getAttribute('title')] = selection[s].getAttribute('id');
							}

						}
					}
				}
				saveDrawingControl.send(DrawingPostInfo);
			}
			title = '';
			MySelf.resetDrawingArea();
		});

	}

	this.addSelection = function(s) {
		DrawingArea[s.getAttribute('title')] = s.getAttribute('id');
	}

	this.getDrawingAreas = function() {
		return DrawingArea;
	}

	this.resetDrawingArea = function() {
		MySelf.clearDrawingArea();
		DrawnPoints = new Array();
	}

	this.clearDrawingArea = function() {
	//	DrawnPoints = new Array();	
		refreshCanvas();
		document.getElementById(ImageControlCanvasId).getContext("2d").clearRect(0,0,1000,1000);
		EventManager.triggerEvent('measuredlength', 0);
	}

	function measureLines() {
		var linesInGroundUnits = 0;
		for(var i = 1; i < DrawnPoints.length ; i++) {
			var gA = MySelf.pointToGroundUnits(new Point(DrawnPoints[i-1].x, DrawnPoints[i-1].y));
			var gB = MySelf.pointToGroundUnits(new Point(DrawnPoints[i].x, DrawnPoints[i].y));
						
			var gUnitSeg =new LineSegment(gA,gB);
			linesInGroundUnits += gUnitSeg.getLength();
		}
		EventManager.triggerEvent('measuredlength', linesInGroundUnits);
	}

	function measureArea() {
		var groundUnits = new Array();
		for(var i = 0; i < DrawnPoints.length ; i++) {
			var gA = MySelf.pointToGroundUnits(new Point(DrawnPoints[i].x, DrawnPoints[i].y));
			groundUnits[i] = gA;
		}	
		var poly = new Polygon();
		groundUnits[groundUnits.length] = new Point(groundUnits[0].x, groundUnits[0].y);
		poly.buildFromPoints(groundUnits);
		EventManager.triggerEvent('measuredlength', Math.abs(poly.area()));
	}

	function clearImageControlFn() {
		var ImageControl = document.getElementById(ImageControlId);
		ImageControl.onmousedown = null;
		ImageControl.onmouseup = null;
		ImageControl.onmousemove = null;
		ImageControl.onclick = null;
		ImageControl.dblclick = null;

		removeEvent(ImageControl, 'click', measureLines);
		removeEvent(ImageControl, 'click', measureArea);
		removeEvent(ImageControl, 'mousedown', startDrawing);
		removeEvent(ImageControl, 'mouseup', stopDrawing);
		removeEvent(ImageControl, 'mousemove', whileDrawing);
		removeEvent(ImageControl, 'mousemove', whileDrawingBox);

		ImageControl = null;
	}

	this.onChangeTool = function() {
		clearImageControlFn();
	}


	this.loadMeasureTool = function(mType) { // area or length
		var ImageControl = document.getElementById(ImageControlId);
		if(mType == 'length') {
			MySelf.loadDrawTool('measureline',true);
			attachEvent(ImageControl, 'click', measureLines);
		} else if(mType == 'area') {
			MySelf.loadDrawTool('measurearea',true);
			attachEvent(ImageControl, 'click', measureArea);
		} else {
			alert('Unknown Measure Tool Type!');
		}
	}

	this.setMapCursor = function(pCursor) {
		var ImageControl = document.getElementById(ImageControlId);
		ImageControl.style.cursor = pCursor;
		ImageControl = null;
	}

	this.loadDrawTool = function(shape,override) {
		var ImageControl = document.getElementById(ImageControlId);

		refreshDrawBox();
		ImageControl.style.zIndex = MAP_CONTROL_INDEX;
		document.getElementById(ImageMapControlId).style.zIndex = MAP_CONTROL_INDEX - 1;
		ImageControl.style.cursor = CURSOR_DRAW;

		if(!override) {
			EventManager.triggerEvent('changetool', 'Draw');
		}

		EventManager.addEventListener('changetool','MapDrawingTools', function () {
			removeEvent(ImageControl, 'mousedown', startDrawing);
			removeEvent(ImageControl, 'mousemove', whileDrawing);
			removeEvent(ImageControl, 'mousemove', whileDrawingBox);
			removeEvent(ImageControl, 'mouseup', stopDrawing);
			EventManager.removeEventListener('changetool','MapDrawingTools');
			EventManager.removeEventListener('finishdrawing','MapZoomTool');
		});
		clearImageControlFn();
		DrawingShape = shape;
		if(shape == 'box' || shape == 'evenbox' || shape == 'scalebox') {
			attachEvent(ImageControl, 'mousedown', startDrawing);
			attachEvent(ImageControl, 'mousemove', whileDrawingBox);
			attachEvent(ImageControl, 'mouseup', stopDrawing);
		} else if(shape == 'measureline') {
			ImageControl.style.cursor = CURSOR_MEASURE;
			DrawnPoints = new Array();
			MySelf.clearDrawingArea();
			ImageControl.onclick = function(event) {
				if(window.event) { event = window.event; }
				refreshCanvas();
				FunctionOffset = objectClientPosition(document.getElementById(ImageControlId));
				ZoomPoint.x = event.clientX - FunctionOffset.x;
				ZoomPoint.y = event.clientY - FunctionOffset.y;
				var ctx = document.getElementById(ImageControlCanvasId).getContext("2d");

				if(DrawnPoints.length <= 0) { ctx.beginPath(); }

				DrawnPoints[DrawnPoints.length] = new Point(ZoomPoint.x, ZoomPoint.y);
				if(DrawnPoints.length > 1) {
					var i = DrawnPoints.length-1;
					ctx.strokeStyle = "red";
					ctx.save();
						ctx.beginPath();
						ctx.moveTo(DrawnPoints[i-1].x, DrawnPoints[i-1].y);
						ctx.lineTo(DrawnPoints[i].x, DrawnPoints[i].y);
						ctx.stroke();
						ctx.closePath();
					ctx.restore();
				}
				ctx.save();
					ctx.strokeStyle = "red";
					ctx.fillStyle = "red";
					ctx.arc(ZoomPoint.x, ZoomPoint.y, 3, 0, Math.PI * 2, true);
					ctx.fill();
					ctx.closePath();
				ctx.restore();
			}

			ImageControl.ondblclick = function(event) {
				for(var i = 0; i < DrawnPoints.length; i++) {
					DrawnPoints[i] = MySelf.pointToGroundUnits(DrawnPoints[i]);
				}
				MySelf.clearDrawingArea();
				Events.triggerEvent('finishdrawing', DrawnPoints);
				DrawnPoints = new Array();
			}
		} else if(shape == 'measurearea') {
			ImageControl.style.cursor = CURSOR_MEASURE;
			DrawnPoints = new Array();
			
			MySelf.clearDrawingArea();

			ImageControl.onclick = function(event) {
				if(window.event) { event = window.event; }
				refreshCanvas();
				FunctionOffset = objectClientPosition(document.getElementById(ImageControlId));
				ZoomPoint.x = event.clientX - FunctionOffset.x;
				ZoomPoint.y = event.clientY - FunctionOffset.y;
				var ctx = document.getElementById(ImageControlCanvasId).getContext("2d");

				if(DrawnPoints.length <= 0) { ctx.beginPath(); }

				DrawnPoints[DrawnPoints.length] = new Point(ZoomPoint.x, ZoomPoint.y);
				MySelf.clearDrawingArea();
				ctx.save();
					ctx.fillStyle = "rgba(0,200,0,.5)";
					ctx.beginPath();
					ctx.moveTo(DrawnPoints[0].x, DrawnPoints[0].y);
					for(var i = 1; i < DrawnPoints.length; i++) {
						ctx.lineTo(DrawnPoints[i].x,DrawnPoints[i].y);
					}
					ctx.closePath();
					ctx.fill();
				ctx.restore();

				ctx.save();
					ctx.strokeStyle = "red";
					ctx.lineWidth = 2;
					if(DrawnPoints.length == 1) {
						ctx.save();
						ctx.fillStyle = "red";
						ctx.beginPath();
							ctx.arc(DrawnPoints[0].x, DrawnPoints[0].y, 2,0,Math.PI*2,true);
							ctx.fill();
						ctx.closePath();
						ctx.restore();
					}
					ctx.beginPath();
					ctx.moveTo(DrawnPoints[0].x, DrawnPoints[0].y);

					for(var i = 1; i < DrawnPoints.length; i++) {
						ctx.lineTo(DrawnPoints[i].x,DrawnPoints[i].y);
					}
					ctx.closePath();
					ctx.stroke();

				ctx.restore();

			}

			ImageControl.ondblclick = function(event) {
				for(var i = 0; i < DrawnPoints.length; i++) {
					DrawnPoints[i] = MySelf.pointToGroundUnits(DrawnPoints[i]);
				}
				Events.triggerEvent('finishdrawing', DrawnPoints);
				DrawnPoints = new Array();
			}

		} else {
			attachEvent(ImageControl, 'mousedown', startDrawing);
			attachEvent(ImageControl, 'mousemove', whileDrawing);
			attachEvent(ImageControl, 'mouseup', stopDrawing);
		}
		ImageControl = null;
	}


	function zoomWheel(event) {
		if(window.event) { event = window.event; }
		var dir = 2;
		var delta = 0;
		if(event.wheelDelta) {
			delta = event.wheelDelta/120;
		} else if(event.detail) {
			delta = -event.detail/3;
		}
		if(delta > 0) {
			dir = .7;
		} else if (delta < 0) {
			dir = 1.5;
		}
		MySelf.zoomTo(ZoomPoint.x, ZoomPoint.y, dir);
	}

	/*
	 * Zooming Related Code
	 */

	function zoomTrackMouse(event) {
		var ImageControl = document.getElementById(ImageControlId);
		if(window.event) { event = window.event; }
		FunctionOffset = objectClientPosition(ImageControl);
		ZoomPoint.x = event.clientX - FunctionOffset.x;
		ZoomPoint.y = event.clientY - FunctionOffset.y;
		var CoordinateObject = document.getElementById(CoordinateObjectId);
		if(CoordinateObject) {
			ZoomPoint.clean();
			var gUnit = MySelf.pointToGroundUnits(new Point(ZoomPoint.x, ZoomPoint.y));
			var llString = '';
			var sysArr = (new String(MAP_COORDINATE_SYSTEM)).split('-');
			if(window.toLatLong) {
				var unitConversion = new Point(gUnit.x, gUnit.y);
				var llPoint = window.toLatLong(sysArr[1], unitConversion);
				llPoint.x = round(llPoint.x,4);
				llPoint.y = round(llPoint.y,4);
				var temp = llPoint.x;
				llPoint.x = llPoint.y;
				llPoint.y = temp;
				llString = ' <b>Lat, Long:</b> '+llPoint.toString(",");
				//llString = getLatLon(gUnit.x, gUnit.y).toString(',');
			}
			var mSize = MySelf.getMapSize();
			mSize.x = Math.round(mSize.x * MapScale);
			mSize.y = Math.round(mSize.y * MapScale);
			CoordinateObject.innerHTML = '<B>X,Y:</B> '+round(gUnit.x,2)+","+round(gUnit.y,2)+llString;
			if(SHOW_MAP_WIDTH) {
				CoordinateObject.innerHTML += " <b>Width, Height: </b>"+mSize.toString(',')+" "+MAP_GROUND_UNITS;
			}

		}
		ImageControl = null;
	}

	var ZoomDirection = 1;
	var ZoomPoint = new Point();	
	function zoomToPoint(event) {
		var ImageControl = document.getElementById(ImageControlId);
		if(window.event) { event = window.event; }
		FunctionOffset = objectClientPosition(ImageControl);
		MySelf.zoomTo(ZoomPoint.x, ZoomPoint.y, ZoomDirection);
		ImageControl = null;
	}


	this.recenterImage = function(x,y,v) {
		var ImageControl = document.getElementById(ImageControlId);
		if(!v) { v = 1; }
		var PanPoint = new Point(x,y);
		var shiftX = ImageControl.offsetWidth / 2 - PanPoint.x;
		var shiftY = ImageControl.offsetHeight / 2 - PanPoint.y;
		var oldW = ImageControl.offsetWidth;
		var oldH = ImageControl.offsetHeight;
		var newW = oldW * (1/v);
		var newH = oldH * (1/v);
		shiftX *= (1/v);
		shiftY *= (1/v);
		for(var l in LayerImages) {
			var img = document.getElementById(LayerId+l);
			img.style.left = img.offsetLeft + shiftX - (newW - oldW) / 2 + 'px';
			img.style.top = img.offsetTop + shiftY - (newH - oldH) / 2 + 'px';
			img.style.width = newW + 'px';
			img.style.height = newH + 'px';
			img = null;
		}
		MySelf.zoomTo(0,0,1);
		ImageControl = null;
	}

	this.recenterOnZoomPoint = function(v) {
		MySelf.recenterImage(ZoomPoint.x, ZoomPoint.y, v);
	}


	/*
	 * Panning Code
	 */
	var PanPoint = new Point(0,0);
	function startPan(e) {
		if(window.event) { e = window.event; e.which = e.button; }
		if(e.which != 1) { return false; } /* Pan only on the left/first mouse button */

		var ImageControl = document.getElementById(ImageControlId);
		ImageControl.Origin = new Point(e.clientX, e.clientY);
		for(var l in LayerImages) {
			var img = document.getElementById(LayerId+l);
			img.originalLeft = img.offsetLeft;
			img.originalTop = img.offsetTop;
			img = null;
		}
		PanPoint.x = 0;
		PanPoint.y = 0;
		ImageControl = null;
	}

	function whilePanning(e) {
		if(window.event) { e = window.event; }

		var ImageControl = document.getElementById(ImageControlId);
		if(ImageControl.Origin) {
			for(var l in LayerImages) {
				var img = document.getElementById(LayerId+l);
				img.style.left = img.originalLeft + (e.clientX - ImageControl.Origin.x) + 'px';
				img.style.top = img.originalTop + (e.clientY - ImageControl.Origin.y) + 'px';
				img = null;
			}
			PanPoint.x = e.clientX - ImageControl.Origin.x;
			PanPoint.y = e.clientY - ImageControl.Origin.y;
		}
		ImageControl = null;
		return preventDefaultEvent(e);
	}

	function endPan(e) {
		var ImageControl = document.getElementById(ImageControlId);
		if(window.event) { e = window.event; e.which = e.button; }
		if(e.which != 1) { return false; }
		MySelf.zoomTo(ImageControl.offsetWidth / 2 - PanPoint.x, ImageControl.offsetHeight / 2 - PanPoint.y, 1);
		ImageControl.Origin = null;
		ImageControl = null;
	}

	function cancelPan(event) {
		var ImageControl = document.getElementById(ImageControlId);
		if(window.event) { event = window.event; }
		var keyCode = getKeyCode(event);
		if(keyCode == 'CTRL+z') {
			ImageControl.Origin = null;
			for(var l in LayerImages) {
				var img = document.getElementById(LayerId+l);
				img.style.left = img.originalLeft+'px';
				img.style.top = img.originalTop+'px';
				img = null;
			}
		}
		ImageControl = null;

	}

	this.loadZoomTool = function(v) {
		var ImageControl = document.getElementById(ImageControlId);
		if(!ImageControl) { return false; }
		clearImageControlFn();
		if(v == 1) { /* Pan */
			ImageControl.style.cursor = CURSOR_ZOOM_PAN;
			ImageControl.onmousedown = startPan;
			ImageControl.onmouseup = endPan;
			ImageControl.onmousemove = whilePanning;
			ImageControl.onkeypress = cancelPan;
		} else if(v != 1) { /* Zoom In  and Zoom Out */
			MySelf.loadDrawTool(ZOOM_BOX_SHAPE,true);

			if(v < 1) {
				ImageControl.style.cursor = CURSOR_ZOOM_IN;
			} else {
				ImageControl.style.cursor = CURSOR_ZOOM_OUT;
			}
	
			EventManager.addEventListener('finishdrawing', 'MapZoomTool', function () { 
				var ImageControl = document.getElementById(ImageControlId);
				var DrawBox = document.getElementById(DrawBoxId);
				var Ratio = DrawBox.offsetWidth / ImageControl.offsetWidth;
				var hRatio = DrawBox.offsetHeight / ImageControl.offsetHeight;
				if(hRatio > Ratio) { Ratio = hRatio; }
				if(DrawBox.offsetWidth < 7) {
					MySelf.recenterImage(DrawnPoints[0].x, DrawnPoints[0].y, v);
				} else {	
					var PanPoint = new Point(DrawBox.offsetLeft + DrawBox.offsetWidth / 2, DrawBox.offsetTop + DrawBox.offsetHeight / 2);
					if(v > 1) { v = 1 / Ratio; }
					else { v = Ratio; }
					var shiftX = ImageControl.offsetWidth / 2 - PanPoint.x;
					var shiftY = ImageControl.offsetHeight / 2 - PanPoint.y;
					var oldW = ImageControl.offsetWidth;
					var oldH = ImageControl.offsetHeight;
					var newW = oldW * (1/v);
					var newH = oldH * (1/v);
					shiftX *= (1/v);
					shiftY *= (1/v);
					for(var l in LayerImages) {
						var img = document.getElementById(LayerId+l);
						if(l == 'NAVIGATION' || MAP_ZOOMIN_STYLE == 'scale' || v > 1) {
							img.style.left = img.offsetLeft + shiftX - (newW - oldW) / 2 + 'px';
							img.style.top = img.offsetTop + shiftY - (newH - oldH) / 2 + 'px';
							img.style.width = newW + 'px';
							img.style.height = newH + 'px';
						} else if(MAP_ZOOMIN_STYLE == 'clip') {
							var x2 = DrawBox.offsetLeft + DrawBox.offsetWidth;
							var y2 = DrawBox.offsetTop + DrawBox.offsetHeight;
							img.style.clip = 'rect('+DrawBox.offsetTop+'px,'+x2+'px,'+y2+'px,'+DrawBox.offsetLeft+'px)';
						} else if(MAP_ZOOMIN_STYLE == 'blank') {
							img.src = BLANK_IMAGE;
						}
						img = null;
					}
					MySelf.zoomTo(0,0,1);

				}
				ImageControl = null;
			});
			EventManager.addEventListener('changetool', 'MapZoomTool', function () {
				EventManager.removeEventListener('finishdrawing','MapZoomTool');
				EventManager.removeEventListener('changetool', 'MapZoomTool');
			});
		}

		ImageControl.style.zIndex = MAP_CONTROL_INDEX;
		if(ImageMapControlId) {
			document.getElementById(ImageMapControlId).style.zIndex = MAP_CONTROL_INDEX - 1;
		}
		ZoomDirection = v;
		ImageControl = null;
	}
	


	this.clearLayerParams = function(mapTitle) {
		LayerParameters[mapTitle] = new Array();
	}

	this.addLayerParam = function(mapTitle,paramName,paramValue) {
		if(!LayerParameters[mapTitle]) { LayerParameters[mapTitle] = new Array(); }
		if(!LayerParameters[mapTitle][paramName]) {
			LayerParameters[mapTitle][paramName] = new Array();
		}
		LayerParameters[mapTitle][paramName].push(paramValue);
	}

	this.getLayerParamString = function(mapTitle) {
		if(!LayerParameters[mapTitle]) { return false; }
		var urlString = '';
		for(var p in LayerParameters[mapTitle]) {
			if(LayerParameters[mapTitle][p]) {
				for(var i = 0; i < LayerParameters[mapTitle][p].length; i++) {
					urlString += p+'='+LayerParameters[mapTitle][p][i]+'&';
				}
			}
		}
		urlString = urlString.substring(0,urlString.length - 1);
		return urlString;
	}

	this.addLayer = function (mapXMLObj) {
		var mapFile = mapXMLObj.getElementsByTagName('file')[0].firstChild.nodeValue;
		var mapTitle = mapXMLObj.getAttribute('title');
		var mapOpacity = mapXMLObj.getAttribute('opacity');
		var mapData = mapXMLObj.getAttribute('popups');
		var zIndex = mapXMLObj.getAttribute('zindex');


		if(!mapData) {
			mapData = MAP_ASSUME_DATA; 
		} else {
			if(mapData.match(/true/i)) {
				mapData = true;
			} else {
				mapData = false;
			}
		}

		LayerLoadData[mapTitle] = mapData;
			

		mapFile = trim(mapFile);
		LayerURLs[mapTitle] = mapFile;
		var newLayer = document.getElementById(LayerId+mapTitle);

		if(!newLayer) {
			LayerImages[mapTitle] = 1;
			newLayer = document.createElement('img');
			newLayer.style.position = 'absolute';
			newLayer.setAttribute('id', LayerId+mapTitle);
			if(ImageParentId) {
				document.getElementById(ImageParentId).appendChild(newLayer);
			}
		}
		if(mapOpacity) {
			if(OPACITY_CONTROLS == 'full') {
				setOpacity(newLayer, mapOpacity);
			}
		}
		

		if(MAP_MAPBOOK_ORDER) {
			if(zIndex) {
				newLayer.style.zIndex = MAP_MAX_ZINDEX - parseInt(zIndex);
			} else {
				newLayer.style.zIndex = MAP_MAX_ZINDEX;
			}
		} else {
			if(!zIndex || zIndex > 0) {
				newLayer.style.zIndex = MAP_MAX_ZINDEX;
				for(var title in LayerImages) {
					var img = document.getElementById(LayerId+title);
					img.style.zIndex = parseInt(img.style.zIndex)-1;
					img = null;
				}
				min_z_index--;
			} else {
				min_z_index--;
				newLayer.style.zIndex = min_z_index;
			}
		}

		MySelf.autoFitLayer(mapTitle);
		MySelf.clearLayerParams(mapTitle);
		var mapParams = mapXMLObj.getElementsByTagName('param');
		for(var i = 0; i < mapParams.length; i++) {
			MySelf.addLayerParam(mapTitle, mapParams[i].getAttribute('name'), mapParams[i].getAttribute('value'));
		}
		/*
		 * Custom Legend settings
		 */
		if(mapXMLObj.getElementsByTagName('legend')[0] && mapXMLObj.getElementsByTagName('legend')[0].firstChild.nodeValue) {
			LayerLegends[mapTitle] = mapXMLObj.getElementsByTagName('legend')[0].firstChild.nodeValue;
		}
		newLayer = null;
		Events.triggerEvent('refreshlayer', mapTitle);
	}

	this.confirmRemoveLayer = function(mapTitle) {
		MySelf.removeLayer(mapTitle);
	}

	this.removeLayer = function(mapTitle) {
		var imageMap = document.getElementById(MapId+'ImageMap-'+mapTitle);
		if(imageMap) {
			var areas = imageMap.getElementsByTagName('area');
			for(var a = areas.length - 1; a >= 0; a--) {
				var p = document.getElementById(areas[a].popup[0]).parentNode;
				for(var pop = 0; pop < areas[a].popup.length; pop++) {
					p.removeChild(document.getElementById(areas[a].popup[pop]));
				}
				imageMap.removeChild(areas[a]);
			}
			var p = imageMap.parentNode;
			p.removeChild(imageMap);
		}
		if(LayerImages[mapTitle]) {
			var img = document.getElementById(LayerId+mapTitle);
			if(img && img.parentNode) {
				var p = img.parentNode;
				p.removeChild(img);
			}
			delete LayerImages[mapTitle];
			delete LayerURLs[mapTitle];
			if(DrawingArea[mapTitle]) {
				delete DrawingArea[mapTitle];
			}
			img = null;
		}
	}

	this.getLayerURLs = function() {
		var zOrdered = MySelf.getLayersByZIndex();
		var urls = new Array();
		for(var i = 0; i < zOrdered.length; i++) {
			if(zOrdered[i] != 'NAVIGATION') {
				urls[zOrdered[i]] = LayerURLs[zOrdered[i]];
			}
		}
		return urls;
	}

	this.getLayerTitles = function() {
		var layers = new Array();
		for(var title in LayerImages) {
			if(title != 'NAVIGATION') {
				layers[layers.length] = title;
			}
		}
		return layers;
	}

	this.getLayersByZIndex = function() {
		var orderedLayers = new Array();
		for(var title in LayerImages) {
			orderedLayers[orderedLayers.length] = title;
		}
		for(var i = 0; i < orderedLayers.length; i++) {
			for(var  j = i; j < orderedLayers.length; j++) {
				var iImage = document.getElementById(LayerId+orderedLayers[i]);
				var jImage = document.getElementById(LayerId+orderedLayers[j]);
				if(parseInt(iImage.style.zIndex) < parseInt(jImage.style.zIndex)) {
					var temp = orderedLayers[i];
					orderedLayers[i] = orderedLayers[j];
					orderedLayers[j] = temp;
				}
				iImage = null;
				jImage = null;
			}
		}
		return orderedLayers;
	}

	this.showOrderedLayers = function() {
		var str = '';
		var layers = this.getLayersByZIndex();
		for(var i = 0; i < layers.length; i++) {
			str = str+layers[i]+'('+LayerImages[layers[i]].style.zIndex+'),';
		}
	}
	
	this.shiftLayer = function(mapTitle, direction) {
		var orderedLayers = this.getLayersByZIndex();
		var selectedLayerIndex = -1;
		
		for(var i = 0; i < orderedLayers.length && selectedLayerIndex < 0; i++) {
			if(orderedLayers[i] == mapTitle) {
				selectedLayerIndex = i;
			}
		}
		if(selectedLayerIndex >= 0) {
			var baseImage = document.getElementById(LayerId+mapTitle);
			var targetImage = null; 
			/* Move the layer up, if it's not at the top*/
			if(direction > 0 && selectedLayerIndex > 0) {
				targetImage = orderedLayers[selectedLayerIndex-1];
			/* Move the layer down, if it's not at the bottom */
			} else if(direction < 0 && selectedLayerIndex < orderedLayers.length - 1) {
				targetImage = orderedLayers[selectedLayerIndex+1];
			}
			if(targetImage) {
				targetImage = document.getElementById(LayerId+targetImage);
				var tempIndex = baseImage.style.zIndex;
				baseImage.style.zIndex = targetImage.style.zIndex;
				targetImage.style.zIndex = tempIndex;
			}
		}
	}

	var REFRESH_LOCKOUT = false;

	this.zoomToScaledImage = function() {
		var ImageControl = document.getElementById(ImageControlId);
		/* zoomLayer will be Scaled to whatever the new image should be */
		var zoomLayer = document.getElementById(LayerId+'NAVIGATION');
		var imageTop = zoomLayer.offsetTop;
		var imageLeft = zoomLayer.offsetLeft;

		var imageWidth = zoomLayer.offsetWidth;
		var imageHeight = zoomLayer.offsetHeight;

		/* ImageControl never changes size */
		var viewportTop = ImageControl.offsetTop;
		var viewportLeft = ImageControl.offsetLeft;
		var viewportWidth = ImageControl.offsetWidth;
		var viewportHeight = ImageControl.offsetHeight;

		/* Scale Change between the two images */
		var scale = viewportWidth / imageWidth * MapScale; 
		
		var groundTop = MapCenterPoint.y - MapScale * viewportHeight / 2;
		var groundLeft = MapCenterPoint.x - MapScale * viewportWidth / 2;

		/* Find the new Centerpoint in Pixel Space */
		var viewportMidX = (viewportLeft - imageLeft) + viewportWidth / 2;
		var viewportMidY = (viewportTop - imageTop) + viewportHeight / 2;
		var imagePercentX = viewportMidX / imageWidth;
		var imagePercentY = 1 - (viewportMidY / imageHeight);	

		var unscaledImageX = imagePercentX*viewportWidth;
		var unscaledImageY = imagePercentY*viewportHeight;

		/* Convert to ground units */
		var groundCenterX = groundLeft + unscaledImageX * MapScale;
		var groundCenterY = groundTop + unscaledImageY * MapScale; 
		EventManager.changePointScale(new Point(groundCenterX, groundCenterY), scale / ScaleFactor);
	}

	this.zoomToViewString = function(str) {
		var psC = convertViewString(str,MySelf.getMapSize());
		EventManager.changePointScale(psC.Center, psC.Radius);
	}
	
	this.zoomTo = function(x,y,direction) {
		var ImageControl = document.getElementById(ImageControlId);
		if(REFRESH_LOCKOUT) return false;

		var zoomLayer = document.getElementById(LayerId+'NAVIGATION');
		var imgW = zoomLayer.offsetWidth;
		var imgH = zoomLayer.offsetHeight;

		var mapSize = MySelf.getMapSize();
		var diffY = ImageControl.offsetTop - zoomLayer.offsetTop;
		var diffX = ImageControl.offsetLeft - zoomLayer.offsetLeft;
		
		var PointImageX = diffX + x;
		var PointImageY = diffY + y;

		var wPercent = PointImageX / imgW;
		var hPercent = PointImageY / imgH;
		// Do some zooming tricks
		var imgSizeFactor = 1 / direction; // Inverse of the scale change
		var newW = imgSizeFactor * imgW;
		var newH = imgSizeFactor * imgH;

		var xLoc = x-(mapSize.x / 2);
		var yLoc = ((mapSize.y / 2) - y);
		var wRatio = newW / ImageControl.offsetWidth;
		var hRatio = newH / ImageControl.offsetHeight;
		if(hRatio > wRatio) { wRatio = hRatio; }

		var newScale = MapScale * wRatio;

		if(newScale < .01) {
			return false;
		}
				
		if(direction != 1) {
			for(var layer in LayerImages) {
				//var layer = 'NAVIGATION';
				var img = document.getElementById(LayerId+layer);
				//img.style.visibility = 'hidden';
				img.style.width = newW + 'px';
				img.style.height = newH + 'px';
				img.style.left = (newW * wPercent * -1 +  x)+'px';
				img.style.top = (newH * hPercent * -1 +  y)+'px';
				//img.style.visibility = 'visible';
				img = null;
			}
		}

		

		window.triggerMapRefresh = function(time) {
			REFRESH_LOCKOUT = true;
			if(time == LastActionTime) {
				MySelf.zoomToScaledImage();
				LastActionTime = 0;
			}
			REFRESH_LOCKOUT = false;
		}
		LastActionTime ++;
		setTimeout("window.triggerMapRefresh("+LastActionTime+")", 1000);
		ImageControl = null;
	}

		
	this.drawPoint = function(x,y) {
		var lastPoint = DrawnPoints[DrawnPoints.length-1];
		if(lastPoint) {
			var distx = (lastPoint.x - x);
			var disty = (lastPoint.y - y);
			
			var dist = distx*distx + disty*disty;
			if(dist < 100) {
				return false;
			}
		}

		var newPoint = document.createElement('div');
		newPoint.style.position = 'absolute';
		newPoint.style.background = 'red';
		newPoint.style.border = 'none';
		newPoint.style.overflow = 'hidden';
		newPoint.style.width = '5px';
		newPoint.style.height = '5px';
		newPoint.style.left = x+'px';
		newPoint.style.top = y+'px';
		newPoint.style.zIndex = MAP_DRAWING_INDEX;
		newPoint.className = 'DrawnPoint';
		document.getElementById(ImageParentId).appendChild(newPoint);
		newPoint = null;

		DrawnPoints[DrawnPoints.length] = new Point(x,y);
	}

	this.getMapSize = function() {
		var ImageControl = document.getElementById(ImageControlId);
		var SizeObject = ImageControl;
		if(!SizeObject.offsetWidth) {
			SizeObject = document.getElementById(MapParentId);
		}
		var point = new Point(SizeObject.offsetWidth, SizeObject.offsetHeight);
		ImageControl = null;
		return point;
	}


	function showPopupMenuFn(popupDivId) {
		return function(event) {
			var ReferenceIndicator = document.getElementById(ReferenceIndicatorId);
			if(ReferenceIndicator) { return true; }
			popupDiv = document.getElementById(popupDivId);

			if(window.event) { event = window.event; event.which = event.button; }
			if(event.which > 1) {
				if(popupDiv.style.visibility == 'hidden') {
					var objLocation = objectClientPosition(document.getElementById(MapParentId));
					popupDiv.style.left = ZoomPoint.x+objLocation.x+'px';
					popupDiv.style.top = ZoomPoint.y+objLocation.y+'px';
					popupDiv.style.visibility = 'visible';
				} else {
					popupDiv.style.visibility = 'hidden';
				}
			}
			return preventDefaultEvent(event);
		}
	}


	function hidePopupMenuFn(popupMenuId) {
		return function () {
			document.getElementById(popupMenuId).style.visibility = 'hidden';
		}
	}

	this.clearMenu = function (event) {
		if(window.event) { event = window.event; }
		var popupDiv = document.getElementById(PopupMenuId);
		if(popupDiv.style.visibility == 'visible') {
			popupDiv.style.visibility = 'hidden';
		}
		popupDiv = null;
	}

	this.setParent = function(p) {
		MapParentId = p;
		if(MAP_ZOOMIN_STYLE == 'auto' && getBrowser().match(/microsoft/i) && getBrowserVersion() < MAP_IE_SCALE_STYLE_SWITCH) {
			MAP_ZOOMIN_STYLE = 'clip';
		} else if(MAP_ZOOMIN_STYLE == 'auto') {
			MAP_ZOOMIN_STYLE = 'scale';
		}
		
		var MapParent = document.getElementById(MapParentId);

		var ImageParent = document.createElement('div');
		ImageParent.setAttribute('id', ImageParentId);
		ImageParent.style.position = 'absolute';
		ImageParent.style.left = '0px';
		ImageParent.style.top = '0px';
		var ImageControl = document.createElement('input');
		ImageControlId = MapId+'ImageControl';
		ImageControl.setAttribute('id',ImageControlId);
		ImageControl.type = 'Image';
		ImageControl.src = BLANK_IMAGE;
		ImageControl.style.zIndex = MAP_CONTROL_INDEX;

		ImageControl.style.position = 'absolute';
		ImageControl.style.border = 'none';
		ImageControl.style.left = '0px';
		ImageControl.style.top = '0px';
		
		var ImageMapControl = document.createElement('img');
		ImageMapControlId = MapId+'ImageMapControl';
		ImageMapControl.setAttribute('id', ImageMapControlId);
		ImageMapControl.src = BLANK_IMAGE;
		ImageMapControl.style.zIndex = MAP_CONTROL_INDEX - 1;

		ImageMapControl.style.position = 'absolute';
		ImageMapControl.style.border = 'none';
		ImageMapControl.style.left = '0px';
		ImageMapControl.style.top = '0px';

		var imageControlCanvas = document.createElement('canvas');
		imageControlCanvas.style.position = 'absolute';
		imageControlCanvas.style.border = 'none';
		imageControlCanvas.style.left = '0px';
		imageControlCanvas.style.top = '0px';
		imageControlCanvas.style.zIndex = MAP_CONTROL_INDEX - 2;
		imageControlCanvas.setAttribute('id', ImageControlCanvasId);


		MapParent.appendChild(ImageParent);
		MapParent.appendChild(ImageControl);
		MapParent.appendChild(ImageMapControl);
		MapParent.appendChild(imageControlCanvas);
		
		ImageParent = null;

		if(MAP_POPUP_MENU) {
			var popupMenu = document.createElement('div');
			document.getElementsByTagName('body')[0].appendChild(popupMenu);

			popupMenu.setAttribute('id',PopupMenuId);
			popupMenu.style.position = 'absolute';
			popupMenu.style.zIndex = MAP_POPUP_ZINDEX; 
			popupMenu.style.background = '#EEE';
			popupMenu.style.border = 'solid 1px #333';
			popupMenu.style.borderLeft = 'solid 1px #AAA';
			popupMenu.style.borderTop = 'solid 1px #AAA';
			popupMenu.style.cursor = 'pointer';
			popupMenu.style.visibility = 'hidden';
			popupMenu.style.left = '100px';
			popupMenu.style.top = '100px';


			for(menu in MAP_POPUP_FUNCTIONS) {
				var newItem = document.createElement('a');
				newItem.appendChild(document.createTextNode(menu));
				newItem.style.display = 'block';
				newItem.style.textDecoration = 'none';
				newItem.style.color = 'black';
				newItem.setAttribute('id', MapId+'Popup-'+menu);
				newItem.setAttribute('href', MAP_POPUP_FUNCTIONS[menu]);
				newItem.onclick = hidePopupMenuFn(PopupMenuId);
				popupMenu.appendChild(newItem);
				newItem = null;
			}

			popupMenu = null;
			attachEvent(ImageMapControl, 'mousedown', showPopupMenuFn(PopupMenuId));
			attachEvent(ImageControl, 'mousedown', showPopupMenuFn(PopupMenuId));
			attachEvent(document, 'click', MySelf.clearMenu);
		}

		

		ImageControl.oncontextmenu = preventDefaultEvent;
		ImageMapControl.oncontextmenu = preventDefaultEvent;

		attachEvent(ImageControl, 'mousemove', zoomTrackMouse);
		attachEvent(ImageMapControl, 'mousemove', zoomTrackMouse);
		if(MAP_DYNAMIC_ZOOM) {
			attachEvent(ImageControl, 'mousewheel', zoomWheel);
		}

		//MapParent.appendChild(DrawBox);
		refreshDrawBox();
		MapParent.style.overflow = 'hidden';
		ImageControl = null;
		ImageMapControl = null;
		MapParent = null;
		imageControlCanvas = null;

		var navMap = document.createElement('map');
		var mapFile = document.createElement('file');
		navMap.appendChild(mapFile);
		mapFile.appendChild(document.createTextNode('relative://'+BLANK_IMAGE+'?'));
		navMap.setAttribute('title','NAVIGATION');
		MySelf.addLayer(navMap);
		mapFile = null;
		navMap = null;

		this.autoFitLayers();	
	}


	this.processURL = function(url, extents, mSize, mapfile) {
		url = url.replace("%EXTENTS%",extents);
		var extentsArr = extents.split(' ');
		url = url.replace("%MINX%", extentsArr[0]);
		url = url.replace("%MINY%", extentsArr[1]);
		url = url.replace("%MAXX%", extentsArr[2]);
		url = url.replace("%MAXY%", extentsArr[3]);
		url = url.replace("%SIZE%", mSize.toString(" "));
		url = url.replace("%WIDTH%", mSize.x);
		url = url.replace("%HEIGHT%", mSize.y);
		url = url.replace("%MAPBOOK%", MAPBOOK_FILE);
		url = url.replace("%MAPFILE%", mapfile);
		return url;

	}

	this.preprocessURL = function(type, mapTitle) {
		var layerURL = MAPSERVER_IMAGE_URL;
		if(type == 'legend') {
			layerURL = MAPSERVER_LEGEND_URL;
		} else if(type == 'data') {
			layerURL = MAPSERVER_DATA_URL;
		}

		if(LayerURLs[mapTitle].match(/http/i)) {
			layerURL = LayerURLs[mapTitle];
		} else if(LayerURLs[mapTitle].match(/relative/i)) {
			layerURL = new String(LayerURLs[mapTitle]).replace('relative://','');
		} else {
			layerURL = layerURL.replace('%MAPFILE%', LayerURLs[mapTitle]);
		}
		var parameters = MySelf.getLayerParamString(mapTitle);
		if(!parameters) { parameters = ''; }
		if(parameters) {
			layerURL  = layerURL + '&' + parameters;
		}
		var date = new Date();
		layerURL = layerURL + '&MOOSETIME='+date.getTime();
		return layerURL;
	}

	this.getExtent = function (delim) {
		var mapSize = MySelf.getMapSize();
		var gisOffsetW = mapSize.x / 2 * MapScale;
		var gisOffsetH = mapSize.y / 2 * MapScale;
		MapCenterPoint.clean();
		var minPoint = new Point(MapCenterPoint.x - gisOffsetW, MapCenterPoint.y - gisOffsetH);
		var maxPoint = new Point(MapCenterPoint.x + gisOffsetW, MapCenterPoint.y + gisOffsetH);
		var MapCoords = new LineSegment(minPoint,maxPoint);

		var mSize = this.getMapSize();

		var extent = MapCoords.toString(delim);
		return extent;
	}


	function onloadNewImage() {
		var layerName = this.getAttribute('layerName');
		var img = document.getElementById(LayerId+layerName);
		if(img) {
			var p = img.parentNode;
			var zIndex = img.style.zIndex;
			this.style.zIndex = zIndex;
			this.style.visibility = img.style.visibility;
			var origOpacity = getOpacity(img);

			if(MAP_FADE_EFFECTS) {
				setOpacity(this, 0);
				img.setAttribute('id',LayerId+layerName+'-old');
				fadeObject(LayerId+layerName+'-old', origOpacity, 0, MAP_FADE_EFFECTS_DURATION, true);
			
				fadeObject(LayerId+layerName, 0, origOpacity, MAP_FADE_EFFECTS_DURATION, false);	
			} else {
				this.style.visibility = 'visible';
				if(OPACITY_CONTROLS == 'full') {
					setOpacity(this, origOpacity);	
				}
			}
			this.setAttribute('id',LayerId+layerName);
			p.removeChild(img);
			img = null;
			/* This is required to make mode='blank' work. */
			this.onload = null;
		} else {
			var MapParent = document.getElementById(MapParentId);
			this.setAttribute('id',LayerId+layerName);
			MapParent.appendChild(this);
			MapParent = null;
		}
		EventManager.triggerEvent('imagelayer', layerName);
		LayerImages[layerName] = 1;
		MySelf.autoFitLayer(layerName);
	}

	function onAbortNewImage() {
		this.src = this.src+'?1=1';
	}

	this.refreshLayer = function(mapTitles) {
		var mapSize = MySelf.getMapSize();
		
		var mSize = this.getMapSize();

		var extent = this.getExtent(" ");
		var size = this.getMapSize().toString(" ");

		for(var i = 0; i < mapTitles.length; i++) {
			if(!LayerURLs[mapTitles[i]]) {
				break;
			}

			/*
			 * Do a little clean up on the Layer Image Maps 
			 */
			var imageMap = document.getElementById(MapId+'ImageMap-'+mapTitles[i]);
			if(imageMap) {
				var areas = imageMap.getElementsByTagName('area');
				for(var a = areas.length - 1; a >= 0; a--) {
					var p = document.getElementById(areas[a].popup[0]).parentNode;
					for(var pop = 0; pop < areas[a].popup.length; pop++) {
						p.removeChild(document.getElementById(areas[a].popup[pop]));
					}
					imageMap.removeChild(areas[a]);
				}
			}

			if(!MapReference) { /* Main Map Takes care of Popups and Legend, no need to make extra calls */
				if(MAP_POPUPS_ENABLED) {
					var parameters = MySelf.getLayerParamString(mapTitles[i]);
					if(LayerLoadData[mapTitles[i]] && !LayerURLs[mapTitles[i]].match(/http/i) && !LayerURLs[mapTitles[i]].match(/relative:\/\//)) {
						var dataURL = MAPSERVER_DATA_URL;
						dataURL = this.processURL(dataURL, extent, mSize, LayerURLs[mapTitles[i]]);
						if(parameters) {
							dataURL = dataURL + '&' + parameters;
						}
						this.loadData(mapTitles[i], dataURL);
						logDebugMessage('Data URL', false, dataURL);
					}
				}

				if(MAP_LEGENDS_ENABLED && (!LayerURLs[mapTitles[i]].match(/http/i) || LayerLegends[mapTitles[i]])) {
					var legendURL = MAPSERVER_LEGEND_URL;
					if(LayerLegends[mapTitles[i]]) {
						legendURL = LayerLegends[mapTitles[i]];
					}
					legendURL = this.processURL(legendURL, extent, mSize, LayerURLs[mapTitles[i]]);
					if(parameters) {
						legendURL = legendURL + '&' + parameters;
					}
					
					var obj = new LegendObj(mapTitles[i], legendURL);
					EventManager.triggerEvent('legendlayer', obj);

					logDebugMessage('Legend URL', false, legendURL);
				}
			}
	
			var imageURL = MAPSERVER_IMAGE_URL;
			/*if(LayerURLs[mapTitles[i]].match(/http/i)) {
				imageURL = LayerURLs[mapTitles[i]];
			}*/
			imageURL = this.preprocessURL('image', mapTitles[i]);
			imageURL = this.processURL(imageURL, extent, mSize, LayerURLs[mapTitles[i]]);
			var newImage = document.createElement('img');
			newImage.setAttribute('layerName',mapTitles[i]);
			newImage.setAttribute('id',LayerId+mapTitles[i]+'-Loading');
			newImage.style.position = 'absolute';
			newImage.style.visibility = 'hidden';
			document.getElementById(ImageParentId).appendChild(newImage);
			newImage.width = 1;
			newImage.height = 1;
			newImage.onload = onloadNewImage;
			/* This is an IE Hack to make jumping around work correctly, you may carry on ... */
			if(document.all) {
				newImage.onabort = onAbortNewImage;
			}
			//newImage.setAttribute('src', imageURL+'&'+parameters);
			newImage.src = imageURL+'&'+parameters;
			logDebugMessage('Image URL', false, imageURL);
			newImage = null;	

		}

	}

	var Popups = new Array();
	this.getPopupData = function(i) {
		return Popups[i];
	}

	this.getPointScale = function() {
		return new Circle(MapCenterPoint, MapScale);
	}
	
	this.clearPopups = function() {
		var p = document.getElementById(MapParentId); //ImageControl.parentNode;
		var d = p.getElementsByTagName('div');
		for(var i = 0; i < d.length; i++) {
			if(d[i].className == 'Popup') {
				d[i].style.visibility = 'hidden';
			}
		}
	}



	function popupAreaMove(event) {
		if(window.event) { event = window.event; }
		var area = getEventTarget(event);
		if(!area.popupMove) { return false; }
		var ImageControl = document.getElementById(ImageControlId);
		var offsetPoint = objectClientPosition(ImageControl);
		var mouseY = event.clientY-offsetPoint.y;
		var mouseX = event.clientX-offsetPoint.x;
		var offsetX = 5;
		var offsetY = 5;
		for(var i = 0; i < area.popup.length; i++) {
			popup = document.getElementById(area.popup[i]);
			popup.style.zIndex =  MAP_POPUP_ZINDEX;
			/*if(mouseY + popup.offsetHeight < ImageControl.offsetHeight) {*/
			if(mouseY < ImageControl.offsetHeight / 2) {
				popup.style.top = mouseY+offsetY+'px';
				popup.style.bottom = 'auto';
			} else {
				popup.style.bottom = (ImageControl.offsetHeight - mouseY)+offsetY+5+'px';
				popup.style.top = 'auto';
			}
			/*if(mouseX + popup.offsetWidth < ImageControl.offsetWidth) {*/
			if(mouseX < ImageControl.offsetWidth /2 ) {
				popup.style.left = mouseX+offsetX+'px';
				popup.style.right = 'auto';
			} else {
				popup.style.right = (ImageControl.offsetWidth - (mouseX-offsetX))+'px';
				popup.style.left = 'auto';
			}

			popup.style.visibility = 'visible';
			offsetY += 10;
			offsetX += 10;
		}
		area = null;
		ImageControl = null;
	}

	function popupAreaOut(event) {
		if(window.event) { event = window.event; }
		var area = getEventTarget(event);
		if(area.popup) {
			for(var i = 0; i < area.popup.length; i++) {
				document.getElementById(area.popup[i]).style.visibility = 'hidden';
			}
		}
		area = null;
	}

	function popupAreaUp(event,area) {
		if(event || window.event) { area = getEventTarget(event); } 
		if(!area) { area = this; }
		if(area.popupMove) {
			removeEvent(area, 'mouseout', popupAreaOut);
			area.popupMove = false;
		} else {
			attachEvent(area, 'mouseout', popupAreaOut);
			area.popupMove = true;
		}
		area = null;
	}

	function closePopup (event) {
		if(window.event) { event = window.event; }
		var area = getEventTarget(event).parentNode; /* Here via a click, so the image gets the target for some reason */
		var myArea = document.getElementById(area.parentNode.getAttribute('AreaId'));
		area.parentNode.style.visibility = 'hidden';
		if(myArea) {
			popupAreaUp(null,myArea);
		}
		area = null;
	}



	this.loadData = function(id, dataCall) {
		var http = getHTTPObject();
		/*var xmlhttp = getHTTPObject();
		xmlhttp.open('HEAD', dataCall, true);
		xmlhttp.onreadystatechange = function() {
			if(xmlhttp.readyState == 4) {
				if(xmlhttp.status == 200) {
					//alert(xmlhttp.getAllResponseHeaders());
				} else {
					return false;
				}
			}
		}
		xmlhttp.send(null);*/

		http.open('GET', dataCall, true);
		http.onreadystatechange = function() {
			if(http.readyState == 4) {
				if(http.responseXML) {
					var ImageControl = document.getElementById(ImageControlId);
					var imageMap = document.createElement('map');
					var imageMapName = MapId+'ImageMap-'+id;
					imageMap.id = imageMapName;
					if(document.all) {
						imageMap = document.createElement('<map name="'+imageMapName+'">');
					} else {
						imageMap.name = imageMapName;
					}
					var imageMapTest = document.getElementById(imageMapName);

					imageMap.className = 'ImageMaps';
					if(imageMapTest) { imageMap = imageMapTest; }
					var popups = http.responseXML.getElementsByTagName('popup');
					if(popups.length > LAYER_MAXIMUM_OBJECTS) { return false; }

					var styleObject = http.responseXML.getElementsByTagName('style')[0];
					var contentsFunction = function () { };
					var titleFunction = function () { };
					
					if(styleObject) {
						contentsFunction = getStyleFunction('contents', styleObject);
						titleFunction = getStyleFunction('title', styleObject);
					}
					var xCoord = new Array();
					var yCoord = new Array();
					var allShapes = new Array();
					var allShapesTypes = new Array();

					var bin = new Array();
					for(var i = 0; i < popups.length; i++) {
						var coords = popups[i].getAttribute('coords');
							var coordsArr = coords.split(',');
							var found = false;

							for(var x in xCoord) {
								var w = Math.pow(xCoord[x] - coordsArr[0],2);
								var h = Math.pow(yCoord[x] - coordsArr[1],2);
								if(w+h < 49) {
									found = true;
									bin[x][bin[x].length] = popups[i];
								}
							}
							if(!found) {
								xCoord[coords] = coordsArr[0];
								yCoord[coords] = coordsArr[1];
								bin[coords] = new Array();
								bin[coords][0] = popups[i];
								allShapes[coords] = popups[i].getAttribute('shape');
							}


					}

					var popupId = 0;
					var areaId = 0;
					for(var b in bin) {
						var area = document.createElement('area');
						imageMap.appendChild(area);
						if(allShapes[b].match(/line/i)) {
							area.shape = 'poly';
							var points = b.split(' ');
							var pA = new Point(), pB = new Point();
							pA.fromString(points[0], ',');
							pB.fromString(points[1], ',');
							var lineSeg = new LineSegment(pA,pB);
							var poly = lineSeg.buffer(3);
							area.coords = poly.toString(',');
						} else {
							area.shape = allShapes[b];
							area.coords = b;
						}
						area.popup = new Array();
						area.setAttribute('id', MapId+id+'Area-'+areaId);
						areaId++;

						for(var i = 0; i < bin[b].length; i++) {
							popupId++;
							var myPopup = document.createElement('div');
							myPopup.style.border = 'solid 1px #333';
							myPopup.style.borderLeft = 'solid 1px #AAA';
							myPopup.style.borderTop = 'solid 1px #AAA';

							myPopup.setAttribute('id', MapId+id+'-Popup-'+popupId);
							myPopup.setAttribute('AreaId', area.getAttribute('id'));
							myPopup.className = 'Popup';
							document.getElementById(MapParentId).appendChild(myPopup);

							var myPopupTitle = document.createElement('div');
							myPopupTitle.setAttribute('id', myPopup.getAttribute('id')+'-Title');
							myPopupTitle.appendChild(document.createTextNode(bin[b][i].getElementsByTagName('title')[0].firstChild.nodeValue));
							myPopup.appendChild(myPopupTitle);
							myPopup.draggable = new Draggable(myPopup.getAttribute('id'), myPopupTitle, true,true,true);

							titleFunction(myPopupTitle);
							contentsFunction(myPopup);
							var items = bin[b][i].getElementsByTagName('item');

							for(var item = 0; item < items.length; item++) {
								var title = items[item].getAttribute('title');
								var val = '';
								if(items[item].firstChild) {
									val = items[item].firstChild.nodeValue;
								}
								var titleObj = document.createElement('span');
								var valObj = document.createElement('span');
								myPopup.appendChild(titleObj);
								myPopup.appendChild(valObj);
								myPopup.appendChild(document.createElement('br'));

								titleObj.style.fontWeight = 'bold';
								if(title) {
									titleObj.appendChild(document.createTextNode(title));
								}
								if(items[item].getAttribute('href')) {
									var link = document.createElement('a');
									link.href = items[item].getAttribute('href');
									var tgt = items[item].getAttribute('target');
									if(!tgt) { tgt = '_blank'; }
									link.setAttribute('target',tgt);
									link.innerHTML = val;
									valObj.appendChild(link);
									link = null;
								} else {
									if(val.match(/href/i)) { /* There's links in here, possibly messed up ones */
										val = val.replace(/\\\"/g, "");
										val = val.replace(/\\\'/g, "'");
									}
									valObj.innerHTML = val;
								}
								titleObj = null;
								valObj = null;
							}

							var closeL = document.createElement('a');
							closeL.style.position = 'absolute';
							closeL.style.right = '0px';
							closeL.style.top = '0px';
							myPopup.appendChild(closeL);

							var closeImg = document.createElement('img');
							closeImg.src = REMOVE_ICON;
							closeImg.style.width = '8px';
							closeImg.style.height = '8px';
							closeL.appendChild(closeImg);

							attachEvent(closeL, 'click', closePopup);

							area.popup[area.popup.length] = myPopup.getAttribute('id');
							closeL = null;
							myPopup = null;
							myPopupTitle = null;
						}
						area.popupMove = true;
						attachEvent(area, 'mousemove', popupAreaMove);
						attachEvent(area, 'mouseup', popupAreaUp);
						attachEvent(area, 'mouseout', popupAreaOut);
						area = null;
					}
					if(!imageMapTest) {
						document.getElementsByTagName('body')[0].appendChild(imageMap);
					}
					if(popups.length > 0) {
						EventManager.triggerEvent('datalayer',id);
					}
					imageMap = null;
				}
				http = null;
			}
		}
		http.send(true);
	}

	this.activateLayer = function(mapTitle) {
		var imageMapName = MapId+'ImageMap-'+mapTitle;
		var ImageMapControl = document.getElementById(ImageMapControlId);
		var imageControlCanvas = document.getElementById(ImageControlCanvasId);
		ImageMapControl.setAttribute('usemap', '#'+imageMapName);
		ImageMapControl.setAttribute('useMap', '#'+imageMapName);
		ImageMapControl.ismap = true;
		
		ImageMapControl.style.zIndex = MAP_CONTROL_INDEX;
		var ImageControl = document.getElementById(ImageControlId);
		ImageControl.style.zIndex = MAP_CONTROL_INDEX - 1;
		imageControlCanvas.style.zIndex = MAP_CONTROL_INDEX - 2;

		ImageControl = null;
		ImageMapControl = null;
		imageControlCanvas = null;
	}

	function refreshCanvas() {
		var imageControlCanvas = document.getElementById(ImageControlCanvasId);
		imageControlCanvas.style.zIndex = MAP_CONTROL_INDEX - 2;
		imageControlCanvas.style.position = 'absolute';
		imageControlCanvas.style.top = '0px';
		imageControlCanvas.style.left = '0px';
		imageControlCanvas = null;
	}



	this.autoFitLayers = function() {
		var MapParent = document.getElementById(MapParentId);
		var mapSize = new Point(MapParent.offsetWidth, MapParent.offsetHeight);
		var ImageParent = document.getElementById(ImageParentId);
		var ImageControl = document.getElementById(ImageControlId);
		var ImageMapControl = document.getElementById(ImageMapControlId);

		ImageParent.style.width = mapSize.x+'px';
		ImageParent.style.height = mapSize.y+'px';
		for(var title in LayerImages) {
			MySelf.autoFitLayer(title);
		}
		ImageControl.style.width = mapSize.x+'px';
		ImageControl.style.height = mapSize.y+'px';
		if(ImageMapControl) {
			ImageMapControl.style.width = mapSize.x+'px';
			ImageMapControl.style.height = mapSize.y+'px';
		}
		refreshCanvas();
		var imageControlCanvas = document.getElementById(ImageControlCanvasId);
		imageControlCanvas.width = mapSize.x;
		imageControlCanvas.height = mapSize.y;
		if(document.all) {
			imageControlCanvas.style.width = mapSize.x+'px';
			imageControlCanvas.style.height = mapSize.y+'px';
		}
	}

	this.autoFitLayer = function(mapTitle) {
		var mapSize = this.getMapSize();
		this.resizeLayer(mapTitle,mapSize.x,mapSize.y);
	}

	this.resizeLayer = function(mapTitle,w,h) {
		//LayerImages[mapTitle].style.visibility = 'hidden';
		var img = document.getElementById(LayerId+mapTitle);
		img.style.top = '0px';
		img.style.left = '0px';
		img.style.width = w+'px';
		img.style.height = h+'px';
		img = null;
		//LayerImages[mapTitle].style.visibility = 'visible';
	}

	this.reloadLayers = function() {
		MySelf.autoFitLayers();
		MySelf.refreshLayers();
	}

	/*
	 * These functions are for Reference Map behaviour
	 */

	function toggleReferenceIndicatorFunction(event) {
		if(window.event) { event = window.event; event.which = event.button; }
		if(event.which > 1) {
			// If you right click, hide the reference map box for better zooming.
			var ReferenceIndicator = document.getElementById(ReferenceIndicatorId);
			event.returnValue = false;
			if(ReferenceIndicator.style.zIndex < MAP_CONTROL_INDEX) {
				ReferenceIndicator.style.zIndex = MAP_CONTROL_INDEX + 1;
			} else {
				ReferenceIndicator.style.zIndex = MAP_CONTROL_INDEX - 1;
			}
			var currentBg = ReferenceIndicator.style.background;
			ReferenceIndicator.style.background = ReferenceIndicator.swapBG;
			ReferenceIndicator.swapBG = currentBg;

			var currentBorder = ReferenceIndicator.style.border;
			ReferenceIndicator.style.border = ReferenceIndicator.swapBorder;
			ReferenceIndicator.swapBorder = currentBorder;

			ReferenceIndicator = null;
		} else {
			if(this._onmousedown) {
				this._onmousedown(event);
			}
		}
		return preventDefaultEvent(event);
	}


	this.refreshLayers = function() {
		if(MapReference) {
			var ImageControl = document.getElementById(ImageControlId);
			var oldMap = MapReference.getMapSize();
			var newW = oldMap.x / ScaleFactor;
			var newH = oldMap.y / ScaleFactor;
			var MySize = MySelf.getMapSize();
			var left = (MySize.x - newW) / 2;
			var top = (MySize.y - newH) / 2;
			var ReferenceIndicator = document.getElementById(ReferenceIndicatorId);
			if(!ReferenceIndicator) { 
				ReferenceIndicator = document.createElement('div');
				ReferenceIndicator.setAttribute('id', ReferenceIndicatorId);
				ReferenceIndicator.gDRAGGER = new Draggable(ReferenceIndicatorId, ReferenceIndicator, true, true, true);

				ImageControl._onmousedown = ImageControl.onmousedown;
				attachEvent(ImageControl,'mousedown', toggleReferenceIndicatorFunction);
				ImageControl.oncontextmenu = preventDefaultEvent;
				ReferenceIndicator.oncontextmenu = preventDefaultEvent;

				attachEvent(ReferenceIndicator, 'mousedown', toggleReferenceIndicatorFunction);


				ReferenceIndicator.gDRAGGER.onDrop = function (trig,obj) {
					trig = obj;
					var diffX = trig.offsetLeft - left;
					var diffY = trig.offsetTop - top;
					for(var l in LayerImages) {
						var img = document.getElementById(LayerId+l);
						img.style.left = img.offsetLeft - diffX + 'px';
						img.style.top = img.offsetTop - diffY + 'px';
						img = null;
					}
					MySelf.zoomToScaledImage();
				}

			}
						
			ReferenceIndicator.style.position = 'absolute';
			ReferenceIndicator.style.top = top + 'px';
			ReferenceIndicator.style.left = left + 'px';
			ReferenceIndicator.style.background = 'white';
			ReferenceIndicator.style.border = 'solid 1px black';
			ReferenceIndicator.style.width = newW+'px';
			ReferenceIndicator.style.height = newH+'px';
			ReferenceIndicator.style.zIndex = MAP_POPUP_ZINDEX;
			ReferenceIndicator.style.overflow = 'hidden';
			ReferenceIndicator.swapBG = '';
			ReferenceIndicator.swapBorder = 'solid 3px #A0A';
			setOpacity(ReferenceIndicator, 75);
			document.getElementById(MapParentId).appendChild(ReferenceIndicator);
			ReferenceIndicator.style.zIndex = MAP_CONTROL_INDEX+1;

			ImageControl = null;
			ReferenceIndicator = null;
		}
		var arr = new Array();
		for(var title in LayerImages) {
			arr[arr.length] = title;
		}
		MySelf.refreshLayer(arr);
	}

	function getStyleFunction(tagType, styleXML) {
		if(!styleXML) { return function(obj) { }; }
		var tag = styleXML.getElementsByTagName(tagType);
		var evalString = '';

		for(var t = 0; t < tag.length; t++) {
			var attrs = tag[t].getElementsByTagName('attr');
			for(var a = 0; a < attrs.length; a++) {
				evalString += ('obj.style.'+attrs[a].getAttribute('name')+'="'+attrs[a].getAttribute('value')+'";');
			}
		}	
		return function(obj) { eval(evalString); };
	}

	this.moveLayerUp = function(title) {
		MySelf.shiftLayer(title, 1);
	}

	this.moveLayerDown = function(title) {
		MySelf.shiftLayer(title, -1);

	}

	this.changeLayerOpacity = function(layerName, amount) {
		var img = document.getElementById(LayerId+layerName);
		var opac = getOpacity(img);
		opac+=amount;
		if(opac < 0) { opac = 0; }
		if(opac > 100) { opac = 100; }
		setOpacity(img, opac);
	}

	this.getOpacity = function(layerName) {
		return getOpacity(document.getElementById(LayerId+layerName));
	}
	
	function checkOpacityAbility() {
		if(OPACITY_CONTROLS == 'prompt' || (OPACITY_CONTROLS == 'auto' && getBrowser().match(/microsoft/i) && getBrowserVersion() < MAP_IE_SCALE_STYLE_SWITCH)) {
			if(OPACITY_CONTROLS_DISABLED_MESSAGE) {
				alert(OPACITY_CONTROLS_DISABLED_MESSAGE);
			}
			return false;
		} else if(OPACITY_CONTROLS == 'auto') { /* Everyone else plays nice with opacity, so just do it! */
			return true;
		}

		if(OPACITY_CONTROLS == 'none') {
			return false;
		}

		/* If it's 'full' or something unknown, return true. */
		return true;

	}
	
	this.fadeLayer = function(title) {
		if(checkOpacityAbility()) {
			MySelf.changeLayerOpacity(title, -10);
		}
	}

	this.unfadeLayer = function(title) {
		if(checkOpacityAbility()) {
			MySelf.changeLayerOpacity(title, 10);
		}
	}

	this.reloadLayer = function(title) {
		var arr = new Array();
		arr[0] = title;
		MySelf.refreshLayer(arr);
	}
	
}
