if (GBrowserIsCompatible()) {
	var map;
	
	var debug = 0;
	
	var mo_x = 0;
	var mo_y = 0;
	
	var sidebar_html = "";
	var gmarkers = [];
	var htmls = [];
	var reviews = [];
	var addreviews = [];
	var sidebar_htmls = [];
	
	var recentReviews;
	
	var i = 0;
	var firstload = true;
	var centerlatlong = '';
	var ua = navigator.userAgent;
	var isFirefox = ( ua != null && ua.indexOf( "Firefox/" ) != -1 );
	var isMSIE = ( ua != null && ua.indexOf( "MSIE" ) != -1 );
	var request = GXmlHttp.create();
	
	var gr_view = new Object;
	var back_stack = new Array();
	var fwd_stack = new Array();
	var history_move = false;
	var ignore_move = false;
	
	var region_plines = new Array();
	var region_markers = new Array();
	var region_ids = new Array();
	var marker_queue = new Array();
		
	var tooltip;
	var preloadcat = new Array();
	var names = new Array();
	var icons = new Array();
	var grcatfilters = new Array();
	
	var dirObj;
	var directionPoints = "";
	var pLine;
	var clearDirDiv;
	var resetDirDiv;
	
	var printWindow;
	var isPrinting = false;
	
	var USstates = Array('Alabama','Alaska','Arizona','Arkansas','California','Colorado','Connecticut','Delaware','District of Columbia','Florida','Georgia','Hawaii','Idaho','Illinois','Indiana','Iowa','Kansas','Kentucky','Louisiana','Maine','Maryland','Massachusetts','Michigan','Minnesota','Mississippi','Missouri','Montana','Nebraska','Nevada','New Hampshire','New Jersey','New Mexico','New York','North Carolina','North Dakota','Ohio','Oklahoma','Oregon','Pennsylvania','Rhode Island','South Carolina','South Dakota','Tennessee','Texas','Utah','Vermont','Virginia','Washington','West Virginia','Wisconsin','Wyoming')
var pattern = '(' + USstates.join('|') + ')';



	// A function to create the marker and set up the event window
	// first check if the marker exists: return
	// are we full?: shift one out
	// add it
	function createDestination(num,point,id,name,markerhtml,iconurl,hovericonurl,iconwidth,iconheight) {
		// add a line to the sidebar html
		if (isPrinting) {
		  sidebar_htmls[id] = '<div class="infohtml" id="info' + id + '"><strong>' + num + ". " + name + '</strong></div>'+markerhtml;
		} else {
		  sidebar_htmls[id] = '<div class="infohtml" id="info' + id + '"><a onmouseover="infomouseover(\'' + id + '\',\'' + hovericonurl +'\',1,1)" onmouseout="infomouseout(\'' + id + '\',\'' + iconurl + '\')" href="javascript:openDestination(\'' + id + '\')">' + name + '</a></div>';
		}
		
		if (gmarkers[id]) return;
		// it's not anywhere in the current map, we can safely toss the tail of the queue
		// (even if we just added it this update, it's at the head of the queue and safe)
		if (marker_queue.length >= gr_view.MAX_OVERLAYS) {
			remove = marker_queue.shift();
			//gmarkers[remove.getId()] = null;
			testId = remove.gr_id;
			gmarkers[testId] = false;
//			for(var i in gmarkers) {
//				if (i == testId) {
//					//alert("removing existing: "+testId);
//					gmarkers[i] = false;
//				}
//			}
			if (remove) {
				map.removeOverlay(remove);
			}
		}
		
		// icon
		var Icon = icons[iconurl+iconwidth];
		if (!Icon) {
			Icon = new GIcon();
			Icon.shadow = "http://www.google.com/mapfiles/shadow50.png";
			Icon.iconSize = new GSize(iconwidth, iconheight);
			Icon.shadowSize = new GSize(iconheight, iconheight);
			Icon.iconAnchor = new GPoint(iconwidth/2, iconheight);
			Icon.infoWindowAnchor = new GPoint(9, 2);
			Icon.infoShadowAnchor = new GPoint(18, 25);
			Icon.image = iconurl ;
			Icon.grImage = iconurl ;
			Icon.grHoverImage = hovericonurl;
			icons[iconurl+iconwidth] = Icon;
		}
		// FF 1.5 fix
		//markerhtml = '<div class="markerhtml">' + markerhtml + '</div>';
		
		var marker;
		
		// if we're printing:
		if (isPrinting) {
//                   var letter = String.fromCharCode("A".charCodeAt(0) + num);
//                   Icon = new GIcon(Icon);
//                   Icon.image = "http://www.google.com/mapfiles/marker" + letter + ".png";
//                   
                  var Icon = new GIcon();
                  Icon.image = 'images/print_marker.png';
                  Icon.iconSize = new GSize(32, 32);
                  Icon.iconAnchor = new GPoint(16, 16);
                  Icon.infoWindowAnchor = new GPoint(25, 7);
                  
                  var plus = 0;
                  if (num > 9) { plus = -3; }
                  opts = { 
                    "icon": Icon,
                    "clickable": true,
                    "labelText": num,
                    "labelOffset": new GSize(-5+plus, -10)
                  };
                  marker = new LabeledMarker(point, opts);

                } else {
                  marker = new GMarker(point, {icon: Icon, title:name});
                }
		
		//marker.setHoverImage(hovericonurl);
		marker.gr_id=id;
		
		if (!isPrinting) {
                  GEvent.addListener(marker, "click", function() {
                          openDestination(id);
                  });
                  
                  GEvent.addListener(marker,"mouseover", function() {
                          infomouseover(id,hovericonurl,0);
                  }) ;
                  GEvent.addListener(marker,"mouseout", function() {
                          infomouseout(id,iconurl);
                  }) ;
		}
		
		// save the info we need to use later for the sidebar
		gmarkers[id] = marker;
		htmls[id] = markerhtml;
		names[id] = name;
		
		map.addOverlay(marker);
		marker_queue.push(marker);
		
		// add tooltip and name for later directions pull
		/*
		var topElement = marker.images[0];
		if (marker.imageMap) {topElement = marker.imageMap;}
		topElement.setAttribute( "title" , name );
		*/
		return marker;
	}
	
	function setDestinationInnerHtml(ih) {
	  var oOverlay=document.getElementById('divOverlay');
          var oDestination=document.getElementById('divDestination');
          oDestination.innerHTML=ih;
          oOverlay.style.display='block';
          oDestination.style.display='block';
          map.disableScrollWheelZoom();
	}
	
        // This function picks up the click and opens the corresponding info window
        function openDestination(i,override) {
	   setDestinationInnerHtml(htmls[i]);
	   if (!override) {
		gr_log('id: '+i);
		// fire off a request so we can record the click:
		var request = GXmlHttp.create();
		var feedurl = gr_view.BASEURL+'grclick.php?id='+i;
		pageTracker._trackPageview('/grclick/'+i);
		request.open("GET", feedurl, true);
		// don't care about response, just send!
		request.send(null);
            }
        }
	
	function CloseD_true() {
		CloseDestination();
		return true;
	}
	
	function CloseDestination() {
	        map.enableScrollWheelZoom();
		var oOverlay=document.getElementById('divOverlay');
		var oDestination=document.getElementById('divDestination');
		oDestination.style.display='none';
		oOverlay.style.display='none';
	}
	
	function showEmail(id, from) {
	  emailHtml = "<h3><div class=\"closeX\"><a href=\"javascript:openDestination("+id+",1)\"><img class=\"closeIcon\" src=\"images/icons/close.gif\" width=\"16\" height=\"16\" /></a></div>Email destination to a friend</h3><form id=\"emailForm\">";
          emailHtml += '<label for="emailFrom">From:</label> <input size="40" type="text" name="emailFrom" id="emailFrom" value="'+from+'"/><br/>';
          emailHtml += '<label for="emailTo">To:</label> <input size="40" type="text" name="emailTo" id="emailTo" value=""/><br/>';
          emailHtml += '<input type="hidden" id="emailId" value="'+id+'"/>';
          emailHtml += "Please include a note here:<br/>";
          emailHtml += "<textarea name=\"email_body\" id=\"email_body\"\" cols=\"40\" rows=\"10\"></textarea>";
          emailHtml += "<input type=\"button\" value=\"Send Email\" onClick=\"sendEmail();\"/>";
          emailHtml += "</form>";
	  setDestinationInnerHtml(emailHtml);
	}
	
	function sendEmail() {
	  // validate:
	  eerr = "";
	  suberr = echeck($('emailFrom').value);
	  if (suberr) eerr += "From: "+suberr+"\n";
	  suberr = echeck($('emailTo').value);
	  if (suberr) eerr += "To: "+suberr+"\n";
	  if (eerr) { alert(eerr); return; }
	  // fire off a request and send the email
          var request = GXmlHttp.create();
          var addon = "";
          if ($('subdomain').innerHTML) addon += '&subdomain='+$('subdomain').innerHTML+'&';
          var emailurl = gr_view.BASEURL+'grsendemail.php?id='+$('emailId').value+'&'+addon+'from='+escape($('emailFrom').value)+'&to='+escape($('emailTo').value)+'&body='+escape($('email_body').value);
	  pageTracker._trackPageview('/grsendemail/'+$('emailId').value);
          request.open("POST", emailurl, true);
          // don't care about response, just send!
          request.send(null);
          openDestination($('emailId').value,1);
          $('aEmail').innerHTML='<span style="color:#99ffcc;">Email sent!</span>';
          $('aEmail').href="#";
	}

/**
 * DHTML email validation script. Courtesy of SmartWebby.com (http://www.smartwebby.com/dhtml/)
 */

function echeck(str) {
		var at="@"
		var dot="."
		var lat=str.indexOf(at)
		var lstr=str.length
		var ldot=str.indexOf(dot)
		if (str.indexOf(at)==-1){ return "Invalid E-mail ID"; }

		if (str.indexOf(at)==-1 || str.indexOf(at)==0 || str.indexOf(at)==lstr){ return "Invalid E-mail ID"; }

		if (str.indexOf(dot)==-1 || str.indexOf(dot)==0 || str.indexOf(dot)==lstr){ return "Invalid E-mail ID"; }

		 if (str.indexOf(at,(lat+1))!=-1){ return "Invalid E-mail ID"; }

		 if (str.substring(lat-1,lat)==dot || str.substring(lat+1,lat+2)==dot){ return "Invalid E-mail ID"; }

		 if (str.indexOf(dot,(lat+2))==-1){ return "Invalid E-mail ID"; }
		
		 if (str.indexOf(" ")!=-1){ return "Invalid E-mail ID"; }
 		 return "";
	}

	function showReview(i) {
	   setDestinationInnerHtml(addreviews[i]);
	}
	
	function showRecentReviews() {
	   setDestinationInnerHtml(recentReviews);
	}
	var doRecentReviews = false;
	function primeRecentReviews() { doRecentReviews = true; }
	
	function userReviews(i) {
	   setDestinationInnerHtml(reviews[i]);
	}
	
	function saveReview(id) {
		var stars = $('rate_'+id).value;
		var review = $('review_'+id).value;
		// fire off a request so we can record the click:
		var request = GXmlHttp.create();
		var feedurl = gr_view.BASEURL+'grreview.php?id='+id+'&stars='+stars+'&review='+escape(review);
		pageTracker._trackPageview('/grreview/'+id);
		request.open("POST", feedurl, true);
		// don't care about response, just send!
		request.send(null);
		openDestination(id,1);
		$('aReview').innerHTML='<span style="color:#99ffcc;">Thanks! Review will show up once approved.</span>';
		$('aReview').href="#";
	}
	
	function saveDestination(id) {
          var currentTime = new Date();
          var month = currentTime.getMonth() + 1;
          var day = currentTime.getDate();
          var year = currentTime.getFullYear();

	  var thedate = prompt('If you visited this destination for your Travelogue, please enter the date.\nOtherwise, just hit cancel!', month + "/" + day + "/" + year);
	  
	       // fire off a request so we can record the click:
		var request = GXmlHttp.create();
		var feedurl = gr_view.BASEURL+'save_to_mine.php?id='+id+'&thedate='+URLEncode(thedate);
		pageTracker._trackPageview('/grsendemail/'+id);
		request.open("POST", feedurl, true);
		// don't care about response, just send!
		request.send(null);
		openDestination(id,1);
		$('aSave').innerHTML='<span style="color:#99ffcc;">Saved!</span>';
		$('aSave').href="#";
	}
	
	function showDirections(id) {
		/*
		var topElement = gmarkers[id].images[0];
		if (gmarkers[id].imageMap) {topElement = gmarkers[id].imageMap;}
		var name = topElement.getAttribute( "title" );
		*/
		var name = names[id];
		var dest = gmarkers[id].getPoint().lat()+','+gmarkers[id].getPoint().lng()+'('+name+')';
		document.getElementById("daddr").value=dest;
		var oDestinationDiv=document.getElementById('divDestination');
		var oDirectionsHolder=document.getElementById('divDirectionsHolder');
		var oDirectionsLinks=document.getElementById('divDestinationLinks');
		oDirectionsLinks.style.display='none';
		oDestinationDiv.innerHTML+=oDirectionsHolder.innerHTML;
	}
	function HideSections() {
		var oDestinationDiv=document.getElementById('divDestination');
		var oDirections=GetObjectFromParent(oDestinationDiv, 'divDirections');
		if (oDirections!=undefined) {oDestinationDiv.removeChild(oDirections);}
		var oLinks=document.getElementById('divDestinationLinks');	
		oLinks.style.display='block';
	}

	function infomouseover(i,hovericonurl,show,fromLabel) {
		//gr_log('in ' + i);
		// do pretty things when user mouses over an item

	  	if (show) {
			theIcon = gmarkers[i].getIcon();
			gmarkers[i].setImage(theIcon.grHoverImage);
			//gmarkers[i].setImage(hovericonurl);
			//gmarkers[i].topMarkerZIndex(); // bring marker to top
		} else {
			//gmarkers[i].showTooltip();
		}
		//scroll to it if we moused over the icon
		if (!fromLabel) {
			new Fx.Scroll($('destinationNames')).scrollTo(0,($('info'+i).getTop()-$('destinationNames').getTop()));
		}
		document.getElementById('info' + i ).style.backgroundColor="#fff";
		
		//gr_log('over '+i+' '+hovericonurl);
		changing = 0;

				/*
		marker = gmarkers[i];
		//tooltip.innerHTML = marker.tooltip;
		
		
		if (isMSIE) {
			tooltip.src = gr_view.BASEURL+"images/trans.gif";
			tooltip.style.filter ="progid:DXImageTransform.Microsoft.AlphaImageLoader(src=" + hovericonurl + ")";
		}else
			tooltip.src = hovericonurl;
		
		//var point=map.getCurrentMapType().getProjection().fromLatLngToPixel(map.getBounds().getSouthWest(),map.getZoom());
		//var offset=map.getCurrentMapType().getProjection().fromLatLngToPixel(marker.point,map.getZoom());
		var point=map.getCurrentMapType().getProjection().fromLatLngToPixel(map.fromDivPixelToLatLng(new GPoint(0,0),true),map.getZoom());
		var offset=map.getCurrentMapType().getProjection().fromLatLngToPixel(marker.getPoint(),map.getZoom());
		gr_log("offset "+offset.x+","+offset.y);
		var anchor=marker.getIcon().iconAnchor;
		gr_log("anchor "+anchor.x+","+anchor.y);
		var newx = offset.x - point.x - anchor.x;
		var newy = offset.y - point.y -anchor.y;
		gr_log("New "+newx+","+newy);
		var pos = new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(newx,newy)); 
		gr_log("Got "+pos.x+","+pos.y);
		pos.apply(tooltip);
		tooltip.onmouseout = function () {
			infomouseout(i,'');
		}
		tooltip.onclick = function () {
			openDestination(i);
		}
		tooltip.style.visibility="visible";
		*/
	}
	
	function infomouseout(i,iconurl) {
		//alert('out');
		theIcon = gmarkers[i].getIcon();
		gmarkers[i].setImage(theIcon.grImage);
	  	//gmarkers[i].setImage(iconurl);
	  	////gmarkers[i].setImage(gmarkers[i].getUserData());
		
		//gmarkers[i].hideTooltip();
		//gmarkers[i].restoreImage();
		//gmarkers[i].restoreMarkerZIndex();
		document.getElementById('info' + i ).style.backgroundColor="#dee1d3";
		//gr_log("out "+i);
		//tooltip.style.visibility="hidden";
	}
	
	// Create a marker for a region
	function createRegionMarker(point, zoom, number, name, description, id, w, h, num_dests) {
		if (isPrinting) { return; }
		var labelIcon = new GIcon();
		safe_str = new String(name);
		safe_str = safe_str.replace(/&/g,"*am*");
        labelIcon.image = gr_view.BASEURL+"include/label.php?text=" + escape(safe_str);
		//gr_log("LABEL: " + labelIcon.image);
        labelIcon.shadow = gr_view.BASEURL+"gmap_images/empty.png";
        labelIcon.iconSize = new GSize(w,h);
        labelIcon.shadowSize = new GSize(14, 14);
		labelIcon.iconAnchor = new GPoint(w/2,h/2);
		//gr_log('createRegion: '+name);
		//var marker = new GMarker(point,labelIcon);
		var marker = new PdMarker(point,labelIcon);
		if (num_dests > 0) {
			marker.setTooltip(num_dests + " destinations in view<br/>"+description+"<br/><i>Click for more</i>");
			marker.setTooltipClass("destinationTooltip")
		}
		GEvent.addListener(marker, 'mouseover', function() {
			map.addOverlay(region_plines[number]);
			marker.showTooltip();
		});
		GEvent.addListener(marker, 'mouseout', function() {
			if (region_plines[number]) {
				map.removeOverlay(region_plines[number]);
			}
			marker.hideTooltip();
		});
		GEvent.addListener(marker, 'click', function() {
			// remove the marker
			if (this) {
				map.removeOverlay(this);
			}
			// and the overlay
			if (region_plines[number]) {
				map.removeOverlay(region_plines[number]);
			}
			ignore_move = true;
			map.setCenter(point, zoom);
			ignore_move = false;
			Moved();
		});

		
		//region_markers[id] = marker;
		region_ids.push(id);
		region_markers.push(marker);
		map.addOverlay(marker);
		// add tooltip:
		/*
		var topElement = marker.images[0];
		if (marker.imageMap) {topElement = marker.imageMap;}
		topElement.setAttribute( "title" , "Zoom to "+name );
		*/
		
		return marker;
	}

	// if the map has been moved or zoomed
	function Moved() {
		if (ignore_move || (drawing_route && !endMarker)) return;
		CloseDestination();
		//alert('moved');
		if (!history_move) {
			// save a copy in the back stack
			back_stack.push(flatten_object(gr_view));
			//alert("back pushed: "+gr_view.gr_lat);
			// clear the forward stack
			fwd_stack = new Array();
		}
		history_move = false;
			
		var center = map.getCenter();
		gr_view.gr_lat = center.lat() ;
		gr_view.gr_long = center.lng() ;
		var span = map.getBounds().toSpan();
		gr_view.gr_h = span.lat();  
		gr_view.gr_w = span.lng();
		gr_view.gr_z = map.getZoom();
		
		gr_log('Moved: loadXMLfile');
		loadXMLfile();
	}
	
	function CitySelected(obj) {
		tmp = obj.value.split(",");
		jump(new GLatLng(tmp[0],tmp[1]),tmp[2]);
	}
	
	// xxx this finds the divs of type cat_filter and checks for cat_filter_on class.  Assembles gr_cats based on this.
	function newCategories() {
		// anything checked comes out of gr_cats (it's an exclude list)
		// checked goes in
		var gr_cats = new Array();

                for (i=0; i<grcatfilters.length; i++) {
                //for each (catfilter in grcatfilters) {
                  catfilter = grcatfilters[i];
                  if (catfilter.hasClass) {
                    if (!catfilter.hasClass('cat_filter_on')) {
                      //alert(catfilter.catId);
                      gr_cats.push(catfilter.catId);
                      //break;
                    }
                  }
                }
                // skip hlf if we're not on that site:
                // NS 4/1/08 xxxhlf xxx hlf
                //if (gr_view.gr_site != 'hlf') gr_cats.push(6);
		// put gr_cats back together
		gr_view.gr_cats = gr_cats.join(',');
		//alert(gr_view.gr_cats);
		// clear it first - otherwise some bad ones can stick around if they've been zoomin
		// xxx - try without this
		//clear_all_destinations();
		// go load it!
		Moved();
	}
	
	function jump(gll,z) {
		z=z/1;
		gr_log(z);
		ignore_move=true;
		map.setCenter(gll, z);
		ignore_move=false;
		Moved();
	}
	
	// the user clicked the "back" button for the map
	// if we have a history:
	// -- save where we are now in the fwd stack
	// -- pop the top one off and go to it
	function map_back() {
		// don't try if there's nothing left to pop
		if (back_stack.length < 1) return;
		fwd_stack.push(flatten_object(gr_view));
		//alert("fwd pushed: "+gr_view.gr_lat);
		gr_view = expand_object(back_stack.pop(),gr_view);
		//alert("back popped: "+gr_view.gr_lat);
		history_move = true;
		jump(new GLatLng(gr_view.gr_lat, gr_view.gr_long), gr_view.gr_z);
		//loadXMLfile();
	}
	
	// the user clicked the "fwd" button for the map
	// if we have a history:
	// -- save where we are now in the back stack
	// -- pop the top one off and go to it
	function map_fwd() {
		// don't try if there's nothing left to pop
		if (fwd_stack.length < 1) return;
		back_stack.push(flatten_object(gr_view));
		//alert("back pushed: "+gr_view.gr_lat);
		gr_view = expand_object(fwd_stack.pop(),gr_view);
		//alert("fwd popped: "+gr_view.gr_lat);
		history_move = true;
		jump(new GLatLng(gr_view.gr_lat, gr_view.gr_long), gr_view.gr_z);
		//loadXMLfile();
	}
	
	function flatten_object(obj) {
		var tmp = "";
		for (var i in obj) {
			if (tmp != "") tmp += "|";
			tmp += obj[i];
		}
		//alert(tmp);
		return tmp;
	}
	
	function expand_object(flat,obj) {
		var x = 0;
		var tmp = flat.split("|");
		for (var i in obj) {
			obj[i] = tmp[x++];
		}
		return obj;
	}
	
	function clear_all_destinations() {
		gmarkers = [];
		while (marker = marker_queue.pop()) {
			if (marker) {
				map.removeOverlay(marker);
			}
		}
	}
	
	function clear_all_regions() {
		for(var i=0;i<region_markers.length;i++) {
                        if (region_markers[i]) {
                                map.removeOverlay(region_markers[i]);
                        }
                }
                region_markers = new Array();
                region_ids = new Array();
	}
	
	// run the search - ask for new coords and zoom to them
	function new_search(what) {
		txtSearch = document.getElementById("txtSearch");
		txtSearch.blur();
		if (what == 'clear') document.getElementById("txtSearch").value = "";
		gr_view.gr_s = txtSearch.value;
		if (gr_view.gr_s == '') {
			gr_view.gr_s = undefined;
			loadXMLfile();
			return;
		}
		var feedurl = gr_view.BASEURL+'gr_searchcoords.php?s='+gr_view.gr_s+'&cats='+gr_view.gr_cats;
		
		if ($('subdomain').innerHTML) feedurl += '&subdomain='+$('subdomain').innerHTML;
		
		pageTracker._trackPageview('/grsearch/'+what);

		request.open("GET", feedurl, true);
		request.onreadystatechange = function() {
			if (request.readyState == 4) {
				var xmlDoc = request.responseXML;
				
				// First check for an error
				var result = xmlDoc.documentElement.getElementsByTagName("result")[0];
				if (result) {
					var lat = GXml.value(result.getElementsByTagName("lat")[0]);
					var lng = GXml.value(result.getElementsByTagName("lng")[0]);
					var zoom = GXml.value(result.getElementsByTagName("zoom")[0]);
					clear_all_destinations();
					jump(new GLatLng(lat,lng),zoom);
				}
				else {
					// no results, we need to reflect that somehow:
					loadXMLfile();
				}
			}
		}
		request.send(null);
		//clear_all_destinations();
		//jump(new GLatLng(46.225453,-94.042969),6);
		//loadXMLfile();
	}

	function permanent_link() {
		//gr_log('permanent_link');
		
      	         var request = GXmlHttp.create();
		var feedurl = gr_view.BASEURL+'gr_bookmark.php?x='+gr_view.gr_long+'&y='+gr_view.gr_lat+'&w='+gr_view.gr_w+'&h='+gr_view.gr_h+'&z='+gr_view.gr_z+'&rg='+gr_view.gr_rg+'&rt='+gr_view.gr_rt+'&md='+gr_view.gr_my_dests+'&s='+gr_view.gr_s+'&cats='+gr_view.gr_cats+'&directionPoints='+directionPoints;
		
		request.open("POST", feedurl, true);
		request.onreadystatechange = function() {
			if (request.readyState == 4) {
				var xmlDoc = request.responseXML;
				var bookmark = GXml.value(xmlDoc.documentElement.getElementsByTagName("bookmark")[0]);
				if(bookmark) {
					document.location.href = gr_view.BASEURL+"index.php?bookmark="+bookmark;
					// XXX set some status here to indicate success and that bookmarks will work
				}
			}
		}
		request.send(null);
	}
	
	function doPrint() {
	   printWindow = window.open(gr_view.BASEURL+'print.php');
	}
	
	function invokePrint() {
            var oDriveFrom = document.getElementById('driveFrom');
            var oDriveTo = document.getElementById('driveTo');
            var oDriveVia = document.getElementById('driveVia');
            // (lng,lat,w,h,z,rg,rt,c,s,cats, max_dests, base_url, route_span, site, dirFrom, dirTo)
            printWindow.isPrinting = true;
	   printWindow.gr_init(gr_view.gr_long,gr_view.gr_lat,gr_view.gr_w,gr_view.gr_h,gr_view.gr_z,gr_view.gr_rg,gr_view.gr_rt,gr_view.gr_c,gr_view.gr_s,gr_view.gr_cats,gr_view.MAX_OVERLAYS,gr_view.BASEURL,gr_view.gr_my_dests,gr_view.gr_site,oDriveFrom.value, oDriveTo.value, oDriveVia.value);

	}
	
	function pullBack() {
	  map.zoomOut();
	  Moved();
	}
	function pullIn() {
	  map.zoomIn();
	  Moved();
	}
	
	// load the XML file
	function loadXMLfile() {
		var startTime=new Date() ;
		gr_log('LoadXMLfile');
		fade_note = 0;
		
		var oLoading=document.getElementById('ajaxLoading');
		oLoading.style.display='block';
		
		if (pLine) getDirectionPointsInView(pLine);
		
		//document.getElementById("destinationNames").innerHTML = '<div class="loading"><img src="'+gr_view.BASEURL+'images/hourglass.gif" width="24" height="36" alt="" /> Loading...</div>';
      	var request = GXmlHttp.create();
		var feedurl = gr_view.BASEURL+'grupdate.php';
		var feedparams = 'x='+gr_view.gr_long+'&y='+gr_view.gr_lat+'&w='+gr_view.gr_w+'&h='+gr_view.gr_h+'&z='+gr_view.gr_z+'&rg='+gr_view.gr_rg+'&rt='+gr_view.gr_rt+'&md='+gr_view.gr_my_dests+'&s='+gr_view.gr_s+'&cats='+gr_view.gr_cats+'&directionPoints='+directionPoints+'&isPrinting='+isPrinting;
		if (gr_view.gr_site == 'hlf') feedparams += '&site=hlf';
		if ($('subdomain').innerHTML) feedparams += '&subdomain='+$('subdomain').innerHTML;
		//feedurl += '&site='+gr_view.gr_site;
		
		var loadCats = (firstload && !gr_view.gr_cats);

                useGet = directionPoints ? false : true;
                if (useGet) {
      		  request.open("GET", feedurl+"?"+feedparams, true);
      		} else {
                  request.open("POST", feedurl, true);
                  //Send the proper header information along with the request
                  request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
                  request.setRequestHeader("Content-length", feedparams.length);
                  request.setRequestHeader("Connection", "close");
                }
      		request.onreadystatechange = function() {
      		        gr_log('***READYSTATE: '+request.readyState);
        		if (request.readyState == 4) {
          			var xmlDoc = request.responseXML;
				i=0;
				var gr_cats = new Array;
				if (gr_view.gr_cats != '') gr_cats=gr_view.gr_cats.split(',');

				// Get feed title and desciption
				//var title = GXml.value(xmlDoc.documentElement.getElementsByTagName("title")[0]);
				sidebar_html = ''; //'<div class="intro">' + GXml.value(xmlDoc.documentElement.getElementsByTagName("description")[0]) +'</div>';
				if (debug) sidebar_html += '<a class="xmlbutton" href="'+feedurl+'?'+feedparams+'" target="_blank" title="View the XML source for this map">XML</a> ';

				//////////////////// Destination
				// first check if there's a region override in effect:
          			var regions_override = xmlDoc.documentElement.getElementsByTagName("regions_override").length;
				if (regions_override) {
				  //alert('override');
				  
				}
				// start over
					clear_all_destinations();
					
				// obtain the array of destinations and loop through it
          			var destinations = xmlDoc.documentElement.getElementsByTagName("destination");
          			if (regions_override) {
          			  sidebar_html += '<p id="dest_note" class="fade-0066FF">Too many destinations to display!<br/><br/><a href="javascript:pullIn()">Zoom in</a> or click on a region name.<br/></p>';
          			  fade_note = 1;
          			}
          			
				if (destinations.length >= gr_view.MAX_OVERLAYS) {
					clear_all_destinations();
					add_s = '';
					if (gr_cats.length < 2) {
					  add_s += '&bull; removing category filters<br/>';
					}
					add_s += '&bull; <a href="javascript:pullIn()">zooming in</a><br/>';
					sidebar_html += '<p id="dest_note" class="fade-0066FF">Too many destinations to display!<br/><br/>You might try:<br/>'+add_s+'</p>';
					fade_note = 1;
				} else if (destinations.length == 0 && !regions_override) {
					//clear_all_destinations();
					add_s = '';
					if (gr_view.gr_s) {
					  add_s += '&bull; <a href="javascript:new_search(\'clear\')">clearing your search term</a><br/>';
					}
					if (pLine) {
					  add_s += '&bull; <a href="javascript:clearDirections()">clearing your route</a><br/>';
					}
					if (gr_cats.length > 1) {
					  add_s += '&bull; adding category filters<br/>';
					}
					add_s += '&bull; <a href="javascript:pullBack()">zooming out</a><br/>';
					sidebar_html += '<p id="dest_note" class="fade-0066FF">No destinations in view!<br/><br/>You might try:<br/>'+add_s+'</p>';
					fade_note = 1;
				} else {
					for (var j = 0; j < destinations.length; j++) {
						// obtain the attribues of each marker
						var id = GXml.value(destinations[j].getElementsByTagName("id")[0]);
						if (!gmarkers[id]) {
							var name = GXml.value(destinations[j].getElementsByTagName("name")[0]);
							var website = GXml.value(destinations[j].getElementsByTagName("website")[0]);
							var summary_html = GXml.value(destinations[j].getElementsByTagName("summary_html")[0]);
							var lng = parseFloat(GXml.value(destinations[j].getElementsByTagName("lon")[0]));
							var lat = parseFloat(GXml.value(destinations[j].getElementsByTagName("lat")[0]));
							var categories = destinations[j].getElementsByTagName("category");
							for (var k = 0; k < categories.length; k++) {
								var catid = GXml.value(categories[k].getElementsByTagName("id")[0]);
								var use = true; // can we use this icon?
								for(var cid in gr_cats) {
									// this is an exclude list, so make it opposite
									if (gr_cats[cid] == catid) {
										use=false;
									}
								}
								if (use) {
									var iconurl = gr_view.BASEURL+"map_icons/"+GXml.value(categories[k].getElementsByTagName("icon")[0])+".png";
									var hovericonurl = gr_view.BASEURL+"map_icons/"+GXml.value(categories[k].getElementsByTagName("icon")[0])+"_hover.png";
									var iconwidth = GXml.value(categories[k].getElementsByTagName("width")[0]);
									var iconheight = GXml.value(categories[k].getElementsByTagName("height")[0]);
									
									break;
								}
							}
							// fake a review
							reviews[id] = GXml.value(destinations[j].getElementsByTagName("reviews")[0]);
							addreviews[id] = "<h3><div class=\"closeX\"><a href=\"javascript:openDestination("+id+",1)\"><img class=\"closeIcon\" src=\"images/icons/close.gif\" width=\"16\" height=\"16\" /></a></div>"+name+"</h3>";
							addreviews[id] += "Please rate "+name+":<br/><input type=\"hidden\" name=\"rate_"+id+"\" id=\"rate_"+id+"\" />";
							addreviews[id] += '<div><ul class="star-rating"><li id="current_'+id+'" class="current-rating" style="width:00%;"></li><li><a onClick="$(\'rate_'+id+'\').value=1;$(\'current_'+id+'\').style.width=\'20%\';" href="#" title="1 star out of 5" class="one-star">1</a></li>		<li><a onClick="$(\'rate_'+id+'\').value=2;$(\'current_'+id+'\').style.width=\'40%\';" href="#" title="2 stars out of 5" class="two-stars">2</a></li>		<li><a onClick="$(\'rate_'+id+'\').value=3;$(\'current_'+id+'\').style.width=\'60%\';" href="#" title="3 stars out of 5" class="three-stars">3</a></li>		<li><a onClick="$(\'rate_'+id+'\').value=4;$(\'current_'+id+'\').style.width=\'80%\';" href="#" title="4 stars out of 5" class="four-stars">4</a></li>		<li><a onClick="$(\'rate_'+id+'\').value=5;$(\'current_'+id+'\').style.width=\'100%\';" href="#" title="5 stars out of 5" class="five-stars">5</a></li></ul></div>';
							addreviews[id] += "Write your review here:<br/>";
							addreviews[id] += "<textarea name=\"review_"+id+"\" id=\"review_"+id+"\" cols=\"40\" rows=\"10\"></textarea>";
							addreviews[id] += "<input type=\"button\" value=\"Submit Review\" onClick=\"saveReview("+id+");\"/>";
							addreviews[id] += "</form>";
							var point = new GLatLng(lat,lng);
							iw = iconwidth;
							ih = iconheight;
							if (regions_override) {
                                                          iw = iw / 2;
                                                          ih = ih / 2;
                                                        }
                                                        
      		        gr_log('createDest: '+name+' '+regions_override);
							var destination = createDestination(j+1,point,id,name,summary_html,iconurl,hovericonurl,iw,ih);
						}
						sidebar_html += sidebar_htmls[id];
	          			}
				}
				
          		var recentReviewsHolder = xmlDoc.documentElement.getElementsByTagName("recent_reviews");
				recentReviews = GXml.value(recentReviewsHolder[0]);
				
				//////////////////// Categories
				// obtain the array of categories and loop through it
				//if (document.getElementById("catFilters").innerHTML.length < 200) {
				if (grcatfilters.length == 0) {
          			var catholder = xmlDoc.documentElement.getElementsByTagName("top_categories");
					var cats = catholder[0].getElementsByTagName("category");
/*					var cat_html = "";
					var dosplit = true;
	          			for (var j = 0; j < cats.length; j++) {
	           				// obtain the attribues of each marker
						var id = GXml.value(cats[j].getElementsByTagName("id")[0]);
						if (gr_view.gr_site != 'hlf' && id == 6) {
							// skip
						} else {
							var name = GXml.value(cats[j].getElementsByTagName("name")[0]);
							var icon = GXml.value(cats[j].getElementsByTagName("icon")[0]);
							var width = GXml.value(cats[j].getElementsByTagName("width")[0]);
							var height = GXml.value(cats[j].getElementsByTagName("height")[0]);
							var description = GXml.value(cats[j].getElementsByTagName("category_description")[0]);
							cat_html += '<input onmouseover="show_tooltip(\''+description+'\');" onmouseout="exit();" type="checkbox" name="cat'+id+'" id="cat'+id+'" ';
							var checked=true;
							for(var cid in gr_cats) {
								// this is an exclude list, so make it opposite
								//alert(gr_cats[cid] + " " + id);
								if (gr_cats[cid] == id) {
									checked=false;
								}
							}
							// preload rollover:
							preloadcat[j] = new Image();
							preloadcat[j].src = gr_view.BASEURL+'map_icons/'+icon+'_hover.png';
							if (checked) cat_html += 'checked="true"';
							//alert(icon+" "+checked);
							cat_html += ' /><label class="cat_label" for="cat'+id+'" onmouseover="show_tooltip(\''+description+'\');" onmouseout="exit();"><img alt="'+description+'" src="'+gr_view.BASEURL+'map_icons/'+icon+'.png" height="20" border="0"/>&nbsp;'+name+'</label>&nbsp;&nbsp;&nbsp;';
							
							//cat_html += ' /><label for="cat'+id+'">'+name+'</label> ';
							//if (dosplit && (j+1 > (Math.floor(cats.length/2)))) {cat_html += "<br/>"; dosplit=false; }
						}
	          			}
					//cat_html += '&nbsp;<input type="button" id="thecatBtn" name="thecatBtn" class="button" value="update map" onclick="javascript:newCategories()" />';
					cat_html += '&nbsp;<img src="images/update.jpg" width="76" height"17" onclick="javascript:newCategories()" onmousedown="this.src=\'images/update2.jpg\'" onmouseup="this.src=\'images/update.jpg\'" onmouseout="this.src=\'images/update.jpg\'"/>';
	         			document.getElementById("catFilters").innerHTML = cat_html;
						
					// fix the transparency on the new images:
					fnLoadPngs();
					replaceChecks();
*/
					
                                        map.addControl(new TextualZoomControl(cats));
				}
				
				if (!drawing_route && !gr_view.gr_my_dests) {
                                  //////////////////// Regions
                                  var prev_reg_ids = new Array();
                                  for(var rid in region_ids) {
                                          prev_reg_ids.push(region_ids[rid]);
                                          //gr_log("was on: "+region_ids[rid]);
                                  }
                                  var new_reg_ids = new Array();
                                  /*
                                  while (marker = region_markers.pop()) {
                                          gr_log('removing region');
                                          map.removeOverlay(marker);
                                  }
                                  */
                                  // obtain the array of "Zoom In" regions and loop through it
                                  var zoomIn = xmlDoc.documentElement.getElementsByTagName("zoom_in");
                                  var regions = zoomIn[0].getElementsByTagName("region");
                                  for (var j = 0; j < regions.length; j++) {
                                          // obtain the attribues of each marker
                                          var id = GXml.value(regions[j].getElementsByTagName("id")[0]);
                                          
                                          new_reg_ids.push(id);
                                          gr_log("now on: "+id);
                                          
                                          // check if this is onscreen - abort if yes.
                                          var onscreen = 0;
                                          for(test_id in prev_reg_ids) {
                                                  if (prev_reg_ids[test_id] == id) {
                                                          onscreen = 1;
                                                  }
                                          }
                                          //if (!onscreen) {
                                                  var name = GXml.value(regions[j].getElementsByTagName("name")[0]);
                                                  var description = GXml.value(regions[j].getElementsByTagName("description")[0]);
                                                  var marker_width = GXml.value(regions[j].getElementsByTagName("marker_width")[0]);
                                                  var marker_height = GXml.value(regions[j].getElementsByTagName("marker_height")[0]);
                                                  var lng = parseFloat(GXml.value(regions[j].getElementsByTagName("lon")[0]));
                                                  var lat = parseFloat(GXml.value(regions[j].getElementsByTagName("lat")[0]));
                                                                  var point = new GLatLng(lat,lng);
                                                  var zoom = parseFloat(GXml.value(regions[j].getElementsByTagName("zoom")[0]));
                                                  var polyline = GXml.value(regions[j].getElementsByTagName("polyline")[0]);
                                                  var contained_destinations = GXml.value(regions[j].getElementsByTagName("contained_destinations")[0]);
                                                  tmp = polyline.split("|");
                                                  pt_arr = new Array();
                                                  for(i=0;i<tmp.length;i++) {
                                                          if(tmp[i] != '') {
                                                                  xy = tmp[i].split(",");
                                                                  pt_arr[i] = new GLatLng(xy[1],xy[0]);
                                                          }
                                                  }
                                                  if (pt_arr.length > 2) {
                                                          gr_log('adding Region '+name+' '+id+' '+j);
                                                          region_plines[id] =new GPolyline(pt_arr,"#3366FF",2,.8);
                                                          //map.addOverlay(region_plines[j]);
                                                          if (!onscreen) {
                                                            marker = createRegionMarker(point, zoom, id, name, description, id, marker_width, marker_height, contained_destinations);
                                                          }
                                                          if (destinations.length >= gr_view.MAX_OVERLAYS || (regions_override && destinations.length==0) ) {
                                                            sidebar_html += '&nbsp;&nbsp;&nbsp;&bull;&nbsp;<a onMouseOver="javascript:map.addOverlay(region_plines['+id+']);" onMouseOut="javascript:if(region_plines['+id+']){map.removeOverlay(region_plines['+id+']);}" href="javascript:if(region_plines['+id+']){map.removeOverlay(region_plines['+id+']);}ignore_move = true;map.setCenter(new GLatLng('+point.lat()+','+point.lng()+'), '+zoom+');ignore_move = false;Moved();">'+name+"</a><br/>";
                                                            
                                                            
  // 							  GEvent.addListener(marker, 'mouseover', function() {
  // 			map.addOverlay(region_plines[number]);
  // 			marker.showTooltip();
  // 		});
  // 		GEvent.addListener(marker, 'mouseout', function() {
  // 			if (region_plines[number]) {
  // 				map.removeOverlay(region_plines[number]);
  // 			}
  // 			marker.hideTooltip();
  // 		});
                  
                  
                                                          }
                                                  }
                                          //}
                                  }
                                          
                                  // compare new_reg_ids and prev_reg_ids
                                  // remove anything in prev_reg_ids that isn't in new_reg_ids
                                  for(var prev_id in prev_reg_ids) {
                                          var ok = 0;
                                          for(var new_id in new_reg_ids) {
                                                  if (new_reg_ids[new_id] == prev_reg_ids[prev_id]) ok = 1;
                                          }
                                          if (!ok) {
                                                  //gr_log("removing "+prev_reg_ids[prev_id]);
                                                  // remove it
                                                  for(var i=0;i<region_ids.length;i++) {
                                                          rid = region_ids[i];
                                                          if (prev_reg_ids[prev_id] == rid) {
                                                                  //gr_log("Removing "+prev_reg_ids[prev_id]);
                                                                  if (region_markers[i]) {
                                                                          map.removeOverlay(region_markers[i]);
                                                                  }
                                                                  region_markers.splice(i,1);
                                                                  region_ids.splice(i,1);
                                                          }
                                                  }
                                          } else {
                                                  //gr_log("keeping "+prev_reg_ids[prev_id]);
                                          }
                                  }
                                          
                                  // obtain the array of "Zoom Out" regions and loop through it
                                  var zoomOut = xmlDoc.documentElement.getElementsByTagName("zoom_out");
                                  var regions = zoomOut[0].getElementsByTagName("region");
                                  var prepend = "";
                                  for (var j = 0; j < regions.length; j++) {
                                          if (j == 0) {
                                                  prepend = "Zoom out to: ";
                                          }
                                          // obtain the attribues of each marker
                                          var id = GXml.value(regions[j].getElementsByTagName("id")[0]);
                                          var name = GXml.value(regions[j].getElementsByTagName("name")[0]);
                                          var lon = parseFloat(GXml.value(regions[j].getElementsByTagName("lon")[0]));
                                          var lat = parseFloat(GXml.value(regions[j].getElementsByTagName("lat")[0]));
                                          var zoom = parseFloat(GXml.value(regions[j].getElementsByTagName("zoom")[0]));
                                          regionLink = "jump(new GLatLng("+lat+","+lon+"), "+zoom+");";
                                          if (j>0) prepend += ', ';
                                          prepend += '<a class="xmlbutton" href="#" onClick="' + regionLink + '">'+name+'</a>';
                                  }
                                  //if (prepend != "") {
                                  //        sidebar_html = prepend + "<br/>" + sidebar_html;
                                  //}
				}
				//////////////////// Ads
				// obtain the array of "Zoom Out" regions and loop through it
				var ads = xmlDoc.documentElement.getElementsByTagName("ad");
				for (var j = 0; j < ads.length; j++) {
				// obtain the attribues of each ad
					var id = GXml.value(ads[j].getElementsByTagName("id")[0]);
					var name = GXml.value(ads[j].getElementsByTagName("name")[0]);
					var url = GXml.value(ads[j].getElementsByTagName("url")[0]);
					// src="gr_ads/'+id+'.jpg"
					ad_id = j+1;
					ad_html = '<a href="'+url+'" target="_blank"><img src="/gr_ad_imgs/'+id+'.jpg" border="0" alt="'+name+'" onClick="javascript: pageTracker._trackPageview(\'/ad_click/'+id+'\'); "/></a>';
					
					target_ad = document.getElementById('ad'+ad_id);
					target_ad.innerHTML = ad_html;
          			}
					
				//////////////////// Cities
				// obtain the array of cities and loop through it
          			var cities = xmlDoc.documentElement.getElementsByTagName("city");
				// clear list first
				document.forms['filterForm'].cityList.length = 0;
				document.forms['filterForm'].cityList.options[0] = new Option('Zoom to a city','');
          			for (var j = 0; j < cities.length; j++) {
           				// obtain the attribues of each marker
					var id = GXml.value(cities[j].getElementsByTagName("id")[0]);
					var name = GXml.value(cities[j].getElementsByTagName("name")[0]);
					var lat = GXml.value(cities[j].getElementsByTagName("lat")[0]);
					var lon = GXml.value(cities[j].getElementsByTagName("lon")[0]);
					var zoom = GXml.value(cities[j].getElementsByTagName("zoom")[0]);
					var map_type = GXml.value(cities[j].getElementsByTagName("map_type")[0]);
					cityLink = lat+","+lon+","+zoom;
					document.forms['filterForm'].cityList.options[j+1] = new Option(name,cityLink);
					//sidebar_html += '<a class="xmlbutton" href="#" onClick="' + cityLink + '">'+name+'</a> ';
          			}
					
							
				
// 				///////////////////// testing route bounds:
// 				var boxes = xmlDoc.documentElement.getElementsByTagName("bbox");
// 				        map.clearOverlays();
// 				for (var j = 0; j < boxes.length; j++) {
// 				// obtain the attribues of each ad
// 					var x1 = GXml.value(boxes[j].getElementsByTagName("x1")[0]);
// 					var y1 = GXml.value(boxes[j].getElementsByTagName("y1")[0]);
// 					var x2 = GXml.value(boxes[j].getElementsByTagName("x2")[0]);
// 					var y2 = GXml.value(boxes[j].getElementsByTagName("y2")[0]);
// 					bline = Array();
// 					bline.push(new GLatLng(y1,x1));
// 					bline.push(new GLatLng(y2,x1));
// 					bline.push(new GLatLng(y2,x2));
// 					bline.push(new GLatLng(y1,x2));
// 					bline.push(new GLatLng(y1,x1));
// 					boxline = new GPolyline(bline,'#cc5555',1,1);
// 					map.addOverlay(boxline);
//           			}
					
				// figure out back and fwd buttons:
				var nav_html = '';
				if (back_stack.length > 0) {
					nav_html += '<a class="xmlbutton" href="#" onClick="map_back();">back</a> ';
				}
				if (fwd_stack.length > 0) {
					nav_html += '<a class="xmlbutton" href="#" onClick="map_fwd();">fwd</a> ';
				}
				// NS - no good place to put this yet...
         			//document.getElementById("map_nav").innerHTML = nav_html;
			        
			        if (destinations.length >= gr_view.MAX_OVERLAYS) {
			          sidebar_html += "<br/>Or click the button on the left to begin drawing you route!!";
			        }
			        
			        if (gr_view.gr_my_dests && !isPrinting) {
			          prepend = "Viewing My Destinations<br/>Click <a href=\"index.php\">here</a> to view all.<br/>";
			        }
			        
          			// put the assembled sidebar_html contents into the sidebar div
         			document.getElementById("destinationPrepend").innerHTML = prepend ? prepend : '';
         			document.getElementById("destinationNames").innerHTML = sidebar_html;
					
				oLoading.style.display='none';
					
				// fade the note, if there is one.
				dn = document.getElementById("dest_note");
				if (fade_note == 1 && dn) {
					//gr_log('fade_note');
					Fat.fade_element(dn, 30, 1000, "#ffffff");
				}
				
				firstload = false;
        		}
			var endTime=new Date();
			if (request.readyState == 4) gr_log('***LoadXMLfile done: '+(endTime-startTime));
			if (doRecentReviews && recentReviews) { showRecentReviews(); doRecentReviews = false; }
      		}
      		if (useGet) { request.send(null); }
      		else { request.send(feedparams); }
      		
      		
	}
	
	// called on keypress
	function DoSearch(oElement, oEvent) {
		// save
		if(oEvent.keyCode==13) {
			str = document.getElementById("txtSearch").value;
			if (str.length < 4) alert("Sorry, search strings must be at least 4 characters");
			else new_search();
		}
	}

	function focusSearch() {
		if (document.getElementById("txtSearch").value == 'search...')
			document.getElementById("txtSearch").value = '';
		else
			document.getElementById("txtSearch").select();
	}
	
	// We define the function first
function TextualZoomControl(cats) {
this.catarr = cats;
}

TextualZoomControl.prototype = new GControl();

var dr_start = "Planning a trip? Click here to draw your route!";
var dr_1 = "Now click the map to choose your origin.";
var dr_2 = "Click again to continue your route.";

// Creates a one DIV for each of the buttons and places them in a container
// DIV which is returned as our control element. We add the control to
// to the map container and return the element for the map class to
// position properly.
TextualZoomControl.prototype.initialize = function(map) {
  var container = document.createElement("div");
if (isPrinting) return container;
  cats = this.catarr;

  var dirLabelDiv = new Element('div', { 'id': 'dirLabelDiv' } );
  dirLabelDiv.innerHTML = "Destination types: (click to filter)";
  dirLabelDiv.addClass('cat_filter');
  dirLabelDiv.addClass('map_info');
  dirLabelDiv.addClass('bg_ccc');
  container.appendChild(dirLabelDiv);
if (cats.length == 0) { dirLabelDiv.addClass('hidden'); }
  var gr_cats = new Array;
  if (gr_view.gr_cats != '') gr_cats=gr_view.gr_cats.split(',');
  for (var j = 0; j < cats.length; j++) {
    // obtain the attribues of each marker
    var id = GXml.value(cats[j].getElementsByTagName("id")[0]);
    if (gr_view.gr_site != 'hlf' && id == 6) {
      // skip
    } else {
      var name = GXml.value(cats[j].getElementsByTagName("name")[0]);
      var icon = GXml.value(cats[j].getElementsByTagName("icon")[0]);
      var width = GXml.value(cats[j].getElementsByTagName("width")[0]);
      var height = GXml.value(cats[j].getElementsByTagName("height")[0]);
      var description = GXml.value(cats[j].getElementsByTagName("category_description")[0]);

      var filterDiv = new Element('div', { 'id': 'filter_'+name } );
      filterDiv.addClass('cat_filter');
      startoff = false;
      for (k = 0; k<gr_cats.length; k++) {
        if (gr_cats[k] == id) {
          startoff = true;
        }
      }
      if (!startoff) {
          filterDiv.addClass('cat_filter_on');
      } else {
        filterDiv.addClass('cat_filter_off');
      }
      container.appendChild(filterDiv);
      filterDiv.description = description;
      filterDiv.addEvent('mouseover',catfiltermo);
      filterDiv.addEvent('mouseout',exit);
      //filterDiv.addEventListener("mouseover",catfiltermo,false);
      //filterDiv.addEventListener("mouseout",exit,false);
      filterDiv.innerHTML='<img alt="'+description+'" src="'+gr_view.BASEURL+'map_icons/'+icon+'.png" height="20" border="0" style="margin-left:5px; margin-right:5px"/>'+name;
      filterDiv.catId = id;
      grcatfilters.push(filterDiv);
      //filterDiv.appendChild(document.createTextNode(name));
      GEvent.addDomListener(filterDiv, "click", filterClick);
      
    }
  }
  
  clearDirDiv = new Element('div', { 'id': 'clearDir' } );
  clearDirDiv.innerHTML = dr_start;
  clearDirDiv.addClass('cat_filter');
  clearDirDiv.addClass('map_info');
  clearDirDiv.addClass('clearDir');
  container.appendChild(clearDirDiv);
  GEvent.addDomListener(clearDirDiv, "click", clearDirections);
  
  resetDirDiv = new Element('div', { 'id': 'resetDir' } );
  resetDirDiv.innerHTML = "Reset route";
  resetDirDiv.addClass('cat_filter');
  resetDirDiv.addClass('map_info');
  resetDirDiv.addClass('hidden');
  resetDirDiv.addClass('resetDir');
  container.appendChild(resetDirDiv);
  GEvent.addDomListener(resetDirDiv, "click", gclearDirections);
  
  map.getContainer().appendChild(container);
  
  return container;
}

function catfiltermo()
{
  show_tooltip(this.description);
}

// By default, the control will appear in the top left corner of the
// map with 7 pixels of padding.
TextualZoomControl.prototype.getDefaultPosition = function() {
  return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(7, 120));
}

function filterClick() {
  this.toggleClass('cat_filter_on');
  this.toggleClass('cat_filter_off');
  newCategories();
}


var startMarker;
var endMarker;
var baseIcon = new GIcon();
baseIcon.iconSize=new GSize(16,16);
baseIcon.iconAnchor=new GPoint(8,8);
baseIcon.infoWindowAnchor=new GPoint(10,0);
var greenIcon = (new GIcon(baseIcon, "images/greenCircle.png", null, ""));
var redIcon = (new GIcon(baseIcon, "images/redCircle.png", null, ""));
var yellowIcon = (new GIcon(baseIcon, "/images/yellowSquare.png", null, ""));

function singleClick(marker, point) {
if (isPrinting) return;
if (!drawing_route) return;
	//window.clearTimeout(clckTimeOut);
	//clckTimeOut = null;

	if (point) {
		if (!startMarker) {
			var oDriveFrom = document.getElementById('driveFrom');
			startMarker = new GMarker(point,{icon:greenIcon,draggable:false,bouncy:false});
			startMarker.formField = oDriveFrom;
			//GEvent.addListener(startMarker,'drag',markerDrag);
			//GEvent.addListener(startMarker,'dragend',getDirections);
			map.addOverlay(startMarker);
			oDriveFrom.value = startMarker.getPoint().lat().toFixed(6) + ',' + startMarker.getPoint().lng().toFixed(6);
			clearDirDiv.innerHTML=dr_2;
			Fat.fade_element(clearDirDiv, 30, 500, "#FFF1B5");
			return;
		}
		else if (!endMarker) {
			var oDriveTo = document.getElementById('driveTo');
			endMarker = new GMarker(point,{icon:redIcon,draggable:false,bouncy:false});
			endMarker.formField = oDriveTo;
			//GEvent.addListener(endMarker,'drag',markerDrag);
			//GEvent.addListener(endMarker,'dragend',getDirections);
			map.addOverlay(endMarker);
			oDriveTo.value = endMarker.getPoint().lat().toFixed(6) + ',' + endMarker.getPoint().lng().toFixed(6);
			getDirections();
			//map.clearOverlays();
			return;
		} else if (endMarker) {
		  // both in place, let's move the endmarker to via and keep going:
		  var oDriveTo = document.getElementById('driveTo');
		  var oDriveVia = document.getElementById('driveVia');
		  if (oDriveVia.value) {
		    oDriveVia.value += ";"
		  }
		  oDriveVia.value += oDriveTo.value;
		  map.removeOverlay(endMarker);
		  map.removeOverlay(pLine);
		  endMarker = new GMarker(point,{icon:redIcon,draggable:false,bouncy:false});
                  endMarker.formField = oDriveTo;
                  //GEvent.addListener(endMarker,'drag',markerDrag);
                  //GEvent.addListener(endMarker,'dragend',getDirections);
                  map.addOverlay(endMarker);
		  oDriveTo.value = endMarker.getPoint().lat().toFixed(6) + ',' + endMarker.getPoint().lng().toFixed(6);
		  getDirections();
                  //map.clearOverlays();
                  return;
		}
	}
} 

function getDirections() {
if (!isPrinting) clearDirDiv.innerHTML=dr_2;
	if (!isPrinting) Fat.fade_element(clearDirDiv, 30, 500, "#FFF1B5");
	var oDriveFrom = document.getElementById('driveFrom');
	var oDriveTo = document.getElementById('driveTo');
	var oDriveVia = document.getElementById('driveVia');
	//var oLocale = document.getElementById('locale');

	//directionsInfoDiv.style.display = '';

	var loadStr;

	if (oDriveFrom.value && oDriveTo.value) {
		loadStr = 'from:' + oDriveFrom.value;
		if (oDriveVia.value) {
			var viaValue = oDriveVia.value.replace(/[\n\r]+/,"");
			var viaSteps = viaValue.split(';');
			for (var n = 0 ; n < viaSteps.length ; n++ ) {
				loadStr += ' to: ' + viaSteps[n];
			}
		}
		loadStr += ' to: ' + oDriveTo.value;
	}
	if (loadStr) {
		//indicateLoading();
		dirObj.load(loadStr,{locale:'en',getPolyline:true,getSteps:true});
		//updateLink();
	}

}

var drawing_route=false;

function clearDirections() {
  //alert("'"+clearDirDiv.innerHTML+"'\n'"+dr_start+"'");
  if (clearDirDiv.innerHTML == dr_start) {
    drawing_route = true;
    clearDirDiv.innerHTML = dr_1;
    clear_all_destinations();
    clear_all_regions();
    resetDirDiv.removeClass('hidden');
    Fat.fade_element(clearDirDiv, 30, 500, "#FFF1B5");
    return;
  }
}

function gclearDirections() {
  if (pLine) map.removeOverlay(pLine);
  if (startMarker) map.removeOverlay(startMarker);
  if (endMarker) map.removeOverlay(endMarker);
  startMarker=null;
  endMarker=null;
  directionPoints = "";
  pLine = null;
  var oDriveFrom = document.getElementById('driveFrom');
  var oDriveTo = document.getElementById('driveTo');
  var oDriveVia = document.getElementById('driveVia');
  oDriveFrom.value="";
  oDriveTo.value="";
  oDriveVia.value="";
  clearDirDiv.innerHTML = dr_start;
  resetDirDiv.addClass('hidden');
  drawing_route = false;
  Fat.fade_element(clearDirDiv, 30, 500, "#FFF1B5");
  Moved();
}

function onDirectionsLoad() {
	var html = '';
	var status = dirObj.getStatus();
	var bounds = dirObj.getBounds();


	//map.clearOverlays();

	var copyrightHTML = dirObj.getCopyrightsHtml();
	var summaryHTML = dirObj.getSummaryHtml();
	var distance = dirObj.getDistance();
	var duration = dirObj.getDuration();
	var numRoutes = dirObj.getNumRoutes();
	var oDriveFrom = document.getElementById('driveFrom');
	var oDriveTo = document.getElementById('driveTo');
	var startLatLng = dirObj.getRoute(0).getStep(0).getLatLng();
	var endLatLng = dirObj.getRoute(numRoutes-1).getEndLatLng();

	pLine = dirObj.getPolyline();
	//pLine = copyPolyline(polyline);
	map.addOverlay(pLine);

// directions if printing:
if (isPrinting) {
        for (var r = 0 ; r < numRoutes ; r++ ) {
		var route = dirObj.getRoute(r);
		var startGeoCode = dirObj.getGeocode(r);//route.getStartGeocode();
		var endGeoCode = dirObj.getGeocode(r+1);//route.getEndGeocode();
		var endLatLng = route.getEndLatLng();
		var routeSummaryHTML = route.getSummaryHtml();
		var routeDistance = route.getDistance();
		var routeDuration = route.getDuration();
		html += '<div class="routeSummaryDiv" onclick="toggleSteps('+r+')" title="Click to view steps">';
		html += '<table cellspacing="0" cellpadding="2" width="100%">';
		html += '<tr>';
		
		if (numRoutes == 1) {
			html += '<td valign="top"><img src="images/greenCircle.png"><br><img src="images/redCircle.png"></td>';
		}
		else {
			if (r == 0) {
				html += '<td valign="top"><img src="images/greenCircle.png"><br><img src="images/yellowSquare.png"></td>';
				var midMarker = new GMarker(endLatLng,{icon:yellowIcon});
				map.addOverlay(midMarker);
			}
			else if (r == numRoutes - 1) {
				html += '<td valign="top"><img src="images/yellowSquare.png"><br><img src="/images/redCircle.png"></td>';
			}
			else {
				html += '<td valign="top"><img src="images/yellowSquare.png"><br><img src="images/yellowSquare.png"></td>';
				var midMarker = new GMarker(endLatLng,{icon:yellowIcon});
				map.addOverlay(midMarker);
			}
		}
		
		html += '<td valign="top"><b>' + startGeoCode.address + '</b> to<br> <b>' + endGeoCode.address + '</b><br>'+routeDistance.html+ ' (' + routeDuration.html +  ')</td>';
		html += '</table></div>';

		var numSteps = route.getNumSteps();
		html += '<table cellspacing="0" cellpadding="0" id="routeTable_'+r+'" style="display:" width="100%">';
		for (var s = 0 ; s < numSteps ; s++ ) {
			var step = route.getStep(s);
			var stepLatLng = step.getLatLng();
			bounds.extend(stepLatLng);

			var stepPolylineIndex = step.getPolylineIndex();
			var stepDescriptionHTML = step.getDescriptionHtml();
			var re = new RegExp(pattern,'g');
			stepDescriptionHTML = stepDescriptionHTML.replace(re,'<b style="color:#00CA39">$1</b>')
			var stepDistance = step.getDistance();
			var stepDuration = step.getDuration();
			html += '<tr class="stepRow" onclick="showStep('+r+','+s+')"><td>&nbsp;&nbsp;' + (s+1) + '.</td><td> ' + stepDescriptionHTML + '</td><td>' + stepDistance.html + '</td></tr>';
		}
		html += '</table>';
	}
	
	$('print_right').innerHTML = html;

}

	Moved();
}

function copyPolyline(p) {
	pLinePoints = Array();
	for (var n = 0 ; n < p.getVertexCount() ; n++ ) {
	  v = p.getVertex(n);
          pLinePoints.push(p.getVertex(n));
	}
	var pLine = new GPolyline(pLinePoints,'#F7098A');
	return pLine;
}

function getDirectionPointsInView(p) {
  directionPoints = "";
  mapBounds = map.getBounds();
  step = 15;
  //if (gr_view.gr_z < 10) step = 20-(gr_view.gr_z*2);
  for (var n = 0 ; n < p.getVertexCount() ; n+=step ) {
    v = p.getVertex(n);
    //if (mapBounds.contains(v)) {  // don't test this here - leave it out so our bounds are always the same
      if (directionPoints) directionPoints += "|";
      directionPoints+=v.lat()+','+v.lng();
    //}
  }
  return directionPoints;
}

function viaDestination(dName,lat,lng) {
  var oDriveVia = document.getElementById('driveVia');
  if (oDriveVia.value) {
    oDriveVia.value += ";"
  }
  oDriveVia.value += lat+","+lng;
  CloseDestination();
  map.removeOverlay(pLine);
  getDirections();
}






	
	//function gr_init(x, y, z, max_dests, base_url, route_span) {
	function gr_init(lng,lat,w,h,z,rg,rt,c,s,cats, max_dests, base_url, my_dests, site, dirFrom, dirTo, dirVia) {
		gr_view.gr_my_dests = my_dests;
		gr_view.gr_long = lng;
		gr_view.gr_lat = lat;
		gr_view.gr_z = z;
		gr_view.gr_w = w;
		gr_view.gr_rg = rg;
		gr_view.gr_rt = rt;
		gr_view.gr_c = c;
		gr_view.gr_s = s;
		gr_view.gr_cats = cats;
		gr_view.gr_site = site;
		var oDriveFrom = document.getElementById('driveFrom');
	        var oDriveTo = document.getElementById('driveTo');
	        var oDriveVia = document.getElementById('driveVia');
	        oDriveFrom.value = dirFrom || '';
	        oDriveTo.value = dirTo || '';
	        oDriveVia.value = dirVia || '';
	        
		
		gr_log('lat long:' + gr_view.gr_lat + ',' + gr_view.gr_long+' '+gr_view.gr_z);
		// create the map
		map = new GMap2(document.getElementById("map"));
		//map.removeMapType(G_SATELLITE_MAP);
		//map.removeMapType(G_HYBRID_MAP);
		if (!isPrinting) {
                  map.addControl(new GSmallMapControl());
                  map.addControl(new GMapTypeControl());
                  map.enableScrollWheelZoom();
                  map.enableDoubleClickZoom();
                }
		map.setCenter(new GLatLng(gr_view.gr_lat,gr_view.gr_long), gr_view.gr_z);
		dirObj = new GDirections();
		GEvent.addListener(dirObj, "load", onDirectionsLoad);
		
		gr_view.MAX_OVERLAYS = max_dests;
		gr_view.BASEURL = base_url;
		
		// get actual span lat & long from map
		var span = map.getBounds().toSpan();
		gr_view.gr_h = span.lat();  
		gr_view.gr_w = span.lng();
		
		if (!isPrinting) {
                  // add move listener
                  GEvent.addListener(map, 'moveend', Moved);
                  //GEvent.addListener(map, 'zoomend', Moved);
                  GEvent.addListener(map, 'click', singleClick);
		}
		
		// ====== set up marker mouseover tooltip div ======
		tooltip = document.createElement("img");
		map.getPane(G_MAP_FLOAT_PANE).appendChild(tooltip);
		tooltip.style.visibility="hidden";
				
		// Load the XML file
		if (dirFrom && dirTo) {
		  getDirections();
		  //loadXMLfile();
		  return;
		}
		if (gr_view.gr_s) {
			document.getElementById("txtSearch").value = gr_view.gr_s;
			new_search();
		} else {
			gr_log('gr_init: loadXMLfile');
			loadXMLfile();
		}
	}
	
	function GetObjectFromParent(oParent, sID) {

		for (var i = 0; oParent.childNodes[i]; i++ ) {
			if (oParent.childNodes[i].id==sID) {
				return oParent.childNodes[i];
			}		
		}
	}
	
	// testing functions
	function dump_marker_q() {
		var out = "";
		for(var i in marker_queue) {
			if (out) out += ", ";
			out += marker_queue[i].getId();
		}
		alert(out);
	}
	
	function gr_log(text) {
		if (debug) GLog.write(text);
	}
	


  }  else {
      alert("Sorry, the Google Maps API is not compatible with this browser");
}

function URLEncode (clearString) {
  var output = '';
  var x = 0;
  clearString = clearString.toString();
  var regex = /(^[a-zA-Z0-9_.]*)/;
  while (x < clearString.length) {
    var match = regex.exec(clearString.substr(x));
    if (match != null && match.length > 1 && match[1] != '') {
    	output += match[1];
      x += match[1].length;
    } else {
      if (clearString[x] == ' ')
        output += '+';
      else {
        var charCode = clearString.charCodeAt(x);
        var hexVal = charCode.toString(16);
        output += '%' + ( hexVal.length < 2 ? '0' : '' ) + hexVal.toUpperCase();
      }
      x++;
    }
  }
  return output;
}

