    var iconRootPath = 'http://idahopublichealth.com/wp-content/shared/icons/marker/';
	
	var iconBlue = new GIcon(); 
    iconBlue.image = 'http://labs.google.com/ridefinder/images/mm_20_blue.png';
    iconBlue.shadow = 'http://labs.google.com/ridefinder/images/mm_20_shadow.png';
    iconBlue.iconSize = new GSize(12, 20);
    iconBlue.shadowSize = new GSize(22, 20);
    iconBlue.iconAnchor = new GPoint(6, 20);
    iconBlue.infoWindowAnchor = new GPoint(5, 1);

    var iconGreen = new GIcon(); 
    iconGreen.image = 'http://labs.google.com/ridefinder/images/mm_20_green.png';
    iconGreen.shadow = 'http://labs.google.com/ridefinder/images/mm_20_shadow.png';
    iconGreen.iconSize = new GSize(12, 20);
    iconGreen.shadowSize = new GSize(22, 20);
    iconGreen.iconAnchor = new GPoint(6, 20);
    iconGreen.infoWindowAnchor = new GPoint(5, 1);

    var iconRed = new GIcon(); 
    iconRed.image = iconRootPath + 'largeTDRedIcons/blank.png';
    iconRed.shadow = 'http://labs.google.com/ridefinder/images/mm_20_shadow.png';
    iconRed.iconSize = new GSize(12, 20);
    iconRed.shadowSize = new GSize(22, 20);
    iconRed.iconAnchor = new GPoint(6, 20);
    iconRed.infoWindowAnchor = new GPoint(5, 1);

    var iconYellow = new GIcon(); 
    iconYellow.image = iconRootPath + 'largeTDYellowIcons/blank.png';
    iconYellow.shadow = 'http://labs.google.com/ridefinder/images/mm_20_shadow.png';
    iconYellow.iconSize = new GSize(12, 20);
    iconYellow.shadowSize = new GSize(22, 20);
    iconYellow.iconAnchor = new GPoint(6, 20);
    iconYellow.infoWindowAnchor = new GPoint(5, 1);

    var iconHeat = new GIcon(); 
    //iconHeat.image = iconRootPath + 'largeTDYellowIcons/blank.png';
    iconHeat.shadow = 'http://labs.google.com/ridefinder/images/mm_20_shadow.png';
    iconHeat.iconSize = new GSize(12, 20);
    iconHeat.shadowSize = new GSize(22, 20);
    iconHeat.iconAnchor = new GPoint(6, 20);
    iconHeat.infoWindowAnchor = new GPoint(5, 1);

    var iconHome = new GIcon(); 
    iconHome.image = 'http://idahopublichealth.com/wp-content/shared/logo.gif';
    //iconHome.shadow = 'http://labs.google.com/ridefinder/images/mm_20_shadow.png';
    iconHome.iconSize = new GSize(40, 40);
    iconHome.shadowSize = new GSize(22, 20);
    iconHome.iconAnchor = new GPoint(6, 20);
    iconHome.infoWindowAnchor = new GPoint(5, 1);

	var iconYuck = new GIcon(); 
    iconYuck.image = 'http://idahopublichealth.com/wp-content/shared/icons/mryuk.png';
    iconYuck.shadow = 'http://labs.google.com/ridefinder/images/mm_20_shadow.png';
    iconYuck.iconSize = new GSize(50, 50);
    iconYuck.shadowSize = new GSize(22, 20);
    iconYuck.iconAnchor = new GPoint(6, 20);
    iconYuck.infoWindowAnchor = new GPoint(5, 1);

    var customIcons = [];
    customIcons["clean"] = iconYellow;
	//customIcons["clean"] = iconGreen;
    customIcons["dirty"] = iconRed;
	customIcons["current"] = iconBlue;
	customIcons["home"] = iconHome;
	customIcons["yuck"] = iconYuck;
	customIcons["heat"] = iconHeat;
	

	// this variable will collect the html which will eventually be placed in the datagrid
	var item_list = "";
	
	// arrays to hold copies of the markers and html used by the datagrid
	// because the function closure trick doesnt work there
	var gmarkers = [];
	
	var lastId = 0;
	var lastlinkid = 0;
	var minX;
	var maxX;
	var minY;
	var maxY;
	var qstring;
	var map;
	var openThis = false;
	var searchType = '';
	
	var xmlData = "http://idahopublichealth.com/wp-content/service/food/mapxml.php";
	var xmlDetailData = "http://idahopublichealth.com/wp-content/service/food/detail-xml.php";
	var htmlHistoryData = "http://idahopublichealth.com/wp-content/service/food/detail.php";
	var estLink = "http://idahopublichealth.com/environment/food/inspection/";
	
	var htmlLoadingImage = '<img src="http://idahopublichealth.com/wp-content/shared/icons/loading/loading-circle-thick.gif" />';
	var img_recenter = "http://idahopublichealth.com/wp-content/shared/icons/silk/map_go.png";
	
	// This function picks up the click and opens the corresponding info window
	function myclick(i) {
		GEvent.trigger(gmarkers[i], "click");
	}

	function mymouseover(i) {
		GEvent.trigger(gmarkers[i], "mouseover");
	}

	function mymouseout(i) {
		GEvent.trigger(gmarkers[i], "mouseout");
	}
	
	function resetMap() {
		//map.setCenter(new GLatLng(46.417964, -117.020895), 16); // Lewiston
		//map.setCenter(new GLatLng(46.04917,-116.362724), 8); // Cottonwood
		map.setCenter(new GLatLng(46.274834,-116.49353), 8); // Craigmont
		map.setMapType(G_NORMAL_MAP);
		getSetData (xmlData + makeQString());
		closeHistory('history');
	}

	function centerMap(lat,lng) {
		closeHistory('history');
        map.setCenter(new GLatLng(lat,lng));
	}

    function load() {
      if (GBrowserIsCompatible()) {
	  	
		/* autosuggest search setup */
		var options = {
			script: xmlData + "?",
			varname: "s",
			json: false,
			maxresults: 10
		};
		var as = new bsn.AutoSuggest('sName', options);

		map = new GMap2(document.getElementById("map"));
        map.addControl(new GSmallMapControl());
        map.addControl(new GMapTypeControl());
		map.enableContinuousZoom();
		map.setCenter(new GLatLng(46.274834,-116.49353), 8); // Craigmont
		
		//alert (xmlData + makeQString());
		getSetData (xmlData + makeQString());

		GEvent.addListener(map,"infowindowclose", function() {
			document.getElementById(lastlinkid).style.background="transparent";
		});
		
		GEvent.addListener(map, "dragend", function() {
			var center = map.getCenter();
			if (searchType != 'single') {
				getSetData(xmlData + makeQString());
			}
		});

		GEvent.addListener(map, "dblclick", function() {
			var center = map.getCenter();
			if (searchType != 'single') {
				getSetData(xmlData + makeQString());
			}
		});

		GEvent.addListener(map, "zoomend", function() {
			var center = map.getCenter();
			if (searchType != 'single') {
				getSetData(xmlData + makeQString());
			}
		});

      }
    }
	
	function activateNearbyButton() {
		//Effect.Appear('shownearby', { duration: 1, from: 0.65, to: 1 });
		Effect.Appear('shownearbycontainer', { duration: 1, from: 0.65, to: 1 });
		//Effect.Highlight('shownearbycontainer', { startcolor: '#ffff99', endcolor: '#ffffff' });
		document.getElementById('shownearby').disabled = false;
		document.getElementById('shownearby').checked = false;
	}
	
	function deactivateNearbyButton() {
		//Effect.Fade('shownearby', { duration: 1, from: 1.0, to: 0.65 });
		Effect.Fade('shownearbycontainer', { duration: 1, from: 1.0, to: 0.65 });
		document.getElementById('shownearby').disabled = true;
		document.getElementById('shownearby').checked = true;
	}
	
	function getSearch () {
		searchType = 'single';
		getSetData (xmlData + makeQString('search'));
		activateNearbyButton();
	}
	
	function getSurrounding () {
		searchType = 'nearby';
		getSetData (xmlData + makeQString());
		deactivateNearbyButton();
	}

	// get the latitude and longitude bounds of the viewport
	function myGetBounds () {
		var bounds = map.getBounds();
		minX = bounds.getSouthWest().lat(); 
		minY = bounds.getSouthWest().lng(); 
		maxX = bounds.getNorthEast().lat();
		maxY = bounds.getNorthEast().lng();
	}
	
	// create a query string with lat and lng bounds
	function makeQString (type) {
		var qstring;
		
		switch (type) {
			/* get data by search */
			case 'search':
					qstring = '';
					qstring += '?s=' + document.getElementById("sName").value;
					qstring += '&c=' + document.getElementById("c").value;
					break;

			/* get data within map bounds */
			default : 
					myGetBounds();
					qstring = '?minX=' + minX;
					qstring += '&minY=' + minY;
					qstring += '&maxX=' + maxX;
					qstring += '&maxY=' + maxY;
					break;
		}
		return qstring;
	}

	/* this will get detailed inspection violation data */ 
	function getSetDetailData(id) {
		// if the history data portal is open
		if (document.getElementById("history").style.display == "block") {
			// also update history data
			getSetHistoryData(id);
		};

		url = xmlDetailData + '?id=' + id;
		document.getElementById("secondary").innerHTML='';
		document.getElementById("secondary").innerHTML=htmlLoadingImage;

		GDownloadUrl(url, 
		function(data) {
          var xml = GXml.parse(data);
          var violations = xml.documentElement.getElementsByTagName("violation");

		  var detailHead = '';
		  var detailHTML = '';
		  var detailFoot = '';
		  var detailPopup = '';
		  var lastInspection = '';
		  var thisInspection = '';

          for (var i = 0; i < violations.length; i++) {
            var insp_no = violations[i].getAttribute("insp_no");
            var name = violations[i].getAttribute("name");
            var address = violations[i].getAttribute("address");
            var city = violations[i].getAttribute("city");
            var state = violations[i].getAttribute("state");
            var zip = violations[i].getAttribute("zip");
            var score = violations[i].getAttribute("score");
            var score_high = violations[i].getAttribute("score_high");
            var score_non = violations[i].getAttribute("score_non");
            var i_date = violations[i].getAttribute("insp_date");
            var close_date = violations[i].getAttribute("close_date");
            var status_license = violations[i].getAttribute("status_license");
            var v_count = violations[i].getAttribute("v_count");
            var code = violations[i].getAttribute("description");
            var codeDescription = violations[i].getAttribute("code_description");
			var lat = parseFloat(violations[i].getAttribute("lat"));
			var lng = parseFloat(violations[i].getAttribute("lng"));
			//var point = new GLatLng(parseFloat(violations[i].getAttribute("lat")), parseFloat(violations[i].getAttribute("lng")));

			thisInspection = insp_no;
			
			if ((thisInspection != lastInspection) &&
				(lastInspection != '')) {break;}
			

			// if this is the first violation record
			if (i == 0) {
				detailHead = name + '<br />';
				detailHead += address + '<br />';
				detailHead += city + ', ' + state + ' ' + zip + ' <a style="cursor:pointer" onclick="centerMap(' + lat + ',' + lng + ')" title="Center Map on ' + name + '"><img src="' + img_recenter + '" border="0" /></a><br />' ;
				detailHead += "<a id=\"history_show\" onclick=\"getSetHistoryData('" + id + "');\">View inspection history</a><br />";
				
				if (close_date != '') {
					detailHead += '<b>Closed: ' + close_date + '</b><br />';	
				}

				if (status_license == 'S') {
					detailHead += '<b class="license_suspended">Permit Suspended</b><br />';	
				}

				detailHead += 'Inspected: ' + i_date + '<br />';
				
				detailFoot = '';
				
				// if there were violations
				if (code != '') {
					// set this to side bar HTML content
					detailHTML += '<li class="code" title="' + codeDescription + '" onclick="toggleDisplay(\'code' + i + '\');">';
					detailHTML += '<a >' + code + '</a>';
					detailHTML += '<div class="codeDescription" id="code' + i + '" style="display:none"><div>' + codeDescription + '</div></div>';
					detailHTML += '</li>';
				}
				// if no violations
				else {
					detailHead += 'No high risk violations.';
					detailHTML = '';
				}
			}
			else {
				// set this to side bar HTML content
				detailHTML += '<li class="code" title="' + codeDescription + '" onclick="toggleDisplay(\'code' + i + '\');">';
				detailHTML += '<a >' + code + '</a>';
				detailHTML += '<div class="codeDescription" id="code' + i + '" style="display:none"><div>' + codeDescription + '</div></div>';
				detailHTML += '</li>';
			}
			lastInspection = insp_no;
          }
		  
		if (detailHTML != "") {
			detailHTML = '<ul id="food_violations">' + detailHTML + '</ul>';
		}

		var myHTML = detailHead + detailHTML + detailFoot + detailPopup;
		document.getElementById("secondary").innerHTML=myHTML;
        });
	}
	
	/* this will get detailed inspection violation data */ 
	function getSetHistoryData(id) {
		url = htmlHistoryData + '?id=' + id;
		el = document.getElementById("history");
		el_data = document.getElementById("history_data");
		el_data.innerHTML = '<div style="width:100; margin: 20px auto;" align="center">' + htmlLoadingImage + '</div>';
		el.style.display = "block";
		
		GDownloadUrl(url, 
		function(data) {
			el_data.innerHTML = data;
        });
	}
	

	function getSetData(url) {
		GDownloadUrl(url, 
		function(data) {
          var xml = GXml.parse(data);
		  
		  // if we actually got data
		  if (xml.documentElement) {
		  
		  	var markers = xml.documentElement.getElementsByTagName("marker");
		  	var bounds = new GLatLngBounds(); // for dynamic zoom levels
			map.clearOverlays(); // remove markers from map
			gmarkers = []; // clear out marker list
			var marker = createHomeMarker();
			map.addOverlay(marker);
			
			item_list = '';
			
			for (var i = 0; i < markers.length; i++) {
				var name = markers[i].getAttribute("name");
				var address = markers[i].getAttribute("address");
				var city = markers[i].getAttribute("city");
				var state = markers[i].getAttribute("state");
				var zip = markers[i].getAttribute("zip");
				var type = markers[i].getAttribute("type");
				var id = markers[i].getAttribute("id");
				var score = markers[i].getAttribute("score");
				var score_high = markers[i].getAttribute("score_high");
				var score_non = markers[i].getAttribute("score_non");
   				var i_date = markers[i].getAttribute("i_date");
				var point = new GLatLng(parseFloat(markers[i].getAttribute("lat")), parseFloat(markers[i].getAttribute("lng")));
				// use heat map
				type = 'heat';
				
				marker = createMarker(point, name, address, type, id, score, score_high, score_non, i_date);
				map.addOverlay(marker);
				
				var tooltip = new Tooltip(marker, decodeHTMLentities(name), 4);
				marker.tooltip = tooltip;
				map.addOverlay(tooltip);
				
				if (searchType == 'single') {
				//map.setCenter(point);
				//searchType = '';
				}
				
				bounds.extend(point); // for dynamic zoom levels
				if (openThis) 
					GEvent.trigger(gmarkers[gmarkers.length - 1], "click");
			}
			
			if (searchType == 'single') {
				if (markers.length == 1) {
					map.setZoom(16);
					map.setCenter(bounds.getCenter()); // for dynamic zoom levels
				}
				else if (markers.length > 1) {
					map.setZoom(map.getBoundsZoomLevel(bounds)); // fit zoom level to all points
				}
			}
			
			// put the assembled table contents into the datagrid div
			tableHead = '<table colspacing="0"><tr id="thead"><th class="index"><!-- &#35; --></th><th class="name">Name</th><th class="address">Address</th>';
			tableHead += '<th class="score">High <br/>Risk <br/>Violations</th><th>Non <br/>Critical<br/>Violations</th></tr>';
			tableFoot = '</table>';
			message = '';
			
			if (markers.length == 50) {
				message = '<tr><td colspan="5"></td></tr>';
				message += '<tr><td></td><td colspan="4">';
				message += 'There are too many establishments to fit on the map, please zoom in or refine your query. You may also <a style="display:inline; clear: both;" href="http://idahopublichealth.com/environment/food/establishments/">browse by city</a>. ';
				message += '</td></tr>';
				item_list = '';
			}
			
			document.getElementById("items").innerHTML = tableHead + item_list + message + tableFoot;
		}
        });
	}
	
	function createHomeMarker () {
		var point = new GLatLng(46.418064, -117.020495);
		var marker = new GMarker(point, customIcons['home']);
		return marker;
	}
	
    function createMarker(point, name, address, type, id, score, score_high, score_non, i_date) {
		
		// use score-based icon
		var heatScore = score;
		var heatScoreText = score;
		if (score > 9) {heatScore = 9; heatScoreText = '9+'}
		
		iconHeat.image = iconRootPath + 'heatmapIcons/marker' + heatScore + '.png';
		
		var opts = {icon:customIcons[type],id:'marker'+id};
		var marker = new GMarker(point, opts);
		
		var linkid = "link" + id;
		var html = "<b>" + name + "</b> <br/>";
		html += address + "<br/>";
		html += 'Last Inspection: ' + i_date + '<br/>';
		html += '<a href="' + estLink + '?id=' + id + '" class="' + type + '">Violation Count: ' + score + '</a>' ;

		if (lastId == id) openThis = true; else openThis = false;
		openThis = false;

		GEvent.addListener(marker, 'click', function() {
			getSetDetailData(id);
			// also update history data
			getSetHistoryData(id);

			marker.setImage(customIcons["current"].image);
			document.getElementById("secondary").style.display = 'block'; 
			document.getElementById("current_score").innerHTML = heatScoreText;
			document.getElementById("current_score").style.display = 'block';
			
			// position the heat marker
			var heatRangeWidth = 55; 
			var heatMarkerWidth = 53;
			var heatMarkerLeft = Math.ceil((heatRangeWidth - heatMarkerWidth) / 2) -1;   
			var marginHeat = heatMarkerLeft + (parseInt(heatScore) * heatRangeWidth);
			var scoreDiv = document.getElementById("current_score");
			new Effect.Move(scoreDiv, { x: marginHeat, y: 0, mode: 'absolute' });
 
			lastId = id;
			lastlinkid=linkid;
		});

		GEvent.addListener(marker, 'mouseover', function() {
			marker.setImage(customIcons["current"].image);
			this.tooltip.show();
		});

		GEvent.addListener(marker, 'mouseout', function() {
			marker.setImage(iconRootPath + 'heatmapIcons/marker' + heatScore + '.png');
			this.tooltip.hide(); 
		});

		// save the info we need to use later for the datagrid
			gmarkers.push(marker);
		
		var lat = marker.getLatLng().lat();
		var lng = marker.getLatLng().lng();
		
		// add a line to the datagrid html
		item_list += '<tr class="datarow" id="'+linkid+'" onclick="javascript:myclick(' + (gmarkers.length-1) + ')" onmouseover="javascript:mymouseover(' + (gmarkers.length-1) + ')" onmouseout="javascript:mymouseout(' + (gmarkers.length-1) + ')" ondblclick="centerMap(' + lat + ',' + lng + ')" title="Center Map on ' + name + '">';
		//item_list += ' <a style="cursor:pointer" onclick="centerMap(' + lat + ',' + lng + ')" title="Center Map on ' + name + '"><img src="' + img_recenter + '" border="0" class="map_recenter" /></a><br />' ;
		item_list += '<td class="index">' + (gmarkers.length) + '</td>';
		item_list += '<td class="name">' + name + '</td>';
		item_list += '<td class="address">' + address + '</td>';
		//item_list += '<td class="date">' + i_date + '</td>';
		item_list += '<td class="score">' + score_high + '</td>';
		item_list += '<td class="score">' + score_non + '</td>';
		item_list += '</tr>';
	  return marker;
    }
	
	function decodeHTMLentities(t){
		//remove carriage returns
		  t = t.replace(new RegExp("\\=\r\n","gim"), "");
		//replace urlencoded values
		  t = unescape(t);
		//replacement values
		  var thechrs = new Array(
		    ' ','!','"','#','$','%','&',"'",'(',')','*','+',',','-','.','/','0','1','2','3',
		    '4','5','6','7','8','9',':',';','<','=','>','?','@','A','B','C','D','E','F','G', 
		    'H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z','[', 
		    '\\',']','^','_','`','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
		    'p','q','r','s','t','u','v','w','x','y','z','{','|','}','~',' ','c','u','e','a',
		    'a','a','a','c','e','e','e','i','i','i','a','a','e','ae','ae','o','o','o','u','u',
		    'y','u','u','o','l','0','x','f','a','i','o','u','n','n','*','O','?','r','_','?',
		    '?','!','<','>','_','_','_','|','|','a','a','a','c','|','|','+','+','c','y','+',
		    '+','-','-','+','-','+','a','a','+','+','-','-','|','-','+','.','.','d','e','e',
		    'e','i','i','i','i','+','+','_','_','|','i','_','o','o','o','o','o','o','u','p',
		    'p','u','u','u','y','y','_',"'",'-','?','_','?','?','S','÷','¸','°','¨','·','¹',
		    '³','²','_',' ');
		//replace js numeric array values
		  var l = 32;
		  for (l = 32; l < 256; l++){
		    t = t.replace(new RegExp("\\[" + l + ",","gim"),"[" + thechrs[l-32] + ",");
		    t = t.replace(new RegExp("\\[" + l + ",","gim"),"[" + thechrs[l-32] + ",");
		  }
		  for (l = 32; l < 256; l++){
		    t = t.replace(new RegExp("," + l + "\\]","gim"),"," + thechrs[l-32] + "]");
		    t = t.replace(new RegExp("," + l + "\\]","gim"),"," + thechrs[l-32] + "]");
		  }
		  for (l = 32; l < 256; l++){
		    t = t.replace(new RegExp("," + l + ",","gim"),"," + thechrs[l-32] + ",");
		    t = t.replace(new RegExp("," + l + ",","gim"),"," + thechrs[l-32] + ",");
		  }
		  ta = t;
		  t = t.replace(new RegExp("(\\[[^\\]]+)\\,([^\\]]+\\])","gim"), "$1$2");
		  while(ta !== t){
		    ta = t;
		    t = t.replace(new RegExp("(\\[[^\\]]+)\\,([^\\]]+\\])","gim"), "$1$2");
		  }
		//replace entities
		  var l = 32;
		  for (l = 32; l < 100; l++){
		    t = t.replace(new RegExp("&#" + l + ";","gim"),thechrs[l-32]);
		    t = t.replace(new RegExp("&#0" + l + ";","gim"),thechrs[l-32]);
		    t = t.replace(new RegExp("&#00" + l + ";","gim"),thechrs[l-32]);
		  }
		  var l = 100;
		  for (l = 100; l < 256; l++){
		    t = t.replace(new RegExp("&#" + l + ";","gim"),thechrs[l-32]);
		    t = t.replace(new RegExp("&#0" + l + ";","gim"),thechrs[l-32]);
		  }
		//return results
		  return t;
		}
	
	function setMessage (text) {
		document.getElementById('message').innerHTML = text;
	}
	
	function toggleDisplay(id) {
		var el = document.getElementById(id);
		Effect.toggle(el,'Appear');
		return false;
	}

	function toggleSlide(id) {
		var el = document.getElementById(id);
		Effect.toggle(el,'Slide');
		return false;
	}

	function closeHistory(id) {
		var el = document.getElementById(id);
		Effect.toggle(el,'Slide');
		return false;
	}
