   	var mapbnds = new GLatLngBounds(); //Create an empty GLatLngBounds() object
	var gmarkers = [];
	gmarkers["single-list"]=[];
	var visiblecells=new Array();
    var lastlinkid;
	//Create an icon for clusters with different lat/lon's
	var iconClusterDiff = new GIcon();
	iconClusterDiff.image = "imgs/clusterdiff.png";
	iconClusterDiff.shadow = "imgs/cluster_shadow.png";
	iconClusterDiff.iconSize = new GSize(26, 25);
	iconClusterDiff.shadowSize = new GSize(22, 20);
	iconClusterDiff.iconAnchor = new GPoint(13, 25);
	iconClusterDiff.infoWindowAnchor = new GPoint(13, 1);
	iconClusterDiff.infoShadowAnchor = new GPoint(26, 13);
	
	//Create an icon for clusters with the same lat/lon
	var iconClusterSame = new GIcon();
	iconClusterSame.image = "imgs/clustersame.png";
	iconClusterSame.shadow = "imgs/cluster_shadow.png";
	iconClusterSame.iconSize = new GSize(26, 25);
	iconClusterSame.shadowSize = new GSize(22, 20);
	iconClusterSame.iconAnchor = new GPoint(13, 25);
	iconClusterSame.infoWindowAnchor = new GPoint(13, 1);
	iconClusterSame.infoShadowAnchor = new GPoint(26, 13);
	
	//create an icon for the single points
	var iconSingle = new GIcon();
	iconSingle.image = "imgs/single.png";
	iconSingle.shadow = "imgs/single_shadow.png";
	iconSingle.iconSize = new GSize(12, 20);
	iconSingle.shadowSize = new GSize(22, 20);
	iconSingle.iconAnchor = new GPoint(6, 20);
	iconSingle.infoWindowAnchor = new GPoint(6, 1);
	iconSingle.infoShadowAnchor = new GPoint(13, 13);	
	/*
	* Function to run on page load
	*/	
	function load() {
	 this.focus();
		if (GBrowserIsCompatible()) {
			document.getElementById('button-sidebar-hide').onclick = function() { return changeBodyClass('sidebar-right', 'nosidebar'); };
			document.getElementById('button-sidebar-show').onclick = function() { return changeBodyClass('nosidebar', 'sidebar-right'); };
			handleResize();//resize function for map
			
			var map = new GMap2(document.getElementById("map"));
			//var mtc = new MapTypeControl();
			//map.addControl(mtc);//custom map and graticule selector
			map.setCenter(new GLatLng(0,0),0); //Set the center to an empty GLatLng
			map.addControl(new GLargeMapControl()); //zoom/pan control in the top left of the map
			map.addMapType(G_PHYSICAL_MAP);
			
			var mapControl = new GHierarchicalMapTypeControl();
			
			// Set up map type menu relationships
			mapControl.clearRelationships();
			mapControl.addRelationship(G_SATELLITE_MAP, G_HYBRID_MAP, "Labels", false);
			
			// Add control after you've specified the relationships
			map.addControl(mapControl);
			
			map.setMapType(G_PHYSICAL_MAP); //set map type
			map.addControl(new GOverviewMapControl(new GSize(100,80))); //bottom right corner small map
			map.addControl(new GScaleControl());//bottom left scale  
			map.addControl(new MapCursorControl());//custom map and graticule selector
			map.addControl(new GZoomControl({nOpacity:.2, sBorder:"2px solid red"},{//zoom button middle left
				sButtonHTML:"<img src='imgs/zoombutton.gif' />",
				sButtonZoomingHTML:"<img src='imgs/zoombutton-activated.gif' />",
				oButtonStartingStyle:{width:'0px',height:'0px'}
			}), new GControlPosition(G_ANCHOR_TOP_LEFT,new GSize(10,285)));	
			mapbnds = new GLatLngBounds(sw,ne);//put bounds into a gmaps object 
			if(numrecs>1){
				map.setZoom(map.getBoundsZoomLevel(mapbnds));//set zoom with bounds
			}else{
				map.setZoom(8);// hardcode zoom? there has to be a better way....
			}
			//The center is calculated by taking the average latitude and longitude from opposite corners of the bounds.
			var centerlat = (mapbnds.getNorthEast().lat() + mapbnds.getSouthWest().lat()) /2;
			var centerlon = (mapbnds.getNorthEast().lng() + mapbnds.getSouthWest().lng()) /2;
			map.setCenter(new GLatLng(centerlat,centerlon));
			document.getElementById('zoomlevel').innerHTML = map.getZoom();
			resultsbygridcell['metadata']['zoomlevel']=map.getZoom();
			updateMarkers(resultsbygridcell, map);//draw all points on the map the first time we load the page
			
			//having two listeners often causes redraw to happen twice!!!!!!!!!!!!!!!!!!!!
			//so is zoomend really necessary?
			/*GEvent.addListener(map,'zoomend',function() {//update markers on map zoom
				visiblecells=findVisibleMarkers(resultsbygridcell, map);
				updateMarkers(visiblecells, map);
	
			});*/
		
			GEvent.addListener(map,'moveend',function() {//update markers on map move
				visiblecells=findVisibleRecords(resultsbygridcell, map);
				updateMarkers(visiblecells, map);
			});
		}
	}
	function changeBodyClass(from, to) {
		 document.body.className = document.body.className.replace(from, to);
		 return false;
	}
	/*
	* control map size in relation to browser window size
	*/	
	function windowHeight() {
		// Standard browsers (Mozilla, Safari, etc.)
		if (self.innerHeight)
			return self.innerHeight;
		// IE 6
		if (document.documentElement && document.documentElement.clientHeight)
			return document.documentElement.clientHeight;
		// IE 5
		if (document.body)
			return document.body.clientHeight;
		// Just in case.
		return 0;
	}
	function handleResize() {
		var height = windowHeight() - document.getElementById('toolbar').offsetHeight - 30;
		document.getElementById('map').style.height = height + 'px';
		document.getElementById('sidebar').style.height = height + 'px';
	}
	/*
	* opens and closes a sidebar item 
	*/
	function sidebarlisttoggle(linkid){//direct link from the sidebar
		if(linkid==lastlinkid){
			toggleList(linkid, 'close');
			lastlinkid=null;				
		}else{
			toggleList(lastlinkid, 'close');
			toggleList(linkid);
			lastlinkid=linkid;
		}
	}
	function toggleList(id, action){
		if(id){
			var arrayidsplit=id.split("_");
			if(arrayidsplit[0]=="single-list"){
				list = document.getElementById(arrayidsplit[0]);
				id=arrayidsplit[1];
				if(list){
					if (list.style.display=="none" && action!='close') {
						list.style.display="block"
						if(id){//click wasn't on the side panel single-list
							GEvent.trigger(gmarkers["single-list"][id], "mouseover");
							document.getElementById(id).style.background="#ffcc33";
						}
					} else if (list.style.display=="block"){
						list.style.display="none"
						if(id){//click wasn't on the side panel single-list
							GEvent.trigger(gmarkers["single-list"][id], "mouseout");
							document.getElementById(id).style.background="#e4dacc";
						}
					}
				}
			} else{
				list = document.getElementById(id)
				if(list){					
					if (list.style.display=="none" && action!='close') {
						list.style.display="block"
						GEvent.trigger(gmarkers[id], "mouseover");
					} else if (list.style.display=="block"){
						list.style.display="none"
						GEvent.trigger(gmarkers[id], "mouseout");
					}
				}
			}
		}
	}
	function hideDetail() {
		document.getElementById('detailbar').style.visibility = 'hidden';
		handleResize()
	}
	function showRecordDetail(fieldnum) {
		var detailbar = document.getElementById('detailbar');
		var height = windowHeight() - document.getElementById('toolbar').offsetHeight - 30;
		document.getElementById('map').style.height = height-75 + 'px';
		detailbar.style.height = '75px';
		detailbar.style.bottom = '-'+ height + 'px';
		detailbar.style.visibility = 'visible';
		document.getElementById('detail').innerHTML = fieldnum;
	}
	/*
	* Creates marker overlay to plot Single points and clustered cells
	*/
	function createMarker(point,infowindowhtml,linkid,icontype) {
		 if(icontype=='clusterdiff') {
			var marker = new GMarker(point,iconClusterDiff);
			GEvent.addListener(marker, "click", function() {
				marker.openInfoWindowHtml(infowindowhtml);		
				sidebarlisttoggle(linkid);	
			 });
			GEvent.addListener(marker,'mouseover',function(){
				marker.setImage("imgs/clusterdiffselected.png");
				document.getElementById("img_"+linkid).src="imgs/clusterdiffselected.png";
			});
			GEvent.addListener(marker,'mouseout',function(){
				if (document.getElementById(linkid).style.display=="none") {
					marker.setImage("imgs/clusterdiff.png");
					document.getElementById("img_"+linkid).src="imgs/clusterdiff.png";
				}
			});
			gmarkers[linkid] = marker;// save the info we need to use later for the side_bar
			return marker;
		}else if(icontype=='clustersame') {
			var marker = new GMarker(point,iconClusterSame);
				GEvent.addListener(marker, "click", function() {//click
				marker.openInfoWindowHtml(infowindowhtml);	
				sidebarlisttoggle(linkid);	
			 });
			GEvent.addListener(marker,'mouseover',function(){
				marker.setImage("imgs/clustersameselected.png");
				document.getElementById("img_"+linkid).src="imgs/clustersameselected.png";
			});
			GEvent.addListener(marker,'mouseout',function(){
				if (document.getElementById(linkid).style.display=="none") {
					marker.setImage("imgs/clustersame.png");
					document.getElementById("img_"+linkid).src="imgs/clustersame.png";
				}
			});
			gmarkers[linkid] = marker;// save the info we need to use later for the side_bar
			return marker;		
		} else { //plot a single point
			var marker = new GMarker(point,iconSingle);
			var id='single-list_'+linkid;
			GEvent.addListener(marker, "click", function() {
				marker.openInfoWindowHtml(infowindowhtml);
				sidebarlisttoggle('single-list_'+linkid);
			 });
			GEvent.addListener(marker,'mouseover',function(){
				marker.setImage("imgs/singleselected.png");
				document.getElementById("img_single").src="imgs/singleselected.png";
			});
			GEvent.addListener(marker,'mouseout',function(){
				//if (document.getElementById(linkid).style.background=="#e4dacc") {//hack need to change to class==selected
					marker.setImage("imgs/single.png");
					document.getElementById("img_single").src="imgs/single.png";
				//}
			});
			gmarkers["single-list"][linkid] = marker;// save the info we need to use later for the side_bar
			return marker;	
		}
	}	
	/*
	* Find visible cells and records in the current zoom
	*/
	function findVisibleRecords(cells, map) {
		visiblecells=[];
		visiblecells['metadata']=[];
		visiblecells['metadata']['markercounts']=[];	
		var currentzoom=map.getZoom();
		visiblecells['metadata']['zoomlevel']=currentzoom;
		if(currentzoom!=resultsbygridcell['metadata']['zoomlevel']){
				document.getElementById('zoomlevel').innerHTML = currentzoom;
		}
		var cellindex=0;
		var visiblenumrecs=0;
		var cellcounts=[];//index=>count (can't sort an associative array in javascript, jack has to hack hack hack)
		var cellcountskey=[];//index=>cellname (can't sort an associative array in javascript, jack has to hack hack hack)
		var mapbnds=map.getBounds();			
		for (cell in cells['metadata']['markercounts']) {
			var recordcount=0;
			var tempcell=cells[cell];
			for (record in tempcell['records']) {
				var lat = tempcell['records'][record]['data'].DecimalLatitude;
				var lon = tempcell['records'][record]['data'].DecimalLongitude;
				if(mapbnds.contains(new GLatLng(lat,lon))){//check if it is in the viewable area, it may not be when zoomed
					tempcell['records'][record].visible=true;
					recordcount++;
				}else{
					tempcell['records'][record].visible=false;
				}
			}
			if(recordcount!=0){
				tempcell['recordcount']=recordcount;
				cellcounts[cellindex]=recordcount;
				cellcountskey[cellindex]=cell;
				visiblenumrecs+=recordcount;
				visiblecells[cell]=tempcell
				cellindex++
			}
		}
		
		visiblecells['metadata']['numrecs']=visiblenumrecs;
		visiblecells['metadata']['markercounts']=sortCells(cellcounts, cellcountskey);
		//test2=visiblecells;
		return visiblecells;
	}
	function sortCells(cellcounts, cellcountskey){
		var finalcellcounts=[];//final associative array with cellname=>count
		cellcounts.sort(function(a,b){return b - a});//sort ascending (really)
		for (key in cellcounts) {
			//alert(cellcountskey[key]+', '+cellcounts[key]);
			finalcellcounts[cellcountskey[key]]=cellcounts[key];
		}
		return finalcellcounts
	}
	function addRecordToCell(record, celldata, tempcells){
		if(tempcells[celldata['cellname']]) {//cell exists in the tempcell array because a record has already been placed in it
			tempcells[celldata['cellname']]['records'].push(record);				
		}else{//first record in this cell add it to the grid cell array
			tempcells[celldata['cellname']]=[];
			tempcells[celldata['cellname']]['plotpoint']=[];
			tempcells[celldata['cellname']]['cellbounds']=celldata['bnds'];	
			tempcells[celldata['cellname']]['plotpoint']['lat']=0;
			tempcells[celldata['cellname']]['plotpoint']['lon']=0;
			tempcells[celldata['cellname']]['recordcount']=0;
			tempcells[celldata['cellname']]['clusteredrecords']=0;
			tempcells[celldata['cellname']]['clusters']=0;
			tempcells[celldata['cellname']]['markercount']=0;
			tempcells[celldata['cellname']]['records']=[];
			tempcells[celldata['cellname']]['records'].push(record);
			tempcells[celldata['cellname']]['originalcell']= celldata['originalcell']				
		}
		if(record['clustername']!=null){//cluster exists don't count the record as a marker add the name
			
			tempcells[celldata['cellname']]['clusteredrecords']++;
			if(!tempcells[celldata['cellname']]['clusters']){
				tempcells[celldata['cellname']]['clusters']=record['clustername'];								
			}
		}else{
			tempcells[celldata['cellname']]['recordcount']++;//increment recordcount
		}
		tempcells[celldata['cellname']]['plotpoint']['lat']+=parseFloat(record['data'].DecimalLatitude);//add together all latitude values for this cell
		tempcells[celldata['cellname']]['plotpoint']['lon']+=parseFloat(record['data'].DecimalLongitude);//add together all latitude values for this cell		
	}
	function quarterCells(cells) {
		var tempcellcounts=cells['metadata']['markercounts'];
		var cellindex=0;
		var cellcounts=[];
		var cellcountskey=[];
		var tempcells=[];
		tempcells['metadata']=cells['metadata'];
		tempcells['metadata']['markercounts']=null;
		tempcells['metadata']['markercounts']=[];
		for (cell in tempcellcounts) {
			var sw = cells[cell].cellbounds.sw;
			var ne = cells[cell].cellbounds.ne;
			var center = cells[cell].cellbounds.center;
			var celltopleft=[];
			celltopleft['bnds']=[];
			celltopleft['bnds']['sw']=[];
			celltopleft['bnds']['ne']=[];
			celltopleft['bnds']['center']=[];
			var celltopright=[]
			celltopright['bnds']=[]
			celltopright['bnds']['sw']=[];
			celltopright['bnds']['ne']=[];
			celltopright['bnds']['center']=[];
			var cellbottomleft=[]
			cellbottomleft['bnds']=[]
			cellbottomleft['bnds']['sw']=[];
			cellbottomleft['bnds']['ne']=[];
			cellbottomleft['bnds']['center']=[];
			var cellbottomright=[]
			cellbottomright['bnds']=[]
			cellbottomright['bnds']['sw']=[];
			cellbottomright['bnds']['ne']=[];
			cellbottomright['bnds']['center']=[];
			//top left cell
			celltopleft['bnds']['sw'].lat=center.lat;
			celltopleft['bnds']['sw'].lon=sw.lon;
			celltopleft['bnds']['ne'].lat=ne.lat;
			celltopleft['bnds']['ne'].lon=center.lon;
			celltopleft['bnds']['center'].lat=(center.lat+ne.lat)/2;
			celltopleft['bnds']['center'].lon=(sw.lon+center.lon)/2;
			celltopleft.bndsobj = new GLatLngBounds(new GLatLng(center.lat,sw.lon), new GLatLng(ne.lat,center.lon));
			celltopleft.cellname=center.lat+','+sw.lon+' '+ne.lat+','+center.lon;
			celltopleft.originalcell=cell;
			//top right cell
			celltopright['bnds']['sw'].lat=center.lat;
			celltopright['bnds']['sw'].lon=center.lon;
			celltopright['bnds']['ne'].lat=ne.lat;
			celltopright['bnds']['ne'].lon=ne.lon;
			celltopright['bnds']['center'].lat=(center.lat+ne.lat)/2;
			celltopright['bnds']['center'].lon=(center.lon+ne.lon)/2;
			celltopright.bndsobj = new GLatLngBounds(new GLatLng(center.lat,center.lon), new GLatLng(ne.lat,ne.lon));
			celltopright.cellname=center.lat+','+center.lon+' '+ne.lat+','+ne.lon;
			celltopright.originalcell=cell;
			//bottom left cell
			cellbottomleft['bnds']['sw'].lat=sw.lat;
			cellbottomleft['bnds']['sw'].lon=sw.lon;
			cellbottomleft['bnds']['ne'].lat=center.lat;
			cellbottomleft['bnds']['ne'].lon=center.lon;
			cellbottomleft['bnds']['center'].lat=(sw.lat+center.lat)/2;
			cellbottomleft['bnds']['center'].lon=(sw.lon+center.lon)/2;
			cellbottomleft.bndsobj = new GLatLngBounds(new GLatLng(sw.lat,sw.lon), new GLatLng(center.lat,center.lon));
			cellbottomleft.cellname=sw.lat+','+sw.lon+' '+center.lat+','+center.lon;
			cellbottomleft.originalcell=cell;
			//bottom right cell
			cellbottomright['bnds']['sw'].lat=sw.lat;
			cellbottomright['bnds']['sw'].lon=center.lon;
			cellbottomright['bnds']['ne'].lat=center.lat;
			cellbottomright['bnds']['ne'].lon=ne.lon;
			cellbottomright['bnds']['center'].lat=(sw.lat+center.lat)/2;
			cellbottomright['bnds']['center'].lon=(center.lon+ne.lon)/2;
			cellbottomright.bndsobj = new GLatLngBounds(new GLatLng(sw.lat,center.lon), new GLatLng(center.lat,ne.lon));
			cellbottomright.cellname=sw.lat+','+center.lon+' '+center.lat+','+ne.lon;
			cellbottomright.originalcell=cell;

			for (record in cells[cell]['records']) {//add each record to 1 of the 4 new cells
				if(cells[cell]['records'][record].visible==true){
					var lat = cells[cell]['records'][record]['data'].DecimalLatitude;
					var lon = cells[cell]['records'][record]['data'].DecimalLongitude;
					if(celltopleft['bndsobj'].contains(new GLatLng(lat,lon))){//check if it is in the top left cell
						var celldata=celltopleft
					}else if(celltopright['bndsobj'].contains(new GLatLng(lat,lon))){//check if it is in the top right cell
						var celldata=celltopright
					}else if(cellbottomleft['bndsobj'].contains(new GLatLng(lat,lon))){//check if it is in the bottom left cell
						var celldata=cellbottomleft
					}else if(cellbottomright['bndsobj'].contains(new GLatLng(lat,lon))){//check if it is in the bottom right cell
						var celldata=cellbottomright
					}else{
						//alert('error assigning visible record ('+record+') to quartered cell ('+cell+')');
					}
						addRecordToCell(cells[cell]['records'][record], celldata, tempcells);
				}
			}
		}
		for (cell in tempcells['metadata']['markercounts']) {//loop through the cell counts for sorting and averaging of values 
			//create two indexed arrays each holding half of the information in the cell count 
			cellcounts[cellindex]=tempcells['metadata']['markercounts'][cell];//index=>count (can't sort an associative array in javascript, jack has to hack hack hack)
			cellcountskey[cellindex]=cell;//index=>cellname (can't sort an associative array in javascript, jack has to hack hack hack)
			cellindex++
			 // divide the sum of the lats and lons by recordcount for an average plotpoint for the cell
			tempcells[cell]['plotpoint']['lat']=tempcells[cell]['plotpoint']['lat']/tempcells[cell]['recordcount'];
			tempcells[cell]['plotpoint']['lon']=tempcells[cell]['plotpoint']['lon']/tempcells[cell]['recordcount'];
			//
			var clustercount;
			var cluster=tempcells[celldata['cellname']]['clusters'];
			if(clusters>0){
				tempcells[cell]['clusteredrecords']+=clusters;//last record in clusters is not counted above add 1 for every cluster for total clustered records
				clustercount=tempcells[cell]['recordcount']-tempcells[cell]['clusteredrecords'];
				if(clustercount==0){clustercount=1;}//all records are clustered
			}else{
				clustercount=tempcells[cell]['recordcount'];//create an array of just cellname=>cellrecordcount
			}
			//tempcells['metadata']['markercounts'][$cellname]=$clustercount;
			tempcells[cell]['markercount']=clustercount;
			tempcells['metadata']['totalmarkers']+=clustercount;	
		}
		tempcells['metadata']['markercounts']=sortCells(cellcounts, cellcountskey);//sort the cells ascending by recordcount and assign them to markercounts
		return tempcells;
	}
	/*
	* Loop through visible cells and determine single points and clustered cells to be plotted
	*/
	function updateMarkers(visiblecells, map) {//update the markers for the visible cells on this map 
		map.clearOverlays();//remove the existing points, should this clear only points that are no longer visible?
		var loadzoom=resultsbygridcell['metadata']['zoomlevel'];
		var currentzoom=map.getZoom();
		//need to make the quarterCells function accept a number of cells and the visible cells (divideCells(visiblecells, 8))*/
		/*if(loadzoom+4<currentzoom){//1=>16
			visiblecells=quarterCells(visiblecells);
			visiblecells=quarterCells(visiblecells);
		}else if(loadzoom+2<currentzoom){//1=>4
			visiblecells=quarterCells(visiblecells);
		}*/
		var visiblenumrecs=visiblecells['metadata']['numrecs'];
		var remainingmarkers=visiblecells['metadata']['totalmarkers'];
		var markercounts=visiblecells['metadata']['markercounts'];
		var clustersSameLoc=[];
		var markersplotted=0;//counter for the number of markers plotted
		var sidepanelelements=[];
		document.getElementById("sidebar-list").innerHTML ='';
				
		for (cell in markercounts) {			
			var infowindowhtml;		
			remainingmarkers=remainingmarkers-markercounts[cell];
			if(remainingmarkers>50){//plot cluster marker with points having different locations until the number of records left to plot is less than max markersplotted
				PlotClusterDiffMarker(visiblecells[cell], sidepanelelements, map);
				markersplotted++;//increment markersplotted
			}else{//plot single markers and clustered same location markers when records left to plot is less than max markersplotted
				for (record in visiblecells[cell].records) {
					if(visiblecells[cell].records[record].clustername==null){// lat/lon does not have multiple points in the same location plot a single point
						if(visiblecells[cell].records[record].visible==true){//check if this record was  marked as being in the viewable area
							PlotSingleMarker(visiblecells[cell].records[record]['data'], sidepanelelements, map);
							markersplotted++;//increment markersplotted
						}
					}else{// plot cluster markers for markers with points having the same location
						if(visiblecells[cell].records[record].visible==true){//check if this record was in the viewable area
							AddtoClusterSameLoc(visiblecells[cell].records[record], clustersSameLoc);				
						}
					}
				} 					
			}
			remainingmarkers=remainingmarkers-markercounts[cell];
			/*if(markersplotted<50 || visiblecells[cell].recordcount==1){//plot single markers and clustered same location markers until reaching max markersplotted
				for (record in visiblecells[cell].records) {
					if(visiblecells[cell].records[record].clustername==null){// lat/lon does not have multiple points in the same location plot a single point
						if(visiblecells[cell].records[record].visible==true){//check if this record was  marked as being in the viewable area
							PlotSingleMarker(visiblecells[cell].records[record]['data'], sidepanelelements, map);
							markersplotted++;//increment markersplotted
						}
					}else{// plot cluster markers for markers with points having the same location
						if(visiblecells[cell].records[record].visible==true){//check if this record was in the viewable area
							AddtoClusterSameLoc(visiblecells[cell].records[record], clustersSameLoc);				
						}
					}
				} 					
			}else{//plot cluster marker with points having different locations after reaching max markersplotted
				PlotClusterDiffMarker(visiblecells[cell], sidepanelelements, map);
				markersplotted++;//increment markersplotted
			}*/
		}
		PlotClusterSameMarkers(clustersSameLoc, sidepanelelements, markersplotted, map);
		document.getElementById("visiblenumrecs").innerHTML = visiblenumrecs;//change the 'Showing: #' number to the current number of recs within map bounds
		document.getElementById("markers").innerHTML = markersplotted;//change the '(# markers)' number to the current number of recs within map bounds
	}
	function PlotSingleMarker(singlerecord, sidepanelelements, map) {//plots single markers
		if(!document.getElementById('single-list')){// check to see if this is the first single marker and add a <li>, the single-list <ul> and the clustersame <span>
			var singlemarker = document.createElement('li');
			var singlemarkerlink = singlemarker.appendChild(document.createElement('a'));
			singlemarkerlink.href = "javascript:sidebarlisttoggle(\'single-list\')"
			singlemarkerlink.innerHTML='<img id="img_single" src="imgs/single.png" alt="Single icon" style="width:6px; height:10px;" /> Single Points';
			var singlelist = singlemarker.appendChild(document.createElement('ul'));
			singlelist.id="single-list";
			singlelist.style.display="none";
			sidepanelelements['singles']=[];							
			document.getElementById('sidebar-list').appendChild(singlemarker);
			var clustersamespan = document.createElement('span');
			clustersamespan.id='clustersamespan'
			document.getElementById('sidebar-list').appendChild(clustersamespan);
		}
		var fieldnum=singlerecord.FieldNumber;
		var latitude=roundNumber(singlerecord.DecimalLatitude, 4);
		var longitude=roundNumber(singlerecord.DecimalLongitude, 4);
		var Collector=singlerecord.Collector;
		var Month=singlerecord.MonthCollected;
		var Day=singlerecord.DayCollected;
		var Year=singlerecord.YearCollected;
		var Genus=singlerecord.Genus;
		var Species=singlerecord.Species;
		var locality=singlerecord.Locality;
		infowindowhtml="<div style='font-size:small; width:200px'>";
		
		infowindowhtml += '<strong>'+fieldnum+'</strong>'; 
		infowindowhtml += ' <em>'+Genus+' '+Species+'</em><br />';
		infowindowhtml += Collector+'   '+Month+'/'+Day+'/'+Year+'<br />';
		infowindowhtml+= locality+' ('+latitude+', '+longitude+')<br />';
		infowindowhtml+='</div>';
		infowindowhtml+="<div style='font-size:small; width:200px'><a href='javascript:showRecordDetail("+fieldnum+")' style='float: right; text-align:right'>Show Detail</a></div>";
		var point = new GLatLng(latitude,longitude);
		var marker = createMarker(point,infowindowhtml, fieldnum,'single');

		var listItem = document.createElement('li');
		listItem.id=fieldnum;
		var listItemLink = listItem.appendChild(document.createElement('a'));
		listItemLink.href = "javascript:showRecordDetail("+fieldnum+")";
		listItem.onclick = function(){GEvent.trigger(gmarkers["single-list"][fieldnum], "click");};//function(){showRecordDetail(fieldnum)};
		//listItemLink.onmouseover=function(){GEvent.trigger(gmarkers["single-list"][fieldnum], "mouseover");};
		//listItemLink.onmouseout=function(){GEvent.trigger(gmarkers["single-list"][fieldnum], "mouseout");};
		listItemLink.innerHTML += '<strong>'+fieldnum+'</strong>'; 
		listItemLink.innerHTML += ' <em>'+Genus+' '+Species+'</em><br />';
		listItemLink.innerHTML += Collector+'   '+Month+'/'+Day+'/'+Year+'<br />';
		listItemLink.innerHTML += latitude+', '+longitude+'</span>';
		//listItemLink.innerHTML +="<span style='text-align:right' onclick='javascript:showRecordDetail("+fieldnum+")'>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Show Detail</span>";
		sidepanelelements['singles'][fieldnum]=listItem;
		document.getElementById('single-list').appendChild(listItem);
		map.addOverlay(marker);		
	}
	function AddtoClusterSameLoc(clusterrecord, clustersSameLoc) {	// adds clustered records at the same location to the temp array ClusterSameLoc
		var clustername = clusterrecord.clustername;
		if( typeof clustersSameLoc[cell] == 'undefined'){//first cluster for this cell
			var clusterlist = document.createElement('ul');
			clusterlist.id=cell+'-'+clustername;
			clusterlist.style.display="none";
			clustersSameLoc[cell] = [];
			clustersSameLoc[cell][clustername] = {
			plotpoint : new GLatLng(clusterrecord['data'].DecimalLatitude,clusterrecord['data'].DecimalLongitude),//is this being used? if it is should it be array(lat=,lon=)
			infowindowhtml:"",
			clustermarker:null,
			recordcount:0};
			clustersSameLoc[cell][clustername].clustermarker = clusterlist;
		}else if(typeof clustersSameLoc[cell][clustername] == 'undefined'){//already put a cluster in this cell but first record for this cluster
			var clusterlist = document.createElement('ul');
			clusterlist.id=cell+'-'+clustername;
			clusterlist.style.display="none";
			clustersSameLoc[cell][clustername] = {
			plotpoint : new GLatLng(clusterrecord['data'].DecimalLatitude,clusterrecord['data'].DecimalLongitude),//is this being used? if it is should it be array(lat=,lon=)
			infowindowhtml:"",
			clustermarker:null,
			recordcount:0};
			clustersSameLoc[cell][clustername].clustermarker = clusterlist;
		}
		var fieldnum=clusterrecord['data'].FieldNumber;
		var latitude=roundNumber(clusterrecord['data'].DecimalLatitude, 4);
		var longitude=roundNumber(clusterrecord['data'].DecimalLongitude, 4);
		var Collector=clusterrecord['data'].Collector;
		var Month=clusterrecord['data'].MonthCollected;
		var Day=clusterrecord['data'].DayCollected;
		var Year=clusterrecord['data'].YearCollected;
		var Genus=clusterrecord['data'].Genus;
		var Species=clusterrecord['data'].Species;
		var locality=clusterrecord['data'].Locality;
		var clusteritem = clustersSameLoc[cell][clustername].clustermarker.appendChild(document.createElement('li'));
		var clusteritemlink = clusteritem.appendChild(document.createElement('a'));
		
		clusteritemlink.innerHTML += '<strong>'+fieldnum+'</strong>'; 
		clusteritemlink.innerHTML += ' <em>'+Genus+' '+Species+'</em><br />';
		clusteritemlink.innerHTML += Collector+'   '+Month+'/'+Day+'/'+Year+'<br />';
		clusteritemlink.innerHTML += latitude+', '+longitude;
		clustersSameLoc[cell][clustername].recordcount++;
	}
	function PlotClusterDiffMarker(clustercell, sidepanelelements, map) {//plots cluster markers with points having different locations after reaching max markersplotted
		var textcolor = map.getCurrentMapType().getTextColor();//best color for writing on the map
		var sw = clustercell.cellbounds.sw;
		var ne = clustercell.cellbounds.ne;
		var cellbounds = (new GLatLngBounds(new GLatLng(sw.lat,sw.lon), new GLatLng(ne.lat,ne.lon)))
		infowindowhtml="<strong>"+clustercell.recordcount+" Records</strong> <br />Bounded by the coordinates: "+clustercell['cellbounds']['sw'].lat+", "+clustercell['cellbounds']['sw'].lon+" and "+clustercell['cellbounds']['ne'].lat+", "+clustercell['cellbounds']['ne'].lon+"<br />See Side Panel for details >>";
		var clustermarker = document.createElement('li');
		var clustermarkerlink = clustermarker.appendChild(document.createElement('a'));
		clustermarkerlink.href = 'javascript:sidebarlisttoggle(\''+cell+'\')'
		clustermarkerlink.innerHTML ='<img src="imgs/clusterdiff.png" id="img_'+cell+'" alt="Cluster icon 1" style="width:12px; height:13px;"/> '+clustercell.recordcount+' Clustered Records<br /> &nbsp;&nbsp;&nbsp;Bounded by the coordinates:<br />&nbsp;&nbsp;&nbsp;'+clustercell['cellbounds']['sw'].lat+', '+clustercell['cellbounds']['sw'].lon+' and '+clustercell['cellbounds']['ne'].lat+', '+clustercell['cellbounds']['ne'].lon;
		var clusterlist = clustermarker.appendChild(document.createElement('ul'));
		clusterlist.id=cell;
		clusterlist.style.display="none";
						
		for (record in clustercell.records) {//go through the records and add them to the sidebar and infowindow
			var fieldnum=clustercell.records[record]['data'].FieldNumber;
			var latitude=roundNumber(clustercell.records[record]['data'].DecimalLatitude, 4);
			var longitude=roundNumber(clustercell.records[record]['data'].DecimalLongitude, 4);
			var Collector=clustercell.records[record]['data'].Collector;
			var Month=clustercell.records[record]['data'].MonthCollected;
			var Day=clustercell.records[record]['data'].DayCollected;
			var Year=clustercell.records[record]['data'].YearCollected;
			var Genus=clustercell.records[record]['data'].Genus;
			var Species=clustercell.records[record]['data'].Species;
			var locality=clustercell.records[record]['data'].Locality;
			clusteritemlinkhtml='';
			//infowindowhtml=clustercell.records[record]['data'].FieldNumber+' ';
			var clusteritem = clusterlist.appendChild(document.createElement('li'));
			//clusteritem.class=cell;//ie doesn't like this
			var clusteritemlink = clusteritem.appendChild(document.createElement('a'));
			clusteritemlink.href = "javascript:showRecordDetail("+fieldnum+")";
			clusteritemlinkhtml += '<strong>'+fieldnum+'</strong>'; 
			clusteritemlinkhtml += ' <em>'+Genus+' '+Species+'</em><br />';
			clusteritemlinkhtml += Collector+'   '+Month+'/'+Day+'/'+Year+'<br />';
			clusteritemlinkhtml += latitude+', '+longitude;
			clusteritemlink.innerHTML=clusteritemlinkhtml;
		}
		infowindowhtml+='</div>'; 
		sidepanelelements[cell]=clustermarker;
		document.getElementById('sidebar-list').appendChild(clustermarker);
	 
		var plotpoint=new GLatLng((clustercell.plotpoint.lat),(clustercell.plotpoint.lon))
		var marker = createMarker(plotpoint,infowindowhtml, cell, 'clusterdiff');//					
		var cellboxhtml= "<span style='color:"+textcolor+"'>"+clustercell.recordcount+'</span>';//used to print the number of records cell contains	
		map.addOverlay(new Rectangle(cellbounds,plotpoint,1,textcolor,cellboxhtml));//used to mark cell boundaries
		map.addOverlay(marker);
	}
	function PlotClusterSameMarkers(clustersSameLoc, sidepanelelements, markersplotted, map) {// plots cluster markers for markers with points having the same location
		var textcolor = map.getCurrentMapType().getTextColor();//best color for writing on the map
		for (cell in clustersSameLoc) {
			for (cluster in clustersSameLoc[cell]) {
				var clusterbounds= new GLatLngBounds(clustersSameLoc[cell][cluster].plotpoint, clustersSameLoc[cell][cluster].plotpoint);//hack, bounds is a point
				var latitude=roundNumber(clustersSameLoc[cell][cluster].plotpoint.y, 4);
				var longitude=roundNumber(clustersSameLoc[cell][cluster].plotpoint.x, 4);
				infowindowhtml="<strong>"+clustersSameLoc[cell][cluster].recordcount+" Records </strong>"+clustersSameLoc[cell][cluster].infowindowhtml+"at this location ("+latitude+", "+longitude+")<br />See Side Panel for details >>";
				var marker = createMarker(clustersSameLoc[cell][cluster].plotpoint,infowindowhtml,cell+'-'+cluster,'clustersame');//
				var cellboxhtml= "<span style='color:"+textcolor+"'>"+clustersSameLoc[cell][cluster].recordcount+'</span>';//used to print the number of records cell contains
				map.addOverlay(new Rectangle(clusterbounds,clusterbounds,1,textcolor,cellboxhtml));//used to mark cell boundaries (actually a point in this case)
				var clustermarker = document.createElement('li');
				var clustermarkerlink = clustermarker.appendChild(document.createElement('a'));
				clustermarkerlink.href = 'javascript:sidebarlisttoggle(\''+cell+'-'+cluster+'\')'
				clustermarkerlink.innerHTML ='<img src="imgs/clustersame.png" id="img_'+cell+'-'+cluster+'" alt="Cluster Same location" style="width:12px; height:13px;"/> '+clustersSameLoc[cell][cluster].recordcount+' Clustered Records<br />&nbsp;&nbsp;&nbsp;Location: '+latitude+', '+longitude;				
				var clusterlist = clustermarker.appendChild(clustersSameLoc[cell][cluster].clustermarker);
				sidepanelelements[cell+'-'+cluster]=clustermarker;
				if(!document.getElementById('clustersamespan')){ //no single records we need to add the span to hold the list
					var clustersamespan = document.createElement('span');
					clustersamespan.id='clustersamespan'
					document.getElementById('sidebar-list').appendChild(clustersamespan);
				}
				document.getElementById('clustersamespan').appendChild(clustermarker);
				map.addOverlay(marker);
				markersplotted++;//increment markersplotted*/
			}	
		}
	}
	/*
	* Rectangle overlay to mark bounds of clustered cells
	*/
	function Rectangle(mapbnds, plotpoint, opt_weight, opt_color, opt_html) {
	  this.bounds_ = mapbnds; this.weight_ = opt_weight || 1; this.html_ = opt_html || ""; this.color_ = opt_color || "#888888";
	}
	Rectangle.prototype = new GOverlay();
	
	Rectangle.prototype.initialize = function(map) {
	  var div = document.createElement("div");
	  div.innerHTML = this.html_;
	  div.style.border = this.weight_ + "px solid " + this.color_;
	  div.style.position = "absolute";
	  map.getPane(G_MAP_MAP_PANE).appendChild(div);
	  this.map_ = map;
	  this.div_ = div;
	}
	Rectangle.prototype.remove = function() { this.div_.parentNode.removeChild(this.div_); }
	Rectangle.prototype.copy = function() { return new Rectangle(this.bounds_, this.weight_, this.color_, this.backgroundColor_, this.opacity_); }
	Rectangle.prototype.redraw = function(force) {
	  if (!force) return;
	  var c1 = this.map_.fromLatLngToDivPixel(this.bounds_.getSouthWest());
	  var c2 = this.map_.fromLatLngToDivPixel(this.bounds_.getNorthEast());
	  this.div_.style.width = Math.abs(c2.x - c1.x) + "px";
	  this.div_.style.height = Math.abs(c2.y - c1.y) + "px";
	  this.div_.style.left = (Math.min(c2.x, c1.x) - this.weight_) + "px";
	  this.div_.style.top = (Math.min(c2.y, c1.y) - this.weight_) + "px";
	} 
	/*
	* mouse cursor controls
	*/

	function fixedLlString(la,lo){
		
		var s = "N";
		var w = "E";
		if (la < 0){
			la = -la;
			s = "S";
			}
		if(lo < 0){
			lo = -lo;
			w = "W";
		}
			
		var lai = Math.floor(la);
		var laf = Math.round((la-lai)*1000000);
		var lais = lai.toString();
		while(lais.length < 2)
			lais = "0" + lais;
		var lafs = laf.toString();
		while(lafs.length < 6)
			lafs = "0" + lafs;
	
		var loi = Math.floor(lo);
		var lof = Math.round((lo-loi)*1000000);
		var lois = loi.toString();
		while(lois.length < 3)
			lois = "0" + lois;
		var lofs = lof.toString();
		while(lofs.length < 6)
			lofs = "0" + lofs;
	
		return lais + "." + lafs + s + ", " + lois + "." + lofs + w;
	}
	
	function MapCursorControl() {
	}
	MapCursorControl.prototype = new GControl();
	
	MapCursorControl.prototype.initialize = function(map) {
	
		  var container = document.createElement("div");
		  container.style.fontFamily='Arial';
		  container.style.fontSize='X-Small';
		  container.style.backgroundColor='rgb(254, 254, 254)';
		  container.id = "txtPtr";
		  
		  GEvent.addListener(map, "mousemove", function(point) {
				var ws; 
				ws = fixedLlString(point.lat(),point.lng()) + " (WGS84)  "; //6fig toString
				container.innerHTML = ws;	
		  });
	
		  map.getContainer().appendChild(container);
		  return container;
	
	}
	
	MapCursorControl.prototype.getDefaultPosition = function() {
	  return new GControlPosition(G_ANCHOR_BOTTOM_LEFT, new GSize(200, 2));
	}
	function roundNumber(number, decimalplaces) {
		if (number!=null & number!=''){
			   if (decimalplaces > 0) {
				  if ((number.toString().length - number.toString().lastIndexOf('.')) > (decimalplaces + 1)) {
					 var Rounder = Math.pow(10, decimalplaces);
					 return Math.round(number * Rounder) / Rounder;
				  }
				  else return number;
			   }
			   else return Math.round(number);
		}
		else return number;
	}
