
// function to generate an XML object from a text string
// usage: xmlObject = load_xml_content_string("<employee><age>12</age></employee>");
function load_xml_content_string(xmlString) 
{
	if (window.ActiveXObject) 
	{
		//for IE
		xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
		xmlDoc.async="false";
		xmlDoc.loadXML(xmlString);
		return xmlDoc;
	} 
	else if (document.implementation && document.implementation.createDocument) 
	{
		//for Mozila
		parser=new DOMParser();
		xmlDoc=parser.parseFromString(xmlString,"text/xml");
		return xmlDoc;
	}
}

function adjustBoundsExtent(glat, glng, number)
{
	//alert ("numb = "+numb)
	//alert ("numb = "+number+" BBox = "+loLat+", "+loLng+" "+hiLat+", "+hiLng);
	//Convert Lat and Long to numerical values
	var lat=parseFloat(glat);
	var lng=parseFloat(glng);

	// add points into sumLat and sumLng
	//if (number == 0){alert ("initialising limits"); loLat=lat; hiLat=lat; loLng=lng; hiLng=lng;}

	// calculate bounding box of coords	
	if (lat < loLat) {loLat=lat;}
	if (lat > hiLat) {hiLat=lat;}
	if (lng < loLng) {loLng=lng;}
	if (lng > hiLng) {hiLng=lng;}
}
// ---------------- Set opacity for different Browsers -------------------//
function setOpacity(obj, opacity) 
{
// obj = object that is to have an opacity set for
// opacity =  integer between 0 & 100
	//alert("opacity = "+opacity)
	opacity = (opacity == 100)?99.999:opacity;

  // IE/Win
	obj.style.filter="alpha(opacity="+ opacity + ")";

  // Safari<1.2, Konqueror
	obj.style.KHTMLOpacity = opacity/100;

  // Older Mozilla and Firefox
	obj.style.MozOpacity = opacity/100;

  // Safari 1.2, newer Firefox and Mozilla, CSS3
	obj.style.opacity = opacity/100;
}


// function to turn xml object into a text string
// usage: xmlString = make_string_from_xml(xmlDoc)
function make_string_from_xml(xmlObject)
{
	if (window.ActiveXObject) 
	{	return xmlObject.xml;}
	else if (document.implementation && document.implementation.createDocument) 
	{	 return (new XMLSerializer()).serializeToString(xmlObject);}
}

function startDownload(file)  
{  
	var url=applicationBase+file;    
	window.open(url,'Download');  
} 

function showHideGraph()
{
	//alert('There are '+nic+' polygons in this group')
	//alert('collection.length = '+collection.length)
	//var delta = nic - limit;
	//if (nic >= limit) {alert ("There are more than "+limit+" polygons in this collection.\n Please remove at least "+delta+" one from the collection."); return;}
	//alert(collection)
	//alert ('currentAtts = '+currentAtts)
	
	if (collection != '')
	{
		var wholeColl = collection;
		graphPopup(wholeColl, currentAtts ); 
	}
}

function checkHex(value)
{
	return /^#([A-Fa-f0-9]{3}$)|([A-Fa-f0-9]{6}$)/.test(value);
}

function mapTemplatePopup() 
{
	var bord = 30;
	var title = 'Enter your Text here (up to 200 characters)';
	
	// setup map annotation controls
	wdt = map.getSize().w;
	hgt = map.getSize().h;
	// override dynamic map size with A4 approx size
	wdt = 800; 
	hgt = 900;
	scale = parseInt(map.getScale());
	width = wdt + 2*bord;
	height = hgt + 5*bord;
	
	// set up location for Map box
	maptop = 4*bord;
	mapleft = bord;
	tablehgt = 3*bord;
	tablewdt = wdt;

	// set up location of map header line
	texttop = bord-15;
	textleft = bord;

	// get the current date data
	var d = new Date();
	day = d.getDate();
	month = d.getMonth()+1;
	year = d.getFullYear();

	// create the new popup window
	winmap = window.open('NuMaps','myconsole',
		'width='+width+',height='+height 
		+',alwaysRaised=1'
		+',menubar=1'
		+',toolbar=0'
		+',status=0'
		+',scrollbars=0'
		+',resizable=0');
	winmap.document.writeln
	(
		'<html><head><title>NuMaps Printable Map</title>'
			+'<style>'
				+'html, body {height: 100%; width: 100%; background-color:#ECE9D8;	overflow-x:hidden;	overflow-y:hidden; font-family:Verdana; font-size:9px; }'
				+'a {text-decoration:none; }'
				+'.whiteBox {border-right:1px solid #d4d4d4; border-bottom: 1px solid #d4d4d4;	border-top:1px solid gray;	border-left:1px solid gray; background-color:white;}'
				+'#printMap {background-color:#B5D6F1; width:100%; height:100%; z-index:0;}'
					
			+'</style>'
		+'</head>'
			+'<body onLoad="self.focus(); ">'
				+'<table border=0 style="position:absolute; top:'+bord+'px; left:'+bord+'px; height:'+tablehgt+'px; width:'+tablewdt+'px; border:1px solid #d2d2d2;">'
					+'<tr>'
						+'<td style="width:100px; height:20px; text-align:left; border-bottom:1px solid #d2d2d2;">'
							+'<a href="http://www.numaps.com.au" target="_blank" ><img border=0 src="images/numapsLogo_small.gif" /></a>'
						+'</td>'
						+'<td  style="height:20px;  font-weight:bold; font-style:Arial; font-size:10px; text-align:center; border-bottom:1px solid #d2d2d2;">'
							+'<textArea cols="200" rows="1" style="width:80%; height:20px; text-align:center; font-style:Arial; font-weight:bold; background-color:transparent; border-style:none; font-size:18px; ">'
								+'Enter Your Map Title Here'
							+'</textArea>'
						+'</td>'
						+'<td  style="width:120px; height:20px; text-align:right; font-size:9px; border-bottom:1px solid #d2d2d2;">'
							+'<span>'
								+'Date : '+day+"/"+month+"/"+year
							+'</span>'
						+'</td>'
					+'</tr>'

					+'<tr>'
						+'<td style="width:100px; height:20px; text-align:left; font-size:9px; border-bottom:1px solid #d2d2d2;">'
							+'<span>'
								
							+'</span>'
						+'</td>'
						+'<td  style="height:20px; text-align:center; font-size:12px; border-bottom:1px solid #d2d2d2;">'
							+'<textArea cols="200" rows="1" style="width:80%; font-size:12px; height:20px; font-style:Verdana; text-align:center; background-color:transparent; border-style:none;">'
								+title
							+'</textArea>'
						+'</td>'
						+'<td  style="width:120px; height:20px; text-align:right; font-size:9px; border-bottom:1px solid #d2d2d2;">'
							+'<span>'
								
							+'</span>'
						+'</td>'
					+'</tr>'

					+'<tr>'
						+'<td style="width:40px; height:20px; text-align:left; font-size:11px; border-bottom:1px solid #d2d2d2;">'
							+'<span>'
								+'Plan No : '
							+'</span>'

							+'<textArea cols="10" rows="1" style="top:2px; width:50px; font-size:11px; height:12px; font-style:Verdana; text-align:left; background-color:transparent; border-style:none;">'
								+'0000'
							+'</textArea>'
							
						+'</td>'
						+'<td  style="height:20px; text-align:center; font-style:Verdana; font-size:12px; border-bottom:1px solid #d2d2d2;">'
							+'<textArea cols="200" rows="1" style="width:80%; font-size:12px; height:20px; font-style:Verdana; text-align:center; background-color:transparent; border-style:none;">'
								+title
							+'</textArea>'
						+'</td>'
						+'<td  style="width:120px; height:20px; text-align:right; font-size:9px; border-bottom:1px solid #d2d2d2;">'
							+'<span>'
								+'Scale 1 : '+scale
							+'</span>'
						+'</td>'
					+'</tr>'

					+'<tr>'
						+'<td>'
						+'</td>'
					+'</tr>'
				+'</table>'
				
				
				+'<div id="canvas2" class="whiteBox" style="position:absolute; top:'+maptop+'px; left:'+mapleft+'px; height:'+hgt+'px; width:'+wdt+'px; background-color:transparent;" >'
					
					+'<div id="printMap">'
						+"<div id='printLegendBox' style='position:absolute; top:20px;left:20px; height:auto; width:auto; z-index:10000;'  >"
						+"</div>"
					+'</div>'

				+'</div>'
			+'</body>'
		+'</html>'
	);
	//filter:alpha(opacity=60);	opacity: 0.6; class='whiteBox'
	winmap.document.close();
	
	PrintMap();
	//application = winmap.document.getElementById("printLegendBox").id;

	if(!drapeNotDone && printLegend){legendBuilder("printLegendBox", sldUrl, null, '', '', true);}

	//alert('printMap done')
}


// this assumes that the Map object is a JavaScript variable named "map"
// changed 20090928:
// * fixed the weird references about iframes, since they're not the usual use case
// * added the Please Wait window
// * used newer-style OpenLayers.Request.POST() for final AJAX call
//var print_wait_win = null;
function PrintMap() 
{
    //-- post a wait message
    //print_wait_win = window.open("pleasewait.html", "print_wait_win", "scrollbars=no, status=0, height=5, width=10, resizable=1");
	newMap = winmap.document.getElementById("printMap");

	// go through all layers, and collect a list of objects
    // each object is a tile's URL and the tile's pixel location relative to the viewport
    var size  = map.getSize();
    var tiles = [];
	baseNotDone = true;
	drapeNotDone = true;
	electBdyNotDone = true;
	electLabelNotDone = true;

	//alert('drape image format = '+drapeImage);
	//opac = 0.5;
	alert('number of layers to add = '+map.layers.length)

	for (layername in map.layers) 
	{
        // if the layer isn't visible at this range, or is turned off, skip it
        var layer = map.layers[layername];
        if (!layer.getVisibility()) continue;
        if (!layer.calculateInRange()) continue;
   		
		// search through base maps to see if this layer is a basemap
		if(baseNotDone)
		{
			// look at all basemaps first
			for(var i=0; i<baseMapsList.length; i++)
			{	
				if(layer.name == baseMapsList[i])	
				{	
					//alert(layer.name+' is the basemap layer')
					baseNotDone = false;

					// create the base map layer in the printMap object
					alert(srs+"  "+defaultSrs)
					if (srs == defaultSrs)	//------------- sphericalMercator option
					{
						var options = 
						{
							projection: srs,  
							units: "m",  
							controls:[],  
							maxResolution: res,  
							displayProjection: new OpenLayers.Projection("EPSG:4326"), 
							//numZoomLevels: 22,  
							maxExtent: new OpenLayers.Bounds(ozBox[0],  ozBox[1],  ozBox[2],  ozBox[3])
						};
						printMap = new OpenLayers.Map(winmap.document.getElementById("printMap"), options);
					}
					else if(srs == "EPSG:4326" )						//------------ standard geographicals option
					{
						var options = 
						{
							projection:srs,  
							controls:[],  
							units:'degrees',  
							maxResolution: res,   
							maxExtent: new OpenLayers.Bounds(ozBox[0],  ozBox[1],  ozBox[2],  ozBox[3])
						};
						printMap = new OpenLayers.Map(winmap.document.getElementById("printMap"), options);
						printMap.addControl(new OpenLayers.Control.LayerSwitcher());
						printMap.addControl(new OpenLayers.Control.NavToolbar());
					}
					else{alert(srs+' coordinate system not supported [epsg:900913 & epsg:4326 supported]'); return;}
					
					//GoogleMaps', 'GoogleHills', 'GoogleHybrid', 'GoogleSat', 'NuMaps', 'NearMap'
					if (layer.name == 'GoogleMaps' && layer.getVisibility())
					{	
						googleMap2 = new OpenLayers.Layer.Google( "GoogleMaps2" , {type: G_NORMAL_MAP, sphericalMercator:spMerc} );
						googleMap2.addOptions({isBaseLayer: true, wrapDateLine: true, buffer: buff, minZoomLevel:4, numZoomLevels:20, maxZoomLevels:20, maxResolution: res });
						printMap.addLayer(googleMap2);
					}
					else if (layer.name == 'GoogleHybrid' && layer.getVisibility())
					{	
						googleHybrid2 = new OpenLayers.Layer.Google( "GoogleMaps2" , {type: G_HYBRID_MAP, sphericalMercator:spMerc} );
						googleHybrid2.addOptions({isBaseLayer: true, wrapDateLine: true, buffer: buff, minZoomLevel:4, numZoomLevels:20, maxZoomLevels:20, maxResolution: res });
						printMap.addLayer(googleHybrid2);
					}
					else if (layer.name == 'GoogleHills' && layer.getVisibility())
					{	
						googleHills2 = new OpenLayers.Layer.Google( "GoogleMaps2" , {type:  G_PHYSICAL_MAP, sphericalMercator:spMerc} );
						googleHills2.addOptions({isBaseLayer: true, wrapDateLine: true, buffer: buff, minZoomLevel:4, numZoomLevels:20, maxZoomLevels:20, maxResolution: res });
						printMap.addLayer(googleHills2);
					}
					else if (layer.name == 'GoogleSat' && layer.getVisibility())
					{	
						googleSat2 = new OpenLayers.Layer.Google( "GoogleMaps2" , {type: G_SATELLITE_MAP, sphericalMercator:spMerc} );
						googleSat2.addOptions({isBaseLayer: true, wrapDateLine: true, buffer: buff, minZoomLevel:4, numZoomLevels:20, maxZoomLevels:20, maxResolution: res });
						printMap.addLayer(googleSat2);
					}
					else if (layer.name == 'NuMaps' && layer.getVisibility())
					{	
						googleNuMaps2 = new OpenLayers.Layer.WMS.Untiled( "NuMaps" , numapsService, { sld:numapsBasemapUrl, sphericalMercator: spMerc, format: drapeImage, quality:'BEST', transparent:true} ); 
						googleNuMaps2.addOptions({isBaseLayer: true, wrapDateLine: true, buffer: buff, minZoomLevel:4, numZoomLevels:20, maxZoomLevels:20, maxResolution: res });
						printMap.addLayer(googleNuMaps2);
					}
					printMap.setCenter(map.getCenter(), map.getZoom());
					//alert('basemap added')
				}		
			}
		}
		if (myElectFlag && electBdyNotDone)
		{
			// create the Polygon Highlight layer
			polygonLayer2 = new OpenLayers.Layer.WMS( "Polygon Layer", meshBlocksBase, { sld_Body: polySld,  format: 'image/png', version:'1.1.3', quality: 'BEST', reaspect: false, transparent: true}, { tileSize: new OpenLayers.Size(512,512)});
			polygonLayer2.addOptions({isBaseLayer: false,  buffer:2, visibility: true, reproject:true});
			printMap.addLayer(polygonLayer2);			
			electBdyNotDone = false;
	
		}
		if( myElectFlag && electLabelNotDone)
		{
			// create the Polygon Highlight layer
			labelLayer2 = new OpenLayers.Layer.WMS.Untiled( "Label Layer", meshBlocksBase, { sld_Body: labelSld,  format: 'image/png', version:'1.1.3', quality: 'BEST', reaspect: false, transparent: true}, { tileSize: new OpenLayers.Size(512,512)});
			labelLayer2.addOptions({isBaseLayer: false,  buffer:2, visibility: true, reproject:true});
			printMap.addLayer(labelLayer2);
			electLabelNotDone = false;
		}

		
		if(drapeNotDone)
		{
			// Assuming not a base and is a normal layer then process as WMS DDrape layer
			//alert(layer.name+' is NOT a base layer')
			// find the layer in the DDrapes array
			//alert('Datts.length = '+Datts.length)
			drapeNumber = -1
			for(var n=0; n<Datts.length; n++)
			{
				var components = Datts[n].split('|');
				//alert(components[5]+'  test  '+layer.name)
				if(components[5] == layer.name)
				{	
					//alert('found')
					drapeWmslayer = components[0]; 
					theme = components[1];
					themeTitle = components[2];
					themeDir = components[3];	
					themeLayer = components[4];
					layName = components[5];
					layFile = components[6];	// this is Dfile which is the DDrape's SLD file from the database
					layStyle = components[7];
					layType = components[8];
					layTitle = components[9];
					layOp = components[10];
					laySldLoc = components[11];
					drapeId = components[12];
					drapeNumber = n;
					break; break;
				}
			}
			// get the opacity of the current Ddrape layer
			//opac= newOpacity;
			//alert('opacity = '+newOpacity);
			
			// if layer is found in the DDrapelist then add it 
			if(drapeNumber >= 0)
			{
				// if a style DDrape then generate from database
				if(layStyle != '' &&  layStyle != 'default' && drapeWmslayer != '')
				{	
					DemoDrape2 = new OpenLayers.Layer.WMS.Untiled
					(
						layName, 
						numapsService, 
						{
							layers: drapeWmslayer,  
							styles: layStyle,  
							format: drapeImage, 
							version:'1.1.3', 
							quality: 'BEST', 
							reaspect: false, 
							transparent:'true', 
							opacity: newOpacity
						});	
				}
				else
				{  
					sldUrl = applicationBase+"inc/sld/"+layFile;
					//alert('sld file = '+sldUrl)

					DemoDrape2 = new OpenLayers.Layer.WMS.Untiled
					(
						layName, 
						numapsService, 
						{	
							SLD: sldUrl,  
							format: drapeImage, 
							version:'1.1.3',   
							quality: 'BEST', 
							reaspect: false, 
							transparent:'true', 
							opacity: newOpacity
						});		
				}
				// now create the layer in printMap
				DemoDrape2.addOptions({isBaseLayer: false, visibility: true, wrapDateLine: true, reproject: true});
				//registerLoadWheel(DemoDrape2, 'loadWheelDrape');
				printMap.addLayer(DemoDrape2);	
				drapeNotDone = false;
			}
			else if(configRequest)// assume this is a configure version of a DDrape
			{				
				DemoDrape2 = new OpenLayers.Layer.WMS.Untiled(layName, numapsService, {SLD: configRequest+configQuery, format: drapeImage, version:'1.1.3',   quality: 'BEST', reaspect: false, transparent:'true', opacity: newOpacity});		
				DemoDrape2.addOptions({isBaseLayer: false, visibility: true, wrapDateLine: true, reproject: true });
				printMap.addLayer(DemoDrape2);
				drapeNotDone = false;
			}

		}
		else
		{
			// finally process all the admin layers
			var layerOnOff = false; labelOnOff = false;
			var layerParts = layer.name.split(' (labels)');
			//alert('layerParts array = '+layerParts)
			
			// for the layer checkbox
			if(layerParts.length == 1)
			{			
				// search the layers array to find the layer number
				var layNum = -1;
				for(var k=0; k<TitleText.length; k++)
				{	//alert(TitleText[k]+ '   test   '+layer.name)
					if(TitleText[k]	== layer.name)
					{ 	layNum = k;	break;		}
				}
				//alert(layNum)
				var layerOnOff = document.getElementById('layers:'+layNum).checked;
				
				// Ok plot the layer and labels if selected
				if(layNum >=0 && (layerOnOff || layerOnOff))
				{
					// get the checkbox status for labels and layers		
					//alert(TitleText[layNum]+" layer selected = "+layerOnOff)
					
					// with an SLD
					if((Sld[layNum] != 'none' || Sld[layNum] != '') && layerOnOff)
					{
						var Bdys = applicationBase+Sld[layNum];
						var printLayer = new OpenLayers.Layer.WMS.Untiled
						( 
							TitleText[layNum], 
							meshBlocksBase, 
							{	sld: Bdys,  
								format: drapeImage, 
								version: Ogc[layNum],  
								quality: quality, 
								reaspect: false, 
								transparent: true ,
								opacity: Opac[layNum]
							}, 
							{reproject: true}
						);
					}
					// for Styles instead of SLD based ddrapes
					else if(Style[layNum] != 'default' && Style[layNum] != 'none' && Style[layNum] != '' && layerOnOff)
					{
						var printLayer = new OpenLayers.Layer.WMS.Untiled
						( 
							TitleText[layNum], 
							meshBlocksBase, 
							{	layers: Name[layNum],
								styles: Style[layNum],
								format: drapeImage, 
								version: Ogc[layNum],  
								quality: quality, 
								reaspect: false, 
								transparent: true,
								opacity: Opac[layNum]
							}, 
							{ reproject: true}
						);
						//alert('style based DDrape prepared')
					}
					
					// now create the layer in printMap
					if(layerOnOff)
					{
						printLayer.addOptions({isBaseLayer: false, visibility: true, wrapDateLine: true, reproject: true});
						printMap.addLayer(printLayer);
						//alert("adding admin layer to printMap : "+TitleText[layNum]);
					}
				}
			}
			else
			{
				// search the layers array to find the layer number
				var layNum = -1;
				for(var k=0; k<TitleText.length; k++)
				{	
					//alert(TitleText[k]+ '   test   '+layerParts[0])
					if(TitleText[k] == layerParts[0])
					{ 	layNum = k;	break;		}
				}
				var labelOnOff = document.getElementById('label:'+layNum).checked;
				
				// now do the labels if required	
				//alert(TitleText[layNum]+" labels selected = "+labelOnOff)
				if((SldLabels[layNum] != 'none' || SldLabels[layNum] != '') && labelOnOff)	
				{	
					var Bdys = applicationBase+SldLabels[layNum];
					var printLayer = new OpenLayers.Layer.WMS.Untiled
					( 
						TitleText[layNum], 
						meshBlocksBase, 
						{	sld: Bdys,  
							format: drapeImage, 
							version: Ogc[layNum],  
							quality: quality, 
							reaspect: false, 
							transparent: true ,
							opacity: Opac[layNum]
						}, 
						{reproject: true}
					);
				}
				// for Styles instead of SLD based ddrapes
				else if(Style[layNum] != 'default' && Style[layNum] != 'none' && Style[layNum] != '')
				{
					var printLayer = new OpenLayers.Layer.WMS.Untiled
					( 
						TitleText[layNum], 
						meshBlocksBase, 
						{	layers: Name[layNum],
							styles: Style[layNum],
							format: drapeImage, 
							version: Ogc[layNum],  
							quality: quality, 
							reaspect: false, 
							transparent: true,
							opacity: Opac[layNum]
						}, 
						{ reproject: true}
					);
					//alert('style based DDrape prepared')
				}
				
				// now create the layer in printMap
				//alert("adding admin layer to printMap : "+TitleText[layNum]);
				if(labelOnOff)
				{
					printLayer.addOptions({isBaseLayer: false, visibility: true, wrapDateLine: true, reproject: true});
					printMap.addLayer(printLayer);
					//alert("adding admin layer to printMap : "+TitleText[layNum]);
				}
			}
		}
	}
}

		// add this layer to the print map window
/*
		// iterate through their grid's tiles, collecting each tile's extent and pixel location at this moment
        for (tilerow in layer.grid) {
            for (tilei in layer.grid[tilerow]) 
			{
                var tile     = layer.grid[tilerow][tilei]
                var url      = layer.getURL(tile.bounds);
                var position = tile.position;
                var opacity  = layer.opacity ? parseInt(100*layer.opacity) : 100;
                tiles[tiles.length] = {url:url, x:position.x, y:position.y, opacity:opacity};
            }
        }
    }
    // hand off the list to our server-side script, which will do the heavy lifting
    //var tiles_json = JSON.stringify(tiles);
   // var params = '&width='+size.w + '&height='+size.h + '&tiles='+escape(tiles_json) ;

	// execute the request via proxy server
	//var appsUrl = applicationBase+'cf/proxycall.cfm?';					// coldfusion version
	//var query  = 'url=json.php'+params;
	//alert(appsUrl+query)
	//ajaxRequest = fetchXml(appsUrl, query, false, 'POST');	
	//if (ajaxRequest.status != 200) {alert('error within proxyRequest function'); }

	//makePopup(fetchXml(appsUrl, query, false, 'POST'), '800', '800', 'auto')
	
	
	//window.open(proxyRequest('', query, '', 'POST'));
	
	OpenLayers.Request.POST
	(
      { url:'print.php',
        data:OpenLayers.Util.getParameterString({width:size.w,height:size.h,tiles:tiles_json}),
        headers:{'Content-Type':'application/x-www-form-urlencoded'},
        callback: function(request) 
		{
          // print_wait_win.close();
           window.open(request.responseText);
        }
      }
    );
*/




// function to determine if a point is inside a polygon array
function isPointInPoly(poly, pt)
{
/*	var ii;
	for(var c = false, ii = -1, l = allX.length, j = l - 1; ++ii < l; j = ii)
		((allY[ii] <= pt[1] && pt[1] < allY[j]) || (allY[j] <= pt[1] && pt[1] < allY[ii]))
		&& (pt[0] < (allX[j] - allX[ii]) * (pt[1] - allY[ii]) / (allY[j] - allY[ii]) + allX[ii])
		&& (c = !c);
	//alert('in-out indicator = '+c);
	return c;
*/
	for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i)
		((poly[i].y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly[i].y))
		&& (pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x)
		&& (c = !c);
	return c;

}
//-----------------------load ststues reporting------------------------//
function genLoadStatus(thisMessage, wheel, percentDone)
{
	//this will write out a message to the apps status area whenever called
	var messDiv = document.getElementById('loadStatus');
	if(thisMessage != '')
	{
		checkRemoveObject('loadMessage');
		var message = document.createElement('div');
		message.id='loadMessage';
		message.setAttribute('id', 'loadMessage');
		var text = document.createTextNode(thisMessage);
		message.appendChild(text);
		message.style.position='relative';
		message.style.top='2px';
		message.style.left='0px';
		//message.style.border='1px solid red';
		messDiv.appendChild(message);
		messDiv.style.display='block';
		if (wheel)
		{	
			if(document.getElementById('loadWheel')){document.getElementById('loadWheel').style.display='block';}
			if(document.getElementById('eventsLogID')){document.getElementById('eventsLogID').style.display='block';}
		}
		else
		{	document.getElementById('loadWheel').style.display='none';		}
	}
	else 
	{
		messDiv.style.display='none';
		if(document.getElementById('loadWheel')){document.getElementById('loadWheel').style.display='none';}
		if(document.getElementById('eventsLogID')){document.getElementById('eventsLogID').style.display='none';}
	}
	// add the progress bar if requested
	if(percentDone != '' && percentDone < 100) // this assumes progress bar is a % complete valus or  nothing
	{
		document.getElementById('completeBar').style.width=percentDone+'%';
		document.getElementById('completeBarHolder').style.display='block';
	}
	else
	{
		document.getElementById('completeBarHolder').style.display='none';
	}

}

// Get all the startup parameters and defaults
function getParams()
{
	//-------------- get the pamaters after the ? of the url submitted -----------	
	params = getUrlVars();
	
	// set up the defaults
	npImg = "images/compass.gif";
	uploadRadius = 40;
	sldLimit = 5000;
	startScale = 14000000;
	goToZoom = 14;
	outFormat = 'BXFS';		// this is default for CubeWerx but can be overwritten via layer control file
	country='Australia';	// this is default but can be overwritted in address entry
	labelsRequired=false;
	pieChartsRequired=false;
	psmaBasemapFile = 'psma_basemap.xml';
	
	// set up the command line changable defaults
	startZoom = 4;
	quality='QUICKEST';			// BEST, MEDIUM, QUICKEST is the other option
	startBasemap = 'GoogleMaps'; 
	currentBasemap = startBasemap;
	start='';
	wdth = '';
	height='';
	configFlag=false;
	userAddress='';
	drapes='numaps'; //drapes = 'inc/drapeLists.xml';
	layersFile = 'data/layers.xml';
	openWithInstructions = false;
	direction='horizontal';  // vertical is option
	tileSize = '512'; 
	defaultSrs = "EPSG:900913";
	srs = defaultSrs; 	//var srs = "EPSG:4326"; this is set in numapsUtils.js
	drapeImage = 'image/png';
	if(browser == 'msie') {drapeImage = 'image/gif';}
	logoImg = 'images/numapsLogo.png'; //logoImg = 'images/numaps_120.png';
	linkAddr = 'http://www.numaps.com.au';
	nuCache = true;
	buff = 1;
	printIT = false;
	area='';
	uploadDivs = 5;
	markerZm = 10;
	vectOpac = 1.0;
	gfiLimit = 10000;
	filterTol=0;
	username='';
	password='';
	account='MASHUP';
	ccNo = 4;
	ccInc = 10000;
	analysis='';
	loadIt = true;
	reverse = false;

	
	// pick off each supported parameter
	for (var i = 0; i<params.length ; i++)
	{
		//alert(params[i] +" = "+params[params[i]])
		if(params[i] == 'accCode')
		{	
			drapes = 'inc/drapeLists_'+params[params[i]]+'.xml';
			//gKey = "../inc/gKey_"+params[params[i]]+".js";
			account = params[params[i]];
		}
		// starting parameters	
		if(params[i] == 'zoom') {startZoom = params[params[i]];}// used to specify initial zoom starting point		
		startZoom = parseInt(startZoom);
		if(startZoom > 18) {startZoom = 18;}
		if(params[i] == 'basemap') // used to preset the basemap
		{	startBasemap = params[params[i]];
			if(startBasemap == 'OpenStreetMap')	{startZoom = startZoom + 1;}	
		}
		
		if(params[i] == 'quality') {quality = params[params[i]];}// used to set the quality of a WMS image request		
		if(params[i] == 'start') {start = params[params[i]];}// used to specify the lat/long of the starting location		
		if(params[i] == 'width') {wdth = params[params[i]];}// map width		
		if(params[i] == 'height') {hght = params[params[i]];}// map height		
		if(params[i] == 'address') // used to specify the starting address location	
		{
			userAddress = params[params[i]];
			// make sure all %20 are removed from address string source
			if(userAddress != '')
			{	userAddress = userAddress.replace(/%20/g, ' ');
				//userAddress = capitaliseIt(userAddress)
			}
		}			
		if(params[i] == 'drapes'){drapes = params[params[i]];}// used to specify the xml file for drape loading
		if(params[i] == 'layers'){layersFile = params[params[i]];}// used to specify the xml file for layers loading		
		if(params[i] == 'help'){openWithInstructions = params[params[i]];}// flag to open with help instructions launched
		if(params[i] == 'psma'){psmaBasemapFile = params[params[i]];}
		
		// map config parameters		
		if(params[i] == 'menu') {direction = params[params[i]];}// used to spacify vertical/horizontal menu
		if(params[i] == 'tileSize'){tileSize = params[params[i]];}// used to specify tile size to be used		
		if(params[i] == 'srs'){srs = params[params[i]];}// used to specify the srs EPSG code
		if(params[i] == 'imgFormat'){drapeImage = params[params[i]];}// used to specify the image format used in a WMS request		  
		if(params[i] == 'logoSrc'){logoImg = params[params[i]];}// used to define the logo disolayed on the map
		if(params[i] == 'home'){linkAddr = params[params[i]];}// used to define the link behind the logo
		if(params[i] == 'cache') {nuCache = params[params[i]];}// flag to indicate if numa cache is active 
		if(params[i] == 'buff') {buff = parseInt(params[params[i]]);}// set to a number between 0 nd 5 for tiles outside of AOI
		if(params[i] == 'print') {printIT = params[params[i]];}// flag to expose print function
		if(params[i] == 'area') {area = params[params[i]];}// not sure???

		// uploading parameters
		if(params[i] == 'updiv'){uploadDivs = params[params[i]];}// set the number of divisions for categories of uploaded points
		if(params[i] == 'markerZm') {markerZm = params[params[i]];}// default zoom value for go to marker
		if(params[i] == 'opac') {vectOpac = params[params[i]];}// default opacity of vector markers
		if(params[i] == 'labels') // default labels for address of vector markers
		{	labelsRequired = params[params[i]];}

		// get feature parameters
		if(params[i] == 'gfiLimit'){gfiLimit = params[params[i]];}// used to limit the number of elements in GFI request
		if(params[i] == 'filter') {filterTol = params[params[i]];}// used to filter out points in a vector geometry
		
		// account related parameters
		if(params[i] == 'username') {username =params[params[i]];}// username
		if(params[i] == 'password') {password = params[params[i]];}// password
		if(params[i] == 'account') {account = params[params[i]];}// Access Control account	

		//if(params[i] == 'accumulate') {accumulate = params[params[i]];}
		if(params[i] == 'ccNo') {ccNo = params[params[i]];}// not sure ??
		if(params[i] == 'ccInc') {ccInc = params[params[i]];}// not sure ??
		if(params[i] == 'analysis') {configFlag = params[params[i]];}// not sure ??
		if(params[i] == 'loader'){loadIt = params[params[i]];}// flag to show loadit image 
	}
	//--------------- sniff the browser being used ----------------
	//var browserName=navigator.appName;  // important for getFeature decoding
	// browserName = Netscape or Microsoft Internet Explorer
	br=new Array(4);
	os=new Array(2);
	flash=new Array(2);
	br = getBrowser();
	browser = br[0]; 
	browserName = br[0];
	version = getMajorVersion(br[1]);
	
	// apply XML browser difference here
	prefix='gml:';
	if ((browser =='firefox' && version == '2') || (browser == 'safari'))
	{	prefix='';	}

/*
	codeName = navigator.appCodeName ;
	appName = navigator.appName ; // use this to detect browser (Netscape/Microsoft Internet Explorer)
	version = navigator.appVersion;
	cookies = navigator.cookieEnabled;
	platform= navigator.platform;
*/

}

function getUrlVars()
{
	var vars = [], hash;
    var hashes = window.location.href.slice(window.location.href.indexOf('?') + 1).split('&');
    for(var i = 0; i < hashes.length; i++)
    {	
		hash = hashes[i].split('=');
        vars.push(hash[0]);
        vars[hash[0]] = hash[1];
    }
    return vars;
}
function goToCoords(address, showMarker)
{
	// check to see if input string is a lat/long
	var p = [];
	var parts = address.split(',');
	if(parts.length > 1) 
	{	// change lat/long coords to map coords
		p[0] = parts[1];
		p[1] = parts[0];
		if (srs == defaultSrs) 
		{	var point = geogs2google(p);
			p = decodePoint(point);
		}
		else
		{	var point = new OpenLayers.LonLat(p[0], p[1]);	}
		
		// plot marker
		if(showMarker)
		{	// create the vector icon on map at thgis location		
			createVectorIcon(p[0], p[1], address);
		}

		// jump to this location
		var point = new OpenLayers.LonLat(p[0], p[1]);
		var zmLevel = 19; 
		if(startBasemap == 'nearmap'){zmLevel = 20;}
		map.setCenter(new OpenLayers.LonLat(p[0], p[1]), zmLevel);

		return true;
	}
	else{ return false;	}
}


function proxyRequest(request, file, type)
{
	// make sure url is set
	//alert(request)
	var appsUrl = applicationBase+'cf/proxycall.cfm?';
	
	// set up the parameter list
	var query  = 'url='+meshBlocksBase.split('?')[0]+"&"+request+"&numakey="+numapsKey+"&domain=*.numaps.com.au";
	
	//alert('inside Proxy server = '+appsUrl + query+"\n\n")
	// do the proxy request
	ajaxRequest = fetchXml(appsUrl, query, false, type);
	if (ajaxRequest.status != 200) {alert('error with this URL : '+appsUrl + query); return ajaxRequest;}
	return ajaxRequest;
}


//http://staging.demos.numaps.com.au/nuserv/cf/proxycall.cfm?url=http://staging.ws.numaps.com.au/nuserv.cfm&request=numagetattributestats&layer=POA_MARITAL_STATUS:ABS&attribute=PERSONS_TOTAL_DIVORCED

function proxyRequestPhp(uri, request, file, type)
{
	// execute the request via proxy server
	var appsUrl = applicationBase+'inc/proxyCall.php?';					// PHP version
	var query  = 'url='+meshBlocksBase.split('?')[0]+"&"+request;
	//alert(appsUrl + query)
	ajaxRequest = fetchXml(appsUrl, query, true, type);	
	if (ajaxRequest.status != 200) {alert('error within proxyRequest function'); return ajaxRequest;}
	return ajaxRequest;
}

//--------------- Generic function to launch a PopUp window --------------------//
function makePopup(url, wdth, hght, overflow) // overflow can be 'scroll', 'resize' or 'both'
{
	if(win) {win.close();}
	if (  (url != "")  &&  (url)  )
	{
		if (hght > 800) {hght = 800;}
		if (wdth > 800)  {wdth = 800;}
		if (overflow == '' || !/^(scroll|resize|both)$/.test(overflow))
		{ overflow = 'both';}
		//alert(wdth+" : "+hght)
		var params = 'width='+wdth+
			', height='+hght+
			', top=100, left=100'+
			', scrollbars='+(/^(scroll|both)$/.test(overflow) ? 'yes' : 'no')+
			', resizable=' +(/^(resize|both)$/.test(overflow) ? 'yes' : 'no')+
			', status=yes'+
			', toolbar=no'+
			', menubar=yes'+
			', location=no'+
			', alwaysRaised';
		// Now launch the window
		win = window.open (url, '', params);
		//win.setZOptions('alwaysRaised');
		return win;
	}
}

function pause(numberMillis) 
{
	var now = new Date();
	var exitTime = now.getTime() + numberMillis;
	while (true) 
	{
		now = new Date();
		if (now.getTime() > exitTime)
		return;
	}
}
// ---------------- function to launch a sized window ---------------
function popUp(Url) 
{
	day = new Date();
	id = day.getTime();
	eval("page" + id + " = window.open(Url, '" + id + "', 'toolbar=0,scrollbars=1,location=1,statusbar=0,menubar=0,resizable=1,width=650,height=300,left = 200,top = 200');");	
}
function killit(path, delfile)
{
	// this will remove the file called 'temp' from the disk
	var url='inc/deletefile.php?';
	var query="path="+path+"&file="+delfile;
	loadXml(url, query);
	return true;
}
//---------------- delete a file on the server ---------------------//
function deleteit(delfile)
{
	
	//alert ('file for delete in deleteit = '+delfile)
	// this will remove the file called delfile passed in from the server
	var url='inc/deleteit.php';
	var query="?file="+delfile;
	//alert(url+query)
	if(!loadXml(url, query, false)) {return false;}
	return true;
}

// -------------------- function to bind an event to an object ------------------------
function bindEvent(object, event, fnct, status)
{
	if (status) status=false;
	if (object.addEventListener)
	{	object.addEventListener(event, fnct, status);  }// for FF 
	else 
	{	object.attachEvent("on"+event, fnct);  }// for IE
}
function unload()
{
	map.destroy;
	OpenLayers.Event.observe(window, 'unload', OpenLayers.Event.unloadCache, false);
	GUnload();
}

function roundNumber(num, dec) 
{
	var result = Math.round(num*Math.pow(10,dec))/Math.pow(10,dec);
	return result;
}
//------------ check that the file of a certain extenstion type is already on server -------------------
function checkFileExists(checkFile, collPath, collExts)
{
	//alert('file = '+checkFile)
	//alert('path = '+collPath)
	//alert('ext = '+collExts)
	
	// get a directory list of files from server in XML
	getFolderList(collPath, collExts);
	// scan through the list of files
	var fileList = ajaxRequest.responseXML.getElementsByTagName("files");
	var fileNames = fileList[0].getElementsByTagName("file");
	for (var k=0; k<fileNames.length; k++)
	{
		var serverFile = fileNames[k].firstChild.nodeValue;
		var serverFilename = serverFile.split('.');				// strip off the extension
		if (checkFile == serverFilename[0]) {return true;}
	}
	return false;
}
// ----------- general routine to make a file copy ------------
function copyFile (oldFileName, fileName, path)
{
	//alert (oldFileName+" : "+fileName)
	var url  = "inc/copyfile.php";
	var query="?oldf="+oldFileName+"&newf="+fileName+"&path="+path;
	loadXml(url, query);
	return true;
}


// ----------- general routine to rename a file ------------
function renameFile (oldFileName, newFileName, path)
{
	//alert (newFileName+" >> "+oldFileName)
	var url  = "inc/renameFile.php";
	var params = "?oldFile="+oldFileName+"&newFile="+newFileName+"&path="+path;
	//alert (url+query)
	loadXml(url, params);
	return true;
}
//------------------ get the file size ------------------------
function fileSize(processFile)
{
	// check that file exists 
	var filesize = '';
	var params = '?file='+processFile;
	ajaxRequest = loadXml(applicationBase+'inc/FileSize.php', params, false);
	filesize = ajaxRequest.responseText;
	//alert('file size = '+filesize);
	return filesize;
}
// ----------- general routine to rename a file ------------
function renameFileText (oldFileName, newFileName, path)
{
	//alert (newFileName+" >> "+oldFileName)
	var url  = applicationBase+"inc/renameFile.php";
	var params="?oldFile="+oldFileName+"&newFile="+newFileName+"&path="+path;
	//alert (url+query)
	ajaxRequest = loadXml(url, params, false);
	fileRenamed = ajaxRequest.responseText;
	if (fileRenamed == 'true') {return true;}
	else {return false;}
}
function dumpData(X,Y,file)
{
	// convert to lat longs
	var p=[];
	for (var i=0; i<X.length ;i++ )
	{
		p[0] = allX[i];
		p[1] = allY[i];
		var point = google2geogs(p);
		p = decodePoint(point);
		X[i]=roundNumber(p[0], 6);
		Y[i]=roundNumber(p[1], 6) ;
	}
	
	// make sure array is a string
	var xstring = X.toString();
	var ystring = Y.toString();

	var query="?x="+xstring+"&y="+ystring+"&file="+file;
	var getFilesUrl = applicationBase+"inc/makeCoordListFile.php"; 	
	//alert(getFilesUrl+query);
	//create a new filesList.xml file on server (directory Listing)
	fetchXml(getFilesUrl, query, false, 'POST');	
}
// ----------- CF routine to replace a file with another ----------
function replaceFileCF(source, destination)
{
	// note must have "/inc/" as preceding part of file
	var url  = applicationBase+"cf/replacefile.cfm";
	var params="?source="+source+"&destination="+destination;
	//alert(">> "+url+params)
	ajaxRequest = loadXml(url, params, false);
	if(ajaxRequest.status == 200)
	{
		var status = ajaxRequest.responseXML.getElementsByTagName("status")[0].firstChild.nodeValue;
		//alert("replacefile.cfm return = "+status)
		if(status == 'false'){ return false;} else {return true;}
	}
	else{return false;}
}

//------------------ check if a file is present on server disk via text file ------------------------
function filePresent(processFile)
{
	// check that file exists
	//alert(processFile)
	var params = '?file='+processFile;
	ajaxRequest = loadXml(applicationBase+'inc/FileExistsText.php',params, false);
	var filePres = ajaxRequest.responseText;
	if (filePres == 'true') {return true;}
	else {return false;}
}

//------------------ check if a file is present on server disk via XML (not working) ------------------------
function filePresentXML(processFile)
{
	// check that file exists
	var filePresent = 'false';
	var params = '?file='+processFile;
	ajaxRequest = loadXml(applicationBase+'inc/FileExists.php',params, false);
	var files = ajaxRequest.responseXML.getElementsByTagName('Files');
	filePresent = files[0].getElementsByTagName('File')[0].firstChild.nodeValue;
	if (filePresent == 'true') {return true;}
	else {return false;}
}
//--------------------- get a list of files from the server ----------------------
function getFolderList(collPath, collExts)
{
	// set up for folder scan
	var filesList = "data/list"+new Date().getTime()+".xml";  // temporary file to hold the list
	var relPath = collPath.split(applicationBase);
	//alert(relPath)
	var query="?path=/"+relPath[1]+"&ext="+collExts+"&file="+filesList;
	//alert(query)
	var getFilesUrl = applicationBase+"inc/getfile_list.php"; 	
	
	//create a new filesList.xml file on server (directory Listing)
	if(!makeXml(getFilesUrl, query, false)) {alert ('Unable to make the XML file on the server'); return false;}
	
	// load the XML into the application DOM
	var query='';
	var filesLists = "inc/"+filesList;
	ajaxRequest = loadXml(filesLists, query, false);
	if(!ajaxRequest.responseXML.getElementsByTagName("files")) { alert ('Unable to return the XML file from the server'); return false;}
	
	// delete the temporary XML file listing on server
	deleteit(filesList);
	return true;
}

//------------ checks that a number is even ---------------//
function evenCheck (numb)
{
	var intNo = parseInt(numb);
	var rem = intNo/2;
	var diff =  Math.ceil(rem) - Math.floor(rem); 
	if (diff == 0)
	{ return true;	}
	else { return false;	}
}

//----------- checks if a value is numeric ---------------//
function checkNumeric(value)
{		
	//alert(value);
	var anum=/(^\d+$)|(^\d+\.\d+$)/	;	
	if (anum.test(value))			return true;		return false;  
}

//--------------Find a centroid of a polygon array ---------------------//
function findCentroid(vertices, area) 
{
	// this actual calculates the center of mass.
	var cx = 0;
	var cy = 0;
	var centroid = 0;
	var i, j, n = vertices.length;
	var factor = 0;

	// make sure the polygon closes
	 if (vertices[0].y == vertices[vertices.length - 1].y &&  vertices[0].x == vertices[vertices.length - 1].x) 
	{  // do nothing.	
	}
	 else 
	{
      // We must close the polygon by adding the first vertices to also be the last.
      vertices[vertices.length] = vertices[0];
	}
	
	// accumulate the geometry values
	for (i=0; i<n; i++) 
	{
      j = (i + 1) % n;
      factor = (vertices[i].y * vertices[j].x - vertices[j].y * vertices[i].x);           
      cx += (vertices[i].y + vertices[j].y) * factor;
      cy += (vertices[i].x + vertices[j].x) * factor;
	}
	area *= 6;
	factor = 1 / area;
	cx *= factor;
	cy *= factor;
 
	centroid = cy+","+cx;
	return centroid;
/*	
	if (cx < 0) 
	{	return new OpenLayers.LonLat(-cy, -cx);}
	else 
	{	return new OpenLayers.LonLat(cy, cx);}
*/
}
function getPolygonCentroid(X,Y)
{
	// make sure polygon closes
	if(X[length-1] == X[0] && Y[lenght-1] == Y[0])
	{	/* do nothing*/	}
	else {X[length]=X[0]; Y[length]=Y[0];}

	// loop through all points to get centroid
	var A = 0.0; var AX =0.0; var AY = 0.0;
	for(var j=0; j<Xlength ; j++)
	{	if(j == 0)
		{	X1 = X[j];	Y1 = Y[j];		}
		else
		{	
			X2 = X[j]; 	Y2 = Y[j];
			DA =  (X1 * Y2) - (X2 * Y1);
			A = A + DA;
			AX = AX + ((X1 + X2) * DA);
			AY = AY + ((Y1 + Y2) * DA);
			X1 = X2;
			Y1 = Y2;
		}
	}
	// calculate centroid for this region
	A = A * 0.5;
	BigA = A*6;
	centX = AX / BigA;
	centY = AY / BigA;

	return cenyX+","+centY;

}

//-------------------- Replaces all instances of the given substring --------------------
// useage: sqlExp[i] = sqlExp[i].replaceAll( oldAttribute, newAttribute )

String.prototype.replaceAll = function(	strTarget, 	strSubString )
{
	//alert(strTarget+"  >>  "+strSubString)
	
	var strText = this;
	strText = strText.toUpperCase();
	strTarget = strTarget.toUpperCase();
	strSubString = strSubString.toUpperCase();
	var intIndexOfMatch = strText.indexOf( strTarget );
	
	
	// Keep looping while an instance of the target string // still exists in the string.
	while (intIndexOfMatch != -1)
	{
		//alert(intIndexOfMatch)
		
		// Relace out the current instance.
		strText = strText.replace( strTarget, strSubString );
		 
		// Get the index of any next matching substring.
		intIndexOfMatch = strText.indexOf( strTarget );
	}
	 
	// Return the updated string with ALL the target strings
	// replaced out with the new substring.
	return strText;
}

// function to check for a CR to complete a data entry field
function checkEnter(e,id)
{
	var characterCode;
	if(e && e.which)
	{
		e = e;
		characterCode = e.which;
	}
	else
	{
		e = e;
		characterCode = e.keyCode;
	}
	// on carriage return trigger action
	if(characterCode == 13)
	{
		document.getElementById('search').value = document.getElementById(id).value;
		if(document.getElementById('search01')) {document.getElementById('search01').value = document.getElementById(id).value;}
//		document.getElementById('propertyButt').className="standardButton"	;
//		document.getElementById('propertyControl').title='show boundary at address';
		//alert('button changed?')
		lastAccuracy = -1;
		showAddress(country, 'geocoder', id, 'selector', 'selForm', 'selBox', 'messHolder', srs); 

	}
	
}
// function to check for a CR to complete a data entry field
function checkEnterAddress(e, newAddr)
{
	var characterCode;
	if(e && e.which)
	{
		e = e;
		characterCode = e.which;
	}
	else
	{
		e = e;
		characterCode = e.keyCode;
	}
	// on carriage return trigger action
	if(characterCode == 13)
	{
		//alert('new addr = '+newAddr)
		// geocode the new address
		geocoder.getLocations(newAddr, function (result)
		{ 
			// Only one in collection so plot it only
			var p = result.Placemark[0].Point.coordinates;
			var currentAccuracy = result.Placemark[0].AddressDetails.Accuracy;
			if(currentAccuracy >= 4)
			{// transform geogs to google if required
				if (srs == defaultSrs) 
				{	
					var point = geogs2google(p);
					p = decodePoint (point);
					baseCoords[0] = p[0];
					baseCoords[1] = p[1];
				}
				else
				{	baseCoords[0] = p[0];
					baseCoords[1] = p[1];
				}
				//alert(baseCoords)
				// create the vector marker for the territory Home location
				makeHomeMarker(true);
			}
			else{alert ('unable to geocode this new address - try again');}
			
		});
	}
	//showAddress(country, 'geocoder', id, 'selector', 'selForm', 'selBox', 'messHolder', srs); 
}
// function to check for an address entry with CR to complete a data entry field
function addrKeyboard(e, id)
{		
	var characterCode = null;
	if(e && e.which){	e = e;	characterCode = e.which	}
	else{e = e;	characterCode = e.keyCode	}
	if(characterCode == 32 || characterCode == 13 )
	{	
		geocodeAddress(country, 'geocoder', 'search', 'selectit', 'selForm2', 'selBox', '', srs, document.getElementById(id).value);
	}	
	else if(characterCode == 13 )
	{	
		//start = document.getElementById(id).value ;
		start ='';
		geocodeAddress(country, 'geocoder', 'search', 'selector', 'selForm', 'selBox', 'messHolder', srs, start)
	}
}

function checkEntry(e)
{	
	 var characterCode
	if(e && e.which)
	{	e = e
		characterCode = e.which
	}
	else
	{	e = event
		characterCode = e.keyCode
	}
	var value2 = document.getElementById('graphCols').value;
	if(value2.length == 1 && characterCode == 8) 
	{	document.getElementById('graphRadio').style.display='none';
		document.getElementById('refreshTitle').style.display='none';}
	else
	{	document.getElementById('graphRadio').style.display='block'; 
		document.getElementById('refreshTitle').style.display='block'; }
}

function checkEnterFile(e,  file)
{
	
	var characterCode
	if(e && e.which)
	{	e = e
		characterCode = e.which
	}
	else
	{	e = event
		characterCode = e.keyCode
	}	 
	if(characterCode == 13)
	{
		saveNewDrapeFile(file);
		return false
	}else { return true}
}

function checkEnterKeyword(e, keywordObj)
{
	var characterCode
	if(e && e.which)
	{	e = e
		characterCode = e.which
	}
	else
	{	e = event
		characterCode = e.keyCode
	}	 
	if(characterCode == 13)
	{		
		if(keywordObj.id == 'keyword')			{	findIt(keyword.value,  "searchResults"); return false;}
		else if(keywordObj.id == 'ddrapeWords')	{	setCheckBoxes(keywordObj.value); return false;}
		else { return true;}
	}
}

function progress(barId, amessage, complete)
{
	
	//alert('message = '+amessage+ '   percent = '+complete);
	var progressBarHolder = document.getElementById(barId);
	if(amessage == '')
	{	
		checkRemoveObject('indicatorText') ; 
		progressBarHolder.style.backgroundColor ='transparent';
		return;
	}
	
	// set up a text tag if first time and update as you go
	if(complete != '') {var newText = amessage+" "+complete+"%";}
	else {var newText = amessage;}
		
	// create a new Div and add new text
	//checkRemoveObject('indicText');
	checkRemoveObject('indicatorText') ;
	var progBar = document.createElement('div');
	progBar.id = 'indicatorText';
	progBar.setAttribute("id", 'indicatorText');
	var textNode = document.createTextNode(newText);	
		
	// position the text Div node inside progressBarHolder
	progBar.style.position='absolute';
	progBar.style.top='2px';
	progBar.style.left='6px';
	progBar.style.height='12px';
	progBar.style.width='90px';
	progBar.style.textAlign='center';
	progBar.style.backgroundColor='transparent';
	progBar.style.zIndex='2000';
	progBar.style.fontSize='10px';
	//progBar.style.border='1px solid red';
	progBar.appendChild(textNode);
	progressBarHolder.appendChild(progBar);
	progressBarHolder.style.textAlign='center';
	
	if(complete == ''){complete=100;}
	// update the file progress bar with complete which should be a % integer
	progressBarHolder.style.width = complete+'%';
	progressBarHolder.style.backgroundColor = '#FFFFD4';
	progressBarHolder.style.display = 'block';
	
}
// ------------ This will build a progress bar inside 'barId' to a percent 'complete' ---------------//
function progressBar(barId, amessage, complete)
{
	
	//alert('message = '+amessage+ '   percent = '+complete);
	var progressBarHolder = document.getElementById(barId);
	if(amessage == '')
	{	
		checkRemoveObject('indicatorText') ; 
		progressBarHolder.style.backgroundColor ='transparent';
		return;
	}
	
	// set up a text tag if first time and update as you go
	if(complete != '') {var newText = amessage+" "+complete+"%";}
	else {var newText = amessage;}
		
	// create a new Div and add new text
	//checkRemoveObject('indicText');
	checkRemoveObject('indicatorText') ;
	var progBar = document.createElement('div');
	progBar.id = 'indicatorText';
	progBar.setAttribute("id", 'indicatorText');
	var textNode = document.createTextNode(newText);	
		
	// position the text Div node inside progressBarHolder
	progBar.style.position='absolute';
	progBar.style.top='2px';
	progBar.style.left='6px';
	progBar.style.height='12px';
	progBar.style.width='90px';
	progBar.style.textAlign='center';
	progBar.style.backgroundColor='transparent';
	progBar.style.zIndex='1000';
	progBar.style.fontSize='10px';
	//progBar.style.border='1px solid red';
	progBar.appendChild(textNode);
	progressBarHolder.appendChild(progBar);
	progressBarHolder.style.textAlign='center';
	
	if(complete == ''){complete=100;}
	// update the file progress bar with complete which should be a % integer
	progressBarHolder.style.width = complete+'%';
	progressBarHolder.style.backgroundColor = '#FFFFD4';
	progressBarHolder.style.display = 'block';
	
}

// ------------------ function to check if object exists and if so remove it --------------------
function checkRemoveObject(oId)
{
	if (document.getElementById(oId))
	{	
		var obj = document.getElementById(oId);
		obj.parentNode.removeChild(obj);
		obj.value=null;
		return true;
	}
	return false;
}
	 
// ------------ This will build a vertical record pointer bar inside 'barId' to a percent 'complete' ---------------//
function recordNumber (barId, currPointer, totalNumber)
{
	
	// set up a text tag if first time and update as you go
	var progressBarHolder = document.getElementById(barId);
	var newText = 'Record Num '+currPointer;
	var complete = Math.ceil(parseInt(currPointer)/parseInt(totalNumber)*100);
	
		// create a new Div and add new text
		//checkRemoveObject('indicatorText') ;
		checkRemoveObject('indicText');
		var progressBar = document.createElement('div');
		progressBar.id = 'indicText';
		progressBar.setAttribute("id", 'indicText');
		var textNode = document.createTextNode(newText);	
			
		// position the text Div node inside progressBarHolder
		progressBar.style.position='absolute';
		progressBar.style.top='2px';
		//progressBar.style.left='6px';
		progressBar.style.height='12px';
		progressBar.style.width='90px';
		if(barId == 'progBar2'){progressBar.style.width='190px';}
		progressBar.style.backgroundColor='transparent';
		progressBar.style.zIndex='1000';
		progressBar.style.fontSize='10px';
		//progressBar.style.border='1px solid red';
		progressBar.appendChild(textNode);
		progressBarHolder.appendChild(progressBar);
		progressBarHolder.style.textAlign='center';
	
	// update the file progress bar with complete which should be a % integer
	
	progressBarHolder.style.width = complete+'%';
	progressBarHolder.style.maxWidth='93px';
	if(barId == 'progBar2'){progressBarHolder.style.maxWidth='196px';}
	//progressBarHolder.style.paddingRight='2px';
	progressBarHolder.style.backgroundColor = '#ECE9D8';
	progressBarHolder.style.borderRight = '2px solid gray';
	progressBarHolder.style.display = 'block';
}
// ------------- date stamp -----------
function getStamp()
{
	stamp = new Date().getTime();
	return stamp;
}

// ----------------- create a readout of the percentage on the slider bar ---------------------------
function showPercent(sliderPosition)
{
	var pos = document.getElementById('position');
	checkRemoveObject('posBox');
	var text = Math.round( 100 * sliderPosition ) ;
	var posBox = document.createElement('div')
	posBox.id='posBox';
	posBox.setAttribute('id','posBox');
	var postext=document.createTextNode(text);
	posBox.appendChild(postext);
	pos.appendChild(posBox);
}
// ----------------- mouse slider function --------------------
function moveFunction(sliderPosition) 
{
	// keep the slider bar iwth the mouse
	myslider.setPosition(sliderPosition);
	
	// echo the percentage position in a div - optional
	//showPercent(sliderPosition);
	if(DemoDrape)
	{
		// set the new opacity for the layer
		newOpacity = (parseFloat(sliderPosition)).toFixed(1);
		newOpacity = Math.min(maxOpacity, Math.max(minOpacity, newOpacity));
		DemoDrape.setOpacity(newOpacity);
	}

}
// ----------------- this fixes it after the mouse has stopped -------------------
function stopFunction(sliderPosition) 
{
	//do something with the position of the slider
	myslider.setPosition(sliderPosition);
		
	//all done, save last known position for purposes of disabling
	lastKnownPosition = sliderPosition;
	
	//Now apply the new opacity to the active legend
	//alert ('newOpacity= '+newOpacity)
	if (DemoDrape){legendBuilder("mapSurround", sldUrl, newOpacity, dvbdy1, dvhdr1, print, mode);}
	//buildLegend (sldUrl, legendBackground, legend, legendTitle, legendTable, legendBox, legendText, tdCell, newOpacity, dvbdy1, dvhdr1);
	//window.alert( 'The final position is ' + Math.round( 100 * sliderPosition ) + '%' );
}
// ----------------- Main slider function to be included in HTML where needed -----------------
function displayDrapeSlider(top, left, horiz, sliderBack)
{
	if(!horiz || horiz == null)
	{	// vertical slider
		var trkHt = 108;
		var trkWd = 19;
		var butHt = 5;
		var butWd = 17;
	}
	else
	{	// horizontal slider
		var trkHt = 19;
		var trkWd = 108;
		var butHt = 17;
		var butWd = 5;
	}
		
	// style controls of slider
	myslider = new slider(
		trkHt,				//height of track
		trkWd,				//width of track
		'transparent',		//colour of track
		0,					//thickness of track border
		'transparent',		//colour of track border
		0,					//thickness of runner (in the middle of the track)
		'#000000',			//colour of runner
		butHt,				//height of button
		butWd,				//width of button
		'#999999',			//colour of button
		1,					//thickness of button border (shaded to give 3D effect)
		'<span id=\"position\" style=\"font-size:8px; \" ><\/span>', //text of button (if any)
		horiz,				//direction of travel (true = horizontal, false = vertical)
		'moveFunction',		//the name of the function to execute as the slider moves
		'stopFunction',		//the name of the function to execute when the slider stops
							//the functions must have already been defined (or use null for none)
		true,				 //optional, false = use default cursor over button, true = use hand cursor
		sliderBack			// the src of the background Image to be used for slider
	);
		
	// Initialise slider
	lastKnownPosition=0.0;
	if (opacityValue){	lastKnownPosition = opacityValue;}
	myslider.setPosition(lastKnownPosition);
	//showPercent(lastKnownPosition);
	//document.write('</div>');
}
// ----------------- mouse slider function --------------------
function moveTerritoryFunction(sliderPosition2) 
{
	// keep the slider bar iwth the mouse
	terrSlider.setPosition(sliderPosition2);
	
	// echo the percentage position in a div - optional
	if(territory)
	{
		// set the new opacity for the layer
		newOpacity2 = (parseFloat(sliderPosition2)).toFixed(1);
		newOpacity2 = Math.min(maxOpacity, Math.max(minOpacity, newOpacity2));
		territory.setOpacity(newOpacity2);
	}
}
// ----------------- this fixes it after the mouse has stopped -------------------
function stopTerritoryFunction(sliderPosition2) 
{
	//do something with the position of the slider
	terrSlider.setPosition(sliderPosition2);
		
	//all done, save last known position for purposes of disabling
	lastKnownPosition2 = sliderPosition2;
	//alert(lastKnownPosition2)
}
// ----------------- Main slider function to be included in HTML where needed -----------------
function displayTerritorySlider(top, left, horiz, sliderBack)
{
	if(!horiz || horiz == null)
	{	// vertical slider
		var trkHt = 108;
		var trkWd = 19;
		var butHt = 5;
		var butWd = 17;
	}
	else
	{	// horizontal slider
		var trkHt = 19;
		var trkWd = 108;
		var butHt = 17;
		var butWd = 5;
	}
		
	// style controls of slider
	terrSlider = new slider(
		trkHt,				//height of track
		trkWd,				//width of track
		'transparent',		//colour of track
		0,					//thickness of track border
		'transparent',		//colour of track border
		0,					//thickness of runner (in the middle of the track)
		'#000000',			//colour of runner
		butHt,				//height of button
		butWd,				//width of button
		'#999999',			//colour of button
		1,					//thickness of button border (shaded to give 3D effect)
		'<span id=\"position\" style=\"font-size:8px; \" ><\/span>', //text of button (if any)
		horiz,				//direction of travel (true = horizontal, false = vertical)
		'moveTerritoryFunction',		//the name of the function to execute as the slider moves
		'stopTerritoryFunction',		//the name of the function to execute when the slider stops
							//the functions must have already been defined (or use null for none)
		true,				 //optional, false = use default cursor over button, true = use hand cursor
		sliderBack			// the src of the background Image to be used for slider
	);
		
	// Initialise slider
	//alert('opacity = '+opacityValue2)
	lastKnownPosition2 = 0.0;
	if (opacityValue2){	lastKnownPosition2 = opacityValue2;}
	terrSlider.setPosition(lastKnownPosition2);
	//showPercent(lastKnownPosition);
	//document.write('</div>');
}

function convertRBGtoHEX(rgbString)
{
	var rgbNumbs = rgbString.replace(/rgb/,'');
	var rgbNumbs = rgbNumbs.replace(/\(/,'');
	var rgbNumbs = rgbNumbs.replace(/\)/,'');
	var R = rgbNumbs.split(',')[0];
	var G = rgbNumbs.split(',')[1];
	var B = rgbNumbs.split(',')[2];
	var hex = RGBtoHex(R,G,B);
	return hex;

}
function RGBtoHex(R,G,B) 
{return toHex(R)+toHex(G)+toHex(B)}

function toHex(N) 
{
	 if (N==null) return "00";
	 N=parseInt(N); 
	 if (N==0 || isNaN(N)) return "00";
	 N=Math.max(0,N); 
	 N=Math.min(N,255); 
	 N=Math.round(N);
	 return "0123456789ABCDEF".charAt((N-N%16)/16)
		  + "0123456789ABCDEF".charAt(N%16);
}



// function to get cookie value from cookie name
function getCookies(searchName)
{
	var cookies = document.cookie.split(";")
	for (var i=0; i < cookies.lenght; i++);
	{
		var cookieCrumbs = cookies[i].split("=");
		var cookieName = cookieCrumbs[0];
		var cookieValue = cookieCrumbs[1];
		if (cookieName == searchName)
		{
			return cookieValue;		// I assume = true/false?
		}
	}
	return false;
}

function getThisId(evt)
{
	// cross browser tool to determine objects ID from an event trigger
	var e_out;
	var ie_var = "srcElement";
	var moz_var = "target";
	var prop_id = "id";
	// "target" for Mozilla, Netscape, Firefox et al. ; "srcElement" for IE
	evt[moz_var] ? e_out = evt[moz_var][prop_id] : e_out = evt[ie_var][prop_id];
	return e_out;
}
// random colour generator
function random_color(format)
{
	// format = 'hex' or 'rgb'
	var rint = Math.round(0xffffff * Math.random());
	switch(format)
	{
		case 'hex':
		return ('#0' + rint.toString(16)).replace(/^#0([0-9a-f]{6})$/i, '#$1');
		break;

		case 'rgb':
		return 'rgb(' + (rint >> 16) + ',' + (rint >> 8 & 255) + ',' + (rint & 255) + ')';
		break;

		default:
		return rint;
		break;
	}
}
function boundaryRequired()
{
	// first get the selected target polygon
	var pLayers='NONE';
	if(document.getElementById('polyLayers') )
	{
		var selectObject = document.getElementById('polyLayers');
		pLayers = selectObject.options[selectObject.selectedIndex].value;
	}
	return pLayers;
}

function textDisplay(targetId, text)
{
	if(targetId)
	{
		// generic function to stuff a text string (text) into the target Object defined by its ID (targetId)
		var drapeWindow = document.getElementById(targetId);
		checkRemoveObject('spanit');
		var span = document.createElement('span');
		span.id='spanit'; span.setAttribute('id','spanit');
		span.style.fontSize='10px';
		span.style.paddingLeft='3px';
		var textObj = document.createTextNode(text);
		span.appendChild(textObj);
		drapeWindow.appendChild(span);
		drapeWindow.value = text;
	}
}
function getListOfFiles(folder)
{
	// get list of files from the target folder
	var query="?path=inc/"+folder+"&time="+new Date().getTime(); // added the time stamp because IE caches this request
	var getFilesUrl = applicationBase+"inc/getXmlFiles.php"; 	
	ajaxRequest = loadXml(getFilesUrl, query, false);
	if(ajaxRequest.status !== 200){return 'error';}
	else {return ajaxRequest;}
}
// function to convert an input string so that the first letter of each word is a capital and all others are lowercase
function capitaliseIt(string)
{
	var nameParts = string.split(" ");
	if(nameParts.length > 1)
	{
		for (var i = 0; i<nameParts.length; i++)
		{
			if(i==0){var newName = stCap(nameParts[i]);}
			else { newName = newName+" "+stCap(nameParts[i]);}
		}
	}
	else
	{	var newName = stCap(nameParts[0]);	}
	return newName;
}

function stCap(strObj)
{	return(strObj.charAt(0).toUpperCase()+strObj.substr(1).toLowerCase());	}

function getCentreBbox(polyBounds)
{
	if(polyBounds)
	{
		var bboxVals = polyBounds.toBBOX(); 
		var bboxVals = bboxVals.split(",");
		var centX = (parseFloat(bboxVals[0]) + parseFloat(bboxVals[2]))/2;
		var centY = (parseFloat(bboxVals[1]) + parseFloat(bboxVals[3]))/2;
		return centX+","+centY;
	}
	else
	{
		return 'error';
	}
}
function bringToTop(layerObject)
{
	//map.Z_INDEX_BASE['Popup'] = 20000;
	if(layerObject)			
	{
		//alert('bringToTop zindex in = '+layerObject.getZIndex());
		layerObject.setZIndex(map.Z_INDEX_BASE['Popup']-10); 
		//alert('bringToTop zindex out = '+layerObject.getZIndex());
		layerObject.redraw();
	}
}
function getBboxOfView(zoom, srs)
{
	// if the user wants to see only for window then generate the smaller ozBox bounds
	var ozBoxGeog = [104.94141,  -44.96480,  180.0,  0.0] ;
	var pnt=[];
	if(!zoom) 
	{
		// get the bounds of the map window
		if (srs == "EPSG:900913")
		{
			// convert first point
			pnt[0] = map.getExtent().left;
			pnt[1] = map.getExtent().bottom;
			var point = google2geogs(pnt);
			loLeft = decodePoint(point);
			point1X = roundNumber(loLeft[0],8);
			point1Y = roundNumber(loLeft[1],8);

			// convert second point
			pnt[0] = map.getExtent().right;
			pnt[1] = map.getExtent().top;
			var point = google2geogs(pnt);
			hiRight = decodePoint(point);
			point2X = roundNumber(hiRight[0],8);
			point2Y = roundNumber(hiRight[1],8);

			// create a new ozBoxGeo
			ozBoxGeog = [point1X, point1Y, point2X, point2Y]
		}
		else
		{
			// create the geographicals version of the ozBoxGeo bound
			ozBoxGeog = [map.getExtent().left, map.getExtent().bottom, map.getExtent().right, map.getExtent().top]; 
		}
	}
	return ozBoxGeog;
}
function maskOtherPolygons(thisLayer, attName, attValue, maskColor, maskOpacity, borderColor, borderThickness)
{
	// this will build a temporary Mask layer called whatever the users pass through 'maskLayerName'
	// thisLayer is the base layer used to build the mask
	// attName is the attribute name as in the Database
	// attValue is the value of attName that is not masked out
	
	// remove all mask layers
	if(maskLayer)	{	maskLayer.destroy();	maskLayer = null;}
	if(polygonLayer){	polygonLayer.destroy(); polygonLayer = null;}
	if(labelLayer){	labelLayer.destroy(); labelLayer = null;}
	//alert('gone');

	// set rendering defaults
	if(maskColor == '' || maskColor == null){maskColor = "#FFFFFF";}
	if(maskOpacity == '' || maskOpacity == null){maskOpacity = 0.8;}
	if(borderColor == '' || borderColor == null){borderColor = "#ff0000";}
	if(borderThickness == '' || borderThickness == null){borderThickness = 7;}
	
	// build the sld_body string
	maskSld = "<StyledLayerDescriptor version='1.0.0' xmlns='http://www.opengis.net/sld'xmlns:sld='http://www.opengis.net/sld' xmlns:ogc='http://www.opengis.net/ogc'xmlns:xlink='http://www.w3.org/1999/xlink' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.opengis.net/sld http://schemas.cubewerx.com/schemas/sld/1.0.0-cw/StyledLayerDescriptor.xsd'>";
	maskSld+= "<NamedLayer><Name>"+thisLayer+"</Name><UserStyle><Name>Area boundaries</Name><Title>Areas</Title><FeatureTypeStyle>";
		maskSld+= "<Rule><Name>Masked Area</Name><Filter><SqlExpression>"+attName+" != '"+attValue+"'</SqlExpression></Filter><PolygonSymbolizer><Fill><CssParameter name='fill'>"+maskColor+"</CssParameter><CssParameter name='fill-opacity'>"+maskOpacity+"</CssParameter></Fill></PolygonSymbolizer></Rule>";
	maskSld+= "</FeatureTypeStyle></UserStyle></NamedLayer></StyledLayerDescriptor>";
	
	// create the Mask layer
	maskLayer = new OpenLayers.Layer.WMS( "Mask Layer", meshBlocksBase, { sld_Body: maskSld,  format: 'image/png', version:'1.1.3', quality: 'BEST', reaspect: false, transparent: true}, { tileSize: new OpenLayers.Size(512,512)});
	maskLayer.addOptions({isBaseLayer: false,  buffer:2, visibility: false, reproject:true});
	map.addLayer(maskLayer);
	maskLayer.setZIndex(map.Z_INDEX_BASE['Popup'] -4200);

	// build the sld_body string
	polySld = "<StyledLayerDescriptor version='1.0.0' xmlns='http://www.opengis.net/sld'xmlns:sld='http://www.opengis.net/sld' xmlns:ogc='http://www.opengis.net/ogc'xmlns:xlink='http://www.w3.org/1999/xlink' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.opengis.net/sld http://schemas.cubewerx.com/schemas/sld/1.0.0-cw/StyledLayerDescriptor.xsd'>";	
	polySld+= "<NamedLayer><Name>"+thisLayer+"</Name><UserStyle><Name>Area boundaries</Name><Title>Areas</Title><FeatureTypeStyle>";	
		polySld+= "<Rule><Name>Highlighted Area</Name><Filter><SqlExpression>"+attName+" = '"+attValue+"'</SqlExpression></Filter><PolygonSymbolizer><Fill><CssParameter name='fill'>transparent</CssParameter></Fill><Stroke><CssParameter name='stroke'>"+borderColor+"</CssParameter><CssParameter name='stroke-width'>"+borderThickness+"</CssParameter></Stroke></PolygonSymbolizer></Rule>";		
	polySld+= "</FeatureTypeStyle></UserStyle></NamedLayer></StyledLayerDescriptor>";

	// create the Polygon Highlight layer
	polygonLayer = new OpenLayers.Layer.WMS( "Polygon Layer", meshBlocksBase, { sld_Body: polySld,  format: 'image/png', version:'1.1.3', quality: 'BEST', reaspect: false, transparent: true}, { tileSize: new OpenLayers.Size(512,512)});
	polygonLayer.addOptions({isBaseLayer: false,  buffer:2, visibility: false, reproject:true});
	map.addLayer(polygonLayer);
	polygonLayer.setZIndex(map.Z_INDEX_BASE['Popup'] -4150);

	// build the sld_body string for label layer
	labelSld = "<StyledLayerDescriptor version='1.0.0' xmlns='http://www.opengis.net/sld'xmlns:sld='http://www.opengis.net/sld' xmlns:ogc='http://www.opengis.net/ogc'xmlns:xlink='http://www.w3.org/1999/xlink' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xsi:schemaLocation='http://www.opengis.net/sld http://schemas.cubewerx.com/schemas/sld/1.0.0-cw/StyledLayerDescriptor.xsd'>";	
	labelSld+= "<NamedLayer><Name>"+thisLayer+"</Name><UserStyle><Name>Area boundaries</Name><Title>Areas</Title><FeatureTypeStyle>";		
		labelSld+= "<Rule><Name>Highlighted Area</Name><Filter><SqlExpression>"+attName+" = '"+attValue+"'</SqlExpression></Filter><TextSymbolizer><Label><PropertyName>"+attName+"</PropertyName></Label><Font><CssParameter name='font-family'>Verdana</CssParameter><CssParameter name='font-size'>18</CssParameter></Font><Fill><CssParameter name='fill'>#000000</CssParameter></Fill><Halo><CssParameter name='fill'>"+borderColor+"</CssParameter></Halo></TextSymbolizer></Rule>";	
	labelSld+= "</FeatureTypeStyle></UserStyle></NamedLayer></StyledLayerDescriptor>";
		
	// create the Polygon Highlight layer
	labelLayer = new OpenLayers.Layer.WMS.Untiled( "Label Layer", meshBlocksBase, { sld_Body: labelSld,  format: 'image/png', version:'1.1.3', quality: 'BEST', reaspect: false, transparent: true}, { tileSize: new OpenLayers.Size(512,512)});
	labelLayer.addOptions({isBaseLayer: false,  buffer:2, visibility: false, reproject:true});
	map.addLayer(labelLayer);
	labelLayer.setZIndex(map.Z_INDEX_BASE['Popup'] -4150);

}

// functuion to determine if a point is inside or outside a polygon
function pointInPolygon(allX, allY, Xcoord, Ycoord, pBbox)
{
//-----------------------------------------------------------------------
// allX and allY are arrays containg polygon geometry
// Xcoord & Ycoord contains point to be tested
// pBbox contains a string of bounding box coords like loX+","+loY+" "+hiX+","+hiY;

// usage:
//       if(pointInPolygon(allX,allY, Xcoord, Ycoord, pBbox))
//		 returns true if point in polygon otherwise false
//-----------------------------------------------------------------------	
	// get the coordinates of testing line
	var hiRight= pBbox.split(' ')[1];
	var hiX = hiRight.split(',')[0];
	var x1 = parseFloat(Xcoord); 
	var y1 = parseFloat(Ycoord); 
	var x2 = parseFloat(hiX); 
	var y2 = parseFloat(Ycoord);
	var ints = 0;
	//alert('p1 = '+x1+", "+y1+'  p2 = '+x2+', '+y2)

	// for each line in the array test to see in there is an intersection with the test line
	for(var i=0; i<allX.length-1; i++)
	{
		// get coords of polygon side i+1
		var x3 = allX[i]; 
		var y3 = allY[i];
		var x4 = allX[i+1]; 
		var y4 = allY[i+1];

		var denom = ((y4-y3)*(x2-x1))-((x4-x3)*(y2-y1));
		var UaNum = ((x4-x3)*(y1-y3))-((y4-y3)*(x1-x3));
		var UbNum = ((x2-x1)*(y1-y3))-((y2-y1)*(x1-x3));
		
		if(denom != 0.0 && UbNum != 0.0 && UaNum != 0.0 )
		{
			var Ua = UaNum / denom;
			var Ub = UbNum / denom;

			if(Ua >= 0.0 && Ua <= 1.0 && Ub >= 0.0 && Ub <= 1.0)
			{
				ints=ints+1
				var newX = x1 + (Ua*(x2-x1));
				var newY = y1 + (Ua*(y2-y1));
			}
		}
	}
	// test to see if ints is odd or even number
	if(evenCheck(ints)){return false;}
	else{ return true;}
}
// ----------------- create a readout of the percentage on the slider bar ---------------------------
function showValue(sliderPosition, id)
{
	// calculate new value
	var delta = numaMax-numaMin;
	var offset = sliderPosition*delta;
	var text = Math.round(numaMin + offset);
	document.getElementById(id).value=text;
}
// ----------------- mouse slider function --------------------
function moveFunction1(sliderPosition1) 
{
	// keep the slider bar iwth the mouse
	myslider1.setPosition(sliderPosition1);
	
	// echo the percentage position in a div - optional
	showValue(sliderPosition1, 'loValue');
}
// ----------------- this fixes it after the mouse has stopped -------------------
function stopFunction1(sliderPosition1) 
{
	// only move slider in increments defind by steps
	var delta = numaMax-numaMin;
	var offset = sliderPosition1*delta;
	var text = Math.round(numaMin + offset);
	var nearestStep = Math.round(text/steps);
	nearestStep = nearestStep*steps;
	sliderPosition1 = (nearestStep-numaMax)/delta;

	// echo the percentage position in a div - optional
	showValue(sliderPosition1, 'loValue');
	
	//do something with the position of the slider
	myslider1.setPosition(sliderPosition1);
		
	//all done, save last known position for purposes of disabling
	lastKnownPosition1 = sliderPosition1;
}
// ----------------- mouse slider function --------------------
function moveFunction2(sliderPosition2) 
{
	// keep the slider bar iwth the mouse
	myslider2.setPosition(sliderPosition2);
	
	// echo the percentage position in a div - optional
	showValue(sliderPosition2, 'hiValue');
}
// ----------------- this fixes it after the mouse has stopped -------------------
function stopFunction2(sliderPosition2) 
{
	// only move slider in increments defind by steps
	var delta = numaMax-numaMin;
	var offset = sliderPosition2*delta;
	var text = Math.round(numaMin + offset);
	var nearestStep = Math.round(text/steps);
	nearestStep = nearestStep*steps;
	sliderPosition2 = (nearestStep-numaMax)/delta;

	// echo the percentage position in a div - optional
	showValue(sliderPosition2, 'hiValue');
		
	//do something with the position of the slider
	myslider2.setPosition(sliderPosition2);
		
	//all done, save last known position for purposes of disabling
	lastKnownPosition2 = sliderPosition2;
}
// ----------------- Mouse slider1 function to be included in HTML where needed -----------------
function displayDoubleSlider()
{
	// set some defaults
	var butHt = 17;
	var butWd = 5;
	var trkWd = 140;
	var trkHt = 4;
		
	// style controls of slider
	myslider1 = new slider(	
		4,					//width of track
		165,				//height of track
		"#D2D2D2",			//colour of track
		0,					//thickness of track border
		'transparent',		//colour of track border
		0,					//thickness of runner (in the middle of the track)
		'#000000',			//colour of runner
		12,				//height of button
		5,				//width of button
		'#999999',			//colour of button
		1,					//thickness of button border (shaded to give 3D effect)
		'<span id=\"position\" style=\"font-size:8px; \" ><\/span>', //text of button (if any)
		true,				//direction of travel (true = horizontal, false = vertical)
		'moveFunction1',		//the name of the function to execute as the slider moves
		'stopFunction1',		//the name of the function to execute when the slider stops
							//the functions must have already been defined (or use null for none)
		true,				 //optional, false = use default cursor over button, true = use hand cursor
		''					// the src of the background Image to be used for slider
	);

	// also create the second slider
	myslider2 = new slider(	
		-3,				//width of track
		165,				//height of track
		"#ff0000",			//colour of track
		0,					//thickness of track border
		'transparent',		//colour of track border
		0,					//thickness of runner (in the middle of the track)
		'transparent',			//colour of runner
		12,				//height of button
		5,				//width of button
		'#999999',			//colour of button
		1,					//thickness of button border (shaded to give 3D effect)
		'<span id=\"position\" style=\"font-size:8px; \" ><\/span>', //text of button (if any)
		true,				//direction of travel (true = horizontal, false = vertical)
		'moveFunction2',		//the name of the function to execute as the slider moves
		'stopFunction2',		//the name of the function to execute when the slider stops
							//the functions must have already been defined (or use null for none)
		true,				 //optional, false = use default cursor over button, true = use hand cursor
		''					// the src of the background Image to be used for slider
	);

	// Initialise first slider
	lastKnownPosition1 =0.0;
	myslider1.setPosition(lastKnownPosition1);
	showValue(lastKnownPosition1, 'loValue');
		
	// Initialise second slider
	lastKnownPosition2 = 1.0;
	myslider2.setPosition(lastKnownPosition2);
	showValue(lastKnownPosition2, 'hiValue');

}
function decodePoint(point)
{
	// this just puts the lon lats into the p array
	var p = [];
	p[0] = point.lon;
	p[1] = point.lat;
/*	
	//break the coordinate pair into its parts 
	var tmpLL = point.toString();
	var tempP = tmpLL.split(',');	
	// stuff parts into an array of [pX, pY] or [pLng, pLat]
	var p = [];
	var lng = tempP[0].split('='); p[0] = lng[1];
	var lat = tempP[1].split('='); p[1] = lat[1];
*/
	return p;
}
function geogs2google (p)
{
	// construct an openlayers object from input p array
	var lonlat = new OpenLayers.LonLat(p[0], p[1]);
	// use OL to reproject from geographicals to East North
	var point = lonlat.transform(new OpenLayers.Projection("EPSG:4326"), new OpenLayers.Projection("EPSG:900913"));
	return point;
}
function google2geogs (p)
{
	// construct an openlayers object from input p array
	var lonlat = new OpenLayers.LonLat(p[0], p[1]);
	// use OL to reproject from East Nort to geographicals
	var point = lonlat.transform(new OpenLayers.Projection("EPSG:900913"), new OpenLayers.Projection("EPSG:4326"));
	return point;
}
var originalWidth = window.outerWidth
var originalHeight = window.outerHeight

function setInner(width, height) {
    window.innerWidth = width
    window.innerHeight = height
}

function setOuter(width, height) {
    window.outerWidth = width
    window.outerHeight = height
}

function restore() {
    window.outerWidth = originalWidth
    window.outerHeight = originalHeight
}
