	/****************************
	 *	GENERAL PURPOSE FUNCTIONS
	 ****************************/

	/* Old debug functions */	
	/* DEBUG: Dump on same page */
	function DebugDump( text ) {
		var debugObject = document.getElementById('jsdump');
		debugObject.innerHTML = text;
	}
	function URLDump( text ) {
		//	3/5/06 -- disabled for now because I removed the urlObject on the main page
		//var urlObject = document.getElementById('urlField');
		//urlObject.value = text;
	}
	function ShowURLinNewWin( url ) {
	//  3/20/06 -- Dump to new page instead.
		var w = window.open();
		w.document.write( url );
		w.document.close();
	}
	
	function ToggleDebug() {
		if (debugOn) {
			debugOn = false;
		} else {
			debugOn = true;
		}
	}
	
	/* DEBUG: Dump to new window */
	function DebugPage( text ) {
		var w = window.open();
		w.document.write( text );
		w.document.close();
	}
	
	
	/* DEBUG: Dump to new window, cached */
	var dbgWindow;
	var dbgCacheText = '';
	var dbgDumpNow = false;
	function Debug( text ) {
		var dbgText = (new Date()).toLocaleString() + ': ' + text + '<br>';
		dbgCacheText += dbgText;
		if (dbgDumpNow) {
			DebugPrint();
		}
	}
	function DebugPrint() {
		if (debugOn) {
			if (!dbgWindow || dbgWindow.closed) {
				dbgWindow = window.open('','Debug');
			}
			try {
				dbgWindow.document.open();
				dbgWindow.document.write( dbgCacheText );
				if (!dbgDumpNow) {
					dbgWindow.document.close();
				}
				dbgCacheText = '';
			}
			catch (error) {
				//alert( 'Debugging Issue: DebugPrint not able to print.  Error = ' + error );
			}
		}
	}
	
	function NotImplemented() {
		alert('Sorry, this feature isn\'t implemented yet.');
	}
	
	/*
	 *	GetAttributes
	 *					This is mostly needed because Safari implements DOM attributes differently than FireFox and IE.
	 *	@param	DOMelement	element
	 *	@param	string		attrName
	 *	@return	null 		if no value is found.
	 *
	 *	example:	attr = GetAttributes( theBtn, 'mapID' );
	 */
	function GetAttributes( element, attrName ) {
		if (element.hasAttributes) {
			//	Mozilla/Safari
			//	Mozilla can also use the .attributes['value'] method, but Safari cannot.
			if (element.attributes.getNamedItem( attrName ) != null) {
				//alert ('getAttr = ' + element.attributes.getNamedItem( attrName ).value);
				return element.attributes.getNamedItem( attrName ).value;
			} else {
				//alert('getAttr = null for element ' + element +' attrName = ' + attrName);
				return null;
			}
		} else {
			//	IE / Firefox
			//	Firefox can support .attributes['value'], but should get caught by the .hasAttributes above.
			if (element.attributes[attrName] != null) {
				//alert ('getAttr = ' + element.attributes[attrName].value);
				return element.attributes[attrName].value;
			} else {
				//alert('not has attribute: getAttr = null for element ' + element +' attrName = ' + attrName);
				return null;
			}
		}
	}
	
	
	/*
	 *	BROWSER DETECTION
	 *
	 *	SAFARI:	We want to know if it's safari to handle the click event after a drag
	 *
	 *	From http://www.webreference.com/tools/browser/sniffer2.js
	 *
	 */
		var agt = navigator.userAgent.toLowerCase();		
		var is_safari = ((agt.indexOf('safari')!=-1)&&(agt.indexOf('mac')!=-1))?true:false;
	
		
	
	/****************************
	 *	BUTTONTOGGLE UI FUNCTIONS
	 ****************************/
	//	Page Specific 
	var compareBtn		= new ButtonToggle();		// jsToggleButton.js
	
	function InitButtons() {
		//	compareBtn
		el = document.getElementById('compareBtn');
		compareBtn.SetElement( el );	
		compareBtn.SetOffMsg( 'Compare Maps' );		//	Compare is off, so clicking button will turn on Compare
		compareBtn.SetOnMsg( 'Show Single Map' );	//	Compare is on, so clicking button will turn off Compare
		compareBtn.ChangeBtnState('off');
		compareBtn.DoAction = function() {
			if (compareBtn.IsOn()) {
				ShowMap2();
			} else {
				HideMap2();
			}
		}
	}
	function AddButtonListeners() {
		//	compareBtn
		var el = document.getElementById('compareBtn');
		addEvent(el, 'click', compareBtn.Listener, false);
	}
	//	INIT
	function WindowButtonInit() {
/* 3/5/06 -- compare button removed
		InitButtons();		//	Buttons MUST be inited before listeners can be added
		AddButtonListeners();
*/	}


	
	//	Set ZOOM buttons
	function HandleZoomOutToFull( event ) {
		mapID = HandleZoomBtn( event );
		DoSubmit( mapID );														//	Force page to refresh, rather than wait for click
		ClearPrevClick( mapID );
	}	
	function HandleZoomBtn( event ) {
		//	Handles clicks on the Zoom buttons
		//alert('HandleZoomBtn called');
		
		//	Get the button
		var theBtn = GetElementFromEvent( event );
		//alert('theBtn = ' + theBtn );

		//	Figure out which zoom button this is
		var mapID			= GetAttributes( theBtn, 'mapID' );
		var cmdStr			= GetAttributes( theBtn, 'cmdStr' );
		//alert( 'mapID = ' + mapID + ' cmdStr = ' + cmdStr);

		//	Clear the other selected commands		
		ClearSetZoomBtns( mapID );												//	Just clear all the zoom buttons, we'll set the clicked one later
		// don't clear the SetInfo btn anymore, since zoom is modeless.  ClearSetInfoBtns( mapID );

		//	Set the display via css
		JsBtnToggleState( theBtn );
		
		SetZoomCmd( cmdStr, mapID, theBtn );
		DoSubmit( mapID );														//	Zoom now! 
		
		ClearPrevClick( mapID );
		ClearCmdStr( mapID );													//	Clear the command so that the next click is not a zoom

		return mapID
	}
	
	function SetZoomCmd( newCmdStr, mapID, theButton ) {
		//	Force them both off b/c we lose track of them after a submit
		//alert('About to call CleaerSetInfoBtns')
		SetCmdStr( newCmdStr, mapID );
	}
	function ClearSetZoomBtns( mapID ) {
		var btn = document.getElementById( mapID + '_zoomIn' );
		ClearSetZoomBtn( btn );

		var btn = document.getElementById( mapID + '_zoomOut' );
		ClearSetZoomBtn( btn );

		var btn = document.getElementById( mapID + '_zoomFull' );
		ClearSetZoomBtn( btn );
	}	
//	No longer  used?  10/15/05
//	function ClearSetZoomBtnById( id ) {
//		theButton = document.getElementById( id );
//		ClearSetZoomBtn(theButton);
//	}	
	function ClearSetZoomBtn( obj ) {
		JsBtnSetState( obj, 'Off' );
	}
	
	
	//	jsBtn Methods
	function HandleJsBtn( event ) {
		//	This handles checkbox buttons (Layer Label checkbox)
		//	The button's name = the checkBox button's name + '_label'.  e.g. if checkBox is 'm1_lyrLakes', then the button name is 'm1_lyrLakes_label'
		//	This makes it easy for us to figure out the both the mapID and the corresponding checkBox.
		//	This also means that we don't have to add a js property to the object just to pass the data along.
		var theBtn = GetElementFromEvent( event );
		//alert('HandleJsBtn: theBtn = ' + theBtn );
		
		//	Set the display state
		JsBtnToggleState( theBtn );

		//	Figure out which checkbox this is
		var nameChunks		= theBtn.id.split('_');
		var mapID			= nameChunks[0];
		var layerCheckboxID	= nameChunks[1];
		var layerCheckbox	= document.getElementById( mapID + '_' + layerCheckboxID );
		//alert( 'layerCheckBoxID = ' + layerCheckboxID + ' layerCheckbox = ' + layerCheckbox);
		
		//	Now set the internal state representation
		ToggleCheckboxLabelState( layerCheckbox );
		
		DoSubmit( mapID );
	}
	function JsBtnToggleState( theBtn ) {
		//	Switches the button display between on and off
		var btnState = theBtn.className.split(' ')[1];	//	Get the current state based on the css class name, e.g. 'jsBtn on'
		if (btnState == 'On') {
			newState = 'Off';
			//Debug('JsBtnToggleState: turning ' + theBtn.id + ' off');
		} else {
			newState = 'On';
			//Debug('JsBtnToggleState: turning ' + theBtn.id + ' on');
		}	
		JsBtnSetState( theBtn, newState );
	}
	function JsBtnSetState( theBtn, newState ) {
		if (newState == 'On') {
			theBtn.className = 'jsBtn On';
		} else {
			theBtn.className = 'jsBtn Off';
		}	
	}
	function JsBtnHoverOn( event ) {
		//alert( 'JsBtnHoverOn called' );
		var theBtn			= GetElementFromEvent( event );
		theBtn.className	+= ' Hover';
	}
	function JsBtnHoverOff( event ) {
		var theBtn	= GetElementFromEvent( event );
		var classes = theBtn.className.split(' ');
		theBtn.className = classes[0] + ' ' + classes[1];
	}
	function ToggleCheckboxLabelState( layerCheckbox ) {
		currentState = layerCheckbox.value.split(',')[1];						//	the .value is the form value that is being passed via GET, e.g. 'm1_lyrLakes=lakes,loff'
		if (currentState == LABELbtn_ON) {
			//Debug('ToggleCheckboxLabelState = ' + currentState + ' turning it OFF');
			newState = LABELbtn_OFF;
		} else {
			//Debug('ToggleCheckboxLabelState = ' + currentState + ' turning it ON');
			newState = LABELbtn_ON;
		}
		SetCheckboxLabelState( layerCheckbox, newState );
	}
	function SetCheckboxLabelState( layerCheckbox, newState ) {
		var baseValue 		= layerCheckbox.value.split(',')[0];
		layerCheckbox.value	= baseValue + ',' + newState;	
		//Debug('SetCheckboxLabelState new layerCheckbox.value for ' + layerCheckbox.id + ' = ' + layerCheckbox.value);
	}
	/* Not used as of 11/10/05.  Buttons are restored upon creation. */
	function RestoreLabelBtns( mapID ) {
		var theList = legendMgr.getLabelBtnIDArray();
		var u = theList.length;
		for (var i=0;i<u;i++) {
			var theBtn = document.getElementById( theList[i] );
			//Debug( '...working on ' + theList[i] + ' and found element ' + el);
			var nameChunks = theBtn.id.split('_');								// theBtn.id = 'm1_lyrWorld_label'
			var checkBoxID = nameChunks[0] + '_' + nameChunks[1];
			var checkBox = document.getElementById( checkBoxID );
			//Debug(checkBox.id + ' value is ' + checkBox.value + ' and setting = ' + checkBox.value.split(',')[1] );
			if ( checkBox.value.split(',')[1] == LABELbtn_OFF ) {
				//	Label is off!
				//alert( checkBox.id + '\'s label is off' );
				newState = 'Off';
			} else {
				//alert( checkBox.id + ' is ON' );
				newState = 'On';
			}
			JsBtnSetState( theBtn, newState );
		}
	}	
	
	
	function ShowClickPointInfo( mapID ) {
		var clickPointInfo	= document.getElementById( mapID + '_clickPointInfo' ).innerHTML;
		//alert ('clickPointInfo = ' + clickPointInfo );
		var clickDisplay	= document.getElementById( 'clickPointDisplayData' );
		//alert ('clickDisplay = ' + clickDisplay );
		clickDisplay.innerHTML = clickPointInfo;
		//DebugPage( clickPointInfo );
	}
	
	function ClearPrevClick( mapID ) {
		var prevx = document.getElementById( mapID+'_prevx' );
		var prevy = document.getElementById( mapID+'_prevy' );
		prevx.value = '';
		prevy.value = '';	
	}
	
	/****************************
	 *	ResetMapImage
	 *
	 *	This is necessary because IE doesn't properly refresh the map image's background
	 *	when the Map Tab is first displayed: the map image is left blank.
	 *	Selecting the Map tab will call this function, which redisplays the map image.
	 *
	 ****************************/
	function ResetMapImage( mapID ) {
		var mapImageObject = document.getElementById(mapID);
		
		//	If ResetMapImage is called too early (e.g. on init), mapurl is still undefined, so just display the blank image
		if (mapurl == undefined) {
			mapurl = '../../hmap/img/onepixel.gif';
		}
		
		//	Precache image so that the map won't flicker when updating
		var tmpImage = new Image();
		tmpImage.src = mapurl;
		mapImageObject.style.backgroundPosition = '0px 0px';					// return map to origin (in case it was moved)
		mapImageObject.style.backgroundImage = 'url('+mapurl+')';
	}
	
	/****************************
	 *	MOVE
	 *
	 *  @param	string	mapID		DOM id of the map element, e.g. 'm1'
	 *	@param	string	direction	Compass direction
	 *
	 ****************************/
	function Move( mapID, direction ) {
		var extentEl 	= document.getElementById( mapID + '_newExtent');
		var oldExtent	= extentEl.value;
		
		// split ' '
		var extentArray = oldExtent.split(' ')
		
		// move by half the size of the current extent
		var moveX		= Math.abs( parseFloat(extentArray[0]) - parseFloat(extentArray[2]) )/3;
		var moveY		= Math.abs( parseFloat(extentArray[1]) - parseFloat(extentArray[3]) )/3;
		
		// add
		var newLeft		= parseFloat(extentArray[0]);
		var newTop		= parseFloat(extentArray[1]);
		var newRight	= parseFloat(extentArray[2]);
		var newBottom	= parseFloat(extentArray[3]);
		
		//	move
		switch (direction) {
			case 'n':
				newTop		+= moveY;
				newBottom	+= moveY;
				break;
			case 'ne':
				newTop		+= moveY;
				newBottom	+= moveY;
				newLeft		+= moveX;
				newRight	+= moveX;
				break;
			case 'e':
				newLeft		+= moveX;
				newRight	+= moveX;
				break;
			case 'se':
				newTop		-= moveY;
				newBottom	-= moveY;
				newLeft		+= moveX;
				newRight	+= moveX;
				break;
			case 's':
				newTop		-= moveY;
				newBottom	-= moveY;
				break;
			case 'sw':
				newTop		-= moveY;
				newBottom	-= moveY;
				newLeft		-= moveX;
				newRight	-= moveX;
				break;
			case 'w':
				newLeft		-= moveX;
				newRight	-= moveX;
				break;
			case 'nw':
				newTop		+= moveY;
				newBottom	+= moveY;
				newLeft		-= moveX;
				newRight	-= moveX;
				break;
		}
		var newExtent	= newLeft + ' ' + newTop + ' ' + newRight + ' ' + newBottom;
		
		// set newExtentEl.value
		extentEl.value = newExtent;
		
		// DoSubmit to redraw.
		DoSubmit( mapID );
	}
	/****************************
	 *	MOVEBY
	 *
	 *	We're relying on the onClick event triggering after this to call DoSubmit
	 *
	 *  @param	string	mapID		DOM id of the map element, e.g. 'm1'
	 *	@param	double	pDeltaX		Percentage of movement (calculated as pixelsDragged / mapWidth)
	 *
	 ****************************/
	function MoveBy( mapID, pDeltaX, pDeltaY ) {
		//alert('MoveBy called');
		
		var extentEl	= document.getElementById( mapID + '_newExtent');
		var oldExtent	= extentEl.value;
		
		// split ' '
		var extentArray = oldExtent.split(' ')
				
		// movement = percentage of px movement * size of extent
		var moveX		= pDeltaX * Math.abs( parseFloat(extentArray[0]) - parseFloat(extentArray[2]) );
		var moveY		= pDeltaY * Math.abs( parseFloat(extentArray[1]) - parseFloat(extentArray[3]) );

		// add
		var newLeft		= parseFloat(extentArray[0]) - moveX;
		var newTop		= parseFloat(extentArray[1]) + moveY;
		var newRight	= parseFloat(extentArray[2]) - moveX;
		var newBottom	= parseFloat(extentArray[3]) + moveY;
		
		var newExtent	= newLeft + ' ' + newTop + ' ' + newRight + ' ' + newBottom;
		
		// set extentEl.value
		extentEl.value = newExtent;
		
	}

	/****************************
	 *	FORM MANAGEMENT FUNCTIONS
	 ****************************/
	
	function SetCmdStr( newCmdStr, mapID ) {
		//	Set the cmdStr for the form
		document.forms[0][mapID+'_cmdStr'].value = newCmdStr;
		//	Save off a local copy
		cmdStr = newCmdStr;
		//document.myLegend.action = submitURL;
		//alert('SetCmdStr: About to updateURL');
		UpdateURL();
		//alert('UpdateURL: Completed');
	}

	function ClearCmdStr( mapID ) {
		//	Set the cmdStr for the form
		document.forms[0][mapID+'_cmdStr'].value = '';
		//	Set local copy
		cmdStr = '';
		UpdateURL();		
	}

	/*
	 *	@return		String			Returns the query string
	 */
	function UpdateURL() {
		//alert( 'UpdateURL called');
		legibleQstring = ConstructQueryString( document.forms[0] );
		//alert('UpdateURL: Continue after ConstructReadableQueryString');
		url = document.location + '?' + legibleQstring;
		URLDump( url );
		
		return legibleQstring;
	}
	
	
	function MarkerIsSet( markerNumber, mapID ) {
		var markerPointStr = document.forms[0].elements[ mapID + '_markerPoint' ];
		var markerPointArray = markerPointStr.value.split(',');
		if ( markerPointArray[markerNumber] == '0 0' ) {
			return false;
		} else {
			return true;
		}
	}
	
	



	/****************************
	 *	MAP 2 FUNCTIONS
	 ****************************/
	
	//	Renders the second map and shows the timeline
	function ShowMap2() {
		restartTime();
		qstring = ConstructQueryString( document.forms[0] );
		DebugDump( qstring);
		RenderMap('m2', qstring, debugOn);
		ShowTimeline2();
	}
	//	Shows the timeline for map2
	function ShowTimeline2() {
		var tObject = document.getElementById('m2_timeline');
		//tObject.innerHTML = unescape("");
	}
	function HideMap2() {
		//	Hide Map
		var m	= document.getElementById('m2');
		offURL	= m2EmptyURL;
		m.src	= offURL;
		
		//	Hide Legend
		var l		= document.getElementById('m2_legend');
		l.innerHTML	= '';
	}	
	
	
	/****************************
	 *	DATES WINDOW DISPLAY
	 ****************************/

	//	Open a new window and show the dates available to each layer
	function ShowDates( dateText ) {
		var DateWin = window.open('','','width=400,height=200')
		DateWin.document.write( '<div style="font-size:10px">' + dateText + '<\/div>' )
		DateWin.document.close()
	}
	
	
	
	/****************************
	 *	LOADING MESSAGE DISPLAY
	 ****************************/
	var loadWin;
	
	function InitLoadWin() {
		var loadWinElement	= document.getElementById('loadWinContainer');
		var loadWinTextEl	= document.getElementById('loadWinText');
		loadWin				= new FloatingWin( loadWinElement, loadWinTextEl );
		//alert( 'loadWin is ' + loadWin + ' loadWinElement is ' + loadWinElement + ' loadWinTextEl is ' + loadWinTextEl);
	}	
	function ShowLoadWin() {
		//	compareBtn
		/*  THis is screwed up. Just hard code it for now
		var containerObj	= document.getElementById( containerObjID );
		//alert( containerObjID + ' = ' + containerObj + ' width=' + containerObj.clientWidth);
		//alert( 'loadWin='+loadWin+' clientWidth='+loadWin.clientWidth);
		alert( 'loadWinElement='+loadWinElement+' clientWidth='+loadWinElement.clientWidth+' clientHeight='+loadWinElement.clientHeight);
		alert('containerObj.offsetLeft='+ containerObj.offsetLeft+'containerObj.offsetTop='+ containerObj.offsetTop);
		var relX	= containerObj.offsetLeft + (containerObj.clientWidth - loadWinElement.clientWidth)/2;
		var relY	= containerObj.offsetTop + (containerObj.clientHeight - loadWinElement.clientHeight)/2;
		alert( 'relX,y = ' + relX + ',' + relY );
		*/
		
		//addEvent(loadWinElement, 'click', loadWin.Listener, false);
		
		//loadWin.SetText( 'Loading...' );
		//loadWin.Show();
// full debug display location		loadWin.DisplayAt( 50, 100, 'm1', '<span id="loadMsg">Loading</span>...<span id="loadMsgTime"></span>' );
		loadWin.DisplayAt( 100, 300, 'm1', '<span id="loadMsg">Loading</span>...<span id="loadMsgTime"></span>' );
		ShowOverlay();
	}
	
	function HideLoadWin() {
		if (loadWin) {
			loadWin.Hide();
		}
		HideOverlay();
	}

	//	Show the loading message
	function ShowLoadingMessage() {
		ShowLoadWin();
		//var mapImageObject = document.getElementById('loadImg')
		//mapImageObject.src = loadingImage.src
		return false
	}
	function ClearLoadingMessage() {
		HideLoadWin();
		//var mapImageObject = document.getElementById('loadImg')
		//mapImageObject.src = onePixel.src
		return true
	}
	
	//	Clear overlay and restore previous map.
	function CancelLoading() {
		alert('loading cancelled');
	}
	
	function SetLoadingMessage( newMsg ) {
		var loadWinMsgEl	= document.getElementById('loadMsg');
		var loadWinMsgTime	= document.getElementById('loadMsgTime');
		
		//	Update the time
		currentTime();

		//	Only show the detailed loading message if debug is On
		if (debugOn) {
			//	Construct history
			var history = loadWinMsgEl.innerHTML + '...' + loadWinMsgTime.innerHTML;
			loadWinMsgEl.innerHTML = history + '<br>' + newMsg;
		}
	}

	
	/****************************
	 *	SUBMIT
	 ****************************/
	var mapIsBeingSubmitted = false;											//	Keeps track of whether DoSubmit has been called, to prevent multiple calls
																				//	cleared by  FinishedLoading
	//	Submit via Legend display controls
	//	Used to automatically update the screen whenever the user changes the layer display (e.g. show/hide, or select new main data layer)
	function DoSubmit( mapID ) {
//Debug('DoSubmit called');

		//	Show the new URL
		var qstring = UpdateURL();
		DoSubmitWithURL( mapID, qstring );

		if ( (currentClickX) && (currentClickY) && (currentClickX!='') && (currentClickY!='') ) {
			//	Only set the previous click values if there was a click.
			//	If there wasn't a click, we want to leave the values alone.
			
			//	Set the previous values
			var prevx = document.getElementById( mapID+'_prevx' );
			var prevy = document.getElementById( mapID+'_prevy' );
			prevx.value = currentClickX;
			prevy.value = currentClickY;
			//alert('Setting previous xy to ' + prevx.value + ',' + prevy.value);
		}
		
		//	Clear the current click after submitting
		currentClickX = '';
		currentClickY = '';
		
		return false;	//	Trap the form from submitting
	}
	function DoSubmitWithURL( mapID, qstring ) {
		if (mapIsBeingSubmitted) {
			return;																//	Don't update if map is being submitted.
		}
		
		//	log time
		restartTime();
		
		//	lock out submits
		mapIsBeingSubmitted = true;

		//	Show Loading Message
		ShowLoadingMessage();
		
		if (!mapID) {
			//	no map submitted, so change both
			//	!!!! THIS IS A HACK!!!!
			alert('no mapID, updating m1 and m2 manually');
			RenderMap('m1', qstring, debugOn);
			RenderMap('m2', qstring, debugOn);
		} else {
			RenderMap(mapID, qstring, debugOn);
		}
		
		DoSubmitContinue();
	
	}
	
	//	Clean up after the submit
	function DoSubmitContinue() {
//		alert('DoSubmitContinue called');
		
		if (!loadingIsCancelled) {
			//	Clear the click points so that the next submit will not use them inadvertantly
			document.getElementById( 'm1_x' ).value = '';
			document.getElementById( 'm1_y' ).value = '';
			document.getElementById( 'm1_keymap_x' ).value = '';
			document.getElementById( 'm1_keymap_y' ).value = '';
		}
	}
	
	
	
	/****************************
	 *	MAP LISTENERS
	 ****************************/
	
	function MapListener(event) {
//		alert('MapListener fired! (usually after onClick event)');
		
		//	Set the source element that triggered the event
		var element;	
		if (window.event && window.event.srcElement)
			// IE
			element = window.event.srcElement;
		if (event && event.target) 
			element = event.target;
		if (!element)
			return;
	
/* 		s = 'e.target='+event.target+' e.layerX is ' + event.layerX + ' layerY= '+ event.layerY + ' screen='+event.screenX+' page='+event.pageX; 
 		s += ' offset='+event.offsetX+' clientX='+event.clientX+' object='+element;
 		s += ' object.offsetLeft= '+element.offsetLeft;
 		s += ' object.offsetTop= '+element.offsetTop;
 	//	s += ' object.style.top= '+this.style.top;
 	//	s += ' parentNode = ' + element.parentNode;
 	//	s += ' parentNode.style = ' + this.parentNode.style;
 	//	s += ' parentNode.style.left = ' + this.parentNode.style.left;
 	//	s += ' parentelementement = ' + element.parentelementement; 		
 	//	s += ' element.id = ' +element.id;
 		//alert( s );
*/

		//	Set the query parameters
		var mx = document.getElementById( element.id+'_x' );
		var my = document.getElementById( element.id+'_y' );

		if (window.event) {
			//	IE
			mx.value = window.event.offsetX;
			my.value = window.event.offsetY;
		} else {
			//	Firefox:	Note that this only works if the element has a style defined, otherwise, the values are relative to the window
			//	Safari:		Doesn't have the same limitation as FireFox.  Will work even if there's no style defined.
			mx.value = event.layerX;
			my.value = event.layerY;
		}

		//	Set the command
		//		Don't set the marker command if we already set drag, or if we're clicking in a keymap
		if ((element.id != 'm1_keymap') && (element.id != 'm2_keymap') && (cmdStr != 'Drag')) {
			//	Set currentClick (center point for zooming)
			currentClickX = mx.value;
			currentClickY = my.value;
			//alert('Setting currentClick to ' + currentClickX +','+ currentClickY);

			//	Set marker 0
			SetCmdStr( 'm1_SetMarker,0', 'm1' );
		}
		
		//	Request the map
		//	We're assuming the id is the first two characters of the el.id.
		DoSubmit( element.id.substr(0,2) );
		
	}
	
	function GetElementFromEvent( event ){
		//	Get the source element that triggered the event
		//	Does browser checking to figure out how to retrieve the element
		if (window.event && window.event.srcElement)
			// IE
			return window.event.srcElement;
		if (event && event.target) 
			return event.target;
		if (!element)
			return;
	}


	function InstallMapListeners() {
		//	This handles all the clicks on the main map and keymap images
		
		var element = document.getElementById('m1');
		addEvent(element, 'click', MapListener, false);
		
		var element = document.getElementById('m2');
		if (element != null) {													//	No second map on a compare page
			addEvent(element, 'click', MapListener, false);
		}	
		
		var element = document.getElementById('m1_keymap');
		addEvent(element, 'click', MapListener, false);
		
		var element = document.getElementById('m2_keymap');
		if (element != null) {
			addEvent(element, 'click', MapListener, false);
		}
	}
	
	function InstallLegendListeners( mapID ) {
	
		//	Label Buttons
		var theList = legendMgr.getLabelBtnIDArray();
		var u = theList.length;
		for (var i=0;i<u;i++) {
			var theBtn = document.getElementById( theList[i] );
			InstallLabelBtnListener( theBtn );
		}
		
	}

	function InstallLabelBtnListener( labelBtn ) {
		addEvent(labelBtn, 'click', HandleJsBtn, false);
		addEvent(labelBtn, 'mouseover', JsBtnHoverOn, false);
		addEvent(labelBtn, 'mouseout', JsBtnHoverOff, false);		
	}
	
	function InstallZoomBtnListeners( mapID ) {
		var btn = document.getElementById( mapID + '_zoomIn' );
		addEvent(btn, 'click', HandleZoomBtn, false);
		addEvent(btn, 'mouseover', JsBtnHoverOn, false);
		addEvent(btn, 'mouseout', JsBtnHoverOff, false);	

		var btn = document.getElementById( mapID + '_zoomOut' );
		addEvent(btn, 'click', HandleZoomBtn, false);
		addEvent(btn, 'mouseover', JsBtnHoverOn, false);
		addEvent(btn, 'mouseout', JsBtnHoverOff, false);	

		var btn = document.getElementById( mapID + '_zoomFull' );
		addEvent(btn, 'click', HandleZoomOutToFull, false);
		addEvent(btn, 'mouseover', JsBtnHoverOn, false);
		addEvent(btn, 'mouseout', JsBtnHoverOff, false);	

	}
	
	function InstallDragMapListeners() {
		dragInit( 'm1' );
		//dragInit( 'm2' );
	}
	
	function addEvent(elm, evType, fn, useCapture) {
 	// cross-browser event handling for IE5+, NS6+ and Mozilla/Gecko 
 	// By Scott Andrew 
 	// from http://www.sitepoint.com/article/dhtml-utopia-modern-web-design/3
 		try 
 		{
			if (elm.addEventListener) { 
				elm.addEventListener(evType, fn, useCapture); 
				return true; 
			} else if (elm.attachEvent) { 
				var r = elm.attachEvent('on' + evType, fn); 
				return r; 
			} else { 
				elm['on' + evType] = fn; 
			}
		} 
		catch (error) 
		{
			Debug('addEvent.Error: ' + error + ' with elm=' + elm + ' and evType ' + evType + ' and fn='+fn);
		}
	}
 
	

	
	/****************************
	 *	DISPLAY MANAGER
	 ****************************/
	var DisplayMgr = {
	
		create:	function( newMapID ) {
			var dmgr = new Object;
			Object.extend( dmgr, DisplayMgr );
			dmgr.mapID = newMapID;
			return dmgr;
		},
		
		attachTimelineButtons: function( timelineButtonsDiv ) {
			var el = document.getElementById('timelineBtns');
			el.parentNode.replaceChild( timelineButtonsDiv, el );
		}
	
	}	





	/****************************
	 *	LOAD MANAGERS
	 ****************************/
	var legendMgr	= new LegendMgr('m1');
	var displayMgr	= DisplayMgr.create('m1');		//	above
	var timelineMgr	= TimelineMgr.create('m1');		//	jsTimelinemgr.js
	
	
	
	
	/****************************
	 *	PAGE INIT
	 ****************************/

	//	Called by hmap_loadMgr.js.ShowMapAndLegend() after maps and legends are loaded
	//	Used to clear loading message and timers
	function FinishedLoading( mapID ) {
		SetLoadingMessage('Setting UI');
		ClearSetZoomBtns( mapID );
		
		displayMgr.attachTimelineButtons( timelineMgr.getTimelineButtonsDiv() );
		timelineMgr.updateButtonsState();
		timelineMgr.updateTimelineButtonDisplay();
		
		InstallLegendListeners( mapID );

		//	Highlight the recent query row
		// new Effect.Highlight('mostRecentQueryResult', {duration: 3});
		
		RSReplaceSelects();					//	Replace SELECTS with css version		RBtnReplaceAll();					//	Replace BUTTONs with css version

		ClearCmdStr( mapID );

		stopTime();
		SetLoadingMessage('Done loading');
		ClearLoadingMessage();

		//	allow submits
		mapIsBeingSubmitted = false;		
				
		DebugPrint();
	}
	 
	function InitPage()	{
		RenderMap('m1',location.search+'&'+pathToSettings);	//	hmap_loadMgr.js
		if (compareMode=='on') 		{
			ShowMap2();
		}
	}
	
	function WindowInit() {
		InitLoadWin();
		InitOverlay();
		ShowLoadingMessage();
		InitPage();
		InstallMapListeners();		//	map image listeners
		InstallZoomBtnListeners('m1');
		InstallDragMapListeners();
		WindowButtonInit();			//	UI buttons
		
		disableIETextSelection();	//	This should be placed in a mouseEnter event for the map object
	}
	
	addEvent(window, 'load', WindowInit, false);
	
	//alert( location.search );
