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 LayerSelections = new Array();
	var LayerMinScale = new Array();
	var LayerMaxScale = new Array();

	var LayerDebug = 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+t);
			if(img) {
				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';

	var PointDrawingSemaphore = true;
	
	function startDrawing(event) {
		var DrawBox = document.getElementById(DrawBoxId);
		DrawBox.style.left = '0px';
		DrawBox.style.top = '0px';
		DrawBox.style.height = '1px';
		DrawBox.style.width = '1px';

		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);
		}
		return preventDefaultEvent(event);

	}

	
	function drawPointOnly(event) {
		if(PointDrawingSemaphore) {	
			whileDrawing(event);
			PointDrawingSemaphore = false;
		}
	}
	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;
		}
		return preventDefaultEvent(event);

	}
	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;
			var DrawBox = document.getElementById(DrawBoxId);
			var GroundUnits = new Array();

			/* Convert Drawn Points into Ground Units */
			if(DrawBox.offsetWidth > 7) {
				var ptA = new Point(DrawBox.offsetLeft, DrawBox.offsetTop);
				var ptB = new Point(ptA.x + DrawBox.offsetWidth, ptA.y + DrawBox.offsetHeight);
				DrawnPoints[0] = ptA;
				DrawnPoints[1] = new Point(ptB.x, ptA.y);
				DrawnPoints[2] = ptB;
				DrawnPoints[3] = new Point(ptA.x, ptB.y);
			}

			for(var i = 0; i < DrawnPoints.length; i++) {
				GroundUnits[i] = MySelf.pointToGroundUnits(new Point(DrawnPoints[i].x,DrawnPoints[i].y));
			}
			EventManager.triggerEvent('finishdrawing', GroundUnits);

			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]);
				}
			}
		}
		PointDrawingSemaphore = true;
	}

	this.mapStats = function() {
		logDebugMessage('Map Statistics', false, MapCenterPoint.toString(",")+' '+MapScale);
	}

	this.getCenterPoint = function() {
		return MapCenterPoint;
	}

	this.getScale = function() {
		return 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.groundUnitsToPixels = function(p) {
		var mapsize = MySelf.getMapSize();
		var x = ((p.x - MapCenterPoint.x ) * (1/MapScale)) + parseInt(mapsize.x/2);
		var y = mapsize.y - (((p.y - MapCenterPoint.y ) * (1/MapScale)) + parseInt(mapsize.y/2));
		p.x = Math.floor(x);
		p.y = Math.floor(y);
		return p;
		
	}

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

	var DrawingArea = new Array();

	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() {
		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;
		ImageControl.onmouseout = 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");
				ctx.strokeStyle = "red";
				ctx.save();
					ctx.beginPath();
					ctx.moveTo(0,0);
					ctx.lineTo(1000,1000);
					ctx.stroke();
					ctx.closePath();
				ctx.restore();
//				return true;

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

				DrawnPoints[DrawnPoints.length] = new Point(ZoomPoint.x, ZoomPoint.y);
				
				MySelf.clearDrawingArea();
				ctx.strokeStyle = "red";

				for(var i = 1; i < DrawnPoints.length; i++) {
					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();
				}

				for(var i = 0; i < DrawnPoints.length; i++) {
					ctx.save();
						ctx.strokeStyle = "red";
						ctx.fillStyle = "red";
						//ctx.arc(ZoomPoint.x, ZoomPoint.y, 3, 0, Math.PI * 2, true);
						ctx.arc(DrawnPoints[i].x, DrawnPoints[i].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();
				EventManager.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]);
				}
				EventManager.triggerEvent('finishdrawing', DrawnPoints);
				DrawnPoints = new Array();
			}
		} else if (shape == 'point') {
			attachEvent(ImageControl, 'mousedown', startDrawing);
			attachEvent(ImageControl, 'mousemove', drawPointOnly);
			attachEvent(ImageControl, 'mouseup', stopDrawing);
		} 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; }
		if(ImageControl && objectClientPosition) { } else { return false; }

		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;
		return preventDefaultEvent(event);
	}

	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 && 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;
		} else {
			return false;
		}
		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;
			ImageControl.onmouseout = endPan;
		} 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 (ZoomPoints) { 
				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);
				//	MySelf.recenterImage(ZoomPoints[0].x, ZoomPoints[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.clearLayerSelection = function(mapTitle) {
		LayerSelections[mapTitle] = new Array();
	}

	this.addLayerSelection = function(mapTitle, selectionValue) {
		if(!LayerSelections[mapTitle]) { LayerSelections[mapTitle] = new Array(); }
		LayerSelections[mapTitle].push(selectionValue);
	}

	this.getLayerSelection = function(mapTitle) {
		return LayerSelections[mapTitle];
	}


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

	/* Makes sure an array is not created */
	this.setLayerParam = function(mapTitle,paramName,paramValue) {
		if(!LayerParameters[mapTitle]) { LayerParameters[mapTitle] = new Array(); }
		LayerParameters[mapTitle][paramName] = new Array(paramValue);
	}

	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.getLayerParam = function(mapTitle, paramName) {
		return LayerParameters[mapTitle][paramName];
	}

	this.getLayerParameters = function(mapTitle) {
		if(!LayerParameters[mapTitle]) { return false; }
		return LayerParameters[mapTitle];
	}

	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 mapTitle = mapXMLObj.getAttribute('title');
		var mapFile;

		/* If the reference attribute is set to "only" it's not displayed
		   in the main map.
		*/
		if(!MapReference && new String(mapXMLObj.getAttribute('reference')).match(/only/i)) {
			return false;
		}

		if(mapXMLObj.getElementsByTagName('file')[0]) {
			mapFile = mapXMLObj.getElementsByTagName('file')[0].firstChild.nodeValue;
			mapFile = trim(mapFile);
			LayerURLs[mapTitle] = mapFile;
		}
		var mapOpacity = mapXMLObj.getAttribute('opacity');
		var mapData = mapXMLObj.getAttribute('popups');
		var zIndex = parseInt(mapXMLObj.getAttribute('zindex'));


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

		LayerLoadData[mapTitle] = mapData;
			

		var newLayer = document.getElementById(LayerId+mapTitle);
		var isNewLayer = false;
		
		if(!newLayer) {
			isNewLayer = true;
			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 != 'none') {
				setOpacity(newLayer, mapOpacity);
			}
		} else {
			setOpacity(newLayer, 100);
		}
			

		if(MAP_MAPBOOK_ORDER) {
			if(zIndex) {
				newLayer.style.zIndex = MAP_MAX_ZINDEX - parseInt(zIndex);
			} else if(isNewLayer) {
				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++) {
			if(mapParams[i].getAttribute('type')) {
				var paramType = new String(mapParams[i].getAttribute('type')).toLowerCase();
				if(paramType == 'today') {
						var formatString = mapParams[i].getAttribute('format');
						if(!formatString) {
							formatString = '%M/%D/%Y';
						}
						var offset = mapParams[i].getAttribute('offset');
						if(offset) {
							offset = parseInt(offset) * 86400000;
						} else {
							offset = 0;
						}
						var d = new Date();
						var dateString = mapParams[i].getAttribute('date');
						if(dateString) {
							d = new Date(dateString);
						}

						mapParams[i].setAttribute('value',strfdate(new Date(d.getTime() + offset), formatString));
				}

			}
			MySelf.addLayerParam(mapTitle, mapParams[i].getAttribute('name'), mapParams[i].getAttribute('value'));
		}

		/* Get possible active sub layers */
		var layers = mapXMLObj.getElementsByTagName('layer');
		var defSubLayers = new Array();
		for(var i = 0; i < layers.length; i++) {
			if(parseBoolean(layers[i].getAttribute('default'),true)) {
				defSubLayers.push(layers[i].getAttribute('name'));
			}
		}
		MySelf.setLayerParam(mapTitle, 'layers', defSubLayers.join(' '));

		MySelf.clearLayerSelection(mapTitle);
		var mapSelection = mapXMLObj.getElementsByTagName('selected');
		for(var i = 0; i < mapSelection.length; i++) {
			MySelf.addLayerSelection(mapTitle, mapSelection[i].getAttribute('id'));
		}

		/* Individual Layer Scale Settings */
		if(mapXMLObj.getAttribute('minscale')) {
			LayerMinScale[mapTitle] = mapXMLObj.getAttribute('minscale');
		}
		if(mapXMLObj.getAttribute('maxscale')) {
			LayerMaxScale[mapTitle] = mapXMLObj.getAttribute('maxscale');
		}
		if(mapXMLObj.getAttribute('debug') && mapXMLObj.getAttribute('debug').match(/true/i)) {
			LayerDebug[mapTitle] = 1;
		}

		/*
		 * Custom Legend settings
		 */
		if(mapXMLObj.getElementsByTagName('legend')[0] && mapXMLObj.getElementsByTagName('legend')[0].firstChild.nodeValue) {
			LayerLegends[mapTitle] = mapXMLObj.getElementsByTagName('legend')[0].firstChild.nodeValue;
		}
		newLayer = null;
		/*EventManager.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];
			}
			var loadingImage = document.getElementById(LayerId+mapTitle+'-Loading');
			if(loadingImage && loadingImage.parentNode) {
				var p = loadingImage.parentNode;
				p.removeChild(loadingImage);
			}
			img = null;
		}
		MySelf.clearLayerParams(mapTitle);
		MySelf.clearLayerSelection(mapTitle);
	}

	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.isRelativeLayer = function(maptitle) {
		if(LayerURLs[maptitle]) {
			return LayerURLs[maptitle].match(/relative/i);
		}
		return false;
	}

	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; 

		if(MapCenterPoint.x != groundCenterX || MapCenterPoint.y != groundCenterY || scale != 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+")", MAP_NAVIGATION_DELAY);
		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+5+'px';
					popupDiv.style.top = ZoomPoint.y+objLocation.y+5+'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;
	}

	function createOrReplaceCanvas(w,h) {
		var MapParent = document.getElementById(MapParentId);
		var testForCanvas = document.getElementById(ImageControlCanvasId);
		if(testForCanvas) {
			MapParent.removeChild(testForCanvas);
		}

		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.width = w;
		imageControlCanvas.height = h;
		if(document.all) {	
			imageControlCanvas.style.width = w+'px';
			imageControlCanvas.style.height = h+'px';
		}			
		imageControlCanvas.setAttribute('id', ImageControlCanvasId);
		MapParent.appendChild(imageControlCanvas);
	}


	this.setParent = function(p) {
		MapParentId = p;
		if(MAP_ZOOMIN_STYLE == 'auto' && getBrowser().match(/microsoft/i) && parseInt(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');
		var ImageControl = document.createElement('img');

		
		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.width = 100;
		imageControlCanvas.height = 100;
		imageControlCanvas.setAttribute('id', ImageControlCanvasId);
*/
		MapParent.appendChild(ImageParent);
		MapParent.appendChild(ImageControl);
		MapParent.appendChild(ImageMapControl);
		
//		MapParent.appendChild(imageControlCanvas);
		createOrReplaceCanvas(100,100);

		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.onmousemove = preventDefaultEvent;
			ImageControl.onmousedown = preventDefaultEvent;
		} else {
			attachEvent(ImageControl, 'mousedown', preventDefaultEvent);
			attachEvent(ImageMapControl, 'mousedown', preventDefaultEvent);
		}

		ImageMapControl.oncontextmenu = preventPopupMenu;
		ImageControl.oncontextmenu = preventPopupMenu;

		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.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;*/
			this.style.visibility = 'visible';
			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 {
			//	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 onerrorNewImage() {
		/* It's "loaded" */
		var layerName = this.getAttribute('layerName');
		EventManager.triggerEvent('imagelayer', layerName);
		LayerImages[layerName] = 1;
		this.style.visibility = 'hidden';

		var img = document.getElementById(LayerId+layerName);
		if(img) {
			img.style.visibility = 'hidden';
		}
	}

	var abortCounter = 0;
	function onAbortNewImage() {
		abortCounter++;
		var url = new String(this.src);
		var sep = '?';
		if(url.indexOf('?') > 0) {
			sep = '&';
		}
		this.src = url+sep+'='+abortCounter;
	}

	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]);
			var imageMap = document.getElementById(MapId+'-'+mapTitles[i]+'-Imagemap');
			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]);
				}
			}


			/* Setup the basic URLs */
			var imageURL = MAPSERVER_IMAGE_URL;
			var legendURL = MAPSERVER_LEGEND_URL;
	

			if(LayerURLs[mapTitles[i]].match(/relative/i)) {
				imageURL = new String(LayerURLs[mapTitles[i]]).replace('relative://','');
				legendURL = false;
			}
			/*
			 * Additional Inputs from the layer parameters
			 */
			var additionalInputs = new Array();
			var layerUrl = LayerURLs[mapTitles[i]];
			if(layerUrl.substring(0,1) == '/' || layerUrl.match(/[A-Za-z]\:/)) {
				additionalInputs['MAPFILE'] = LayerURLs[mapTitles[i]];
			} else {
				additionalInputs['MAPFILE'] = MAPSERVER_MAPFILE_ROOT + LayerURLs[mapTitles[i]];
			}
			/* Get the Layer Parameters */
			var parameters = MySelf.getLayerParamString(mapTitles[i]);

			if(parameters && parameters != 'null') {
				var imageSep = '?';
				var dataSep = '?';
				var legendSep = '?';
				
				if(imageURL.indexOf('?') > 0) { imageSep = '&'; } 
				imageURL  = imageURL + imageSep + parameters;

				if(legendURL) {
					if(legendURL.indexOf('?') > 0) { legendSep = '&'; } 
					legendURL  = legendURL + legendSep + parameters;
				}
			}
			if(MAP_TIMESTAMP_REQ) {
				additionalInputs['MOOSETIME'] = (new Date()).getTime();
				imageURL += '&MOOSETIME=%MOOSETIME%';
			}


			/* Now we need to do a little manipulation to see if the Layer needs any special 
			 * treatment.  relative:// will be stripped and just try to accessd a static relative URL
			 * http:// can be used to access WMS services
			 */
			if(LayerURLs[mapTitles[i]].match(/http/i)) {
				imageURL = LayerURLs[mapTitles[i]];
				if(MAP_TIMESTAMP_REQ) {
					imageURL += '&MOOSETIME=%MOOSETIME%';
				}
				legendURL = false;
			}

			if(!MapReference) { /* Main Map Takes care of Popups and Legend, no need to make extra calls */
				if(MAP_LEGENDS_ENABLED && (legendURL || LayerLegends[mapTitles[i]])) {
					/* If there is a preset Legend Image, use that */
					if(LayerLegends[mapTitles[i]]) {
						legendURL = LayerLegends[mapTitles[i]];
					} else { /* Do some string processing... */
						additionalInputs['MODE'] = 'legend';
						legendURL = ProcessURLString(this, legendURL, new Array(), additionalInputs,' ',' '); 
					}

					var obj = new LegendObj(mapTitles[i], legendURL);
					EventManager.triggerEvent('legendlayer', obj);
					
					logDebugMessage('Legend URL', false, legendURL);
				}
			}
			var layerMode = 'map';
			if(imageURL.indexOf('mapshape') > 0) {
				layerMode = 'nquerymap';
			}
			if(MySelf.getLayerParam(mapTitles[i], 'MOOSEMODE')) {
				layerMode = MySelf.getLayerParam(mapTitles[i], 'MOOSEMODE');
			}
	
			additionalInputs['MODE'] = layerMode;
			imageURL = ProcessURLString(this, imageURL, new Array(), additionalInputs,' ',' '); 

			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;
			newImage.onerror = onerrorNewImage;
			/* This is an IE Hack to make jumping around work correctly, you may carry on ... */
			if(document.all) {
				newImage.onabort = onAbortNewImage;
			}

			if(!MySelf.isLayerVisible(mapTitles[i])) {
				imageURL = BLANK_IMAGE+'?rtime='+(new Date()).getTime(); // The Rtime trick is meant to fix some of the IE caching bugs that will happen (It will forget to trigger the onload event
			}

			
			if(LayerDebug[mapTitles[i]] || MAP_DEBUG_LAYERS) {
				debugLayer(mapTitles[i], imageURL);
			} else {
				newImage.src = imageURL;
			}

			logDebugMessage('Image URL', false, imageURL);
			newImage = null;	
		}

	}


	this.isLayerVisible = function(mapTitle,overrideMin, overrideMax) {
		var inchScale = pixelScaleToInchScale(MySelf, MapScale);
		var layerMinScale = LayerMinScale[mapTitle];
		var layerMaxScale = LayerMaxScale[mapTitle];
		if(overrideMin) { layerMinScale = overrideMin; }
		if(overrideMax) { layerMaxScale = overrideMax; }
		return !((layerMinScale && inchScale < layerMinScale) || (layerMaxScale && inchScale > layerMaxScale));
	}

	function debugLayer(mapTitle, imageURL) {
		var debugLayer = getHTTPObject();
		if(imageURL.match('http://') || imageURL.match('relative://')) {
			document.getElementById(LayerId+mapTitle).src = imageURL;
			EventManager.triggerEvent('imagelayer', mapTitle);
			LayerImages[mapTitle] = 1;
			return true;
		}

		debugLayer.open('GET', imageURL, true);
		debugLayer.onreadystatechange = function () {
			if(debugLayer.readyState == 4) {
				if(!debugLayer.getResponseHeader('Content-type').match(/image/)) {
					var LAYER_BROKEN_MESSAGE = 'The layer "%LAYER%" is broken, would you like to debug it?';
					var msg = LAYER_BROKEN_MESSAGE.replace('%LAYER%',mapTitle);
					if(confirm(msg)) {
						window.open(imageURL);
					}
				}
				LayerImages[mapTitle] = 1;
				EventManager.triggerEvent('imagelayer', mapTitle);
				document.getElementById(LayerId+mapTitle).src = imageURL;

			}
		}
		debugLayer.send();

	}

	this.debugLayerOn = function(title) {
		LayerDebug[title] = true;
	}

	this.debugLayerOff = function(title) {
		LayerDebug[title] = false;
	}

	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 == 'popupParent') {
				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.preprocessURL = function(type, mapTitle) {
		var layerURL = MAPSERVER_IMAGE_URL;
		layerURL = layerURL.replace('%MODE%','map')
		if(type == 'legend') {
			layerURL = MAPSERVER_LEGEND_URL;
			layerURL = layerURL.replace('%MODE%','legend')
		} 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;
		}
		return layerURL;
	}



	this.getId = function() {
		return MapId;
	}

	this.getParentId = function() {
		return MapParentId;
	}

	this.getImageControlId = function() {
		return ImageControlId;
	}

	this.clearActiveLayer = function() {
		var ImageMapControl = document.getElementById(ImageMapControlId);
		ImageMapControl.setAttribute('usemap', '');
		ImageMapControl.setAttribute('useMap', '');
		ImageMapControl = null;
	}

	this.onActivateLayer = function(mapTitle) {
		var imageMapName = MapId+mapTitle+'-Imagemap';
		var ImageMapControl = document.getElementById(ImageMapControlId);
		var imageControlCanvas = document.getElementById(ImageControlCanvasId);
		var ImageControl = document.getElementById(ImageControlId);

		if(POPUP_LAYERCHANGE_CLEAR) {
			/* Clear all the other popups */
			MySelf.clearPopups();
		}
		if(POPUPS_TRIGGER_CHANGETOOL) {
			ImageMapControl.setAttribute('usemap', '#'+imageMapName);
			ImageMapControl.setAttribute('useMap', '#'+imageMapName);
			ImageMapControl.ismap = true;
			
			ImageMapControl.style.zIndex = MAP_CONTROL_INDEX;
			ImageControl.style.zIndex = MAP_CONTROL_INDEX - 1;
			imageControlCanvas.style.zIndex = MAP_CONTROL_INDEX - 2;
		} else {
			ImageControl.style.zIndex = MAP_CONTROL_INDEX;
			ImageControl.setAttribute('usemap', '#'+imageMapName);
			ImageControl.setAttribute('useMap', '#'+imageMapName);
			ImageControl.ismap = true;
		}
		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';
		}
		if(getBrowser().match(/microsoft/i)) {
			var imageControlCanvas = document.getElementById(ImageControlCanvasId);
			imageControlCanvas.width = mapSize.x;
			imageControlCanvas.height = mapSize.y;
			imageControlCanvas.style.width = mapSize.x+'px';
			imageControlCanvas.style.height = mapSize.y+'px';
		} else {
			createOrReplaceCanvas(mapSize.x, mapSize.y);
		}
	}

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


	function preventPopupMenu(event) {
		return preventDefaultEvent(event);
	}

	this.refreshLayers = function() {
		var ImageControl = document.getElementById(ImageControlId);
		var ImageMapControl = document.getElementById(ImageControlId);

		if(MapReference) {
			var WorkingScale = ScaleFactor;
			var oldMap = MapReference.getMapSize();
			var newW = oldMap.x / WorkingScale;
			var newH = oldMap.y / WorkingScale;
			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 = preventPopupMenu;
				ReferenceIndicator.oncontextmenu = preventPopupMenu;
				*/

				ImageControl.oncontextmenu = preventPopupMenu;
				ReferenceIndicator.oncontextmenu = preventPopupMenu;

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

		/** Clear out any active image map **/
		if(POPUPS_TRIGGER_CHANGETOOL) {
			if(ImageMapControl) {
				ImageMapControl.setAttribute('usemap', '');
				ImageMapControl.setAttribute('useMap', '');
				ImageMapControl.ismap = false;
			}
		} else {
			if(ImageControl) {
				ImageControl.setAttribute('usemap', '');
				ImageControl.setAttribute('useMap', '');
				ImageControl.ismap = false;
			}
		}

		var arr = new Array();
		for(var title in LayerImages) {
			arr[arr.length] = title;
		}
		MySelf.clearActiveLayer(); // Reset the Imagemap
		MySelf.refreshLayer(arr);
	}

	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);
		var oo = opac;
		opac+=amount;
		if(opac <= 0) { opac = 0; }
		if(opac > 100) { opac = 100; }
		setOpacity(img, opac);
	}

	this.getLayerOpacity = 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);
	}
	
	/* Blank out a layer */
	this.clearLayer = function(title) {
		if(LayerURLs[title]) {
			LayerURLs[title] = 'relative://'+BLANK_IMAGE;	
		}
		MySelf.reloadLayer(title);
	}

	this.itemQueryLayer = function(title, queryLayer, columnName, queryValue, queryFile) {
		if(queryFile) {
			LayerURLs[title] = queryFile;
		}
		this.clearLayerParams(title);
		this.addLayerParam(title, 'MOOSEMODE', 'itemquerymap');
		this.addLayerParam(title, 'qitem', columnName);
		this.addLayerParam(title, 'qstring', queryValue);
		this.addLayerParam(title, 'qlayer', queryLayer);
		MySelf.reloadLayer(title);
	}

	this.initializeEvents = function () {
		EventManager.addEventListener('removelayer', MapId,MySelf.removeLayer);
		EventManager.addEventListener('addlayer', MapId, MySelf.addLayer);
		EventManager.addEventListener('addselection', MapId, MySelf.addSelection);
		EventManager.addEventListener('navigate', MapId, [MySelf.onChangePointScale, MySelf.clearPopups]);
		EventManager.addEventListener('activatelayer', MapId, MySelf.onActivateLayer);
		EventManager.addEventListener('movelayerup',MapId, MySelf.moveLayerUp);
		EventManager.addEventListener('movelayerdown', MapId, MySelf.moveLayerDown);
		EventManager.addEventListener('fadelayer',MapId, MySelf.fadeLayer);
		EventManager.addEventListener('unfadelayer', MapId, MySelf.unfadeLayer);
		EventManager.addEventListener('refreshlayer', MapId, MySelf.reloadLayer);
		EventManager.addEventListener('refreshlayers', MapId, MySelf.refreshLayers);
		EventManager.addEventListener('zoom', MapId, MySelf.loadZoomTool);
		EventManager.addEventListener('changetool', MapId, MySelf.onChangeTool);
		EventManager.addEventListener('measure', MapId, MySelf.loadMeasureTool);
		EventManager.addEventListener('windowresize',MapId,MySelf.reloadLayers);
	}
}
