//
//	Call from Body as: <body onload="loadMap(xmlMarkerFile, xmlPolygonFile, initLat, initLng, initZoom, initTitle)"   ....
//		xmlMarkerFile		- XML file with Markers
//		xmlPolygonFile		- XML file with Polygons
//		imagePath			- Path to Images
//		initLat				- Startup Latitude		(can overide in calling program - see function qs)
//		initLng				- Startup Longitude		(can overide in calling program - see function qs)
//		initZoom 			- Startup Zoom				(can overide in calling program - see function qs)
//		initTitle			- Title of popups			(can overide in calling program - see function qs)
//
//	Assumes:
//		- Zoom levels for
//			- markerManager: 10
//			- geoCoder: 13
//		

//
// Global variables
//

	var
		mapListProgram='../Map_Lists/Map_Lists.html',	// Adds the capability to link to another program to provide further details - see displayPolyMarker(a)
		mapListEnabled=true,									// Enable / Disable the link from the popup to an external webpage

		jFocus = 0,
		startList=0,												// The group number for Pulldown list items 
		startGroup=5,												// The group number for Pulldown list groups
		displayPolyNamesInit = false,	 						// Set True (False) to Display (Not Display) Polyline names on startup  
		toggleStateMarkersInit = false;						// Set True (False) to Display (Not Display) Markers on startup


		
	var 
		map, 
		mgr, 
		markers,
		mapTotalLength,
		mapDataLength,
		popupTitle,
		latStart, 
		lngStart, 
		zoomStart,
		thisImagePath,
		containsPolylines,
		containsMarkers,
		polyIcon,
		displayPolyNames,  
		toggleStateMarkers;

		
	var
		jFocus = 0,
		startList=0,								// The group number for Parishes
		startGroup=5,								// The group number for Counties
		displayPolyNamesInit = false,	 		// Set True (False) to Display (Not Display) Polyline names on startup  
		toggleStateMarkersInit = false;		// Set True (False) to Display (Not Display) Markers on startup
		
	var
		mapLat = new Array,
		mapLng = new Array,
		mapId = new Array,
		mapDescription = new Array,
		mapLocation = new Array,
		mapNotes = new Array,
		mapImageOwner = new Array,
		mapImageUrl = new Array,
		mapWebUrl = new Array,
		mapZoom = new Array,
		mapDisplay = new Array,
		mapMarker = new Array,
		qsParm = new Array(),

		
// The group names are read from the xml file and stored here
		numberOfGroups,					// Calculated
		groupName= new Array(),			// Contains list group types

		
// The polygon info is read and stored in these arrays		

		polyFillCol = new Array(),		// Fill Colour
		polyName = new Array(),			// Polygon Name
		polyLatAdj = new Array(),		//	Adjustment to Marker latitude position 
		ployLngAdj = new Array(),		//	Adjustment to Marker longitude position
		polyOutline = new Array(),		// Polygon outline? (n or the outline group it belongs to)
		polyGroup = new Array(),		// Polygon Group Name  - note 2d array (no. of polygons x number of groups) - from g0, g1 ...
		polyLineEnc = new Array(),		//	Encoded line data
		polyLineLev = new Array(),		// Encoded line data

// calculated data	
		polyBuilt = new Array();		// Polgon built? - used as the Polygons are built on the fly as they are first displayed - for speed reasons 	
		polyLat = new Array();			// Polygon Name Latitude - calculated from polygon center
		polyLng = new Array();			// Polygon Name Longitude - calculated from polygon center
		polyMarker = new Array();		// Polygon Marker
		polyLineDisp = new Array(),	// Polyline displayed? - stops duplicates being added 
		polyNameDisp = new Array(),	// Polyline name displayed? - stops duplicates being added 
		polyInfo = new Array();			// Polygon itself

		
// Create marker icon for Polygons
      polyIcon = new GIcon();
      polyIcon.shadow = "../Maps/Images/shadow.png";
      polyIcon.iconSize = new GSize(20, 34);
      polyIcon.shadowSize = new GSize(37, 34);
      polyIcon.iconAnchor = new GPoint(9, 34);
      polyIcon.infoWindowAnchor = new GPoint(9, 2);
		polyIcon.infoShadowAnchor = new GPoint(18, 25);
		polyIcon.transparent = "../Maps/Images/markerTransparent.png";


//
// read any parameters passed to the map:
//		Lat - if set center the map here (if Lat or Lng not set use initLat and initLng)
//		Lng - 
//		Zoom - at this Zoom level (if Zoom not set, uses initZoom)
//		Name - Name to display in popup
//  
//		call as (eg): <a class="mapLink" href="../Ballymaguigan/Ballymaguigan_Map.html?Lat=54.82808&Lng=-6.40778&Zoom=13&Name=Clooney Road" target="_blank">Clooney Road</a>
//
   function qs() 
	{
      var query = window.location.search.substring(1);
      var parms = query.split('&');
      for (var i=0; i<parms.length; i++) 
		{
         var pos = parms[i].indexOf('=');
         if (pos > 0) 
			{
            var key = parms[i].substring(0,pos);
            var val = parms[i].substring(pos+1);
	// As this is passed in the url spaces appear as %20. Firefox does not convert %20 to a space (IE does) so fix it now
            qsParm[key] = val.replace(/%20/," ");
         }
      }
   }

//
// Polygons -------------------------------
//
      

//
//	Build the pull down Select list
//
//		nameList contains the labels that are displayed in the list
//		actionList contains actions that go into the 'value' field  
//		select list must be called 'groupList'
//

//
//		Add Item to Array if it isn't aready in it
//
	function addUnique(addItem,addArray)
		{
			var inGroup=false;
			for (var c = 0; c < addArray.length; c++)
			{
				if (addItem==addArray[c])
				{
					var inGroup=true;
				}
			}
			if (!inGroup){addArray[c]=addItem}
		};

	function addItemToPulldownList(group,item,title)
	{
      opt=document.createElement("option");
      opt.setAttribute("value",item);
      opt.appendChild(document.createTextNode(item)); 
      opt.setAttribute("title",title);
      group.appendChild(opt);	
	}


	function buildPulldownLists()
	{
		buildGroupList()
		buildItemList()
	};
	

	function buildGroupList()
	{

		selectGroup=document.getElementById("groupSelect");

	//	Insert sub-heading
      addItemToPulldownList(selectGroup," .. Group by:",-1)
      addItemToPulldownList(selectGroup,"____________________",-1)

		for (var g = groupName.length-1; g>-1 ;g--)
		{
         addItemToPulldownList(selectGroup,groupName[g],g)
		}

	// Initial grouping
		gLevel=startGroup;
		iLevel=startList;	
	};
	
//
// Build a list of items of group "itemLevel" grouped by group "groupLevel"
//

	function buildItemList()
	{
		var groupByList = new Array();
		var itemList = new Array();
		var subName= new Array();

		if (gLevel>0)
		{
		// gLevel = 0 for parishes, this list has to be build differently
   	// build a sorted list of "gLevel" names
   		for (var g = 0; g < polyGroup[gLevel].length; g++)
   		{
   		// the string could contain several names seperated by "; "
   		
   			subName=polyGroup[gLevel][g].split("; ")
   
   			for (var n = 0 ; n < subName.length; n++)
   			{
   				addUnique(subName[n],groupByList);
   			}
   		}
   		groupByList=groupByList.sort();
   
   	// now build the form by extracting the "iLevel" names which have the "gLevel" name 
   
   			selectGroup=document.getElementById("groupList");
   
   	// Heading
            addItemToPulldownList(selectGroup," .. Select by "+groupName[gLevel]+":",-1);
            addItemToPulldownList(selectGroup,"",-1);
            addItemToPulldownList(selectGroup,"Clear All",-1);
   
   		for (var g = 0; g < groupByList.length; g++)
   		{
   			itemList.length=0;  // clear the list
   			for (var h = 0; h < polyGroup[iLevel].length; h++)
   			{
   
   				subName=polyGroup[gLevel][h].split("; ")
   								
      			for (var n = 0 ; n < subName.length; n++)
      			{
      				if (subName[n]==groupByList[g])
      				{
      					addUnique(polyGroup[iLevel][h],itemList)
      				}
   				}
   			}
   			itemList=itemList.sort();
   
   	//	Insert sub-heading
            addItemToPulldownList(selectGroup,"_________________________________",-1)
            addItemToPulldownList(selectGroup," .. "+groupName[iLevel]+" list for "+groupName[gLevel]+":",-1)
            addItemToPulldownList(selectGroup,groupByList[g],gLevel+"; "+groupByList[g])
            addItemToPulldownList(selectGroup,"------------",-1)
   
   	// Add list
      		for (var c = 0; c < itemList.length; c++)
      		{
   				addItemToPulldownList(selectGroup,itemList[c],iLevel+"; "+groupByList[g])
      		}
   		}
		}
		else
		{
		// gLevel = 0 for parishes, this list has to be build differently
			for (var h = 0; h < polyGroup[iLevel].length; h++)
			{

				subName=polyGroup[gLevel][h].split("; ")
								
   			for (var n = 0 ; n < subName.length; n++)
   			{
  					addUnique(polyGroup[iLevel][h],itemList)
				}
			}
  			itemList=itemList.sort();
   
	//	Insert sub-heading
         addItemToPulldownList(selectGroup," .. Select by "+groupName[gLevel]+":",-1);
         addItemToPulldownList(selectGroup,"",-1);
         addItemToPulldownList(selectGroup,"Clear All",-1);
         addItemToPulldownList(selectGroup,"_________________________________",-1)

	// Add list
   		for (var c = 0; c < itemList.length; c++)
   		{
				addItemToPulldownList(selectGroup,itemList[c],iLevel)
   		}

		
		
		}
	}	


	function clearItemList()
	{
		itemList=document.getElementById("groupList");

		for (i=itemList.options.length-1; i>-1 ;i--)
		{
			itemList.options[i] = null;
		}
	};


//
// Select Grouping of the Pulldown list
//		called from the pull down list
//
	function selectGrouping(selection) 
	{
		gLevel = selection.options[selection.selectedIndex].title;
		if(gLevel>-1)
		{
   		clearItemList();
   
   	// rebuild with new grouping
   		buildItemList()
		}
	}		


//
//		build the polygon from the encoded line data
//
//		and find the center location
//
	function buildPolygon(a)
	{
		if (!polyBuilt[a])
		{
   		var fillColour=polyFillCol[a];
   		var fill=true;
         if (fillColour=="") {fill = false};

		//
   	// Draw outline according to map type to increase contrast
		//    this doesn't work perfectly as the lines are built ones and even if Cleared ot Reset the colour etc is retained
		// 
      	if (map.getCurrentMapType()==G_NORMAL_MAP)
      	{
      		if (polyOutline[a]=="n")
				{
					lineColour= "#555555";
		    		lineWidth = 1.0;
				}
				else
				{
					lineColour= "#333333";
		    		lineWidth = 2.0;
				}
      	}
      	else
      	{
      		if (polyOutline[a]=="n")
				{
					lineColour= "#333333";
		    		lineWidth = 1.0;
				}
				else
				{
					lineColour= "#ffff00";
		    		lineWidth = 2.0;
				}
      	}
    		lineOpacity = 1.0;

   	// Fixed fill info
   		fillOpacity	= .25;
   
   	// Fixed data for encoded lines
   		lineNumber = 18;
   		lineZoom = 2;
   		
   		
         polyInfo[a]=new GPolygon.fromEncoded(
         {
            polylines:
            [{
               points:		polyLineEnc[a],
               levels:		polyLineLev[a],
               color:		lineColour,
               opacity:		lineOpacity,
               weight:		lineWidth,
               numLevels:	lineNumber,
               zoomFactor:	lineZoom
            }],
            fill: 		fill, 
            color:		fillColour, 
            opacity:		fillOpacity,
            outline:		true
         });
   		
   	//	Find the polygon's center and size
         var latTempC=polyInfo[a].getBounds().getCenter().lat(); 			//latitude of centre of rectangle containing polygon 
         var lngTempC=polyInfo[a].getBounds().getCenter().lng(); 			//longitude of centre of rectangle containing polygon 
         
         polyLat[a]=latTempC+polyLat[a];				//latitude of label position = center of the containing rectangle + latOffset (to adjust for odd shapes)
         polyLng[a]=lngTempC+polyLng[a]; 				//longitude of label position = center of the containing rectangle + lngOffset (to adjust for odd shapes)
			
// Recover some memory by clearing the original data
               polyLineEnc[a]=""
               polyLineLev[a]=""
					
		}
		polyBuilt[a]=true;
	};

	
//
//	The XML file containing Polylines has two formats for the lines: unencoded and encoded. Most of the data is common between the two formats:
//
//
//	Group Name, defined in the same order as the polygon groups g0, g1, g2 etc:
//		group - name of the g0 group
//		group - name of the g1 group
//			etc
//
//	Common data:
//
//		Fill:
//			fCol 						colour of fill
//			fOpa						opacity of fill
//
//		Label - this is automatically positioned in the center of the polygon: 
//			name						name of the polygon
//			nLat						latitude offset of the label from the automatic position
//			nLng						longitude offset of label
//
//		Outline: 
//			lCol 						colour of outline 
//			lWid 						width of outline
//			lOpa 						opacity of line
//
//		Group - each polygon can belong to a number of groups (eg a parish, barony, county etc)  
//			g0 to gn					name of the group
//			outline					if the polygon is an outline, this tells the program which group the outline belongs to
//										only used i 
//
//		Encoded lines  - the list of vertices is encoded and zoom extra controls to reduce resolution at low zoom levels
//							- see http://facstaff.unca.edu/mcmcclur/GoogleMaps/EncodePolyline/
//
//			lEnc						points: 
//											the string containing the compressed vertices
//			lLev						levels: 
//											the length of the levels string equals the number of points determining the path
//											the character in a particular position of the levels string tells us when the corresponding point from the points list should be plotted
//			lNum						numLevels: 
//											indicates how many different zoom levels are associated with the polyline, normally 18
//			lZom						zoomFactor:
//											the step in zoom between zoom levels, normally 2
//					eg if numLevels is 9, set zoomfactor to 4
//
//			Example:
//			  	<line fCol="#ff00ff" colourLine="#000000" width="1" name="Cranfield" nLat="0" nLng="0" outline="b" group="Cranfield"
//    		 	lEnc=" " lLev= " " lNum=" " lZom= " ">
//				</line>
//


	function readXMLLines(xmlLineFile)
	{
		GDownloadUrl(xmlLineFile , function(googleLines)
		{
      	var xmlLines = GXml.parse(googleLines);

	// Get the group names
			var groups =  xmlLines.documentElement.getElementsByTagName("group");
			for (var a = 0; a < groups.length; a++) 
         {
				groupName[a]= groups[a].getAttribute("name");
			}
			numberOfGroups=groupName.length;

		
	//	Create 2d array for the Group Names: polyGroup[numberOfGroups][numberOfItems]
	      for (i=0; i < numberOfGroups; i++) 
			{
				polyGroup[i]=new Array()
			}


	// Get the polygon info			
         lines = xmlLines.documentElement.getElementsByTagName("line");

			for (var a = 0; a < lines.length; a++) 
         {

	// Initflags
				polyLineDisp[a]=false;	// not displayed
				polyNameDisp[a]=false;	// not displayed
				polyBuilt[a]=false; 		// not built
	//
	// Get the Outline Flag which is either:
	//		n - if it is not an Outline or
	//		digit - for the group level of the Outline
	//
				polyOutline[a]=lines[a].getAttribute("outline");

	//
	// Get the Polygon group
	//	each polygon can belong to a number of groups: g0, g1 etc which are read from the XML file
	//
				for (var i = 0; i < numberOfGroups; i++)
				{
   				if (lines[a].getAttribute("g"+i)!="")
   				{
   					polyGroup[i][a]=lines[a].getAttribute("g"+i);
   				}
				}

	//	Save the marker position offset             
            polyLat[a] = parseFloat(lines[a].getAttribute("nLat"));
            polyLng[a] = parseFloat(lines[a].getAttribute("nLng"));

	// Polygon line information

				polyLineEnc[a] = lines[a].getAttribute("lEnc");
				polyLineLev[a] = lines[a].getAttribute("lLev");
				polyFillCol[a] = lines[a].getAttribute("fillCol"); 

				
	// Polygon name information
				polyName[a] = lines[a].getAttribute("name");
         }
			
// 			
//	The file has now been downloaded (remember that this is an async function
// The following will execute once polydata has been read:
//
   
	//	Build the pulldownlist		
			buildPulldownLists()

   //		to display a specific polygon or group of polygons (similar to clicking on an item in the pulldown)
   //			qName			- the name of the item(s) to be displayed
   //			qLevel		- the level of the item(s) to be displayed
   //			qGroupName	- the name of the group 
   //			qGroupLevel	- the level of the group - if absent or 0 all items of qName will be displayed 
	//			qIcon			- 'y' to show icons
	//
	//			the main difference to the pulldownlist is that by using qGroup items can be filtered more tahan the pulldown list.
	//			the pulldown only filters on qGroupLevel if qLevel=0.
	//			this method will filter all levels. 
	//

/*/ test stuff
	qsParm['qName']='Dungannon Upper'
	qsParm['qLevel']='2'
	qsParm['qGroupName']='Tyrone'
	qsParm['qGroupLevel']='5'
	qsParm['qIcon']='y'
//alert("Name: "+qsParm['qName']+"; Level: "+qsParm['qLevel']+"; Group name: "+qsParm['qGroupName']+"; Group level: "+qsParm['qGroupLevel']+"; Display Icon: "+qsParm['qIcon'])
*/

      	qName=qsParm['qName']
      	qLevel=qsParm['qLevel']
      	qGroupName=qsParm['qGroupName']
      	qGroupLevel=qsParm['qGroupLevel']
			qIcon=qsParm['qIcon']
//alert("Name: "+qName+"; Level: "+ qLevel +"; Group name: "+ qGroupName +"; Group level: "+ qGroupLevel+"; Display Icon: "+qIcon)

			if(qName==null || qName=='' || qLevel<0 || qLevel>groupName.length-1 || qLevel==null || qLevel=='')
			{
			}
			else
			{
      		if (qGroupLevel<0 || qGroupLevel>groupName.length-1 || qGroupLevel==null) 
      		{	
      			qGroupLevel=0
      		}

     			for (var a = 0; a < lines.length; a++) 
     			{

     				//Correct Group?
					// for level 0 the group doesn't matter so show all with matching nanes
					// otherwise match both the group and name
					if (qGroupLevel==0)
					{
						var inGroup=true;
					}
					else
					{
						var inGroup=(polyGroup[qGroupLevel][a].match(qGroupName)== qGroupName)?true: false
					}

      			subName=polyGroup[qLevel][a].split("; ")					
					
      			for (var n = 0 ; n < subName.length; n++)
      			{
						// Do the selected name and the selected group match?
	  					if (qName==subName[n] && inGroup)
						{
							displayPolyline(a);

            		// center map on polygon - if more than one it will point to the last one
   						if (polyOutline[a]!="n")
   						{
               			var point = new GLatLng(polyLat[a],polyLng[a]);
               			map.setCenter(point);
   						};

      			//Enable markers
     						polyNameDisp[a]=true;
   					}
					}
				}
				// Turn on markers only if requested
				if (qIcon=='y')
				{
					// Now turn on the markers, sort out the button text etc.
					changeButton(document.getElementById('Label'), togglePolyNames(), 'Icons On', 'Icons Off');
				}
			}
		});
	}

	
//
//	Display of polygon markers
//

//
// build polygon marker
//
	function createPolyMarker(marker,tableData,maxZoom,lab1,lab2)
	{
		GEvent.addListener(marker, "click", function() {marker.openInfoWindowHtml(tableData);});
		GEvent.addListener(marker, "dblclick", function() {marker.openInfoWindowHtml(tableData);});
      GEvent.addListener(marker, "mouseover", function() {showName(lab1,lab2); });
      GEvent.addListener(marker, "mouseout", function() {showName("","");});
		mgr.addMarker(marker,maxZoom);
	};


	function displayPolyMarker(a)
	{	
      var pIcon= new GIcon(polyIcon);
		var pType="";
      if (polyOutline[a]=="n") 
      {
      	pIcon.image = "../Maps/Images/iconT.png";
			pType="Townland";
      }
		else
      {
			// Icon shows first letter of Group Name
			var initLetter=groupName[polyOutline[a]].charAt(0);
   	   pIcon.image = "../Maps/Images/icon"+initLetter+".png";

			// Top of popup shows polgon Name and Group Name
			pType=groupName[polyOutline[a]];
      }
		
		var tableData=	
   	'<table class="mapStylePopup">'+
   		'<tr class="mapStyleHead">'+
    	   '<td colspan="2" class="mapStyleTB">'+polyName[a]+' '+pType
   
  		for (var i = 1; i < numberOfGroups; i++)
  		{
  			tableData=tableData+
  				'<tr>'+
     	   	'<td class="mapStyleCol1">'+groupName[i]+
     	      '<td class="mapStyleCol2">'+polyGroup[i][a]
  		}

	//
	//	create a link, passing it's name and all of it's group names as parameters  
	//
      if (polyOutline[a]!="n"&&mapListEnabled) 
      {
   		tableData=tableData+
           	'<tr>'+
        	   	'<td class="mapStyleCol1">Townland List'+
        	      '<td class="mapStyleCol2"><a href="'+mapListProgram+
					'?0='+polyGroup[0][a]

     		for (var i = 1; i < numberOfGroups; i++)
     		{
     			tableData=tableData+
     				'&'+i+'='+polyGroup[i][a]
     		}

   		tableData=tableData+
				'" target="_blank">'+polyName[a]+'</a>'
		}
		
		
		

		tableData=tableData+
        	'<tr>'+
  		      '<td colspan="2" class="mapStyleTB">&#169; 2007 Murray Lynn'+
           	'</tr>'+
        '</table>';
		if (polyOutline[a]=="n")
		{
			maxZoom=12;
		}
		else
		{
			maxZoom=9;
		};
		var point = new GLatLng(polyLat[a],polyLng[a]);
		polyMarker[a] = new GMarker(point,{icon:pIcon});

		infoName1=polyName[a]+' '+pType;
		if (polyOutline[a]=="n")
		{
			infoName2=groupName[0]+": "+polyGroup[0][a];
		}
		else
		{
			infoName2=groupName[gLevel]+": "+polyGroup[gLevel][a];
		}
		
		createPolyMarker(polyMarker[a], tableData, maxZoom, infoName1, infoName2);
	}
	
	
//
//	Remove a polygon marker
//
	function removePolyMarker(a)
	{	
		mgr.removeMarker(polyMarker[a]);
	}
		

//
//		Display Polygon
//
	function displayPolyline(a)
	{
		//Only display if not already on display, else doubles up
		if (!polyLineDisp[a]) 
      {
		//The polygon is built the first time it is displayed 		
			buildPolygon(a); 
      	map.addOverlay(polyInfo[a]);
	  		polyLineDisp[a]=true;

//
// It would be nice to change the colour of the polygon if the maptype changes, however this can't be done as the Polygon Outline Color is not accessible
// The code to detect the type looks like this: if (map.getCurrentMapType() == G_NORMAL_MAP){ alert("normal");}

  		}
	}

//
//		Remove Polygon
//
	function removePolyLine(a)
	{
		map.removeOverlay(polyInfo[a]);
	};
	

//
//	Turn on/off Polygon Icons
//		called by Icons on / off button
//
	function togglePolyNames()
	{	
      for (var a = 0; a < lines.length; a++) 
      {
		//Should the name be on? (don't change this flag here)
			if (polyNameDisp[a])
         {
	         if (displayPolyNames)
  		      {
					removePolyMarker(a);
        		}
      	   else
  	      	{
					displayPolyMarker(a);
      	   }
			}
		}
      displayPolyNames=!displayPolyNames;
		return displayPolyNames;
	}

//
// Turn on/off selected polygons
//		called from the pull down list
//
	function displayPolygons(selection) 
	{
		var selVal = selection.options[selection.selectedIndex].value;
		var polyCenter = false; // used to stop multiple recentering
		var subName= new Array();
		var listVal = selection.options[selection.selectedIndex].title;
		
		
	// Don't execute if there are no lines (as it is not necessary to load a line file)
		if (containsPolylines) 
		{
		// Clear: turn off lines and names unconditionally
      	if(selVal=="Clear All") 
			{   
            for (var a = 0; a < lines.length; a++) 
            {
         		if (polyLineDisp[a]) 
               {
						removePolyLine(a);
           		}
           		polyLineDisp[a]=false;

         		if (polyNameDisp[a] && displayPolyNames) 
               {
						removePolyMarker(a);
         		}
         		polyNameDisp[a]=false;
            }
			}
				
         else if (selVal=="all")
         { 
	  			for (var a = 0; a < lines.length; a++) 
     			{
					displayPolyline(a)					
					
			//Display makers only if it is not already displayed and polgon labels are enabled
  				  		if (!polyNameDisp[a])
           			{
	   			  		if (displayPolyNames)
   						{
   							displayPolyMarker(a);
   						}
   						polyNameDisp[a]=true;
   					}
   			}
			}

				
			else if (selVal=="")
			{
			}

			
			else if (listVal != -1)
			{
     			for (var a = 0; a < lines.length; a++) 
     			{
				// listVal is in the form: groupVal; groupName

					var groupSelected=listVal.split("; ")
					
     				//Correct Group?
					// for level 0 the group doesn't matter so show all with matching nanes
					// otherwise match both the group and name
					if (gLevel==0)
					{
						var inGroup=true;
					}
					else
					{
						var inGroup=(polyGroup[gLevel][a].match(groupSelected[1])== groupSelected[1])?true: false
					}

      			subName=polyGroup[groupSelected[0]][a].split("; ")					
					
      			for (var n = 0 ; n < subName.length; n++)
      			{
						// Do the selected name and the selected group match?
	  					if (selVal==subName[n] && inGroup)
						{
							displayPolyline(a);
   
            		// center map on polygon - but only if it is an outline and only for the first one
   						if (polyOutline[a]!="n" && !polyCenter)
   						{
               			var point = new GLatLng(polyLat[a],polyLng[a]);
               			map.setCenter(point);
   							polyCenter=true;
   						};
   
   				
      			//Display markers only if not already displayed and polygon labels are enabled
     				  		if (!polyNameDisp[a])
              			{
   	   			  		if (displayPolyNames)
      						{
      							displayPolyMarker(a);
      						}
      						polyNameDisp[a]=true;
      					}
						}
					}
  				}
      	}
		}
	}
	
	
// 
// Markers --------------------------------
//
	
//
// read the data from the XML file into array mapData, ignoring points whose lat/lng are not defined
//		
	function readXMLPoints(xmlDataFile)
	{
		GDownloadUrl(xmlDataFile , function(googleMap)
		{
      	var xmlMap = GXml.parse(googleMap);
         markers = xmlMap.documentElement.getElementsByTagName("Fields");
			var j=0; //count valid points

   	// Create marker icon
         var baseIcon = new GIcon();
         baseIcon.shadow = "../Maps/Images/shadow.png";
         baseIcon.iconSize = new GSize(20, 34);
         baseIcon.shadowSize = new GSize(37, 34);
         baseIcon.iconAnchor = new GPoint(9, 34);
         baseIcon.infoWindowAnchor = new GPoint(9, 2);
   		baseIcon.infoShadowAnchor = new GPoint(18, 25);
   		baseIcon.transparent = "../Maps/Images/markerTransparent.png";

			for (var i = 0; i < markers.length; i++) 
         {
				var lati=markers[i].getAttribute("Lat");
				var lngi=markers[i].getAttribute("Lng");

				if (lati!=null) //Ignore points whose positions aren't defined
				{
               mapLat[j] = parseFloat(lati);
               mapLng[j] = parseFloat(lngi);
   				mapId[j] = markers[i].getAttribute("ID");
	            if (mapId[j]==null) {mapId[j]=""}
					
               mapDescription[j] = markers[i].getAttribute("Description");
	            if (mapDescription[j]==null) {mapDescription[j]=""}
					
   				mapLocation[j] = markers[i].getAttribute("Location");
	            if (mapLocation[j]==null) {mapLocation[j]=""}
					
               mapNotes[j] = markers[i].getAttribute("Notes");
	            if (mapNotes[j]==null) {mapNotes[j]=""}

//	No need to save in array as it is saved later as a marker
					var mapIcon = markers[i].getAttribute("Icon");
//Catch undefined Icons - use Question Mark Icon.
					if (mapIcon==null) {mapIcon="Que"}
// Should also check here for non existent files but needs ActiveX   
					mapIcon="../Maps/Images/icon"+mapIcon+".png";

               mapImageOwner[j] = markers[i].getAttribute("ImageOwner");
               mapImageUrl[j] = markers[i].getAttribute("ImageURL");
               mapWebUrl[j] = markers[i].getAttribute("WebURL");
					mapZoom[j]= markers[i].getAttribute("Zoom");
	            if (mapZoom[j]==null) {mapZoom[j]=10} else {mapZoom[j]=parseFloat(mapZoom[j])};
					
//	Set all "ON" or "OFF" to start according to toggleStateMarkers
					if (toggleStateMarkers)
					{
						mapDisplay[j]= true;
					}
					else
					{
						mapDisplay[j]= false;
					}

					var cIcon= new GIcon(baseIcon);
					cIcon.image = mapIcon;
					
               var point = new GLatLng(mapLat[j],mapLng[j]);
               mapMarker[j]=  new GMarker(point,{icon:cIcon});
			
					j++;
				}
			}
	//	The file has now been downloaded (remember that this is an async function
	// The following code must be here to ensure data has been downloaded before it is executed
			mapTotalLength=j; //the total database size
			mapDataLength=j;  //the filtered database size
			displayData();	

	// if a Place parameter has been passed to the map, recenter there
		if (qsParm['Lat']==null||qsParm['Lng']==null) {	}
		else
		{
			if (qsParm['Zoom']==null){qsParm['Zoom']=zoomStart};
			qsParm['Zoom']=parseFloat(qsParm['Zoom']);
	      map.setCenter(new GLatLng(qsParm['Lat'], qsParm['Lng']), qsParm['Zoom']);		
	// put a marker here - only shows if no other marker
         point = new GLatLng(parseFloat(qsParm['Lat']), parseFloat(qsParm['Lng']));
         marker = new GMarker(point);
         map.addOverlay(marker);
			
			if (qsParm['Name']==null) {qsParm['Name']="Selected Location"} 

			var addressData=
				'<table class="mapStylePopup">'+
					'<tr class="mapStyleHead">'+
 		            '<td colspan="2" class="mapStyleTB">'+qsParm["Name"]+

					'<tr>'+
			   	   '<td class="mapStyleCol1">&#160;'+
      
            	'<tr>'+
		            '<td colspan="2" class="mapStyleTB">&#169; 2007 MPL'+
   
            	'</tr>'+
      		'</table>';
         marker.openInfoWindowHtml(addressData);
		}
		
		})
	};

	
   function createMarker(marker, point, zoom, tableData, lab1, lab2) 
   {
      GEvent.addListener(marker, "click", function() {marker.openInfoWindowHtml(tableData);});
      GEvent.addListener(marker, "dblclick", function() {map.setCenter(point,zoom); showNumZoom();});
      GEvent.addListener(marker, "mouseover", function() {showName(lab1,lab2); });
      GEvent.addListener(marker, "mouseout", function() {showName("","");});

      //Add Marker visible at level 9 & greater
      mgr.addMarker(marker,9);
   }

	function displayData()
	{
		var lat, lng, iHeight, thisImageUrl, thisWebUrl, compareText, filterText;
      for (var i = 0; i < mapLat.length; i++) 
		{
			if (mapDisplay[i])
			{
            
            thisLocation = mapLocation[i];
            thisNotes = mapNotes[i];
            thisImageOwner = mapImageOwner[i];
            if (thisImageOwner==null) 
            {
               thisImageOwner="";
               ILabel="&#160;";
            }
            else
            {
               thisImageOwner=thisImageOwner+'<br>';
               ILabel="Image&#160;by:";
            }
            
            thisImageUrl = mapImageUrl[i];
            if (thisImageUrl==null) 
            {
               thisImageUrl="Photo needed."
               iHeight=10;
            } 
            else 
            {
               thisImageUrl='<a href="'+thisImagePath+thisImageUrl+'" target="_blank"><img src="'+thisImagePath+thisImageUrl+'" height="150"></a><br>Click Photo to enlarge';
               iHeight=160;
					iWidth=500;
            }
         
            thisWebUrl = mapWebUrl[i];
         	if (thisWebUrl==null) 
         	{
         		thisWebUrl="";
         	}
         	else
         	{
         		thisWebUrl='<br><a href="'+thisWebUrl+'">Website</a>';
         	}

				tableData=	
   				'<table class="mapStylePopup">'+
   					'<tr class="mapStyleHead">'+
    		            '<td colspan="2" class="mapStyleTB">'+popupTitle+
   
   					'<tr>'+
   			   	   '<td class="mapStyleCol1">Place:'+
   			      	'<td class="mapStyleCol2">'+ mapDescription[i]+
   
   					'<tr>'+
   			   	   '<td class="mapStyleCol1">Location:'+
   			      	'<td class="mapStyleCol2">'+mapLocation[i]+
   
   					'<tr>'+
   			   	   '<td class="mapStyleCol1">Notes:'+
   			      	'<td class="mapStyleCol2">'+mapNotes[i]+
   
   					'<tr height="'+iHeight+'px">'+
   			      	'<td class="mapStyleCol1">'+ILabel+
   			   	   '<td class="mapStyleCol2">'+thisImageOwner+thisImageUrl+thisWebUrl+
   
               	'<tr>'+
   		            '<td colspan="2" class="mapStyleTB">&#169; 2007 MPL'+
   
               	'</tr>'+
         		'</table>';

				var point = new GLatLng(mapLat[i],mapLng[i]);
				var marker = mapMarker[i];
								
				createMarker(marker, point, mapZoom[i], tableData, mapDescription[i], mapLocation[i])

			}
			showNumZoom()		//show the Number of points and the Zoom level
	   }
	};
	

// Called to "Show" (showData=true) or "Add" (showData=false) points
	function filterData(filterText,showData)
	{
	//Clear the markers
      if (filterText!="") //if it is blank, do nothing
      {
			for (var i=0; i<mapMarker.length;i++)
			{
				mgr.removeMarker(mapMarker[i]);
			}

//   		mgr.clearMarkers();
   		mapDataLength=0; // count the number of icons displayed
         for (var i = 0; i < mapLat.length; i++) 
   		{
      		if (showData) // Clear display flag if it is Show
      		{
      			mapDisplay[i]=false;			
      		}
   			matchText= mapDescription[i] + mapLocation[i] + mapNotes[i];
   			filterText=filterText.toLowerCase();
   			matchText=matchText.toLowerCase();
   			if (matchText.match(filterText))
   			{
   				mapDisplay[i]=true;
   			}
   			if (mapDisplay[i])  //may already be set if adding
   			{
   				mapDataLength++;
   			}
   		}
			displayData();
		}
	};

	//Geocoder
	function addAddressToMap(response)
	{
      if (!response || response.Status.code != 200) 
		{
       	alert("Sorry, we were unable to geocode that address");
      } 
		else 
		{
         place = response.Placemark[0];
         point = new GLatLng(place.Point.coordinates[1],place.Point.coordinates[0]);
         marker = new GMarker(point);
         map.addOverlay(marker);
			var addressData=
				'<table class="mapStylePopup">'+
					'<tr class="mapStyleHead">'+
 		            '<td colspan="2" class="mapStyleTB">Search Results'+

					'<tr>'+
			   	   '<td class="mapStyleCol1">Place:'+
			      	'<td class="mapStyleCol2">'+ place.address+
      
					'<tr>'+
			   	   '<td class="mapStyleCol1">'+
			      	'<td class="mapStyleCol2">&#160;'+
      
					'<tr>'+
			   	   '<td class="mapStyleCol1">Lat, Lng:'+
			      	'<td class="mapStyleCol2">'+place.Point.coordinates[1]+', '+place.Point.coordinates[0]+
      
            	'<tr>'+
		            '<td colspan="2" class="mapStyleTB">&#169; 2007 MPL'+
   
            	'</tr>'+
      		'</table>';
         marker.openInfoWindowHtml(addressData);
      }
	}


	
   function showAddress(address) 
	{
		geocoder.getLocations(address, addAddressToMap);
  	}

	
	function showNumZoom()
	{
			var zoom=map.getZoom();
			var provIcons=mgr.getMarkerCount(6); //the number of icons displayed at level 6
			document.getElementById("mZoom").firstChild.nodeValue = zoom;
			document.getElementById("cCount").firstChild.nodeValue = mapDataLength;
	}

	function showName(lab1,lab2)
	{
		document.getElementById("Name1").firstChild.nodeValue = lab1;		
		document.getElementById("Name2").firstChild.nodeValue = lab2;		
	}
   
//
// < * > buttons:   		
// step = 0 -  go to first
// step = 1 -  go to next
// step = -1 - go to last
//
	function iFocus(step)
	{
		if (mapDataLength!=0)
		{
			loop=true;
			while (loop)
			{
   			if (step==0){jFocus=mapTotalLength-1; step=1;}; //fiddle to go to the start
            jFocus=jFocus+step;
            if (jFocus>mapTotalLength-1){jFocus=0};
            if (jFocus<0){jFocus=mapTotalLength-1};

				if (mapDisplay[jFocus]) 
				{
					loop=false;
				}
			}
	//center map on point
         map.setCenter(new GLatLng(mapLat[jFocus],mapLng[jFocus]),mapZoom[jFocus]);
			GEvent.trigger(mapMarker[jFocus], "click");
			showNumZoom();
		}		
		else
		{
		   alert("No data selected");
		}
	}
	
	function iHelp()
	{
		parent.location.href='#Help'; 
	}

	
	function iFilter(filterText, filterType) //show filtered markers - retain map zoom level
	{
		filterData(filterText,filterType);
	  	toggleStateMarkers = false;	 //changes the toggle state so next click shows all if it has been filtered		
		displayData();
		showNumZoom();				//show the Number of points and the Zoom level
		map.closeInfoWindow(); 	//to clear any open info windows 
	}
		
	function iMarkerToggle() //show all markers retaining map zoom level
	{
		// Clear all markers either way, otherwise it adds duplicates when restoring markers

			for (var i=0; i<mapMarker.length;i++)
			{
				mgr.removeMarker(mapMarker[i]);
			}

   	if (toggleStateMarkers) 
		{      
		  	toggleStateMarkers = false;	
     	} 
		else 
		{
         for (var i = 0; i < mapLat.length; i++) 
   		{
   			mapDisplay[i]=true;
   		}
   		mapDataLength=mapTotalLength;
   		displayData();
   		showNumZoom();				//show the Number of points and the Zoom level
   		map.closeInfoWindow(); 	//to clear any open info windows 
			toggleStateMarkers = true;
   	}
		return toggleStateMarkers;
	};


	function initialiseButton(flag,button,trueText,falseText)
	{
	//note: the button text is set to opposite of state
		if (flag)
		{
			button.value=falseText;
		}
		else
		{
			button.value=trueText;
		}
	}	

//
//******************************************* Change the Text on a button ******************************************************
//	called as: changeButton(document.getElementById('Marker'), currentstate , trueText, falseText);
//		where 
//			'Marker' is the id / name of the button
//			currentstate is true or false
//			trueText is shown when the state is false - ie if the state is off, the text would show: 'Turn On'
//
		
	function changeButton(button,state,trueText,falseText)
	{
	//note: the button text is set to opposite of state
		if (state)
		{
			button.value=falseText;
		}
		else
		{
			button.value=trueText;
		}
	}
		
	
	function mapReset() //reset map zoom level retaining current filters
	{
	//clear any search results
		map.clearOverlays();

	//recenter & rezoom
      map.setCenter(new GLatLng(latStart, lngStart), zoomStart);		

	//turn Markers on or off according to initial state
		toggleStateMarkers = !toggleStateMarkersInit;  				
		iMarkerToggle();

	//show the Number of points and the Zoom level
		showNumZoom();

	//to clear any open info windows
		map.closeInfoWindow();

 	//restore map type
		map.setMapType(G_NORMAL_MAP );
		
	//turn off Polgons and names
      for (var a = 0; a < lines.length; a++) 
      {
   		if (polyLineDisp[a]) 
         {
				removePolyLine(a);
     		}
     		polyLineDisp[a]=false;

   		if (polyNameDisp[a] && displayPolyNames) 
         {
				removePolyMarker(a);
   		}
   		polyNameDisp[a]=false;
      }

      displayPolyNames=displayPolyNamesInit;
		
	// NOTE - the button labels must be reset in the HTML code

	// Reset the pull down lists
		gLevel=startGroup;
		clearItemList();
		buildItemList();

	// Reset Forms otherwise the last entry is retained
		resetForms();	
	};
	

//
//	Reset the entry forms - otherwise it can keep the information there on next restart
//
	function resetForms()
	{	
      for (i=0; i < document.forms.length; i++) 
   	{
        document.forms[i].reset();
      }
	};
	

//Map Setup	

	function setupmap(xmlPointFile, xmlLineFile)
	{
     	map = new GMap2(document.getElementById("map"));
      
      map.addControl(new GLargeMapControl());
     	map.addControl(new GMapTypeControl());
      map.addControl(new GScaleControl(500));
      map.addControl(new GOverviewMapControl());

      geocoder = new GClientGeocoder();

/*
// create a local search control and add it to your map
      var lsc = new google.maps.LocalSearch(); 
      map.addControl(lsc);  
*/
        
      map.enableDoubleClickZoom();		  
      new GKeyboardHandler(map);
				
      map.setCenter(new GLatLng(latStart, lngStart), zoomStart);		
		
	// Add Div over map to show Lat & Lng of cursor, and other data
      var place = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(70,6));
      place.apply(document.getElementById("position"));
      map.getContainer().appendChild(document.getElementById("position"));
		
      mgr = new MarkerManager(map, {borderPadding: 10});
 
		containsMarkers=false;
		if (xmlPointFile!= '')
		{
			containsMarkers=true;
			readXMLPoints(xmlPointFile); // Fetch the Markers from the XML file - also must execute displayData() so it only occurs once the data has been downloaded.
		}
		 
	// Add listener to Track & Display Coords of Mouse

		GEvent.addListener(map, "mousemove", function(point)
		{
			document.getElementById("latpos").firstChild.nodeValue = point.y.toFixed(5);
			document.getElementById("lngpos").firstChild.nodeValue = point.x.toFixed(5);
			showNumZoom();		//show the Number of points and the Zoom level (picks up Zoom changes)
		});
		
	// Is there a Polyname file?
	// if so go get it
		
		containsPolylines=false;
		if (xmlLineFile!= '')
		{
			containsPolylines=true;
			readXMLLines(xmlLineFile);
		}
	}

	
//
//	In the HTML map program. call as body(0nload="loadMap(xmlPointFile, xmlLineFile, initLat, initLng, initZoom, initTitle)" ... )
//			xmlPointFile	- path from HTML file to XML file contaaining point data
//			xmlLineFile		- path from HTML file to XML file containing Polygon data (if empty use '')
//			initLat			- Startup Latitude
//			initLng			- Startup Longitude
//			initZoom 		- Startup Zoom
//			initTitle		- Title of popups
//
//	The HTML program calling the HTML map can also pass parameters, which overide the local calls, eg: 
//		<a class="mapLink" href="../Ballymaguigan/Ballymaguigan_Map.html?Lat=54.82808&Lng=-6.40778&Zoom=13&Name=Clooney Road" target="_blank">Clooney Road</a>
//
//		to center the map at a lat, lng:
//			Lat, Lng			- startup map center
//			Zoom 				- startup map zoom
//			Name				- the title of the initial popup box
//
//		to display a specific polygon or group of polygons (identical to clicking on an item in the pulldown)
//			qName			- the name of the item(s) to be displayed
//			qLevel		- the level of the item(s) to be displayed
//			qGroupName	- the name of the group
//			qGroupLevel	- the level of the group - if absent or 0 all items of qName will be displayed 
//			qIcon			- 'y' to turn on marker icons
//
	
   function loadMap(xmlPointFile, xmlLineFile, imagePath, initLat, initLng, initZoom, initTitle)
	{
      if (GBrowserIsCompatible()) 
		{
//
//		Import the extension for Google Maps to add labels 
//   <script src="../Maps/elabel.js" type="text/javascript"></script> 
//
//         var headID = document.getElementsByTagName("head")[0];         
//         var newScript = document.createElement('script');
//         newScript.type = 'text/javascript';
//         newScript.src = '../Maps/elabel.js';
//         headID.appendChild(newScript);

//
// reset forms else they retain last startup values
//			
			resetForms();

// 
//	initialise & read any parameters passed from html call
//
         qsParm.length=0;
         qs();
//
// and save javascript call parameters to global variables
//
			latStart=initLat;
			lngStart=initLng;
			zoomStart=initZoom;
			popupTitle=initTitle;
			thisImagePath=imagePath;

//
//		Get the initial display states of Markers & Polygons
//
			displayPolyNames = displayPolyNamesInit;	 		  
			toggleStateMarkers = toggleStateMarkersInit;

//
//		And now set up the map
//
			setupmap(xmlPointFile, xmlLineFile);


	   }
		else
		{
			alert("Sorry, your Browser does not support Google Maps");
		}
   }


