var dataset = 'ivy.dataset';
var themeColor = '_b';
var buttonStyle = 'icon';
var clickDragRelease = false;
var decor = 'barAndNorth.layer';
/******************************************************************************
 * 
 * Copyright (c) 2003 GenaWare Pty. Ltd
 * This software is protected by Copyright, and
 * cannot be copied, modified, or altered in any way,
 * without the expressed written permission of GenaWare Pty Ltd.
 * This notice must appear in any copy, altered or not, of this software.
 *
 *
 * ivy_map.js contains the javascript that handles mouse events occuring within the
 * "map" area of the application.
 *****************************************************************************/
 
/**
 * The map image identifier
 */
var _MAPIMAGE 		= "gwimage";

/**
 * Valid mouse operations
 */
var _MOUSEOP_ZOOMIN 	= "zoomin";
var _MOUSEOP_ZOOMOUT 	= "zoomout";
var _MOUSEOP_ZOOMSCALE 	= "zoomscale";
var _MOUSEOP_PAN	= "pan";
var _MOUSEOP_QUERY	= "query";

/**
 * Zoom/pan box layers
 */
var _BOX_LEFT			= 0;
var _BOX_TOP			= 1;
var _BOX_RIGHT			= 2;
var _BOX_BOTTOM			= 3;

/**
 * Frames
 */
var _FRAME_Layers		= "Layers";
var _FRAME_Map			= "MapWindow";
var _FRAME_Span			= "Span";
var _FRAME_NavBar		= "NavBar";
var _FRAME_QueryOpt		= "QueryOpt";
var _FRAME_FindOpt		= "FindOpt";
var _FRAME_Work			= "Work";
var _FRAME_Search		= "Search";
var _FRAME_Result		= "Result";
var _FRAME_ResultPopup		= "ResultPopup";
var _FRAME_Query		= "Query";
var _FRAME_User			= "User";

/**
 * Supported query types
 */
var _QUERY_Point		= "point";
var _QUERY_BufferedPoint	= "buffered";
var _QUERY_Line			= "line";
var _QUERY_BufferedLine		= "bufferedLine";
var _QUERY_MultiPoint		= "multi";
var _QUERY_Polygon		= "polygon";
var _QUERY_Neighbour		= "neighbour";
var _QUERY_Distance		= "distance";
var _QUERY_Selection		= "selection";
var _QUERY_Cancel		= "cancel";

/**
 * Server Side printing variables.
 */
var A4P = false ; 
var A4L = false ;
var A3P = false ; 
var A3L = false ;
var A2P = false ; 
var A2L = false ;
var A1P = false ; 
var A1L = false ;
var A0P = false ; 
var A0L = false ;

var A4P_v = "" ;
var A4L_v = "" ;
var A3P_v = "" ;
var A3L_v = "" ;
var A2P_v = "" ;
var A2L_v = "" ;
var A1P_v = "" ;
var A1L_v = "" ;
var A0P_v = "" ;
var A0L_v = "" ;


/**
 * The current mouse operation mode, defaults to zoom in
 */
var mouseMode			= _MOUSEOP_ZOOMIN;

/**
 * The default map image size
 */
var mapImageWidth	= 500;
var mapImageHeight	= 450;

/**
 * Default color for the rubberbanding selector
 */
var rubberColor			= "#ff0000";

/**
 * The currently open dataset, default to the basic dataset
 */
var openDataset = dataset;

/**
 * default style properties
 */
var themeColor 			= "_b";
var otherColor 			= "_y";
var fontColor 			= "#ffffff";
var fontColorHighlite 	= "#0000ff";
var bgColor 			= "#0000ff";
var bgColorHighlite 	= "#000000";

var buttonStyle			= "icon";

/**
 * The global name to be used for all requests
 */
var myname				= undefined;

/**
 * The current window extent
 */
var curwindow			= undefined;
var span				= undefined;

/**
 * This variable determines if the dataset selection ui will be displayed
 */
var showDataset			= true;

var	autoSearch;
var	drawOnStart 		= true;

/**
 * Image handling functionality
 */
 
function initMapWindow( drawStatus )
{
	var window = getFrame( _FRAME_Map );

	if (isNetscape())
	{
		mapImageWidth = window.innerWidth;
		mapImageHeight = window.innerHeight;
	}
	else
	{
		mapImageWidth = window.document.body.offsetWidth;
		mapImageHeight = window.document.body.offsetHeight;
	}
	

	if (drawStatus != undefined)
	{

		/* Save the search string, to be used */
		/* when "drawMap()" is first called */

		if (isNetscape())
			autoSearch = location.search;
		else
			autoSearch = location.search;
		if (autoSearch == '')
			autoSearch = undefined;

		/* Can immediately draw as soon as layers are */
		/* loaded if not doing an autosearch. Otherwise, */
		/* must wait until the Finds are loaded */

		if (autoSearch == undefined)
			drawOnStart = drawStatus;
		else
			drawOnStart = 0;
	}
}


function resizeMapWindow()
{
	initMapWindow( true );
	drawMap( "-in 0 0 " + mapImageWidth + " " + mapImageHeight );
}


function getImageSizeParam()
{
	var mapFrame = getFrame( _FRAME_Map );
	var mapWidth;
	var mapHeight;
	
	if (isNetscape())
	{
		mapWidth = mapFrame.innerWidth;
		mapHeight = mapFrame.innerHeight;
	}
	else
	{
		mapWidth = mapFrame.document.body.offsetWidth;
		mapHeight = mapFrame.document.body.offsetHeight;
	}
	
	return mapWidth + " " + mapHeight;
}


/**
 * loadImage is called by onLoad()
 */
function loadImage( imgElem )
{
	var uspan;

	/**
	 * we only work on the map window
	 */
	var window = getFrame( _FRAME_Map );

	/**
	 * Reset status text display
	 */
	top.status = "";


	window.document.getElementById("busydiv").style.visible=false;
	
	/**
	 * Setup the mouse event handling
	 */
	setupMouseEventHandler( window.document );
	
	/**
	 * Setup the new window properties
	 */
	if (isNetscape())
	{
		var src = getFrame( _FRAME_Map ).document.forms["infoForm"];
		var dst = getFrame( _FRAME_Layers ).document.forms["layForm"];
		
		dst.elements['curwindow'].value =
			src.elements['curwindow'].value;
		dst.elements['prevwindow'].value =
			src.elements['prevwindow'].value;
		dst.elements['initwindow'].value =
			src.elements['initwindow'].value;
			
		curwindow = src.elements['curwindow'].value;
		span = src.elements['span'].value;
		uspan = src.elements['uspan'].value;
	}
	else
	{
		var src = window.document.all['curwindow'];
		var dst = getFrame("Layers").document.all['curwindow'];
		dst.value = src.value;
		curwindow = src.value;

		var src = window.document.all['prevwindow'];
		var dst = getFrame("Layers").document.all['prevwindow'];
		dst.value = src.value;

		var src = window.document.all['initwindow'];
		var dst = getFrame("Layers").document.all['initwindow'];
		dst.value = src.value;

		span = window.document.all['span'].value;
		uspan = window.document.all['uspan'].value;
	}
	
	/**
	 * Extract the name of the units
	 */
	var i = span.indexOf( " " );
	if ((i != undefined) && 
		(++i < span.length))
	{
		unitName = span.substring( i, span.length );
		span = span.substring( 0, i );
	}

	updateLayerVisibility( uspan );

	/**
	 * Update the span
	 */
	var frame = getFrame( "Span" );
	if (frame != undefined)
	{
		var doc = frame.document.open();
		doc.write( "<html><head><link REL='stylesheet' HREF='" );
		doc.write( serverName + "/gw.css' TYPE='text/css'></head> ");
		doc.write( "<body class='span'><table><tr><td class='formlabel'>" );
		doc.write( "Map Width:</td><td class='formvalue'>" );
		doc.write( span + "</td></tr></table></body></html>" );
		
		doc.close();
	}

	
	// Display any warnings accompanying the image.
	// Stop plotting the FIND layer if we get an error.

	var warning;
	if (isNetscape())
		warning = getFrame( _FRAME_Map ).document.forms["infoForm"].elements["warn"];
	else
		warning = window.document.all["warn"];

	if (warning == undefined)
		return;
	
	if (warning.value == 'aid=0')
	{
		top.status = 'Refreshing the selection...';
		performFind( curwindow );
	}
	else
	{
		plotFind = undefined;

		/**
		 * Display the error result in the result frame
		 */
		queryError( warning.value );
	}

}
 

function showBusy() {
	var frame = getFrame( "MapWindow" );
	var doc = frame.document;
	var divs = doc.getElementById('busydiv');
	if (divs.style.display == 'none'){
		divs.style.display = "";
	}
}

function hideBusy() {
	var frame = getFrame( "MapWindow" );
	var doc = frame.document;
	var divs = doc.getElementById('busydiv');
	if (divs.style.display == ''){
		divs.style.display = "none";
	}
}
			
/**
 * drawMap sends a command for the gena world to redraw the required images.
 */
function drawMap(extra)
{
	cancelQuery();

	showBusy();

	var	layers;
	var	form = getFrame( "Layers" ).document.layForm;
	var	globals;

	/**
	 * Generate the list of layers to render.
	 */
	layers = plotLayers( true );

	// Gets settings made by the user, if any

	globals = ""; //getUserSettings();

	/**
	 * Set the query properties
	 */
	form.command.value =
		"global openDataset=" + openDataset + ";" +
		globals +
		"geov.zoompix '" + layers + "' " + getImageSizeParam();

	/**
	 * Run a find straight away.
	 */

	if (autoSearch != undefined)
	{
		var	cache = autoSearch;

		autoSearch = undefined;
		autoFind(cache);

		/**
		 * If we got this far (ie: autoFind() failed),
		 * default to normal init
		 */
	}

	if (extra != undefined)
	{
		form.command.value += " " + extra;
	}

	if (curwindow != undefined)
	{
		form.curwindow.value = curwindow;
	}

	//alert( "drawMap() - " + form.command.value );
		
	form.target 		= "MapWindow";
	form.service.value 	= "RAWTEXTPROVIDER";
	form.save.value 	= "on";
	form.genauser.value = getMyName();
	
	form.submit();

	/**
	 * Show draw message on status bar
	 */
	top.status = "Retrieving map, please wait...";

}


function redraw()
{
	if (helping)
	{
		loadHelp('Show');
		return;
	}

	drawMap("-redraw");
}

/**
 * Javascript layer handling functionality
 */

 
/***************************************************************
 Layer objects
 ***************************************************************/

var layerStatus;
var serverName;
var helping 				= false;
var unitName 				= "units";

var plotFind				= undefined;

var urlParameters			= null;


function initLayerStatus( server )
{
	serverName = server;
	/**
	 * Load the query and find panes for this dataset
	 */
	loadFinds();
	setTimeout( "loadQuery()", 250 );
	setTimeout( "loadPrint()", 250 );
	
	/**
	 * The second condition is to maintain backwards compatibility.
	 */
	if ((drawOnStart == true) || (drawOnStart > 0)) {
		setTimeout( "drawMap('')", 250 );
	}
}


function updateLayerVisibility( uspan )
{
	var index;
	var minSpan;
	var maxSpan;
	var min;
	var max;
	var newStatus;

	var layerFrame = getFrame( _FRAME_Layers );
	var layerForm = layerFrame.document.forms[0];
	for (i = 0; i < layerForm.elements.length; i++)
	{
		if (layerForm.elements[i].name.indexOf( "layer" ) != -1)
		{
			index = layerForm.elements[i].name.substring( 5 );
			
			minSpan = layerForm.elements["N" + index].value;
			maxSpan = layerForm.elements["X" + index].value;
			
			min = parseFloat( minSpan );
			max = parseFloat( maxSpan );
			if ((min == 0) && (max == 0))
			{
				continue;
			}
			
			newStatus = (uspan >= min) && ((uspan <= max) || (max == 0));
			layerForm.elements[i].disabled = !newStatus;
		}
	}
}


function highliteLayer(imgname, imgnum)
{
	if (layerStatus[imgnum] > 1)
		return;

	var images = getFrame("Layers").document.images;

	if (layerStatus[imgnum] == 1)
		images[imgname].src = serverName + _LAYER_SELECTEDHI;
	else
		images[imgname].src = serverName + _LAYER_UNSELECTEDHI;
}


function normalLayer(imgname, imgnum)
{
	if (layerStatus[imgnum] > 1)
		return;

	var images = getFrame("Layers").document.images;

	if (layerStatus[imgnum] == 1)
		images[imgname].src = serverName + _LAYER_SELECTED;
	else
		images[imgname].src = serverName + _LAYER_UNSELECTED;
}


/**
 * Builds the list of layers to be plotted, be careful to build the list in
 * reverse as the order will have an impact on the image generated.
 *
 * The list needs to be built in reverse as the way layers are added with the
 * server scripts causes the least significant to lie on the bottom.
 *
 * @param display flag to enable plotting of decor layer
 */
function plotLayers( display )
{
	var toPlot = "";
	var i;

	var form = getFrame( _FRAME_Layers ).document.forms[0];
	for (i = 0; i < form.elements.length; i++)
	{
		if ((form.elements[i].name.indexOf( "layer" ) != -1) &&
			(form.elements[i].checked == true))
		{
			toPlot += " " + form.elements[i].value;
		}
	}

	if (display == true)
	{
		var	undef;

		if (plotFind != undef)
			toPlot += " " + plotFind;
	}
	
	return toPlot;
}


function layerScales()
{
	var scales = "";
	var form = getFrame( _FRAME_Layers ).document.forms[0];
	for (i = 0; i < form.elements.length; i++)
	{
		if ((form.elements[i].name.indexOf( "layer" ) != -1) &&
			(form.elements[i].checked == true))
		{
			var index = form.elements[i].name.substring( 5 );
			
			scales += " " + form.elements["N" + index].value;
			scales += " " + form.elements["X" + index].value;
		}
	}
	
	//alert( scales );

	return scales;
}


function getMyName()
{
	var undef;
	if (myname == undef)
	{
		var date = new Date();
		myname = date.getTime() + Math.random();
	}
	
	return myname;
}


function loadLayers()
{
	var	form = getFrame("Layers").document.forms[0];

	/**
 	 * the loadLayers() function should be the first function called
	 * under most circumstance. The first time this function gets
	 * called, we need to determine if the dataset has been selected
	 * using the URL parameters, and if we should display the 
	 * dataset selector.
	 *
	 * The basic rule is if the dataset has been set in the URL
	 * parameters then the dataset selector will not be shown.
	 */

	if ((urlParameters == undefined) || (urlParameters == null))
	{
		getParameterValues();
	}

	datasetparam = getParameterValue( "dataset" );
	if (datasetparam != null)
	{
		openDataset = datasetparam;
		showDataset = false;
	}

	if (showDataset == true)
	{
		form.command.value = "global showDataset=true;";
	}
	else
	{
		form.command.value = "global showDataset=false;";
	}

	form.command.value += "global openDataset=" + openDataset +
		";global baseColor=" + themeColor +
		";global buttonStyle=" + buttonStyle +
		";geov.dataset -layer " + openDataset;
				
	form.target 		= "Layers";
	form.genauser.value = top.getMyName();
	
	form.submit();
}


function selectDataset( elem )
{
	var newDataset = elem.options[elem.selectedIndex].value;
	if (openDataset != newDataset)
	{
		openDataset = newDataset;
		plotFind = undefined;
		
		/**
		 * Reload the new layers properties
		 */
		loadLayers();
	}
}
/**
 * Rectangle selection box for zoom and pan operations
 */
var rectBox 			= undefined;

/**
 * Mouse click cross lines
 */
var vertCrossLine		= undefined;
var horzCrossLine		= undefined;

/**
 * The starting and current mouse positions
 */
var startX;
var startY;
var mouseX;
var mouseY;

var imageLeft;
var imageTop;
var imageRight;
var imageBottom;

/**
 * Operation flags
 */
var panStarted			= false;
var zoomStarted			= false;

/**
 * vector graphics library for line drawing
 */
var jg 				= undefined;


function setupMouseEventHandler( document )
{
	document.onmousedown = onMouseDown;
	document.onmousemove = onMouseMove;
	document.onmouseup = onMouseUp;
	if (isNetscape())
	{
		document.captureEvents( 
			Event.MOUSEDOWN | Event.MOUSEMOVE | Event.MOUSEUP );
	}
	else
		document.oncontextmenu = onMouseDown;
	
	/**
	 * The rectangle boxes must be recreated each time the image is updated
	 * because it will be a new document and the previous layers would have had
	 * become invalid.
	 */
	createRectBox( document );
	
	vertCrossLine = createLineLayer( document, "vert-cross" );
	horzCrossLine = createLineLayer( document, "horz-cross" );
	document.body.appendChild( vertCrossLine );
	document.body.appendChild( horzCrossLine );
	
	showMouseCross( false );
	
	if (mouseMode == _MOUSEOP_ZOOMIN)
	{
		initToolbar( "zoomin" );
	}
}	// end setupMouseEventHandler()


function setMouseOperation( operation )
{
	mouseMode = operation;
}


function onMouseDown( event )
{
	/**
	 * Do nothing on mouse down if its a query operation
	 */
	if (mouseMode == _MOUSEOP_QUERY)
	{
		return false;
	}
	
	/**
	 * Only process if left mouse button
	 */
	if (isLeftClick( event ) == false)
		return false;
		
	var x;
	var y;
	var target;
	
	if (isNetscape())
	{
		x = event.pageX;
		y = event.pageY;
		target = event.target;
	}
	else
	{
		var mapFrame = getFrame( _FRAME_Map );
		x = mapFrame.window.event.clientX;
		y = mapFrame.window.event.clientY;
		target = mapFrame.window.event.srcElement;
		
		mapFrame.window.event.cancelBubble = true;
		mapFrame.window.event.returnValue = false;
	}
		
	/**
	 * We also only handle clicks on image elements
	 */
	if (target.tagName != "IMG")
		return false;
	
	if (mouseMode == _MOUSEOP_ZOOMIN)
		return startZoom( target, x, y );

	if (mouseMode == _MOUSEOP_ZOOMSCALE)
		drawCross( x, y );

	return false;	/* cancel any further default event handling */
}


function onMouseUp( event )
{
	var x;
	var y;
	
	if (isNetscape())
	{
		x = event.pageX;
		y = event.pageY;
	}
	else
	{
		var mapFrame = getFrame( _FRAME_Map );
		x = mapFrame.window.event.clientX;
		y = mapFrame.window.event.clientY;
		
		event = mapFrame.window.event;
	}
	
	if (mouseMode == _MOUSEOP_QUERY)
	{
		queryMouseUp( event, x, y );
		drawCross( x, y );
		return false;
	}

	/**
	 * Continue processing only if left mouse button
	 */
	if (isLeftClick( event ) == false)
		return false;

	if (mouseMode == _MOUSEOP_PAN)
	{
		drawCross( x, y );
		drawMap( "-pan " + x + " " + y );
	}
	else if (mouseMode == _MOUSEOP_ZOOMSCALE)
	{
		var	form = getFrame( _FRAME_NavBar ).document.NavBarForm;
		var	element = form.elements["scaleValue"];
		var	scale = element.value;

		if (element == null || scale == null || scale == "")
		{
			alert("Please enter a scale value in the navigation bar");
			return false;
		}
		drawMap("-scale " + x + " " + y + " " + scale);
		return false;
	}
	else
	{
		return stopZoom();
	}
}


function onMouseMove( event )
{
	var x;
	var y;
	
	if (isNetscape())
	{
		x = event.pageX;
		y = event.pageY;
	}
	else
	{
		var mapFrame = getFrame( _FRAME_Map );
		x = mapFrame.window.event.clientX;
		y = mapFrame.window.event.clientY;
	}
	
	if (zoomStarted == true)
	{
		return adjustZoomBox( x, y );
	}
	else if (panStarted == true)
	{
		return adjustPanBox( x, y );
	}
	
	return false;
}


/******************************************************************************
  zoom functions
 *****************************************************************************/


/**
 * Starts to zoom operation
 */
function startZoom( image, x, y )
{
	if (zoomStarted)
		return false;
		
	/**
	 * determine the MAP image bounds. Right now we hardcode this to
	 * be 0, 0 because I couldnt find a way to get the image's bounds in IE.
	 */
	imageLeft = 0;
	imageTop = 0;
	imageRight = image.width;
	imageBottom = image.height;

	/**
	 * zoom operations are only allowed within the bounds of the MAP image.
	 */
	if ((x < imageLeft) || (x > imageRight) ||
		(y < imageTop) || (y > imageBottom))
	{
		alert( "attempting to zooming zoom outside image bounds." );
		return true;
	}
	
	/**
	 * Save the starting coordinates.
	 */
	startX = x;
	startY = y;
	mouseX = undefined;
	mouseY = undefined;
	
	/**
	 * create the layers if this is the first zoom start call.
	 */
	showRectBox( "visible" );
	
	zoomStarted = true;
	
	/**
	 * Cancel default event handling.
	 */
	return false;
}


/**
 * Stops the zoom operation.
 */
function stopZoom()
{
	if (zoomStarted)
	{
		showRectBox( "hidden" );
		zoomStarted = false;
		
		/**
		 * clicking on the spot will result in adjustZoom() not being called and hence
		 * mouseX and mouseY values will not have been initialized
		 */
		if ((mouseX == undefined) || (mouseY == undefined))
		{
			return;
		}
		
		/**
		 * Determine new bounds to be sent to the server. This needs to be a
		 * value that is relative to the top-left corner of the image. The
		 * calculations for the new extent will take place on the server.
		 */
		var left, right, top, bottom;
		if (startX < mouseX)
		{
			left = startX;
			right = mouseX;
		}
		else
		{
			left = mouseX;
			right = startX;
		}
		
		if (startY < mouseY)
		{
			top = startY;
			bottom = mouseY;
		}
		else
		{
			top = mouseY;
			bottom = startY;
		}
		
		/**
		 * execute a request for the new image. This part has been taken out of 
		 * the old ivy javascripts which only allowed zoom if an area of more 
		 * than 5 pixels have been selected
		 */
		var dx = mouseX - startX;
		var dy = mouseY - startY;
		if ((dx <= 5 && dx >= -5) ||
		    (dy <= 5 && dy >= -5))
		{
			return;
		}
		
		drawMap( "-in " + startX + " " + startY + " " + mouseX + " " + mouseY );
		
		/**
		 * Cancel default event handling.
		 */
		return false;
	}
	
	return true;
}


/**
 * Kicks off the panning operation.
 */
function startPan( x, y )
{
	if (panStarted)
		return false;
	
	/**
	 * determine the MAP image bounds
	 */
	var image = findNamedImage( top, _MAPIMAGE );
	if (image == null)
	{
		alert ("Image not found" );
		return;
	}
		
	imageLeft = 0;
	imageTop = 0;
	imageRight = imageLeft + image.width;
	imageBottom = imageTop + image.height;
	
	/**
	 * zoom operations are only allowed within the bounds of the MAP image.
	 */
	if ((x < imageLeft) || (x > imageRight) ||
		(y < imageTop) || (y > imageBottom))
	{
		return true;
	}
	
	/**
	 * Save the starting coordinates.
	 */
	startX = x;
	startY = y;
	
	/**
	 * create the layers if this is the first zoom start call.
	 */
	if (panLayer == null)
	{
		createPanLayer();
	}

	panLayer.visibility = "visible";	
	panStarted = true;
	
	return false;
}


function stopPan()
{
	if (panStarted)
	{
		panLayer.style.visibility = "hidden";	
		panStarted = false;
		
		requestPan( mouseX - startX, mouseY - startY );
		
		/**
		 * Cancel default event handling.
		 */
		return false;
	}
	
	return true;
}


/**
 * Adjusts the zoom box to the new mouse event.
 */
function adjustZoomBox( x, y )
{
	mouseX = Math.min( Math.max( x, imageLeft ), imageRight );
	mouseY = Math.min( Math.max( y, imageTop ), imageBottom );
	
	var left, right, top, bottom;
	if (startX < mouseX)
	{
		left = startX;
		right = mouseX;
	}
	else
	{
		left = mouseX;
		right = startX;
	}
	
	if (startY < mouseY)
	{
		top = startY;
		bottom = mouseY;
	}
	else
	{
		top = mouseY;
		bottom = startY;
	}
	
	moveRectBox( left, top, right, bottom );
	
	return false;
}	// end adjustZoomBox()


function adjustPanBox( x, y )
{
	mouseX = x;
	mouseY = y;
	
	var left, right, top, bottom;
	left 	= imageLeft + (mouseX - startX);
	top 	= imageTop + (mouseY - startY);
	right 	= imageRight + (mouseX - startX);
	bottom 	= imageBottom + (mouseY - startY);

	/**
	 * Hide the layers that "overlap" the image bounds
	 */
	rectBox[_BOX_LEFT].visibility 	= (left < 0) ? "hidden" : "visible";
	rectBox[_BOX_TOP].visibility 	= (top < 0) ? "hidden" : "visible";
	rectBox[_BOX_RIGHT].visibility 	= (left < 0) ? "visible" : "hidden";
	rectBox[_BOX_BOTTOM].visibility = (top < 0) ? "visible" : "hidden";
	
	/**
	 * clip the box to the image bounds
	 */
	left 	= Math.max( left, imageLeft );
	top 	= Math.max( top, imageTop );
	right 	= Math.min( right, imageRight );
	bottom 	= Math.min( bottom, imageBottom );
	
	moveRectBox( left, top, right, bottom );
	
	return false;
}


/******************************************************************************
  Map selection rectangle functionality
 *****************************************************************************/


/**
 * Creates the zoom and pan's rubberbanding box
 */
function createRectBox( document )
{
	/**
	 * we only need to create the box once and just hide/show it
	 */
	if (rectBox == undefined)
	{
		rectBox 				= new Array(4);
	}
	
	rectBox[_BOX_LEFT] 		= createLineLayer( document, "LEFT" );
	rectBox[_BOX_TOP] 		= createLineLayer( document, "TOP" );
	rectBox[_BOX_RIGHT] 	= createLineLayer( document, "RIGHT" );
	rectBox[_BOX_BOTTOM] 	= createLineLayer( document, "BOTTOM" );
	
    /**
     * The layers needs to be added to the document
     */
    document.body.appendChild( rectBox[_BOX_LEFT] );
	document.body.appendChild( rectBox[_BOX_TOP] );
	document.body.appendChild( rectBox[_BOX_RIGHT] );
	document.body.appendChild( rectBox[_BOX_BOTTOM] );
}


function showRectBox( visibility )
{
	var i;
	for (i = 0; i < 4; i++)
	{
		rectBox[i].visibility = visibility;
	}
}


/**
 * Creates a single layer object with default values.
 */
function createLineLayer( document, name )
{
	var div = document.createElement( "DIV" );

	/**
	 * set default layer properties	
	 */
	var layer = div.style;
    layer.position 			= "absolute";
    layer.overflow 			= "hidden";
    layer.name 				= name;
    layer.backgroundColor 	= rubberColor;
    layer.left 				= "1px";
    layer.top 				= "1px";
    layer.height 			= "1px";
    layer.width 			= "1px";
    layer.zIndex 			= 2;
    layer.visibility 		= "visible";
	
	/**
	 * MozOpacity might be mozilla only
	 */
	layer.MozOpacity 		= 0.75;
    
	return div;
}


function moveRectBox(
		left,
		top,
		right,
		bottom )
{
	/**
	 * Reposition/resize left layer
	 */
	rectBox[_BOX_LEFT].style.left 		= left;
	rectBox[_BOX_LEFT].style.top 		= top;
	rectBox[_BOX_LEFT].style.height 	= bottom - top;
		
	/**
	 * Reposition/resize top layer
	 */
	rectBox[_BOX_TOP].style.left 		= left;
	rectBox[_BOX_TOP].style.top 		= top;
	rectBox[_BOX_TOP].style.width		= right - left;

	/**
	 * Reposition/resize right layer
	 */
	rectBox[_BOX_RIGHT].style.left		= right - 1;
	rectBox[_BOX_RIGHT].style.top		= top;
	rectBox[_BOX_RIGHT].style.height	= bottom - top;
		
	/**
	 * Reposition/resize bottom layer
	 */
	rectBox[_BOX_BOTTOM].style.left		= left;
	rectBox[_BOX_BOTTOM].style.top		= bottom - 1;
	rectBox[_BOX_BOTTOM].style.width	= right - left;
}


function isLeftClick( event )
{
	if (isNetscape())
	{
		return event.which == 1;
	}
	else
	{
		var mapFrame = getFrame( _FRAME_Map );
		return mapFrame.window.event.button == 1;
	}
}


/**
 * Draw a cross at the required map position
 * 
 * Drawing the lines as permanent prevents them from being removed
 * when another cross is plotted
 */
function drawCross( x, y )
{
	showMouseCross( true );

	/**
	 * Position the crosses
	 */
	vertCrossLine.style.left 	= x;
	vertCrossLine.style.top 	= y - 4;
	vertCrossLine.style.height	= 9;
	horzCrossLine.style.left	= x - 4;
	horzCrossLine.style.top		= y;
	horzCrossLine.style.width	= 9;
}


function showMouseCross( visibility )
{
	if (vertCrossLine != undefined)
		vertCrossLine.style.visibility = visibility ? "visible" : "hidden";
		
	if (horzCrossLine != undefined)
		horzCrossLine.style.visibility = visibility ? "visible" : "hidden";
}


/******************************************************************************
  Map querying functionality
 *****************************************************************************/


function cleanupQuery()
{
	showMouseCross( false );
}


/******************************************************************************
  Map painting functionality
 *****************************************************************************/


function drawQueryHints( queryType, pointsArray, complete )
{
	if (jg == undefined)
	{
		jg = new jsGraphics( "imagediv", getFrame( _FRAME_Map ) );
	}
	
	var i;
	var x1 = queryEvents[0];
	var y1 = queryEvents[1];
	var x2;
	var y2;

	jg.setColor( "#ff0000" );
	
	if (queryType == _QUERY_MultiPoint)
	{
		jg.drawLine( x1 - 3, y1, x1 + 3, y1 );
		jg.drawLine( x1, y1 - 3, x1, y1 + 3 );
		jg.paint();
	}
	
	if ((queryType == _QUERY_Polygon) &&
			 (complete == true))
	{
		/**
		 * Close off the polygon
		 */
		x1 = queryEvents[0];
		y1 = queryEvents[1];
		x2 = queryEvents[ queryEvents.length - 2 ];
		y2 = queryEvents[ queryEvents.length - 1 ];
		
		jg.drawLine( x1, y1, x2, y2 );
		jg.paint();
	}
	else
	{
		for (i = 1; i < (queryEvents.length / 2); i++)
		{
			x2 = queryEvents[ i * 2 ];
			y2 = queryEvents[ (i * 2) + 1 ];
			
			if (queryType == _QUERY_MultiPoint)
			{
				jg.drawLine( x2 - 3, y2, x2 + 3, y2 );
				jg.drawLine( x2, y2 - 3, x2, y2 + 3 );
			}
			else
			{
				jg.drawLine( x1, y1, x2, y2 );
			}
			
			jg.paint();
			
			x1 = x2;
			y1 = y2;
		}
	}
}


function hideQueryHints()
{
	if (jg != undefined)
	{
		jg.clear();
		jg = undefined;
	}
} 


var findFields 		= undefined;

/**
 * Get rid of this once the search scripts get fixed
 */
var warnedAlready;

/**
 * We need to always save the last query command issued, as we might need to
 * perform the query again if the user chooses to pop up the results in an
 * external frame.
 */
var queryCommand 		= undefined;

/**
 * The currently selected search action
 */
var currentQuery 		= undefined;
var currentQueryType	= undefined;
var inQueryAction		= undefined;

/**
 * The currently selected find query
 */
var currentFind		= undefined;

/**
 * The list of mouse click events for querying
 */
var queryEvents		= undefined;

function setupFind()
{
	if (helping)
	{
		loadHelp('Finds');
		return;
	}
	if (drawOnStart == 0)
	{
		drawOnStart = undefined;
		drawMap('');
		return;
	}
	
	var doc = getFrame( _FRAME_Search ).document;
	var div = doc.getElementById( 'findContent' );
	if (div == undefined)
	{
		alert( "Can't find <DIV>" );
		return;
	}

	/**
	 * Theres no other way to accurately set the DIV size.
	 */
	div.style.height = div.parentNode.clientHeight;
	
	var selected = doc.forms["findForm"].findselect.selectedIndex;
	var hidden = doc.forms["findForm"].elements['F' + selected];
	
	var focusto = 0;
	var htmlText;
	var i;
	var entryNum = 0;
	
	htmlText = "<form name='findFieldsForm' method='POST' onkeypress='javascript:top.keyPressed(window.event);' action='javascript:top.doNothing()' onload='javascript:top.setFocus();'>";
	htmlText += "<table width='100%'>";

	/**
	 * Generate the custom find form
	 */	
	if (hidden != undefined)
	{
		/**
		 * Set some globals which we need to hang around!
		 */
		findFields = hidden.value.split(/#/);

		/**
		 * Start at 1, as fields[0] is the enquiry name.
		 */
		for (i = 1; i < findFields.length; i += 5)
		{
			var change = findFields[i+2].slice(0,1);
			if (change == 'f')
				continue;

			var def = findFields[i+2].slice(2);
			
			htmlText += "<tr><td>" + findFields[i+1] + "</td></tr>";

			/**
			 * User types in value to search for.
			 */
			if (change == 't')
			{
				focusto = ++entryNum;
				
				htmlText += "<tr><td><input type='hidden' name='findindex' value='" + entryNum;
				htmlText += "'><input type='text' size='17' name='E" + entryNum;
				htmlText += "' value='" + def + "'></td></tr>";
				
				continue;
			}

			/**
			 * A list of options: display select menu.
			 */
			 
			htmlText += "<tr><td><select name='tagsT' multiple size='4'>";
			
			if (isNetscape() && !v5)
				var opts = def.split(/|/);
			else
				var opts = def.split(/\|/);
				
			for (var j = 0; j < opts.length; j++)
			{
				htmlText += "<option value='" + opts[j] + "'>" + opts[j] + "</option>";
			}
			
			htmlText += "</select></tr>";
		}
	}
	
	htmlText += "</table></form><center><button onclick='javascript:top.performFindQuery();'>Go-Find</button></center><br>";
	div.innerHTML = htmlText;
}

function initFindCommand(info, extent)

{
	var layerForm = getFrame( _FRAME_Layers ).document.layForm;
	
	layerForm.target = _FRAME_Map;
	layerForm.save.value = "on";
	
	/* Start the find command */

	layerForm.command.value = "global openDataset=" + openDataset + ";" +
		"global queryZoom=true;" +
		"geov.enqraw -image " + getImageSizeParam();

	if (extent != undefined)
		layerForm.command.value += " '" + extent + "' ";
	else
		layerForm.command.value += " '' ";

	plotFind = undefined;
	layerForm.command.value += info[0] + " '" + plotLayers() + "' ";
	plotFind = info[0];
	return layerForm;
}

var elIndex;
var entered;

function getAttributeValue(layerForm, i, info, field, specified)

{
	var change = info[i+2].slice(0,1);

	if (change == 'f')
	{
		// For auto-run Finds, all field values must be given

		if (field != undefined)
		{
			alert('URL-initiated Finds must have preset fields supplied with the default value');
			return false;
		}

		// User driven: Handle fields which are hard-wired

		specified = info[i+2].slice(2);
	}
	else if (field == undefined)
	{
		// Get value user has entered for this field
		
		var findForm = getFrame(_FRAME_Search).document.forms["findFieldsForm"];
		var element = findForm.elements["E" + elIndex++];

		if (element == undefined)
		{
			alert("Cannot find the text box for entry of an element");
			return false;
		}
		specified = element.value;
	}
	else if (specified == undefined)
	{
		alert("URL: No Value specified for " + field);
		return false;
	}
	else if (info[i] != field)
		return false;		/* maybe the next info block is for this field? */

	entered = true;
	var append = info[i] + " ";

	// If using numeric comparators, change them to letters!
	
	var comparator = info[i+3].slice(2);
	if (comparator == '=')
		comparator = 'EQ';
	else if (comparator == '<')
		comparator = 'LT';
	else if (comparator == '<=')
		comparator = 'LE';
	else if (comparator == '>')
		comparator = 'GT';
	else if (comparator == '>=')
		comparator = 'GE';
	else if (comparator == '!=')
		comparator = 'NE';
	
	append += comparator + " ";
	append += "'" + specified + "' ";

	if (info[i+4] != undefined)
		append += info[i+4].slice(2) + " ";

	layerForm.command.value += append;
	currentFind += append;
	return true;
}

function performFind( extent )
{
	if (helping)
	{
		loadHelp('Go');
		return;
	}
	
	if (findFields == undefined)
		return;

	var layerForm = initFindCommand(findFields, extent);
	var i;

	if (findFields[1] == "TAG-GW")
	{
		var taglist = "";
		var findForm = getFrame( _FRAME_Search ).document.forms["findFieldsForm"];

		/*
		 * Depending on how the query was set up, the user can choose
		 * via an option list or by entering in a text value.
		 */
		if (findForm.tagsT != undefined)
		{
			/*
			 * Retrieve the selected option list value[s]
			 */
			for (i = 0; i < findForm.tagsT.length; i++)
			{
				if (findForm.tagsT.options[i].selected)
					taglist += findForm.tagsT.options[i].value + '|';
			}
		}
		else
		{
			/*
			 * Retrieve the entered text value
			 */
			var	index = findForm.findindex.value;
			taglist = findForm.elements['E' + index].value + '|';
		}

		if (taglist == "")
		{
			if (curwindow == undefined)
			{
				alert('Please select some values to Find!');
			}
			else if (warnedAlready == undefined)
			{
				warnedAlready = 'y';
				alert('Sorry: unable to recover previous Find.');
			}
			
			return;
		}
		
		layerForm.command.value += " -tags " + "'" + taglist + "'";
		currentFind = " -tags '" + taglist + "'";
	}
	
	/**
	 * Do an attribute find
	 */
	else
	{
		currentFind = " -attribute ";
		layerForm.command.value += "-attribute ";
	
		elIndex = 1;
		entered = false;
		for (i = 1; i < findFields.length; i += 5)
			getAttributeValue(layerForm, i, findFields);
	}

		
	clearQueryResults();

	warnedAlready = undefined;
	
	layerForm.genauser.value = getMyName();
	layerForm.action = '/servlet/GenaService';
	layerForm.submit();
}

function keyPressed(event)
{
	var key = event.keyCode;
	if (key == 13)
		performFindQuery();
	return true;
}


function autoFind(params)

{
	// Discard the leading "?"

	if (params.indexOf("?") == 0)
		params = params.substring(1);

	// First, pluck out the parameters we've been given

	var arrURLParams = params.split("&");
	if (arrURLParams == undefined)
		return;

	var p;
	var i = 0;
	var init = 0;
	var saveParams = new String(params);
	var doc = getFrame( _FRAME_Search ).document;
	var list = doc.forms["findForm"].findselect;
	var layerForm = undefined;

	// Capture the parameters we're interested in

	findFields = undefined;
	for (p = 0; p < arrURLParams.length; p++)
	{
		var sParam =  arrURLParams[p].split("=");
		var value;

		if (sParam[1] == "")
			continue;
		value = unescape(sParam[1]);
		if (sParam[0] == 'dataset')
		{
			openDataset = value;
			continue;
		}
		else if (sParam[0] == 'find')
		{
			// which Find has been chosen?

			for (i = 0; i < list.length; i++)
			{
				var hidden;
				hidden = doc.forms["findForm"].elements['F'+i];
				findFields = hidden.value.split(/#/);
				if (findFields[0] == value)
					break;
			}
			if (i == list.length)
			{
				findFields = undefined;
				alert("Unknown Find: " + value);
				return;
			}
			//list.selectedIndex = i;
			layerForm = initFindCommand(findFields);
			continue;
		}
		else if (findFields == undefined)
		{
			alert('Invalid URL: specify find=... _before_ values');
			return;
		}

		// Field values: either tags or attributes

		if (findFields[1] == "TAG-GW")
		{
			layerForm.command.value += " -tags '" + sParam[1] + "'";
			break;
		}

		// Attributes: 1 or more can be supplied as params

		if (init == 0)
		{
			layerForm.command.value += "-attribute ";
			init = 1;
		}

		var found = false;
		for (var j = 1; j < findFields.length; j += 5)
		{
			found = getAttributeValue(layerForm, j, findFields,
					  sParam[0], value);
			if (found == true)
				break;
		}

		if (found == false)
		{
			var possible = "\nChoices are: ";

			for (var j = 1; j < findFields.length; j += 5)
				possible += findFields[j] + ' ';
			alert("URL has invalid field: '"+sParam[0]+"' "+possible);
			return;
		}
	}

	/* Make sure we've got everything needed */

	if (openDataset == undefined || layerForm == undefined)
	{
		alert("Invalid find parameters supplied; " + saveParams);
		return;
	}

	// Finished: send off our command

	clearQueryResults();
	warnedAlready = undefined;
	layerForm.genauser.value = getMyName();
	layerForm.action = '/servlet/GenaService';
	layerForm.submit();
}

function performFindQuery()
{

	if (findFields == undefined)
		return;

	performFind();

	//The query is the find selection
	currentQueryType	= findFields[0];
	queryCommand		= undefined;

	runQuery( _QUERY_Selection );
}

function loadPrint()
{
	var searchForm;
	searchForm = getFrame( _FRAME_Layers ).document.forms["layForm"];
	
	searchForm.command.value = "ivy.print " + openDataset;
	searchForm.genauser.value = getMyName();
	searchForm.target = _FRAME_Result;
	searchForm.submit();
}

function loadFinds()
{
	var searchForm;
	searchForm = getFrame( _FRAME_Layers ).document.forms["layForm"];
	
	searchForm.command.value = "geov.dataset -enq1 " + openDataset;
	searchForm.genauser.value = getMyName();
	searchForm.target = _FRAME_Search;
	searchForm.submit();
}

function loadQuery()
{
	var searchForm;
	searchForm = getFrame( _FRAME_Layers ).document.forms["layForm"];
	
	var URL = searchForm.action;
	URL += "?application=" + searchForm.application.value;
	URL += "&genauser=" + getMyName();
	URL += "&service=" + searchForm.service.value;
	URL += "&browser=" + searchForm.browser.value;
	URL += "&command=" + "geov.dataset -enq2 " + openDataset;
	
	var divElem = getFrame( _FRAME_NavBar ).document.getElementById( "Query" );
	divElem.src = URL;
}


function setupQuery( queryType )
{
	currentQueryType = queryType;
}


function testOnLoad()
{
	alert( "testOnLoad" );
	
	//var divElem = getFrame( _FRAME_NavBar ).document.getElementById( "Query" );
	var frameDiv = getFrame( _FRAME_Query );
	alert( frameDiv.body.innerHTML );
}


function setSearchType( selectElem )
{
	currentQueryType = selectElem.options[ selectElem.selectedIndex ].value;
}


function startSearch( queryAction )
{
	if (queryAction != currentQuery)
	{
		/**
		 * Query type has changed, need to restart the entire query action
		 */
		cancelQuery();
	}

	setMouseOperation( _MOUSEOP_QUERY );
	currentQuery = queryAction;
}


function startSearchFind( div, fields )
{
	/**
	 * Save the fields globally
	 */
	findFields = fields;

	htmlText = "<form name='findForm' method='POST' action='javascript:top.doNothing()' onload='javascript:top.setFocus();'>";
	htmlText += "<table class='findQuery' width='100%'>";
	
	entryNum = 0;

	/**
	 * Start at 1, as fields[0] is the enquiry name.
	 */
	for (i = 1; i < findFields.length; i += 5)
	{
		var change = findFields[i+2].slice(0,1);
		if (change == 'f')
			continue;

		var def = findFields[i+2].slice(2);
		
		htmlText += "<tr><td>" + findFields[i+1] + "</td></tr>";

		/**
		 * User types in value to search for.
		 */
		if (change == 't')
		{
			focusto = ++entryNum;
			
			htmlText += "<tr><td width='100%'><input type='hidden' name='findindex' value='" + entryNum;
			htmlText += "'><input type='text' size='17' name='E" + entryNum;
			htmlText += "' value='" + def + "'></td></tr>";
			
			continue;
		}

		/**
		 * A list of options: display select menu.
		 */
		 
		htmlText += "<tr><td><select name='tags' multiple size='4'>";
		
		if (isNetscape() && !v5)
			var opts = defalt.split(/|/);
		else
			var opts = defalt.split(/\|/);
			
		for (var j = 0; j < opts.length; j++)
		{
			htmlText += "<option value='" + opts[j] + "'>" + opts[j] + "</option>";
		}
		
		htmlText += "</select></tr>";
	}
	
	htmlText += "</table></form><center><button onclick='javascript:top.performFindQuery();'>Go-Find</button></center><br>";

	/**
	 * Set the new html into the div segment
	 */
	div.innerHTML = htmlText;
}


function runQuery( queryType )
{
	var layerForm = getFrame( _FRAME_Layers ).document.forms["layForm"];
	var result = setupQueryForm( layerForm, "geov.enqraw", false, queryType );
	if (result == false)
		return;

	/**
	 * Excute the query
	 */	
	layerForm.submit();
	
	inQueryAction = false;
	
	/**
	 * Show query message on status bar
	 */
	top.status = "Performing spatial query, please wait...";
}


function runQueryPopup()
{
	if (queryCommand == undefined)
		return;
		
	var layerForm = getFrame( _FRAME_Layers ).document.forms["layForm"];
	setupQueryForm( layerForm, "geov.enqraw", true );

	/**
	 * Precreate the popup frame. We need to do this to ensure that the poped up
	 * frame has the same "top" value as the current frame.
	 */
	var popupFrame = getFrame( _FRAME_ResultPopup );
	if (popupFrame == undefined)
	{
		popupFrame = window.open( "", _FRAME_ResultPopup );
		
		/**
		 * The best implementation would be to set the "top" value of the new
		 * frame. However this can't be done in IE. Because of this, I'm not
		 * going to be able to support export to .csv in the poped up window.
		 */
	}
		
	/**
	 * Excute the query
	 */	
	layerForm.target 			= _FRAME_ResultPopup;
	layerForm.submit();	
}


/**
 * This function intercepts the anchor launch, and sets its href correctly for the
 * appropriate query.
 *
 * The csv export functionality has to be done this way to prevent a new empty frame
 * from being poped up.
 */
function exportQuery(csvlink)
{
	if (queryCommand == undefined)
		return;
		
	var layerForm = getFrame( _FRAME_Layers ).document.forms["layForm"];
	setupQueryForm( layerForm, "geov.enqcsv", false );
	
	/**
	 * Create the URL to execute
	 */
	var URL = layerForm.action;
	URL += "?application=" + layerForm.application.value;
	URL += "&browser=" + layerForm.browser.value;
	URL += "&command=" + layerForm.command.value;
	URL += "&genauser=" + layerForm.genauser.value;
	URL += "&service=" + layerForm.service.value;
	URL += "&server=" + layerForm.server.value;
	//URL += "&rtncontenttype=" + "application/octet-stream";
	URL += "&rtncontenttype=" + "application/unknown";
	
	csvlink.href=URL;
}


function queryError( message )
{
	top.status = "";
	
	var resultFrame = getFrame( _FRAME_Result );

	/**
	 * Format the error into something more presentable
	 */
	var opts = message.split(/\|/);
   	var str = opts[1];
    if (str == undefined)
    {
	   str = "";
	}

	if (opts[0] == 'F')
	{
		message = "Query failed";
	}
	else if (opts[0] == 'L')
	{
		message = 'No <i>'+str+'</i> information on chosen item.';
	}
	else if (opts[0] == 'N')
	{
		message = 'No <i>'+str+'</i> items at chosen location.';
	}
	
	resultFrame.document.body.innerHTML = 
		"<html><head><link REL='stylesheet' HREF='" + serverName + "/gw.css' TYPE='text/css'></head><body>" +
		message + "</body></html>";
}


function cancelQuery()
{
	//findFields = undefined;

	/**
	 * Cleanup any stored values
	 */
	queryEvents = undefined;
	inQueryAction = false;
	
	/**
	 * Reset the display
	 */
	hideQueryHints();
	
	cleanupQuery();
}


function loadURL()
{
	/*
	var	form = getFrame( _FRAME_Result ).document.forms[0];

	if ((form == undefined) || 
		(form.url == undefined))
		return;
		
	var w = window.open( 
		form.url.value, 
		"ivyurl",
		"width=500,height=400,status=no,resizable=yes,scrollbars=yes,toolbar=yes",
		true );
	w.focus();
	*/
}


function printQuery()
{
	var resultsFrame = getFrame( _FRAME_Result );
	resultsFrame.print();
}


/**
 * Sets up the form for a query request
 *
 * @param queryForm		the form to be set up
 * @param queryCmd		the query command to execute
 * @param queryPopup	the flag to determine the results controls returned
 * @param queryType		the type of query to be executed
 */
function setupQueryForm( queryForm, queryCmd, queryPopup, queryType )
{
	/**
	 * Generate the query command
	 */
	var command = "global openDataset=" + openDataset + ";";
	command += "global queryZoom=true;";
	command += "global queryPopup=" + (queryPopup == true ? "true;" : "false;");
	command += queryCmd;
	
	if (queryCommand != undefined)
	{
		command += queryCommand;
	}
	else
	{
		if (queryType == _QUERY_Distance)
		{
			queryCommand = " -length ";
		}
		else
		{
			queryCommand = " -pickatt ";
		}
			
		queryCommand += getImageSizeParam() + " '";
		if (curwindow != undefined)
			queryCommand += curwindow;
		
		queryCommand += "' " + currentQueryType + " ";
		
		if (queryType == _QUERY_Point)
		{
			queryCommand += "-point ";
			queryCommand += getQueryPoints();
		}
		else if (queryType == _QUERY_BufferedPoint)
		{
			queryCommand += "-point ";
			queryCommand += getQueryPoints();
			
			/**
	 		 * Get the buffer distance
	 		 */
			var distance = prompt( "Please enter the buffer distance in meters:" );
			if (distance == null)
				return;
			
			queryCommand += " " + distance;
		}
		else if (queryType == _QUERY_Neighbour)
		{
			queryCommand += "-neighbour ";
			queryCommand += getQueryPoints();
		}
		else if (queryType == _QUERY_Line)
		{
			/**
			 * query of line only valid if more than 1 point has been selected
			 */
			if (queryEvents.length < 4)
				return false;
		
			queryCommand += "-line '";
			queryCommand += getQueryPoints();
			queryCommand += "'";
		}
		else if (queryType == _QUERY_BufferedLine)
		{
			/**
			 * query of line only valid if more than 1 point has been selected
			 */
			if (queryEvents.length < 4)
				return false;
		
			queryCommand += "-line '";
			queryCommand += getQueryPoints();
			queryCommand += "'";
			
			/**
	 		 * Get the buffer distance
	 		 */
			var distance = prompt( "Please enter the buffer distance in meters:" );
			if ((distance == null) || (distance == undefined))
				return false;
			
			queryCommand += " " + distance;
		}
		else if (queryType == _QUERY_MultiPoint)
		{
			queryCommand += "-multi '";
			queryCommand += getQueryPoints();
			queryCommand += "'";
		}
		else if (queryType == _QUERY_Polygon)
		{
			/**
			 * polygon query only valid if more than 2 points have been selected
			 */
			if (queryEvents.length < 6)
				return false;
		
			queryCommand += "-polygon '";
			queryCommand += getQueryPoints();
			queryCommand += "'";
		}	
		else if (queryType == _QUERY_Distance)
		{
			/**
			 * line distance query only valid if more than 1 point has been selected
			 */
			if (queryEvents.length < 4)
				return false;

			queryCommand += "'" + getQueryPoints() + "'";
		}
		else if (queryType == _QUERY_Selection)
		{
			queryCommand += currentFind;
		}
		
		command += queryCommand;
	}	
//alert("Query: " +command);	
	/**
	 * Setup the form for query
	 */
	queryForm.target 			= _FRAME_Result;
	queryForm.service.value 		= "RAWTEXTPROVIDER";
	queryForm.save.value 			= "off";
	queryForm.genauser.value 		= getMyName();
	queryForm.command.value 		= command;	
	queryForm.rtncontenttype.value		= "text/html";
	
	return true;
}


function queryMouseUp( event, x, y )
{
	queryCommand = undefined;
	
	if ((inQueryAction == undefined) ||
		(inQueryAction == false))
	{
		/**
		 * This cancelQuery() call ensures that any existing query states gets cleaned up
		 */
		cancelQuery();
	}
	
	if (queryEvents == undefined)
	{
		queryEvents = new Array();
	}
	
	inQueryAction = true;
	queryEvents.push( x );
	queryEvents.push( y );
	
	drawQueryHints( currentQuery, queryEvents, false );
	
	/**
	 * Handle the query event
	 */
	if ((currentQuery == _QUERY_Point) ||
		(currentQuery == _QUERY_BufferedPoint) ||
		(currentQuery == _QUERY_Neighbour))
	{
		runQuery( currentQuery );
	}
	else
	{
		/**
		 * End all other operations if its a right click or a shift-left click
		 */
		var shiftKey = event.shiftKey;
		if ((isLeftClick( event ) == false) ||
			(shiftKey == true) ||
			(queryEvents.length == 18))
		{
			runQuery( currentQuery );
			
			if (currentQuery == _QUERY_Polygon)
			{
				drawQueryHints( currentQuery, queryEvents, true );
			}
		}
	}
	
	/**
	 * disable default mouse event handling
	 */
	return false;
}


function getQueryPoints()
{
	var points = "";
	for (i = 0; i < queryEvents.length; i++)
	{
		if (i > 0)
			points += " ";
		
		points += queryEvents[i];
	}

	return points;
}


function queryComplete()
{
	top.status = "";
}


function clearQueryResults()
{
	var resultFrame = getFrame( _FRAME_Result );
	resultFrame.document.body.innerHTML = "";
}

function zoomSelect(elem, enquire)
{
	var layerForm = getFrame( _FRAME_Layers ).document.forms["layForm"];

	layerForm.target = _FRAME_Map;
	layerForm.save.value = "on";

	/**
	 * Generate the zoomObject
	 */
	layerForm.command.value = "global openDataset=" + openDataset + ";" +
		'geov.enqraw -object  ' + getImageSizeParam() + " '";

	layerForm.command.value += "' " +  enquire + " ' " + plotLayers() + "' ";
	layerForm.command.value += " -tag " + "'" + elem + "'";

	layerForm.genauser.value = getMyName();
	layerForm.target                = "MapWindow";
	layerForm.service.value         = "RAWTEXTPROVIDER";
	layerForm.save.value    = "on";
	layerForm.action = '/servlet/GenaService';

	layerForm.submit();

}


/**
 * The currently highlight button from the zoom/pan group
 */
var zoomButton 	= undefined;
var queryButton = undefined;


function initToolbar()
{
	if ((zoomButton != undefined) || (queryButton != undefined))
	{
		/**
		 * Already initialized so do nothing
		 */
		return;
	}

	var navbarFrame = getFrame( _FRAME_NavBar );
	for (i = 0; i < navbarFrame.document.images.length; i++)
	{
		if (navbarFrame.document.images[i].name == "zoomin")
		{
			zoomButtonClick( navbarFrame.document.images[i] );
			break;
		}
	}
}


/**
 * Sets the button's image based upon the selected state. The allowed states are:
 * -1 : disabled
 * 0  : normal
 * 1  : highlighted
 */
function buttonState( elem, state )
{
	/**
	 * Dont toggle the currently highlighted button
	 */
	if ((elem == zoomButton) || (elem == queryButton))
	{
		return;
	}

	var newSrc = "/ivy/images/" + elem.name;
	if (state == -1)
	{
		newSrc += "_dis";
	}
	else if (state == 1)
	{
		newSrc += "_hi";
	}
	else if (state == 2)
	{
		newSrc += "_sel";
	}

	newSrc += ".gif";
	elem.src = newSrc;
}


function zoomButtonClick( elem )
{
	/**
	 * If this button has already been selected, then do nothing
	 */
	if (elem == zoomButton)
	{
		return;
	}
	
	var action = elem.name;
	if (action == _MOUSEOP_PAN)
	{
		setMouseOperation( _MOUSEOP_PAN );
	}
	else if (action == _MOUSEOP_ZOOMIN)
	{
		setMouseOperation( _MOUSEOP_ZOOMIN );
	}
	else if (action == _MOUSEOP_ZOOMSCALE)
	{
		setMouseOperation( _MOUSEOP_ZOOMSCALE );
	}
	else if (action == _MOUSEOP_ZOOMOUT)
	{
		drawMap( "-out" );
		return;
	}
	else if (action == "reset")
	{
		drawMap( "" );
		return;
	}
	else if (action == "refresh")
	{
		plotFind = undefined;
		clearQueryResults();
		drawMap( "-redraw" );
		return;
	}
	else
	{
		return;
	}
	
	/**
	 * Button clicked, reset any currently selected zoom button and set 
	 * state to highlighted
	 */
	resetZoomButton();
	resetQueryButton();
	buttonState( elem, 2 );
	zoomButton = elem;
}


function queryButtonClick( elem, queryAction )
{
	if (elem == queryButton)
	{
		return;
	}
	
	if (queryAction == _QUERY_Cancel)
	{
		cancelQuery();
	}
	else
	{
		startSearch( queryAction );

		/**
		 * Button clicked, reset any currently selected query button and set 
		 * state to highlighted
		 */
		resetZoomButton();
		resetQueryButton();
		buttonState( elem, 2 );
		queryButton = elem;
	}
}


function printButtonClick( elem )
{
	printToServer();
}


function resetZoomButton()
{
	if (zoomButton != undefined)
	{
		var elem = zoomButton;
		zoomButton = undefined;
		buttonState( elem, 0 );
	}
}


function resetQueryButton()
{
	if (queryButton != undefined)
	{
		var elem = queryButton;
		queryButton = undefined;
		buttonState( elem, 0 );
	}
}

/**
 * Browser identification functionality
 */
var net		= (navigator.appName.indexOf("Netscape") >= 0);
var net4 	= false;
var ie 		= false;
var v5 		= false;
 
if (net)
{
	if (parseFloat(navigator.appVersion) < 5)
		net4 = true;
	else
		v5 = true;
}
else if (navigator.appVersion.indexOf("MSIE 5") > 0)
{
	v5 = true;
}
else
{
	ie = true;
}


function isNetscape()
{
	return net;
}


/**
 * Dynamic frames.  These frames have content which is updated by the
 * application.
 */
var MapWindowFrame;
var FindOptFrame;
var QueryOptFrame;
var WorkFrame;
var LayersFrame;
var ShowFrame;
var SpanFrame;
var SpanFrameChecked	= false;
var NavBarFrame;


/**
 * A routine to find the "special" frames (i.e. ones with dynamic content)
 * anywhere they like, rather than in a fixed point in the application
 * structure.
 */
function getFrame(name)
{
	if (name == "MapWindow")
	{
		if (MapWindowFrame == undefined)
			MapWindowFrame = findFrame(window, name);
		return MapWindowFrame;
	}
	else
	if (name == "FindOpt")
	{
		if (FindOptFrame == undefined)
			FindOptFrame = findFrame(window, name);
		return FindOptFrame;
	}
	else
	if (name == "QueryOpt")
	{
		if (QueryOptFrame == undefined)
			QueryOptFrame = findFrame(window, name);
		return QueryOptFrame;
	}
	else
	if (name == "Work")
	{
		if (WorkFrame == undefined)
			WorkFrame = findFrame(window, name);
		return WorkFrame;
	}
	else
	if (name == "Layers")
	{
		if (LayersFrame == undefined)
			LayersFrame = findFrame(window, name);
		return LayersFrame;
	}
	else
	if (name == "Show")
	{
		if (ShowFrame == undefined)
			ShowFrame = findFrame(window, name);
		return ShowFrame;
	}
	else
	if (name == "Span")
	{
		/* the "Span" frame is optional */
		if (SpanFrame == undefined && !SpanFrameChecked)
		{
			SpanFrame = findFrame(window, name);
			SpanFrameChecked = true;
		}
		return SpanFrame;
	}
	else
	if (name == "NavBar")
	{
		if (NavBarFrame == undefined)
			NavBarFrame = findFrame(window, name);
		return NavBarFrame;
	}
	
	else
		return findFrame( window, name );
}


/**
 * Recursively traverse the FRAME tree looking for a match.
 */
function findFrame( window, name )
{
	var i;

	if (window.name == name)
		return window;

	if (window.frames)
	{
		for (i = 0; i < window.frames.length; i++)
		{
			var frame = findFrame( window.frames[i], name );
			if (frame != undefined)
			{
				return frame;
			}
		}
	}

	return undefined;
}


function getMyName()
{
	if (myname == undefined)
	{
		var date = new Date();
		myname = date.getTime() + Math.random();
	}
	
	return myname;
}


/**
 * Searches for the appropriate map image.
 */
function findNamedImage( name )
{
	alert( "findNamedImage() - " + document.title );
	
    var i;
    for (i = 0; i < document.images.length; i++)
    {
        if (document.images[i].name == name)
            return document.images[i];
    }

    return null;
}


function cloneObject( sourceObject ) 
{
    for (i in sourceObject) 
    {
        if (typeof sourceObject[i] == 'object') 
        {
            this[i] = new cloneObject( sourceObject[i] );
        }
        else
        {
            this[i] = sourceObject[i];
        }
    }
}

function savePrint()
{
	var window = getFrame( _FRAME_Result );
	var src = window.document.forms["initPrintForm"];
	A4P = eval(src.elements['A4P'].value);
	A4L = eval(src.elements['A4L'].value);
	A3P = eval(src.elements['A3P'].value);
	A3L = eval(src.elements['A3L'].value);
	A2P = eval(src.elements['A2P'].value);
	A2L = eval(src.elements['A2L'].value);
	A1P = eval(src.elements['A1P'].value);
	A1L = eval(src.elements['A1L'].value);
	A0P = eval(src.elements['A0P'].value);
	A0L = eval(src.elements['A0L'].value);
	A4P_v = src.elements['A4P_v'].value;
	A4L_v = src.elements['A4L_v'].value;
	A3P_v = src.elements['A3P_v'].value;
	A3L_v = src.elements['A3L_v'].value;
	A2P_v = src.elements['A2P_v'].value;
	A2L_v = src.elements['A2L_v'].value;
	A1P_v = src.elements['A1P_v'].value;
	A1L_v = src.elements['A1L_v'].value;
	A0P_v = src.elements['A0P_v'].value;
	A0L_v = src.elements['A0L_v'].value;
}

function printToServer()
{
	var newFrame = window.open("","_BLANK","menubar=no,height=430,width=320,resizable=yes");
	/**
	* Get the current map image size
	*/
	var imageSize = getImageSizeParam();
	var index = imageSize.indexOf( ' ' );
	var imageWidth = imageSize.substring( 0, index );
	var imageHeight = imageSize.substring( index + 1 );

	newFrame.document.write(
	"<html><head><title>Server Side Printing</title>" +
	"<meta http-equiv='Content-Type' content='text/html;'>" +
	"<meta http-equiv='Cache-Control' content='no-cache;'>" +
	"<meta http-equiv='Cache-Control' content='no-store;'>" +
	"<link rel='stylesheet' href='" + serverName + "/gw.css' type='text/css'>" +
	"<basefont size='2' face='Arial' color='#000000'>" +
	"<script language='JavaScript1.2'>" +
	"var A4P = " + A4P + ";" +
	"var A4L = " + A4L + ";" +
	"var A3P = " + A3P + ";" +
	"var A3L = " + A3L + ";" +
	"var A2P = " + A2P + ";" +
	"var A2L = " + A2L + ";" +
	"var A1P = " + A1P + ";" +
	"var A1L = " + A1L + ";" +
	"var A0P = " + A0P + ";" +
	"var A0L = " + A0L + ";" +
	"var A4P_v = '" + A4P_v + "';" +
	"var A4L_v = '" + A4L_v + "';" +
	"var A3P_v = '" + A3P_v + "';" +
	"var A3L_v = '" + A3L_v + "';" +
	"var A2P_v = '" + A2P_v + "';" +
	"var A2L_v = '" + A2L_v + "';" +
	"var A1P_v = '" + A1P_v + "';" +
	"var A1L_v = '" + A1L_v + "';" +
	"var A0P_v = '" + A0P_v + "';" +
	"var A0L_v = '" + A0L_v + "';" +
	"function form_setup() {" +
	"frm = document.printForm;" +
	"box = document.printForm.paperSize;" +
	"ClearOptions(box);" +
	"for (var i = 4; i >= 0;i--) {" +
	"var ppp = 'A' + i;" +
	"port = eval(ppp + 'P');" +
	"land = eval(ppp + 'L');" +
	"if (( port == true) || ( land == true )) {" +
	"AddToOptionList(box, ppp, ppp);" +
	"}" +
	"}" +
	"paperClick();" +
	"}" +
	"function paperClick() {" +
	"box = document.printForm.paperSize;" +
	"paper = box.options[box.selectedIndex].value;" +
	"orient = document.printForm.orientation;" +
	"port = eval(paper + 'P');" +
	"land = eval(paper + 'L');" +
	"if (( port == true ) && ( land == true )) {" +
	"orient[0].disabled = false;" +
	"orient[1].disabled = false;" +
	"orient[0].checked = true;" +
	"} else if (( port == true ) && ( land == false )) {" +
	"orient[0].disabled = false;" +
	"orient[1].disabled = true;" +
	"orient[0].checked = true;" +
	"} else if (( port == false ) && ( land == true )) {" +
	"orient[0].disabled = true;" +
	"orient[1].disabled = false;" +
	"orient[1].checked = true;" +
	"}" +
	"ClearOptions(document.printForm.template);" +
	"orient_click(); }" +
	"function populate_frames(pSize) {" +
	"arr1 = eval(pSize).split('^');" +
	"for (i = 0; i < arr1.length;i++) {" +
	"arr2 = arr1[i].split('|');" +
	"AddToOptionList(document.printForm.template, arr2[1] + '|' + arr2[2] + '|' + arr2[3], arr2[0]);" +
	"} }" +
	"function orient_click() {" +
	"orient = document.printForm.orientation;" +
	"box = document.printForm.paperSize;" +
	"paper = box.options[box.selectedIndex].value;" +
	"ClearOptions(document.printForm.template);" +
	"if ( orient[0].checked == true ) { populate_frames(paper + 'P_v'); }" +
	"else { populate_frames(paper + 'L_v'); } }" +
	"function ClearOptions(OptionList) { for (x = OptionList.length; x >= 0; x--) { OptionList[x] = null; } }" +
	"function AddToOptionList(OptionList, OptionValue, OptionText) { OptionList[OptionList.length] = new Option(OptionText, OptionValue); }" +
	"function submitForm() {" +
	"document.printForm.submit(); }" +
	"function cancelForm() {" +
	"window.close();}" +
	"function showCoords(){}</script>" +
	"</head>" +
	"<body onLoad='javascript:form_setup();' topmargin='5' leftmargin='5' marginheight='0' marginwidth='0'>");

	var formText =
	"<form name=printForm method=post action='/servlet/GenaService'>" +
	"<input type=hidden name=application value='ivy'>" +
	"<input type=hidden name=browser value='true'>" +
	"<input type=hidden name=command value='dynamic.servprint'>" +
	"<input type='hidden' name='service' value='RAWIMAGEPROVIDER'>" +
	"<input type='hidden' name='rtncontenttype' value='application/pdf'>" +
	"<input type='hidden' name='genauser' value='" + getMyName() + "'>" +
	"<input type='hidden' name='MBR' value='" + curwindow + "'>" +
	"<input type='hidden' name='dataset' value='" + openDataset + "'>" +
	"<input type='hidden' name='windowX' value='" + imageWidth + "'>" +
	"<input type='hidden' name='windowY' value='" + imageHeight + "'>" +
	"<input type='hidden' name='aliasList' value='Alias: " + plotLayers() + "'>" +
	"<input type='hidden' name='scaleList' value='Scale: " + layerScales() + "'>";

	newFrame.document.write( formText );

	newFrame.document.write(
	"<table class='printForm'>" +
	"<tr><td><b>Page Layout:</b><br></td>" +
	"<td><select name=paperSize size='1' onChange='paperClick();'>" +
	"<option value='A4' selected>A4</option>" +
	"<option value='A3'>A3</option>" +
	"<option value='A2'>A2</option>" +
	"<option value='A1'>A1</option>" +
	"<option value='A0'>A0</option>" +
	"</select></td></tr>" +
	"<tr><td><b>Template:</b><br></td>" +
	"<td><select name=template size='1'>" +
	"<option value='topC|mapC' selected>Sample A4 Portrait</option>" +
	"<option value='topC|mapC'>Test Frame A4 Portrait</option>" +
	"</select></td></tr>" +
	"<tr><td><b>Orientation:</b><br></td></tr>" +
	"<tr><td>" +
	"<input type=radio name=orientation value='Portrait' onClick='orient_click()' checked>" +
	"<img src='images/portrait.gif' width=22 height=29 alt='Portrait' border=0>" +
	" &nbsp; </td>" +
	"<td><input type=radio name=orientation value='Landscape' onClick='orient_click()'>" +
	"<img src='images/landscape.gif' width=29 height=22 alt='Landscape' border=0>" +
	" &nbsp; </td></tr>" +
	"<tr><td><br></td></tr>" +
	"<tr><td><b>Display Scale:</b><br></td>" +
	"<td><input type=text name=outputScale value='' size=6 maxlength=6><br></td></tr>" +
	"<tr><td colspan='2'><small>Leave the display scale entry empty to print out the<br>currently visible map area.</small></td></tr>" +
	"<tr><td><br></td></tr>" +
	"<tr><td><b>Map Title:</b><br></td></tr>" +
	"<tr><td>Title1:&nbsp;</td><td width='200'>" +
	"<input type=text name=TITLE value='' size=20 maxlength=50><br></td></tr>" +
	"<tr><td>Title2:&nbsp;</td><td width='200'>" +
	"<input type=text name=TITLE1 value='' size=20 maxlength=50><br></td></tr>" +
	"<tr><td colspan='2'>&nbsp;</td></tr>" +
	"<tr><td colspan='2' align='center'><button onclick='javascript:submitForm();'>Print</button>" +
	"<button onclick='javascript:closeForm()'>Cancel</button></td></tr>" +
	"</table></form></body></html>" );
	newFrame.document.close();
}

function printToServer_old()
{
	var newFrame = window.open( "print.html", "_BLANK", "menubar=no,height=420,width=300" );
	
	/**
	 * Get the current map image size
	 */
	var imageSize = getImageSizeParam();
	var index = imageSize.indexOf( ' ' );
	var imageWidth = imageSize.substring( 0, index );
	var imageHeight = imageSize.substring( index + 1 );
}


/**
 * Returns the value of the named parameter from the document's
 * URL parameters.
 */
function getParameterValues()
{
	if ((urlParameters != undefined) && (urlParameters != null))
	{
		/**
		 * The parameters have already been processed
		 */
		return;
	}

	urlParameters = new Array();

	var index = document.URL.indexOf( "?" );
	if  (index == -1)
	{
		return;
	}

	var counter = 0;
	var params = document.URL.substring( index + 1 );
	while (params != null)
	{
		var param;
		index = params.indexOf( "&" );
		if (index == -1)
		{
			param = params;
			params = null;
		}
		else
		{
			param = params.substring( 0, index );
			params = params.substring( index + 1 );
		}

		index = param.indexOf( "=" );
		urlParameters[counter++] = new Array(
			param.substring( 0, index ),
			param.substring( index + 1 ) );
	}	
}	/* end getParameterValues() */


function getParameterValue( parameter )
{
	if (urlParameters == null)
	{
		return null;
	}

	for (i = 0; i < urlParameters.length; i++)
	{
		if (urlParameters[i][0] == parameter)
		{
			return urlParameters[i][1];
		}
	}

	return null;
}	/* end getParameterValue() */
