
//################################################################
//================================================================
//  Map
//================================================================
//################################################################

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  MapClicked
//  The map should only be clicked once for Omniture reporting.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var MapClicked = false;

	
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  map
//  Variable to hold map object. Set to null here and redefined 
//  on page load.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var map = null;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  InLocationSearch()
//  Determines if we're doing an "In Location Search" or not.
//  Checks radio button in form above map.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//function InLocationSearch()
//{
    //if (gE("tmf_location") != null)
    //{
    //    if (gE("tmf_location").checked)
    //    {
    //        return true;
    //    }
    //}
    //return false;
    
//}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  New logic for SCRIPPS
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  DoReloadResults = true if the checkbox is checked.
//  All other logic follows suit.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function DoReloadResults()
{
    if (gE("mlo_loc"))
    {
        if (gE("mlo_loc").checked)
        {
            return false;
        }
    } 
     return true;
}  
    
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  PageLoader()
//  Called on Page Load. Captures mouse position for Region Marker
//  rollover bubble and loads map.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function PageLoader()
{
    CaptureMouseXY();
	LoadMap();
	
	//for displaying an ad on the map - ana 11/17/08
	lat49App.init(map);
	lat49App.eventFired();//to display the ad when the page loades
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  Alters the CSS opacity of a Div Object
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function DivObjOpacity(DivObj, Op)
{
    if (DivObj.id == "map") // the DIV containing the map
    {
        var re = /MSIE\s(\d+\.\d+);/;
        if (re.test(navigator.userAgent)) //test for MSIE x.x;
        { 
            var matches = re.exec(navigator.userAgent);
            var ieversion= new Number(matches[1]); // capture x.x portion, make a number
//            if (ieversion < 7)
//            {
                return;
//            }
        }
    }
    	DivObj.style.opacity = Op / 100;
	DivObj.style.filter = 'alpha(opacity=' + Op + ')';
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// A TextualZoomControl is a GControl that displays textual "Zoom In"
// and "Zoom Out" buttons (as opposed to the iconic buttons used in
// Google Maps).
// We define the function first
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function TextualZoomControl() {}

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // To "subclass" the GControl, we set the prototype object to
    // an instance of the GControl object
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    TextualZoomControl.prototype = new GControl();
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // 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"); 
        container.className = "map_zoom clearfix";
        container.id = "ZoomContainer";
        var zoomInDiv = document.createElement("div");  
        zoomInDiv.className = "zoom_in";
        //this.setButtonStyle(zoomInDiv);  
        container.appendChild(zoomInDiv);  
        zoomInDiv.innerHTML = "<img src='" + WebRoot + "images/zoom_bar/zoom_in.gif' />";
        //zoomInDiv.appendChild(document.createTextNode("+"));  
        GEvent.addDomListener(zoomInDiv, "click", function() 
        {    
            DoZoomIn();
        });
        
        var zoomLevel = document.createElement("div");  
        zoomLevel.className = "level";
        //this.setLevelStyle(zoomLevel);  
        container.appendChild(zoomLevel);  
        zoomLevel.innerHTML = "<img src='" + WebRoot + "images/zoom_bar/" + map.getZoom() + ".gif' usemap='#ZTracker' />";
        GEvent.addDomListener(map, "zoomend", function() 
        {   
            zoomLevel.innerHTML = "<img src='" + WebRoot + "images/zoom_bar/" + map.getZoom() + ".gif' usemap='#ZTracker' />";
        });
        
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  HoverZoom() is Obsolete.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~        
//        GEvent.addDomListener(container, "mouseover", function() 
//        {   
//            HoverZoom('on');
//        });
//        GEvent.addDomListener(container, "mouseout", function() 
//        {   
//            HoverZoom('off');
//        });
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

        var zoomOutDiv = document.createElement("div");  
        zoomOutDiv.className = "zoom_out";
        //this.setButtonStyle(zoomOutDiv);  
        container.appendChild(zoomOutDiv);  
        zoomOutDiv.innerHTML = "<img src='" + WebRoot + "images/zoom_bar/zoom_out.gif' />";
        //zoomOutDiv.appendChild(document.createTextNode("-"));  
        GEvent.addDomListener(zoomOutDiv, "click", function() 
        {    
            DoZoomOut();  
        });
        
        map.getContainer().appendChild(container);  
        return container;
    };
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // 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(8, 8));
    };

    
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  DoZoomOut()
//  Function controls Zoom Out button on Zoom control
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function DoZoomOut()
{
    if ((map.getZoom()-1) > 3)
    {
        //MCO.AddPan(map.getCenter(), map.getZoom());
        map.zoomOut();
        
        //ana - if it's a school district search don't requeryonbounds just do zoomOut
        var isschoolsearch = false;
	    if (gE('isschoolsearch'))
	        isschoolsearch = true;
	        
	    if (!isschoolsearch)
            RequeryOnBounds(false,true);
    }
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  DoZoomIn()
//  Function controls Zoom In button on Zoom control
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function DoZoomIn()
{
    if ((map.getZoom()+1) <= 16)
    {
        //MCO.AddPan(map.getCenter(), map.getZoom());
        map.zoomIn();
        
        //ana - if it's a school district search don't requeryonbounds just do zoomIn
        var isschoolsearch = false;
	    if (gE('isschoolsearch'))
	        isschoolsearch = true;
	        
	    if (!isschoolsearch)
            RequeryOnBounds(false,true);
    }
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  DoZoom(num)
//  Function controls Zoom Level Links on Zoom control
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function DoZoom(num)
{
    if ((num <= 16) && (num >= 2))
    {
        //MCO.AddPan(map.getCenter(), map.getZoom());
        map.setZoom(num);
        
        //ana - if it's a school district search don't requeryonbounds
        var isschoolsearch = false;
	    if (gE('isschoolsearch'))
	        isschoolsearch = true;
	        
	    if (!isschoolsearch)
            RequeryOnBounds(false,true);
    }
}

function MapPosCache()
{
    this.Center = null;
    this.Zoom = null;
    
    MapPosCache.prototype.Save = function(MapObject)
    {
        this.Center = MapObject.getCenter();
        this.Zoom = MapObject.getZoom();
    };
    
    MapPosCache.prototype.Restore = function(MapObject)
    {
        MapObject.setCenter(this.Center, this.Zoom);
    };
}

var MapPosCache = new MapPosCache();

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  LoadMap()
//  Main function called to initialize the map
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function LoadMap()
{
    map = new GMap2(gE("map"));
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  OVControl
    //  The small version of the map in the lower right corner
    //  After added to the map, you can get a reference to the 
    //  Overview map control using this syntax:
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  var OVMap = OVControl.getOverviewMap();
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    var OVControl = new GOverviewMapControl();
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  Add controls to the map
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	map.addControl(OVControl);                  // Overview Control
	//OVControl.hide(true); 

	map.addControl(new GMapTypeControl());      // Map Type ie. Map, Satellite, Hybrid
	map.addControl(new TextualZoomControl());   // Custom Zoom Control
	
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  DefaultLatitude, DefaultLongitude, DefaultZoom
    //  are defined on the loading page before this script is called
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	map.setCenter(new GLatLng(DefaultLatitude, DefaultLongitude), DefaultZoom);
	
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  Add map event listeners
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	GEvent.addListener(map, "dragend", function()
	{
	    //ana - if it's a school district search don't requeryonbounds
	    var isschoolsearch = false;
	    if (gE('isschoolsearch'))
	        isschoolsearch = true;
	        
	    //ZoomCache.factor = 0;
	    crosshair();
	    //map.savePosition();
	    //````````````````````````````````````````````````````````````````
	    // don't requery if the info window is open.
	    //````````````````````````````````````````````````````````````````
	    
	    var topLat = map.getBounds().getNorthEast().lat(); // 85
        var botLat = map.getBounds().getSouthWest().lat(); // -85
        
        if (topLat > 85 || botLat < -85)
        {
            
            MapPosCache.Restore(map);
            //alert(" A ha! ");
            return;
        }
	    if ((map.getInfoWindow().isHidden())&&(!isschoolsearch))
	    {
	        //when the map is draged it automatically switch to map area and reloads results - ana_12/5/2008
	        gE('mlo_map').checked ='checked';
	        ToggleMapLoadOption(gE('mlo_map'));
	     //   window.setTimeout(function(){ // allows crosshairs to exit before pause caused by query
           //     RequeryOnBounds(false,true);
         //   },100);
		}
//		 var SW = map.getBounds().getSouthWest();
//         var NE = map.getBounds().getNorthEast();
//         var string = "";
//         string += "\nSW Lat: " + SW.lat();
//         string += "\nSW Lng: " + SW.lng();
//         string += "\nNE Lat: " + NE.lat();
//         string += "\nNE Lng: " + NE.lng();
//        alert(string);
        
        

	});
	
	
	GEvent.addListener(map, "dragstart", function()
	{
	     crosshair();
	     MapPosCache.Save(map);
	});		
    
    
    GEvent.addListener(map, "mousedown", function()
	{
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	    //  OmEvent = calls Omniture script for reporting events
	    //  Should only report first click on map for any full page load
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		if (MapClicked == false)
		{
		    OmEvent(this, 6, 'map_clicked');
		    MapClicked = true;
		}
	});
	
    GEvent.addListener(map, "infowindowopen", function()
	{
		map.savePosition();
	});
	GEvent.addListener(map, "infowindowclose", function()
	{
		map.returnToSavedPosition();
	});

	       
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  FirstLoad()
    //  The FirstLoad function is defined on the front end page
    //  before this script is called. The script in the function comes
    //  from the XML document, from C#. It plots the Listings and 
    //  Regions on the map for itinial page load.
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	FirstLoad();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  NextLoad(ListingsJS, RegionsJS, Recenter)
//  Manages clearing the map and redrawing overlays from the data
//  aquired through Sarissa
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function NextLoad(ListingsJS, RegionsJS, Recenter)
{
    OverlayCache.RemoveCacheTypes(["GLatLng", "Listing", "Region", "Neighborhood"]);
    map.clearOverlays();
    eval(RegionsJS);
    eval(ListingsJS);
    if (DoReloadResults())
    {
        OverlayCache.RemoveOverlayType("Neighborhood");
        OverlayCache.RemoveCacheType("Neighborhood");
        OverlayCache.RemoveOverlayType("PrimeNeighborhood");
        OverlayCache.RemoveCacheType("PrimeNeighborhood");
    }
    if (PageCache.MapBestFit != "neighborhoods")
	{
        RenderMapOptions(Recenter);
    }
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  PostPointLoading(Recenter)
//  Called after all points have been drawn on the map
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function PostPointLoading(Recenter)
{
	//ShowLoading(null,false);
	if (Recenter==true)
	{
	    MapBestFit();
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  MapBestFit()
//  Recenters and zooms map based on current OverlayCache.GetType("GLatLng")
//  array only. Does not take Regions Markers into account.
//  Only called once per data refresh.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function MapBestFit()
{
    
    var GLatLngs = OverlayCache.GetType("GLatLng");
    
    //if (CacheListingsGLatLng.length==0){return;}
    if (GLatLngs.length==0){return;}
    
    var Bounds = new GLatLngBounds();
    
    for (var i=0; i<GLatLngs.length; i++)
    {
        Bounds.extend(GLatLngs[i]);
    }
    var Zoom = map.getBoundsZoomLevel(Bounds);
    var Center = Bounds.getCenter();
        map.setCenter(Center, Zoom);
        
        //CacheListingsGLatLng = new Array(); // reset
        OverlayCache.RemoveCacheType("GLatLng"); // reset
}

function MapBestFitBounds(Bounds, PadBoundsPercent)
{
    
    if (PadBoundsPercent == undefined)
    {
        PadBoundsPercent = 0;
    }
        var SW = Bounds.getSouthWest();
        var NE = Bounds.getNorthEast();
        var LatMin  = SW.lat();
        var LatMax  = NE.lat();
        var LngMin  = SW.lng();
        var LngMax  = NE.lng();
        
        var LngWidth;
        var LatHeight;
        
        var OneMileDegree  = 0.014456985391147119775966262872049;
        var OneMeterDegree = OneMileDegree / 1609.344;
        
            LatHeight = (new GLatLng(LatMin,LngMin).distanceFrom(new GLatLng(LatMax,LngMin))) * OneMeterDegree;
            LngWidth  = (new GLatLng(LatMin,LngMin).distanceFrom(new GLatLng(LatMin,LngMax))) * OneMeterDegree;

        var PaddingLat = ( LatHeight / 100 ) * ( PadBoundsPercent / 2 );
        var PaddingLng = ( LngWidth / 100 ) * ( PadBoundsPercent / 2 );
        
        //alert(PaddingLat + ":" + PaddingLng);
        
        var PaddingPointSW = new GLatLng(SumPadding(SW.lat(), PaddingLat, -1), SumPadding(SW.lng(), PaddingLng, -1));
        var PaddingPointNE = new GLatLng(SumPadding(NE.lat(), PaddingLat, +1), SumPadding(NE.lng(), PaddingLng, +1));
        
        //var PaddingPointSW = new GLatLng(SW.lat() - PaddingLat, SW.lng() - PaddingLng);
        //var PaddingPointNE = new GLatLng(NE.lat() + PaddingLat, NE.lng() + PaddingLng);
        
            //var Bounds1 = new GLatLngBounds(Bounds.getSouthWest(), Bounds.getNorthEast());
            var BoundsNew = new GLatLngBounds(PaddingPointSW, PaddingPointNE);
         
         
            //alert(Bounds1 + "\n" + Bounds2);
            
    //alert(map.getZoom());
    var Zoom = map.getBoundsZoomLevel(BoundsNew);
    var Center = BoundsNew.getCenter();
    //alert(Zoom);
        map.setCenter(Center, Zoom);
}

function SumPadding(value, padding, sign)
{
    padding = padding * sign;
	value += padding;
	return value;
}

function RenderMapOptions(Recenter)
{
    if (Recenter)
    {
        var MapBounds;
        switch(PageCache.MapBestFit)
        {
            case "mapbounds":
                    MapBounds = GetBoundsFromQueryString(PageCache.QueryString);
                    MapBestFitBounds(MapBounds);
                    break;
            case "regions":
                    MapBounds = OverlayCache.GetMapBoundsByType("Region");
                    var Zoom = map.getBoundsZoomLevel(MapBounds);
                    if (Zoom <= 3) // international
                    {
                        MapBestFitBounds(MapBounds, 25);
                    }
                    else
                    {
                        MapBestFitBounds(MapBounds, 5);
                    }
                    break;
            case "neighborhoods":
                    MapBounds = OverlayCache.GetMapBoundsByType("PrimeNeighborhood");
                    MapBestFitBounds(MapBounds, 1);
                    break;
            case "listings":
                    MapBounds = OverlayCache.GetMapBoundsByType("Listing");
                    MapBestFitBounds(MapBounds, 2);
                    break;
            default:
                    MapBounds = OverlayCache.GetMapBoundsByType("Listing");
                    MapBestFitBounds(MapBounds, 2);
                    break;
        }
        
    }
    var RenderMapTypes = ["Region", "PrimeNeighborhood"];
    if (PageCache.ShowListingsOnMap)
    {
        RenderMapTypes.push("Listing");
    }
    OverlayCache.RenderOverlayTypes(RenderMapTypes);
   // gE("map").style.opacity = 1.0;
	//gE("map").style.filter = 'alpha(opacity=100)';
    //LdImgs.Init("listingimg", "images/no_photo2.gif");
}

function GetBoundsFromQueryString(QueryString)
{
    var LatMin, LatMax, LngMin, LngMax;
    var Bounds = new GLatLngBounds();
    var UGen = new UrlGen(QueryString);
    var eles = unescape(UGen.GetParam("Nf")).split("||");
    var isLatLng = 0;
    for (var x=0;x<eles.length;x++)
    {
        var Filter = eles[x].split("|");
        if (Filter[0].toLowerCase() == "latitude")
        {
            var FilterVals = Filter[1].split(" ");
                LatMin = parseFloat(FilterVals[1]);
                LatMax = parseFloat(FilterVals[2]);
                if (!(isNaN(LatMin) | isNaN(LatMax)))
                {
                    isLatLng++;
                }
                
        }
        else if (Filter[0].toLowerCase() == "longitude")
        {
            var FilterVals = Filter[1].split(" ");
                LngMin = parseFloat(FilterVals[1]);
                LngMax = parseFloat(FilterVals[2]);
                if (!(isNaN(LatMin) | isNaN(LatMax)))
                {
                    isLatLng++;
                }
        }
    }
    if (isLatLng > 1)
    {
        Bounds.extend(new GLatLng(LatMin, LngMin));
        Bounds.extend(new GLatLng(LatMax, LngMax));
    }
    return Bounds;
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  gEOpenNearCities
//  gECloseNearCities
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  Controls the opening and closing of the "nearbyCities" and
//  "NearbyNeighborhoods" flyout menus
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function gEOpenNearCities(objId, objId2, display)
{
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  Problem: we cannot get values from the div related to 
    //  position unless the object style.display = "block"
    //  Solution: we set visibility = "hidden" so we can perform 
    //  the move "in the dark", then make it visible later.
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    gE(objId).style.visibility = "hidden"; 
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    gE(objId).style.display = display;
    gE(objId2).style.background = '#E9F3F3';
    var ObjMenuOffset   = new RecurseOffset(objId);
    var ObjAnchorOffset = new RecurseOffset(objId2);
    var WinBounds = new GetWindowBunds();
    var MenuBottom = ObjMenuOffset.offsetTop + ObjMenuOffset.offsetHeight;
    var ScrollBottom = WinBounds.VisibleTop + WinBounds.VisibleHeight;
    
    if (MenuBottom > ScrollBottom) // perform the move only if we need to
    {
        var buffer = 10;
        var MoveTo = ((MenuBottom - ScrollBottom) + buffer) * -1;
        /*
        // debug info
        alert(String.format("MenuBottom:{0}\n\
ScrollBottom:{1}\n\
MoveTo:{2}",
        MenuBottom,
        ScrollBottom,
        MoveTo));
        */           
        gE(objId).style.top = MoveTo + "px";

    }
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  Hide form select elements in collision with the menu
    //  see global.js
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    SweepSelects(objId);
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  Finally, Restore Visibility
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    gE(objId).style.visibility = "visible";

    
}
function gECloseNearCities(objId, objId2, display)
{
    gE(objId).style.top = "0"; // ensure menu object is reset to default relative position
    gE(objId).style.display = display;
    gE(objId2).style.background = 'none';
    RestoreSelects(); // bring back selects hidden in Opener
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  Controls the "crosshair" that appears in the center of the 
//  map when dragging
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function crosshair()
{
    var C = new RecurseOffset(gE("crosshair"));
    var M = new RecurseOffset(gE("map"));
    var D = gE("crosshair").style.display;
//    var sts = " offsetWidth:" + M.offsetWidth + ": offsetHeight:" + M.offsetHeight;
//        sts += " offsetLeft:" + M.offsetLeft + ": offsetTop:" + M.offsetTop;
//        sts += " -- " + ( parseInt((M.offsetWidth/2) + M.offsetLeft,10) -4 ) + ":" + ( parseInt((M.offsetHeight/2) + M.offsetTop,10) -3 );
//    window.status = sts;
    switch(D)
    {
        case "block":
            gE("crosshair").style.left = "-100px"
            gE("crosshair").style.display = "none";
            break;
        case "none":
            gE("crosshair").style.left = ( parseInt((M.offsetWidth/2) + M.offsetLeft,10) -4 ) + "px";
            gE("crosshair").style.top  = ( parseInt((M.offsetHeight/2) + M.offsetTop,10) -3 ) + "px";
            gE("crosshair").style.display = "block";
            break;
    }
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  getN
//  Calls polygon data through Ajax
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  TODO: Add encrypted request code
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function getN(strRID, fillColor, borderColor, boolPrimaryNeighborhood)
{
    var NiD = "Neighborhood";
    if (boolPrimaryNeighborhood == true)
    {
        NiD = "Prime" + NiD;
    }
    else
    {
        boolPrimaryNeighborhood = false;
        removeN(strRID);
    }
    
    //alert(NiD + ":" + strRID + ":" + borderColor + ":" + boolPrimaryNeighborhood);
    
    var strURL = String.format("{0}Controls/AjaxCalls/GetN.aspx?RID={1}&B={2}", WebRoot, strRID, borderColor);
    
    //OverlayCache.RemoveCacheType("Neighborhood");
    //if (boolPageLoad == undefined)
    //{
    //    boolPageLoad = false;
    //}
    //if (boolPageLoad)
    //{

    if (OverlayCache.GetByTypeId("PrimeNeighborhood", strRID) != null)
    {
        //  Do not highlight neighborhood or add neighborhood 
        //  if it is already the prime neighborhood
        return;
    }
    
    
    $AJAX.GetForDelegate(function(AjaxResponse)
    {
        OverlayCache.RemoveOverlayType("Neighborhood");
        OverlayCache.RemoveCacheType("Neighborhood");
        OverlayCache.Add(NiD, strRID, eval("new GPolygon.fromEncoded({\
		      polylines: [" + AjaxResponse + "],\
		      fill: true,\
		      color: '#" + fillColor + "',\
		      outline: true\
		    });"));
	    OverlayCache.RenderOverlayType(NiD);
		
		if (NiD=="PrimeNeighborhood")
		{
		    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		    //  if we're here, then it's a new Primary Neighborhood,
		    //  requiring that we recenter on the neighborhood boundaries
		    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		    RenderMapOptions(true);
		}
		
    }, strURL);
    return;
    //}
    /*
    for (var x=0;x<Pollies.length;x++)
    {
        if (Pollies[x][0] == strRID)
        {
            map.addOverlay(Pollies[x][1]);
            return;
        }
    }
    
    $AJAX.GetForDelegate(function(AjaxResponse)
    {
        var tPoly = eval("new GPolygon.fromEncoded({\
			  polylines: [" + AjaxResponse + "],\
			  fill: true,\
			  color: '#" + fillColor + "',\
			  outline: true\
			});");
			
         Pollies.push([strRID, tPoly]);
		 map.addOverlay(tPoly);
		 
    }, strURL);
    */
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  removeN(strRID)
//  Removes all highlighted neighborhoods from map, except Prime
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function removeN(strRID)
{
    //alert("here");
    OverlayCache.RemoveOverlayType("Neighborhood");
    OverlayCache.RemoveCacheType("Neighborhood");
    //OverlayCache.RenderOverlayType("Neighborhood");
    //alert("here");
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  CustomZIndexOrder
//  This is the delegate to pass to the zIndexProcess property of the 
//  Marker constructor. Don't know what the b value is or what it's used for.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function CustomZIndexOrder(Marker, b) 
{
    return GOverlay.getZIndex(Marker.getPoint().lat()) + Marker.CustomZIndex * 1000000;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  ReturnLastPan()
//  Returns map to last queried state
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function ReturnLastPan()
{
	RunQuery(PageCache.LastQueryString, true);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  Get_Detail(IdListing)
//  Jump to the Listing Detail page
//  We need to carry several hidden form parameters with us
//  for Paging and Return to Results
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function Get_Detail(IdListing)
{
    var UGen = new UrlGen(PageCache.QueryString);
        UGen.RemoveParams(["LID","LIDS","T"]);
        UGen.AddParam("T",PageCache.TotalRecords);
        UGen.AddParam("LID",IdListing);
        UGen.AddParam("LIDS",PageCache.ListingIds.replace(/,/g,'--'));
        
        var strURL = WebRoot + "controls/ajaxcalls/DetailListingPath.aspx?" + UGen.ToString();
        //alert(strURL);
        $AJAX.GetForDelegate(function(AjaxResponse)
        {
            //alert(AjaxResponse);
            window.location.href = AjaxResponse;
            
        }, strURL);
        
//        if (WebRoot != "/")
//        {
//            window.location.href = WebRoot + "detail.aspx?" + UGen.ToString();
//            return;
//        }
//        
//        var theTarget = String.format("/for-sale/listing/{1}", WebRoot, IdListing);

//        document.SEO.Query.value = UGen.ToString();
//        document.SEO.action = theTarget;
//        document.SEO.submit();
}



//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  ToggleMapLoadOption
//  manages the ckeckbox that allows users to either reload the entire
//  page of results, or only the map.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function ToggleMapLoadOption(ele)
{
    var CookieName = LastSearchCookieName; // Defined in the top of results.aspx
    var Key = "MapLoadOption";
    var Value = "False";
//    alert(ele.id);
//     alert(ele.checked);
    if (ele.checked)
    {
        if (ele.id == "mlo_map")
        {
            Value = "True";
            window.setTimeout(function()
            {
                RequeryOnBounds(false, true);
            },100);
        }
    }
    SetCookieState(CookieName, Key, Value);
}




//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  MapHelp
//  Opens the map help div using jquery thickbox
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function MapHelp()
{
    tb_show('Map Help', WebRoot + "help/help_results_map.aspx?&height=400&width=550", false);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  MarkerNumbers Array
//  Contains paths to MArker Number images that appear on top of 
//  Listing MArkers
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var MarkerNumbers = new Array();
for(var i = 1; i < 51; i++)
{
	if(i < 10)
	{
		MarkerNumbers[i] = WebRoot + 'images/map_markers/0' + i + '.png';
	}
	else
	{
		MarkerNumbers[i] = WebRoot + 'images/map_markers/' + i + '.png';
	}
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  AddRegionMarker()
//  Adds Region Icon to the map
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function AddRegionMarker(RegionName, ListingsCount, ENEQueryString, RegionId, Latitude, Longitude, Level)
{
    var Point = new GLatLng(parseFloat(Latitude), parseFloat(Longitude));
    
    if (PageCache.CenterOnRegions == true)
    {
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //  cache points for use when recentering map on points
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //CacheListingsGLatLng.push(Point);
        OverlayCache.Add("GLatLng", RegionId, Point);
    }
        
    var IconConstructor = new GIcon();
        IconConstructor.image = WebRoot + 'images/map_markers/region' + Level + '_off.png';
        IconConstructor.iconSize = new GSize(16.0, 16.0);
	    IconConstructor.shadow = WebRoot + 'images/map_markers/region' + Level + '_shadow.png';
        IconConstructor.shadowSize = new GSize(25.0, 16.0);
        IconConstructor.iconAnchor = new GPoint(8.0, 8.0);
        IconConstructor.infoWindowAnchor = new GPoint(8.0, 8.0);
        IconConstructor.transparent = WebRoot + 'images/map_markers/region' + Level + '_transparent.png';
        IconConstructor.imageMap = [6,2,12,4,14,8,12,11,9,13,6,13,2,9,3,5];
        
	    
    var Icon = new GIcon(IconConstructor);

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  Creation of the actual marker
    //  zIndexProcess controls the ZIndex of the marker itself
    //  The property requires a Function reference to be passed to it
    //  The Function evaluates when map.addOverlay is called.
    //  Note: You cannot pass a Delegate to this property, only a 
    //  Delegate/Function by name
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  The higher the value passed to the Marker.CustomZIndex property,
    //  the highr to the top the marker will lay
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //var Marker = new GMarker(Point, Icon);
    var Marker = new GMarker(Point, {zIndexProcess:CustomZIndexOrder, icon:Icon});
        Marker.CustomZIndex = Level * -1; // states overlap city, cities overlap neighborhood
        
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //    Set Rollover and Popup text
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
       var s = "s";
       if (parseInt(ListingsCount,10) == 1)
       {
            s = "";
       }
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  LevelName is Obsolete
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /*
    var LevelName = "";
    switch(Level)
    {
        case 1:
            LevelName = "State";
            break;
        case 2:
            LevelName = "County";
            break;
        case 3:
            LevelName = "City";
            break;
         case 4:
            LevelName = "Neighborhood";
            break;
    }
    */
        
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //    Set the event listeners
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    GEvent.addListener(Marker, "click", function()
    {
	    ROut();
	    LocationQuery(ENEQueryString.replace(/&amp;/gi,"&"), true, false); 
    });
    
    if (Level==4) // neighborhood
    {
        GEvent.addListener(Marker,"mouseover",function()
        {	
            Marker.setImage(WebRoot + 'images/map_markers/Region' + Level + '_on.png');
            
            ROInfoGMap("<B>" + RegionName + "<BR>" + FormatNumber(ListingsCount) + "</B> Listing" + s);
            //~~~~~~~~ Output Debug Info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            //ROInfoGMap("<B>" + RegionName + "<BR>" + RegionId + "<BR>" + FormatNumber(ListingsCount) + "</B> Listing" + s);
            //ROInfoGMap("<B>" + RegionName + "<BR>" + FormatNumber(ListingsCount) + "</B> Listing" + s + "<BR>Lat:" + Latitude + "<BR>Lng:" + Longitude);
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            getN(RegionId, "4444bb", "0909fa");
        });
        GEvent.addListener(Marker,"mouseout",function()
        {	
            Marker.setImage(WebRoot + 'images/map_markers/Region' + Level + '_off.png');
            ROut();
            window.setTimeout(function()
            {
                removeN(RegionId);  
            },250);
        });
    }
    else
    {
        GEvent.addListener(Marker,"mouseover",function()
        {	
            Marker.setImage(WebRoot + 'images/map_markers/Region' + Level + '_on.png');
            //~~~~~~~~ Output Debug Info ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            //ROInfoGMap("<B>" + Level + ":" + RegionName + "<BR>" + FormatNumber(ListingsCount) + "</B> Listing" + s);
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            ROInfoGMap("<B>" + RegionName + "<BR>" + FormatNumber(ListingsCount) + "</B> Listing" + s);
            removeN(); 
        });
        GEvent.addListener(Marker,"mouseout",function()
        {	
            Marker.setImage(WebRoot + 'images/map_markers/Region' + Level + '_off.png');
            ROut();
            removeN(); 
        });
    }
    
    OverlayCache.Add("Region", RegionId, Marker);
    //map.addOverlay(Marker);
}
    
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  AddListingMarker()
//  Adds listings marker to the map
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function AddListingMarker(lat, lng, mType, rollOverText, UniqueId)
{ 
    var Point = new GLatLng(lat, lng);
    
    //CacheListingsGLatLng.push(Point); // caches points for use when zooming on bounds
    OverlayCache.Add("GLatLng", UniqueId, Point);

	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//	Create a new GIcon / GMarker object and set its location
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	
	var IconConstructor = new GIcon();
	switch(mType)
	{
	    case "single":
	        IconConstructor.image = WebRoot + 'images/map_markers/singlepoint_off.png';
	        IconConstructor.iconSize = new GSize(24.0, 24.0);
	        IconConstructor.shadow = WebRoot + 'images/map_markers/singlepoint_shadow.png';
	        IconConstructor.shadowSize = new GSize(37.0, 24.0);
	        IconConstructor.iconAnchor = new GPoint(12.0, 12.0);
	        IconConstructor.infoWindowAnchor = new GPoint(12.0, 12.0);
	        IconConstructor.transparent = WebRoot + 'images/map_markers/singlepoint_transparent.png';
	        IconConstructor.imageMap = [1,5,8,1,16,5,16,15,12,15,10,26,6,15,1,15];
	        var Label = {"url":MarkerNumbers[UniqueId+1], "anchor":new GLatLng(3,5), "size":new GSize(14,14)};
	        break;
	    case "featured":
	        IconConstructor.image = WebRoot + 'images/map_markers/featured_off.png';
	        IconConstructor.iconSize = new GSize(24.0, 24.0);
	        IconConstructor.shadow = WebRoot + 'images/map_markers/featured_shadow.png';
	        IconConstructor.shadowSize = new GSize(37.0, 24.0);
	        IconConstructor.iconAnchor = new GPoint(12.0, 12.0);
	        IconConstructor.infoWindowAnchor = new GPoint(12.0, 12.0);
	        IconConstructor.transparent = WebRoot + 'images/map_markers/featured_transparent.png';
	        IconConstructor.imageMap = [1,5,8,1,16,5,16,15,12,15,10,26,6,15,1,15];
	        var Label = {"url":MarkerNumbers[UniqueId+1], "anchor":new GLatLng(3,5), "size":new GSize(14,14)};
	        break;
	        
	        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	        //  Multi and Featured not currently implemented
	        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            //	    case "multi":
            //	        IconConstructor.image = WebRoot + 'images/map_markers/multipoint_off.png';
            //	        IconConstructor.shadow = WebRoot + 'images/map_markers/multipoint_shadow.png';
            //	        IconConstructor.iconSize = new GSize(24.0, 36.0);
            //	        IconConstructor.shadowSize = new GSize(52.0, 36.0);
            //	        IconConstructor.iconAnchor = new GPoint(0.0, 0.0);
            //	        IconConstructor.infoWindowAnchor = new GPoint(9.0, 12.0);
            //	        IconConstructor.transparent = WebRoot + 'images/map_markers/multipoint_transparent.png';
            //	        IconConstructor.imageMap = [10,25,10,18,3,18,0,16,0,2,3,0,16,0,18,3,18,17,10,25];
            //	        var Label = {"url":MarkerNumbers[UniqueId+1], "anchor":new GLatLng(5,5), "size":new GSize(14,14)};
            //	        break;
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	}
	
	var Icon = new GIcon(IconConstructor, null, Label);
	//var Icon = new GIcon(IconConstructor);
      
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  Creation of the actual marker
    //  zIndexProcess controls the ZIndex of the marker itself
    //  The property requires a Function reference to be passed to it
    //  The Function evaluates when map.addOverlay is called.
    //  Note: You cannot pass a Delegate to this property, only a 
    //  Delegate/Function name
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  The higher the value passed to the Marker.CustomZIndex property,
    //  the highr to the top the marker will lay
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	var Marker = new GMarker(Point, {zIndexProcess:CustomZIndexOrder, icon:Icon});
	    
	    if (mType == "featured")
	    {
	        Marker.CustomZIndex = 7;
	    }
	    else
	    {
	        Marker.CustomZIndex = 5;
	    }
	    
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	    //  Set marker event listeners
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	    GEvent.addListener(Marker, "click", function()
	    {
	        ROut();
		    map.savePosition();
		    Marker.openInfoWindowHtml(GetInfowindowBubble(MapPointCollection[UniqueId]));
	    });
    	
        GEvent.addListener(Marker,"mouseover",function()
        {	
            ROInfoGMap(rollOverText);
            Marker.setImage(WebRoot + 'images/map_markers/singlepoint_on.png');
        });
        GEvent.addListener(Marker,"mouseout",function()
        {	
            ROut();
            Marker.setImage(WebRoot + 'images/map_markers/singlepoint_off.png');
        });
	    
		//map.addOverlay(Marker);
		
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	    //  Add marker to OverlayCache
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	    OverlayCache.Add("Listing", parseInt(UniqueId,10), Marker);
	    //CacheListingMarkers[UniqueId] = Marker;
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  DisplayInfoWindow(num)
//  Pops open info window on map from ID of element selected
//  in CacheListingMarkers[] array
//  Called from click on page outside of map
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function DisplayInfoWindow(num)
{
    if (MapState.Current == "map_hidden")
    {
        MapState.Set("map_default", true);
        map.clearOverlays();
        RenderMapOptions(true);
    }
    var MapTop = RecurseOffset(gE("results_results")).offsetTop;
    if (document.documentElement)
    {
        var scrollTop = document.documentElement.scrollTop;
    }
    else
    {
        var scrollTop = document.body.scrollTop;
    }
    if (scrollTop > MapTop)
    {
        window.scrollTo(0,MapTop);
    }
	LsInfoWindow(num);
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  InfoWindow(num)
//  Called directly from Marker
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function LsInfoWindow(num)
{
    var Listing = OverlayCache.GetByTypeId("Listing", parseInt(num,10));
        Listing.openInfoWindow(GetInfowindowBubble(MapPointCollection[parseInt(num,10)]));

    //CacheListingMarkers[num].openInfoWindow(GetInfowindowBubble(MapPointCollection[num]));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  LsBlowup(num)
//  Shows blowup map view over marker. Called from marker only.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function LsBlowup(num)
{
    var bZoom = ( (map.getZoom() + 2) <= 17 ) ? (map.getZoom() + 2) : 17;
    var Listing = OverlayCache.GetByTypeId("Listing", parseInt(num,10));
        Listing.showMapBlowup({zoomLevel:bZoom});

    //CacheListingMarkers[num].openInfoWindow(GetInfowindowBubble(MapPointCollection[num]));
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  DisplayInfoWindow(num)
//  Pops open info window on map from ID of element selected
//  in CacheListingMarkers[] array
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function GetInfowindowBubble(data)
{
	if (PageCache.QueryString == null) { return "<div></div>"; }
	if (PageCache.XML == null)
	{
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	    //  IF there is no Cached XML doc, it's a fresh page load
	    //  and Sarissa has not been called yet
	    //  Make a call to get the XML doc 
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	    //  We need the XML because we call InfoWindows content 
	    //  from the XML doc
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		var xmlDocPath = "";
        xmlDocPath = "results_xml.aspx?" + PageCache.QueryString;
         
		var XMLDoc = Sarissa.getDomDocument();
		XMLDoc.async = false;
		var xmlhttp = new XMLHttpRequest();
		xmlhttp.open('GET', AbsoluteWebRoot + xmlDocPath, false);
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//  XKp
		//  An encrypted key used for (kind of) secure web requests
		//  To make it harder for scrapers to get our XML content
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		xmlhttp.setRequestHeader("Authorization", XKp);
		xmlhttp.send('');
		PageCache.XML = xmlhttp.responseXML;
            
		XSLProcessors.loadAll();
		XSLProcessors.loaded = true;
	}
    
	var arrElements = data.split(',');
    
	if (arrElements.length > 1)
	{
		var strHTML = "<div class=\"info_window_multi\">";
	}
	else
	{
		var strHTML = "";
	}
	for (var i=0; i<arrElements.length; i++)
	{
		var thisEle = arrElements[i].split('|');
		var thisXPath = String.format("/results/listings/listing[./idlisting='{0}']", thisEle[1]);
		var TempXDoc = GetSingleNodeDoc(PageCache.XML, thisXPath);
		var newDocument = XSLProcessors.listinginfobubble.transformToDocument(TempXDoc);   
    
		strHTML += new XMLSerializer().serializeToString(newDocument); 
	}
	if (arrElements.length > 1)
	{
		strHTML += "</div>";
	}
	else
	{
		strHTML += "";
	}
	
	return strHTML;
}


//################################################################
//================================================================
//  Auth
//================================================================
//################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  The following logic calls an encryption key into 
//  the variable "XKp" to be used for requesting XML, or whatever
//  you want protected.
//  The variable must be sent in the "Authorization" header
//  for the request to be validated.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  The root script p.aspx renders a new key through an Ajax call
//  String.fromCharCode(112,46,97,115,112,120) == "p.aspx"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var XmV = 5;     // how many minutes to wait before re-requesting the key
var XKC = 24;    // how many times to re-request the key, total = 2 hours
var XKp = "";    // empty key
var XDh = function(a){XKp=a;};
function $AX(){$AJ.GD(XDh,WebRoot+String.fromCharCode(112,46,97,115,112,120));} 
$AX();window.setInterval(function(){if(XKC>0){$AX();XKC--;}},XmV*60000);

function NearbyManagerElement(strId, strStatus, divObject)
{
    this.Id     = strId;
    this.Status = strStatus;
    this.DivObj = divObject;
    
    NearbyManagerElement.prototype.Render = function()
    {
        //alert(this.Id  + ":" + this.Status);
        
        with(this)
        {
            switch(Status)
            {
                case "open":
                    DivObj.style.display = "block";
                    DivObj.className = "accordion_selected";
                    //DivObj.getElementsByTagName("a")[0].className = "selected";
                    SetListDiv("block");
                    break;
                case "closed":
                    DivObj.style.display = "block";
                    DivObj.className = "";
                    //DivObj.getElementsByTagName("a")[0].className = "";
                    SetListDiv("none");
                    break;
                case "none":
                    DivObj.style.display = "none";
                    DivObj.className = "";
                    SetListDiv("none");
                    break;
            }
        }
    };
    
    NearbyManagerElement.prototype.SetListDiv = function(style)
    {
        if (this.DivObj.getElementsByTagName("div")[0])
        {
            this.DivObj.getElementsByTagName("div")[0].style.display = style;
        }
    };    
}

function NearbyManager(initCity, initNeig)
{
    this.ObjNeig = null;
    this.ObjCity = null;
    
    NearbyManager.prototype.Render = function()
    {
        this.ObjNeig.Render();
        this.ObjCity.Render();
    };
    
    NearbyManager.prototype.Control = function(eleId)
    {
        with(this)
        {
            switch(eleId)
            {
                case "city":
                    if (ObjNeig.Status == "none")
                    {
                        return;
                    }
                    if (ObjNeig.Status == "open")
                    {
                        ObjNeig.Status = "closed";
                        ObjCity.Status = "open";
                        Render();
                        break;
                    }
                    break;
                case "neig":
                    if (ObjCity.Status == "none")
                    {
                        return;
                    }
                    if (ObjCity.Status == "open")
                    {
                        ObjNeig.Status = "open";
                        ObjCity.Status = "closed";
                        Render();
                        break;
                    }
                    break;
            }
        }
    };
    
    NearbyManager.prototype.NextLoad = function(statusCity, statusNeig)
    {
        this.ObjCity.Status = statusCity;
        this.ObjNeig.Status = statusNeig;
        this.Render();
    };
    
    NearbyManager.prototype.Init = function(initCity, initNeig)
    {
        this.ObjCity = new NearbyManagerElement("city", initCity, gE("nearestcities"));
        this.ObjNeig = new NearbyManagerElement("neig", initNeig, gE("nearestneighborhoods"));
        this.Render();
    };
    
    this.Init(initCity, initNeig);
    
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  LoadImgages
//  Class that manages image requests
//  If images are a certain image, that image request is recalled
//  on a timed interval. Gives up after set number of tries.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var LdImgs = new LoadImgages();
    LdImgs.Init("listingimg", "images/no_photo2.gif", PageCache.MaxPerPage);
    
function LoadImgages()
{
    this.Timer = null;
    this.Counter = null;
    this.OnFailureImg = null;
    this.IdPrefix = null;
    this.Retries = 10;
    this.MaxPerPage = 0;
    
    var My = this;
    LoadImgages.prototype.Init = function(IdPrefix, OnFailureImg, MaxPerPage)
    {
        this.IdPrefix = IdPrefix;
        this.OnFailureImg = OnFailureImg;
        this.MaxPerPage = MaxPerPage;
        this.Loadem();
        if (this.Timer != null)
        {
            //this.Dispose();
            window.clearInterval(this.Timer);
        }
        this.Timer = window.setInterval(function(){My.Loadem();},1000);
        //window.status = "LdImgs Running";
    };

    LoadImgages.prototype.Loadem = function()
    {with(this){
    
        if (!ActionRequired)
        {
            return;
        }
//        Counter += 1;
//        if (Counter >= Retries)
//        {
//            //Dispose();
//            window.clearInterval(Timer);
//            Timer = null;
//            return;
//            window.status = "LdImgs Idle";
//        }
        var imgs = document.getElementsByTagName("img");
        for (var x=0; x < imgs.length; x++)
        {
            if (imgs[x].id.toLowerCase().indexOf(IdPrefix) > -1)
            {
                if (imgs[x].src.toLowerCase().indexOf("reloadem.gif") > -1)
                {
                    // get scrollHeight of window
                    var WinBounds = new GetWindowBunds();
                    
                    if (WinBounds.isDefined)
                    {
                        // get offsetTop of image
                        var imgTop = RecurseOffset(imgs[x]).offsetTop;
                        var winViewBottom = WinBounds.VisibleTop + WinBounds.VisibleHeight;
                        if (imgTop < winViewBottom)
                        {
                            imgs[x].src = imgs[x].getAttribute("name");
                            //window.status = "Try Load " + imgs[x].getAttribute("name");
                        }
                    }
                    else
                    {
                        imgs[x].src = imgs[x].getAttribute("name");
                    }
                }
            }
        }
    }};

    LoadImgages.prototype.ActionRequired = function()
    {
        var imgs = document.getElementsByTagName("img");
        for (var x=0; x < imgs.length; x++)
        {
            if (imgs[x].id.toLowerCase().indexOf(IdPrefix) > -1)
            {
                if (imgs[x].src.toLowerCase().indexOf("reloadem.gif") > -1)
                {
                   return true;
                }
            }
        }
        return false;
    };
    
    LoadImgages.prototype.Dispose = function()
    {with(this){
        Counter=0;
        failure = 0;
        var imgs = document.getElementsByTagName("img");
        for (var x=0; x < imgs.length; x++)
        {
            if (imgs[x].id.toLowerCase().indexOf(IdPrefix) > -1)
            {
                if (imgs[x].src.toLowerCase().indexOf("reloadem.gif") > -1)
                {
                    imgs[x].src = OnFailureImg;
                    failure++;
                }
                else if (imgs[x].complete == false)
                {
                    imgs[x].src = OnFailureImg;
                    failure++;
                }
            }
        }
        window.clearInterval(Timer);
        Timer = null;
    }};
}
    
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  MapState
//  Manages the "State" of the map
//  Values: default, expanded, hidden
//  Writes cookie to keep state persistant
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
var MapState = new Object();
    MapState.Current = MapStateDefault; // Default State
    MapState.Previous = "map_default"; // Default State
    MapState.Set = function(state, DoReload)
    {
        if (DoReload == undefined)
        {
            DoReload = true;
        }
        MapState.Previous = MapState.Current;
        MapState.Current = state;
        MapState.Render(DoReload);
    };
    
    MapState.Init = function()
    {
        MapState.Render(false);
    };
    
    MapState.Mute = function(eleName)
    {
        gE(eleName).style.display = "none";
        gE(eleName).innerHTML = "";
    };
    
    MapState.Render = function(DoReload)
    {
        if (DoReload == undefined)
        {
            DoReload = true;
        }
        
        gE("map").className = MapState.Current;
            
        map.checkResize();
        
        switch(MapState.Current)
        {
            case 'map_expanded':
                MapState.Mute("map_state_hidden");
                gE("adcontainer").style.display = "block";               
                gE("map_state").style.display = "block";
                gE("map_function_toggle").style.display = "block";
                gE("map_status").style.display = "block";
                gE("map_state").innerHTML = "\
                <a href=\"javascript:MapState.Set('map_default');\" id=\"map_btn_contract\">contract map</a>\
                <a href=\"javascript:MapState.Set('map_hidden');\" id=\"map_btn_hide\">hide map</a>";
                break;
            case 'map_default':
                MapState.Mute("map_state_hidden");
                gE("adcontainer").style.display = "block";
                gE("map_state").style.display = "block";
                gE("map_function_toggle").style.display = "block";
                gE("map_status").style.display = "block";
                gE("map_state").innerHTML = "\
                <a href=\"javascript:MapState.Set('map_expanded');\" id=\"map_btn_expand\">expand map</a>\
                <a href=\"javascript:MapState.Set('map_hidden');\" id=\"map_btn_hide\">hide map</a>";
                break;
            case 'map_hidden':
                MapState.Mute("map_state");
                MapState.Mute("map_function_toggle");
                MapState.Mute("map_status");
                gE("adcontainer").style.display = "none";
                gE("map_function_toggle").style.display = "none";
                gE("map_state_hidden").style.display = "block";
                gE("map_state_hidden").innerHTML = String.format("\
                <a href=\"javascript:MapState.Set('{0}');\">show map</a>", MapState.Previous);
                break;
        }

        if (DoReload && MapState.Current != "map_hidden")
        {
            RunQuery(PageCache.QueryString);
            RenderMapOptions(true);
        }
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //  SetCookieState
        //  Defined in global.js
        //  Sets cookie using Ajax through .NET for compatibility
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        SetCookieState(LastSearchCookieName, "MapState", MapState.Current);
        
    };
    
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  OverlayCache
//  Contains all current map overlays, and methods for mamaging them
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function OverlayObjectBase(Type, Id, Obj)
{
    this.Type   = Type;
    this.Id     = Id;
    this.Obj    = Obj;
}

function OverlayCacheBase()
{
    this.OCollection = new Array();
    
    OverlayCacheBase.prototype.Add = function(type, id, obj)
    {
        var OverlayObject = new OverlayObjectBase(type, id, obj);
        // prevent duplicates
        for (var x=0;x<this.OCollection.length;x++)
        {
            if (this.OCollection[x].Type == type &&
                this.OCollection[x].Id == id)
            {
                return;
            }
        }
        this.OCollection.push(OverlayObject);

    };
    
    OverlayCacheBase.prototype.Remove = function(obj)
    {
        var TempOCollection = new Array();
        for (var x=0;x<this.OCollection.length;x++)
        {
            if (this.OCollection[x].Obj != obj)
            {
                TempOCollection.push(this.OCollection[x]);
            }
        }
        this.OCollection = TempOCollection;
    };
    
    OverlayCacheBase.prototype.RemoveCacheType = function(Type)
    {
        var TempOCollection = new Array();
        for (var x=0;x<this.OCollection.length;x++)
        {
            if (this.OCollection[x].Type != Type)
            {
                TempOCollection.push(this.OCollection[x]);
            }
        }
        this.OCollection = TempOCollection;
    };
    
    OverlayCacheBase.prototype.RemoveCacheTypes = function(arrTypes)
    {
        for(var x=0;x<arrTypes.length;x++)
        {
            this.RemoveCacheType(arrTypes[x]);
        }
    };
    
    OverlayCacheBase.prototype.GetType = function(Type)
    {
        var TempOCollection = new Array();
        for (var x=0;x<this.OCollection.length;x++)
        {
            if (this.OCollection[x].Type == Type)
            {
                TempOCollection.push(this.OCollection[x].Obj);
            }
        }
        return TempOCollection;
    };
    
    OverlayCacheBase.prototype.GetByTypeId = function(Type, Id)
    {
        for (var x=0;x<this.OCollection.length;x++)
        {
            if (this.OCollection[x].Type == Type)
            {
                if (this.OCollection[x].Id == Id)
                {
                    return this.OCollection[x].Obj;
                }
            }
        }
        return null;
    };
    
    OverlayCacheBase.prototype.RemoveByTypeId = function(Type, Id)
    {
        var TempOCollection = new Array();
        for (var x=0;x<this.OCollection.length;x++)
        {
            if (this.OCollection[x].Type != Type)
            {
                if (this.OCollection[x].Id != Id)
                {
                    TempOCollection.push(this.OCollection[x]);
                }
            }
        }
        this.OCollection = TempOCollection;
    };
    
    OverlayCacheBase.prototype.RenderOverlayTypes = function(arrType)
    {
        for (var x=0;x<arrType.length;x++)
        {
            for (var y=0;y<this.OCollection.length;y++)
            {
                if (this.OCollection[y].Type == arrType[x])
                {
                    map.addOverlay(this.OCollection[y].Obj);
                }
            }
        }
    };
    
    OverlayCacheBase.prototype.RenderOverlayType = function(Type)
    {
        for (var y=0;y<this.OCollection.length;y++)
        {
            if (this.OCollection[y].Type == Type)
            {
                map.addOverlay(this.OCollection[y].Obj);
            }
        }
    };
    
    OverlayCacheBase.prototype.RemoveOverlayType = function(Type)
    {
        for (var y=0;y<this.OCollection.length;y++)
        {
            if (this.OCollection[y].Type == Type)
            {
                map.removeOverlay(this.OCollection[y].Obj);
            }
        }
    };
    
    OverlayCacheBase.prototype.RemoveOverlayTypes = function(arrTypes)
    {
        for(var x=0;x<arrTypes.length;x++)
        {
            this.RemoveOverlayType(arrTypes[x]);
        }
    };
    
    OverlayCacheBase.prototype.GetMapBoundsByTypes = function(arrType)
    {
        var MapBounds = new GLatLngBounds();
        for (x=0;x<arrType.length;x++)
        {
            MapBounds = this.ExtendMapBoundsByType(arrType[x], MapBounds);
        }
        return MapBounds;
    };
    
    OverlayCacheBase.prototype.GetMapBoundsByType = function(Type)
    {
        //alert(Type);
        if (Type == "PrimeNeighborhood")
        {
            //alert(this.GetType(Type).length);
            if (this.GetType(Type).length > 0)
            {
                var Bounds = new GLatLngBounds();
                    Bounds = this.GetType(Type)[0].getBounds();
                    //alert(Bounds);
                return Bounds;
            }
            else
            {
                return this.GetMapBoundsByType("Listing");
            }
        }
        else
        {
            var MapBounds = new GLatLngBounds();
                MapBounds = this.ExtendMapBoundsByType(Type, MapBounds);
            return MapBounds;
        }

    };
    
    OverlayCacheBase.prototype.ExtendMapBoundsByType = function(Type, MapBounds)
    {
        var arrElements = this.GetType(Type);
        for(var x=0;x<arrElements.length;x++)
        {
            MapBounds.extend(arrElements[x].getPoint());
        }
        return MapBounds;
    };
}

var OverlayCache = new OverlayCacheBase();

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  RequeryByLocation(EndecaId)
//  Called when clicking on Toggle Map Funcitons "In Location"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function RequeryByLocation(EndecaId)
{
    var QG = new UrlGen(PageCache.QueryString);
        QG.AddParam("E",EndecaId);
        
    var strURL = WebRoot + "controls/AjaxCalls/GetInLocationQuery.aspx?" + QG.ToString();
    
    $AJAX.GetForDelegate(function(AjaxResponse)
    {
        RunQuery(AjaxResponse, true, false, false);
        
    }, strURL);
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  UrlGen
    //  Function in global.js used for managing Querystrings easily.
    //  Modelled after the class of the same name from Endeca
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /*
    var UGen = new UrlGen(PageCache.QueryString);
    
    if (PageCache.TotalRecords == 0)
    {
        if (trim(PageCache.LastQueryString) != "")
        {
            UGen = new UrlGen(PageCache.LastQueryString);
        }
    }
    
	var strNf ="";
	strNf = UGen.GetParam("Nf");
	var PriceNf = "";
	if ((strNf != undefined) && (strNf.length > 0))
	{
	    if (strNf.indexOf("Price") > -1)
	    {
	        arrNf = strNf.split("||")
	        PriceNf = arrNf[0];
	    }
	}
	var NewN = UGen.GetParam("N");
	if (NewN != undefined)
	{
		arrNewN = NewN.split('+');
		var _tempN = new Array();
        for (var i=0; i < arrNewN.length; i++)
		{
			if (arrNewN[i] != PageCache.Location)
			{
				_tempN.push(arrNewN[i]);
			}
		}
		
		_tempN.push(EndecaId);
		
		UGen.RemoveParam("Ntt");
		UGen.RemoveParam("Ntk");
		UGen.RemoveParam("Ntx");
		UGen.RemoveParam("N");
		UGen.AddParam("N",_tempN.join('+'));

		UGen.RemoveParams(["Nf","No","Ne"]);
		if (PriceNf.length > 0)
		{
		    UGen.AddParam("Nf",PriceNf);
		}
		
	}
	
	UGen.RemoveParam("Z");
    Recenter = true;
    ReloadMapOnly = false;
    AddToHistory = false; // Map History is currently disabled
    
    //alert(UGen.ToString());
	RunQuery(UGen.ToString(), Recenter, ReloadMapOnly, AddToHistory);
	*/
}


//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  RequeryOnBounds(Recenter, AddZoom, AddToHistory)
//  Taking the boundaries of the map, and the contents of the 
//  current query, generates a new query and refreshes data.
//
//  Recenter     bool    true = recenter when done loading
//  AddZoom      bool    true = add current zoom level to Query
//  AddToHistory bool    true = Add to map history ( Obsolete )
//                       History not currently being used
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function RequeryOnBounds(Recenter, AddZoom, AddToHistory)
{
    var Query = PageCache.QueryString;
    if (PageCache.TotalRecords == 0)
    {
        if (trim(PageCache.LastQueryString) != "")
        {
            Query = PageCache.LastQueryString;
        }
    }
    
    AddToHistory = false;
    
    if (Recenter == undefined)
    {
        Recenter = false;
    }
    if (AddZoom == undefined)
    {
        AddZoom = true;
    }
    
    ReloadMapOnly = false;

    var CurrentBounds = map.getBounds();
	var SW = CurrentBounds.getSouthWest();
	var NE = CurrentBounds.getNorthEast();
	var LngMin = SW.lng();
	var LngMax = NE.lng();
	var LatMin = SW.lat();
	var LatMax = NE.lat();
	
	var strURL = String.format("{0}Controls/AjaxCalls/GetBoundsQuery.aspx?LngMin={1}&LngMax={2}&LatMin={3}&LatMax={4}&Zoom={5}&DoReloadResults={6}&{7}",
	        WebRoot, LngMin, LngMax, LatMin, LatMax, map.getZoom(), DoReloadResults(), Query);
	
    $AJAX.GetForDelegate(function(AjaxResponse)
    {
        if (AjaxResponse != "")
        {
            if (!DoReloadResults())
            {
                Recenter = false;
                ReloadMapOnly = true;
            }
	        RunQuery(AjaxResponse, Recenter, ReloadMapOnly, AddToHistory);
	    }
    },strURL);
    

//    if (AddToHistory == undefined)
//    {
//        AddToHistory = true;
//    }

/*
    AddToHistory = false;
    
    if (Recenter == undefined)
    {
        Recenter = false;
    }
    if (AddZoom == undefined)
    {
        AddZoom = true;
    }
	var CurrentBounds = map.getBounds();
	var SW = CurrentBounds.getSouthWest();
	var NE = CurrentBounds.getNorthEast();
	var LngMin = SW.lng();
	var LngMax = NE.lng();
	var LatMin = SW.lat();
	var LatMax = NE.lat();
	//alert(LngMin + ":" + LngMax + ":" + LatMin + ":" + LatMax);
	var searchBounds = String.format('Latitude|BTWN+{0}+{1}||Longitude|BTWN+{2}+{3}', LatMin, LatMax, LngMin, LngMax);

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  UrlGen
    //  Function in global.js used for managing Querystrings easily.
    //  Modelled after the class of the same name from Endeca
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    var UGen = new UrlGen(PageCache.QueryString);
    //alert(UGen.ToString());
    if (PageCache.TotalRecords == 0)
    {
        if (trim(PageCache.LastQueryString) != "")
        {
            UGen = new UrlGen(PageCache.LastQueryString);
        }
    }
    
	var strNf ="";
	strNf = UGen.GetParam("Nf");
	var PriceNf = "";
	if ((strNf != undefined) && (strNf.length > 0))
	{
	    if (strNf.indexOf("Price") > -1)
	    {
	        arrNf = strNf.split("||")
	        PriceNf = arrNf[0];
	    }
	}
	var NewN = UGen.GetParam("N");
	if (NewN != undefined)
	{
		arrNewN = NewN.split('+');
		var _tempN = new Array();
		
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//  Remove location from Query
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        for (var i=0; i < arrNewN.length; i++)
	    {
	        //alert(arrNewN[i] + ":" + PageCache.Location);
		    if (parseInt(arrNewN[i],10) != parseInt(PageCache.Location))
		    {
			    _tempN.push(arrNewN[i]);
		    }
	    }
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//  Add it back if it's an in-location search
		//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
		//alert("DoReloadResults()" + DoReloadResults());
		//alert(PageCache.Location);
		//if (!DoReloadResults())
		//{
		//    _tempN.push(PageCache.Location);
		//}
		
		UGen.RemoveParam("Ntt");
		UGen.RemoveParam("Ntk");
		UGen.RemoveParam("Ntx");
		UGen.RemoveParam("N");
		UGen.AddParam("N",_tempN.join('+'));

		UGen.RemoveParams(["Nf","No","Ne"]);
		if (PriceNf.length > 0)
		{
		    searchBounds = PriceNf +"||"+searchBounds;
		}
		UGen.AddParam("Nf",searchBounds);
		
	}
	
	if (AddZoom)
	{
	    UGen.RemoveParam("Z");
        UGen.AddParam("Z",map.getZoom());
    }
    
    ReloadMapOnly = false;
    if (!DoReloadResults())
    {
        Recenter = false;
        ReloadMapOnly = true;
    }
    
    //alert(UGen.ToString());
	RunQuery(UGen.ToString(), Recenter, ReloadMapOnly, AddToHistory);
	//ReloadFrameAds();
	//OmEvent(gE("map"), 6, "map_event");
	*/
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  RefinementQuery(Query)
//  Special case for Refinements, we need to scroll to the page top
//  if the results are out of view
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function RefinementQuery(Query)
{
    OverlayCache.RemoveOverlayTypes(["Neighborhood", "PrimeNeighborhood"]);
    OverlayCache.RemoveCacheTypes(["Neighborhood", "PrimeNeighborhood"]);
    RunQuery(Query, true, false);
    var WrapTop = RecurseOffset(gE("results_results")).offsetTop;
    if (document.documentElement)
    {
        var scrollTop = document.documentElement.scrollTop;
    }
    else
    {
        var scrollTop = document.body.scrollTop;
    }
    if (scrollTop > WrapTop)
    {
        window.scrollTo(0,WrapTop);
    }
    
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  PagingQuery(Query)
//  When clicking a page link [1,2,3], should jump to above the fold
//  only if map is out of view
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
function PagingQuery(Query)
{
    OverlayCache.RemoveOverlayTypes(["Neighborhood", "PrimeNeighborhood"]);
    OverlayCache.RemoveCacheTypes(["Neighborhood", "PrimeNeighborhood"]);
    RunQuery(Query, true, false);
    
    var WindowBounds = new GetWindowBunds(); // see global.js
	var Target = (RecurseOffset(gE("map")).offsetTop - 15);
	if (WindowBounds.VisibleTop > Target)
	{
		window.scrollTo(0,0);
	}
	
}

//================================================================
//  LocationQuery
//  Special case when clicking a location on either the map or 
//  on the Nearby Cities / Neighborhoods
//  Ensures that all neighborhoods are initially removed from
//  the map
//================================================================
function LocationQuery(Query, Recenter, ReloadMapOnly, AddToHistory)
{
    OverlayCache.RemoveOverlayTypes(["Neighborhood", "PrimeNeighborhood"]);
    OverlayCache.RemoveCacheTypes(["Neighborhood", "PrimeNeighborhood"]);
    RunQuery(Query, Recenter, ReloadMapOnly, AddToHistory);
    
}

//################################################################
//================================================================
//  Sarissa
//================================================================
//################################################################

var XSLProcessors = new Object();
    XSLProcessors.listings = null;
    XSLProcessors.paging = null;
    XSLProcessors.status = null;
    XSLProcessors.sortoptions = null;
    XSLProcessors.navrefinements = null;
    //XSLProcessors.breadcrumbs = null;
    XSLProcessors.featuredlistings = null;
    XSLProcessors.featuredagents = null;
    XSLProcessors.rss = null;
    XSLProcessors.results = null;
    XSLProcessors.listinginfobubble = null;
    XSLProcessors.nearestneighborhoods = null;
    XSLProcessors.NewBreadcrumbs = null;
    
    XSLProcessors.loaded = false;
    XSLProcessors.load = function(XSLPath)
    {
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	    // create an instance of XSLTProcessor   
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	    var processor = new XSLTProcessor(); 
             
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	    // create a DOM Document containing an XSLT stylesheet   
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	    var xslDoc = Sarissa.getDomDocument(); 
	    xslDoc.async = false;
	    var xmlhttp = new XMLHttpRequest();
	    xmlhttp.open('GET', AbsoluteWebRoot + XSLPath, false);
	    xmlhttp.send('');
	    xslDoc = xmlhttp.responseXML;
                    
	    processor.importStylesheet(xslDoc);
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	    //  Debug:alert(new XMLSerializer().serializeToString(xslDoc));
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	    return processor; 
    };

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  Load all XML into client side cache on initial page load.
//  Each XSL is pulled from Cache after that for speed.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
XSLProcessors.loadAll = function()
{
    XSLProcessors.listings              = XSLProcessors.load("includes/xsl/listings/results_listings.xsl");
	XSLProcessors.paging                = XSLProcessors.load("includes/xsl/listings/results_pagination.xsl");
	XSLProcessors.status                = XSLProcessors.load("includes/xsl/listings/results_listings_status.xsl");
	XSLProcessors.mapstatus             = XSLProcessors.load("includes/xsl/listings/results_map_status.xsl");
    XSLProcessors.sortoptions           = XSLProcessors.load("includes/xsl/listings/results_sort_options.xsl");
	XSLProcessors.navrefinements        = XSLProcessors.load("includes/xsl/listings/results_nav_refinements.xsl");
	XSLProcessors.navselections         = XSLProcessors.load("includes/xsl/listings/results_nav_selections.xsl");
	XSLProcessors.rss                   = XSLProcessors.load("includes/xsl/listings/results_rss.xsl");
	XSLProcessors.listinginfobubble     = XSLProcessors.load("includes/xsl/listings/results_map_info_bubble.xsl");
	XSLProcessors.nearestcities         = XSLProcessors.load("includes/xsl/listings/results_nearest_cities.xsl");
	XSLProcessors.results               = XSLProcessors.load("includes/xsl/listings/results_results.xsl");
	XSLProcessors.nearestneighborhoods  = XSLProcessors.load("includes/xsl/listings/results_nearest_neighborhoods.xsl");
	//XSLProcessors.breadcrumbs           = XSLProcessors.load("includes/xsl/listings/results_breadcrumb.xsl");
	XSLProcessors.featuredlistings      = XSLProcessors.load("includes/xsl/listings/featured_listings.xsl");
	XSLProcessors.featuredagents        = XSLProcessors.load("includes/xsl/listings/featured_agents.xsl");
	XSLProcessors.searchlocation        = XSLProcessors.load("includes/xsl/listings/results_search_location.xsl");
	XSLProcessors.newbreadcrumbs        = XSLProcessors.load("includes/xsl/listings/results_nav_NewBreadcrumbs.xsl");
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	//  remove following line comment to cache all XSL client side
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
	XSLProcessors.loaded = true;
};


//================================================================
//  RunQuery(Query, Recenter, AddToHistory)
//  Calls XML through Sarissa and reloads elements of the page
//  with the data parsed from the XML
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  Query           String  The Endeca Query to execute
//  Recenter        Bool    Whether to recenter after results
//  ReloadMapOnly   Bool    sic
//  AddToHistory    Bool    Whether to add Query to History
//                          ( Not currently implemented )
//================================================================
function RunQuery(Query, Recenter, ReloadMapOnly, AddToHistory)
{

    //alert(gE("map").offsetWidth + ":" + gE("map").offsetHeight);
//   alert(Query);
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //   See SetDefault in global.js
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //   AddToHistory = SetDefault(AddToHistory, true);
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    AddToHistory    = false;
    Recenter        = SetDefault(Recenter, true);
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    //gE("map").style.opacity = .40;
	//gE("map").style.filter = 'alpha(opacity=40)';
	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
	    
    //ReloadMapOnly   = SetDefault(ReloadMapOnly, false);    
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  isMapSearch
    //  Defines whether the search being conducted contains Lat/Lng
    //  information, sent when the user pans the map
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  Revised
    //  isMapSearch is now dependent on the radio toggle on the map, if the 
    //  user is not doing an "in location search" then it's logically
    //  a map search
    //  New variable and value is isMapPanSearch
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    var isMapSearch = false;
    var isMapPanSearch = false;
    
    if (!DoReloadResults())
    {
        isMapSearch = true;
    }
    
    if (unescape(Query).toLowerCase().indexOf("latitude|btwn") > -1 &&
        unescape(Query).toLowerCase().indexOf("longitude|btwn") > -1)
    {
        isMapPanSearch = true;
    }

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  UrlGen
    //  Function in global.js used for managing Querystrings easily.
    //  Modelled after the class of the same name from Endeca
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    var QGen = new UrlGen(Query);
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  isZipSearch
    //  Check to see if user searched by Zip Code
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    var isZipSearch = false;
    if (QGen.GetParam("Ntk").toLowerCase() == "addrzip")
    {
        isZipSearch = true;
    }
    
    var isSchoolDistrictSearch = false;
    if (QGen.GetParam("Ntk").toLowerCase() == "schooldistrictid")
    {
        isSchoolDistrictSearch = true;
        isMapSearch = false;
    }
    

   
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    //  Switch the Search Bar to Small Sales search
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    //SwitchSearch('sales', 'small', Query);
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    //  History not currently implemented
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    /*
    if (isMapSearch == false)
    {
        if (AddToHistory)
        {
            MCO.AddQuery(Query, Recenter);
        }
    }
    */
    
    //----------------------------------------------------------------
    //  For Non-Sarissa Compliant Browsers
    //----------------------------------------------------------------
    if ((!window.XSLTProcessor) && (!window.ActiveXObject))
    {
       var QGen = new UrlGen(Query);
           QGen.RemoveParams(["sb", "ms"]);
           QGen.AddParam("sb", sb);
           QGen.AddParam("ms", MapState.Current);
       window.location.href = window.location.href.substr(0,indexOf('?')) + QGen.ToString();
       return;
    }
        
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    //  stop trying to load images
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    //LdImgs.Dispose();
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    //  Load XSL into memory
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
	if (XSLProcessors.loaded == false)
	{
		XSLProcessors.loadAll();
	}
    
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    //  Fetch the XML using Sarissa
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
    //  This routine uses the XK value for Authorization secutiry
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
	var xmlDocPath = "";
        xmlDocPath = "results_xml.aspx?" + Query;    
	var XMLDoc = Sarissa.getDomDocument();
	    XMLDoc.async = false;
	var xmlhttp = new XMLHttpRequest();
	    xmlhttp.open("GET", AbsoluteWebRoot + xmlDocPath, false);
	    xmlhttp.setRequestHeader("Authorization", XKp);
	    xmlhttp.send('');
	    XMLDoc = xmlhttp.responseXML;
	    PageCache.XML = XMLDoc; // Add XML to PAge Cache
        
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
        //  Debug - uncomment following line to see Raw XML
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
	    //  alert(new XMLSerializer().serializeToString(XMLDoc));
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
	    
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
	    //  We don't need to change the Status message unless new data is loaded.
	    //  Uncomment following line to re-instate this logic.
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
	    //  gE("status").innerHTML = "<span class=\"loading\">Loading</span>";  
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
	    
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
	    //  GetSingleNodeContent
	    //  Function is in Sarissa.Global.js
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
	    var NoResults     = GetSingleNodeContent(XMLDoc, '/results/breadcrumbs/noresults');
	    var ListingPoints = GetSingleNodeContent(XMLDoc, '/results/listings/mappedlistingsjs');
        var RegionPoints = GetSingleNodeContent(XMLDoc, "/results/regions");
        var viewstate = GetSingleNodeContent(XMLDoc, "/results/viewstate");
        
        PageCache.ShowListingsOnMap = GetSingleNodeContent(XMLDoc, "/results/showlistingsonmap");
        PageCache.MapBestFit = GetSingleNodeContent(XMLDoc, "/results/mapbestfit");
        PageCache.Location        = GetSingleNodeContent(XMLDoc, '/results/querystringendecalocationid');
        
        if (PageCache.ShowListingsOnMap.toLowerCase() == "false")
        {
            ListingPoints = "";
        }
	    
	     
         
        //#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@
        //================================================================
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //  if ReloadMapOnly == true, Stop Processing Here
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //````````````````````````````````````````````````````````````````
        if (ReloadMapOnly)
        {
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
            //gE("map").style.opacity = 1.0;
	        //gE("map").style.filter = 'alpha(opacity=100)';
	        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
            map.clearOverlays();
            //eval(RegionPoints);
            eval(RegionPoints);
            //OverlayCache.RemoveOverlayTypes(["Region", "PrimeNeighborhood", "Listing"]);
            OverlayCache.RenderOverlayTypes(["Region", "PrimeNeighborhood", "Listing"]);
            //var showlistingsonmap = GetSingleNodeContent(XMLDoc, "/results/showlistingsonmap").toLowerCase();
            //if (showlistingsonmap == "true")
            //{
            //    OverlayCache.RenderOverlayTypes(["Region", "PrimeNeighborhood"]);
            //}
            //else
            //{
            //     OverlayCache.RenderOverlayTypes(["Listing", "Region", "PrimeNeighborhood"]);
            //}
//            Sarissa.updateContentFromNode(XMLDoc, gE("map_status"), XSLProcessors.newbreadcrumbs);
//            UnescapeCommonInnerHTML(gE("map_status"));
            Sarissa.updateContentFromNode(XMLDoc, gE("nearestcities"), XSLProcessors.nearestcities);
            UnescapeCommonInnerHTML(gE("nearestcities"));
            Sarissa.updateContentFromNode(XMLDoc, gE("nearestneighborhoods"), XSLProcessors.nearestneighborhoods);
            UnescapeCommonInnerHTML(gE("nearestneighborhoods"));
            PageCache.Location = GetSingleNodeContent(XMLDoc, '/results/querystringendecalocationid');
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            //  Call NearbyManager (NbMg) for Accordian effect
            //  NbMg.NextLoad(statusCity, statusNeighborhood);
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            if (gE("nearestneighborhoods").innerHTML.length < 25)
            {
                NbMg.NextLoad("open", "none");
            }
            else
            {
                NbMg.NextLoad("closed", "open");
            }
            
            return;
        }
        //````````````````````````````````````````````````````````````````
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //================================================================
        //#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@
    
	    PageCache.CenterOnRegions = eval(GetSingleNodeContent(XMLDoc, "/results/centeronregions"));
	   
	   	var SELECTED_Map = "";
		var SELECTED_Loc = "";
        
        var isLocSrch = GetSingleNodeContent(XMLDoc, "/results/islocationsearch").toLowerCase();
        var isLocationSearch = false;
            if (isLocSrch == "true")
            {
                isLocationSearch = true;
            }
		if (isLocationSearch)
		{
			SELECTED_Loc = "checked=checked";
		}
		else
		{
			SELECTED_Map = "checked=checked";
		}

//		gE("map_function_toggle").innerHTML = String.format("\
//		<div><input type='checkbox' id='mlo' name='mlo' onclick='ToggleMapLoadOption(this);' {0}> update the results below while I navigate the map</div>\
//		", SELECTED);

	//ana - if it's a school district search don't show the radio buttons with map area and location
	if (!isSchoolDistrictSearch)
	{
		gE("map_function_toggle").innerHTML = String.format("\
<table>\
<tr>\
<td>Search by:</td>\
<td><input type='radio' id='mlo_map' value='map' name='mlo' onclick='ToggleMapLoadOption(this);' {0}></td>\
<td><label for='mlo_map'>Map Area</label></td>\
<td><span>or</span></td>\
<td><input type='radio' id='mlo_loc' value='loc' name='mlo' onclick='ToggleMapLoadOption(this);RequeryByLocation({1});' {2}></td>\
<td><label for='mlo_loc'>Location: {3}</label></td>\
<td><a href=\"javascript:MapHelp();\"><img src=\"{4}images/map_btn_help.gif\" alt=\"how to use the map\"/></a></td>\
</tr>\
</table>\
		",  SELECTED_Map, 
		    GetSingleNodeContent(XMLDoc, '/results/centerregionendecaid'),
		    SELECTED_Loc, 
		    GetSingleNodeContent(XMLDoc, '/results/centerregionname'),
		    GetSingleNodeContent(XMLDoc, '/results/webroot'));
		    
        UnescapeCommonInnerHTML(gE("map_function_toggle"));
		}		
	    if (gE("testingQuery") != null)
        {
            gE("testingQuery").value = unescape(GetSingleNodeContent(XMLDoc, "/results/querystring")).replace(/&amp;/g,"&");
            gE("viewstate").value = viewstate;
        }
        
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
	    //  SEOPath
	    //  Search engine friendly path back to this search page result
	    //  Append to the end of the current window.location.href after anchor
	    //  The page reloading is handled in global.js regarding this
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
	    // To save the SEO URL in the saved searches instead of actual querystring
        // vrb 10/13/08
	    PageCache.SEOPath = GetSingleNodeContent(XMLDoc, '/results/seopath');
	    window.location.href = "#" + PageCache.SEOPath;

	
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
	    //  Not currently doing anyting different if there's no listings
	    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
	    /*
	    if (NoResults == "True")
	    {
	        //------
	    }
	    */
    	    
    	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    	//  UnescapeCommonInnerHTML
    	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    	//  Sarissa has a bad habit of ignoring the XSL
    	//  disable-output-escaping directive.
    	//  This does this unescaping in a simple way. 
    	//  UnescapeCommonInnerHTML is in Sarissa.Global.js
    	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        var hasNeighborhoods = false;
        var hasCities = false;
        
	    //gE("nearestcities").style.display = "block";
	    //gE("nearestneighborhoods").style.display = "block";
    	
        Sarissa.updateContentFromNode(XMLDoc, gE("nearestcities"), XSLProcessors.nearestcities);
        UnescapeCommonInnerHTML(gE("nearestcities"));
        
        if (gE("nearestcities").innerHTML.length > 10)
        {
            hasCities = true;
        }
        
        Sarissa.updateContentFromNode(XMLDoc, gE("nearestneighborhoods"), XSLProcessors.nearestneighborhoods);
        UnescapeCommonInnerHTML(gE("nearestneighborhoods"));
        
        if (gE("nearestneighborhoods").innerHTML.length > 10)
        {
            hasNeighborhoods = true;
        }
        
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //  Call NearbyManager (NbMg) for Accordian effect
        //  NbMg.NextLoad(statusCity, statusNeighborhood);
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        if (gE("nearestneighborhoods").innerHTML.length < 25)
        {
            NbMg.NextLoad("open", "none");
        }
        else
        {
            NbMg.NextLoad("closed", "open");
        }
           
        Sarissa.updateContentFromNode(XMLDoc, gE("results_results"), XSLProcessors.results);
        UnescapeCommonInnerHTML(gE("results_results"));
        
        //Sarissa.updateContentFromNode(XMLDoc, gE("breadcrumbs"), XSLProcessors.breadcrumbs);

        //gE("nearestneighborhoods").innerHTML = '<div id="breadcrumbs2" style="border-bottom: 1px dashed #ccc;padding-bottom:2px;margin-bottom:4px;"></DIV>' + gE("nearestneighborhoods").innerHTML;
        //Sarissa.updateContentFromNode(XMLDoc, gE("breadcrumbs2"), XSLProcessors.breadcrumbs);

        //HandleNearbyTabs(hasCities, hasNeighborhoods);
        
        PageCache.TotalRecords    = parseInt(GetSingleNodeContent(XMLDoc, '/results/pagination/pages/totalrecords'),10);
        
        if (isNaN(PageCache.TotalRecords))
        {
            PageCache.TotalRecords = 0;
        }
        
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //  Use Sarissa to update page contents and PageCache
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        
	    Sarissa.updateContentFromNode(XMLDoc, gE("paging_top"), XSLProcessors.paging);
	    Sarissa.updateContentFromNode(XMLDoc, gE("paging_bottom"), XSLProcessors.paging);
	    Sarissa.updateContentFromNode(XMLDoc, gE("sortoptions"), XSLProcessors.sortoptions);
	    Sarissa.updateContentFromNode(XMLDoc, gE("navrefinements"), XSLProcessors.navrefinements);
	    Sarissa.updateContentFromNode(XMLDoc, gE("navselections"), XSLProcessors.navselections);
	    Sarissa.updateContentFromNode(XMLDoc, gE("status"), XSLProcessors.status);
	    Sarissa.updateContentFromNode(XMLDoc, gE("results_rss"), XSLProcessors.rss);
        Sarissa.updateContentFromNode(XMLDoc, gE("results_breadcrumbs"), XSLProcessors.newbreadcrumbs);
            UnescapeCommonInnerHTML(gE("results_breadcrumbs"));
	    
	    Sarissa.updateContentFromNode(XMLDoc, gE("map_status"), XSLProcessors.mapstatus);
	    if (jQuery.browser.msie)
	        XSLProcessors.listings.setParameter("useEscaping",'false', null);	    
	    Sarissa.updateContentFromNode(XMLDoc, gE("results_listings"), XSLProcessors.listings); 	    
	    UnescapeCommonInnerHTML(gE("results_listings")); 
	    Sarissa.updateContentFromNode(XMLDoc, gE("results_search_location"), XSLProcessors.searchlocation);

	    Sarissa.updateContentFromNode(XMLDoc, gE("featured_agents_wrap"), XSLProcessors.featuredagents);
	    //Sarissa.updateContentFromNode(XMLDoc, gE("featured_listings_wrap"), XSLProcessors.featuredlistings);
    	
    	//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
        //  NextLoad
        //  Redraws listing and region points on the map
        //  Only reload the listing points if it's not an inlocation search
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
        window.setTimeout(function()
        {
            NextLoad(ListingPoints, RegionPoints, Recenter);
            var zoomOverride = GetSingleNodeContent(XMLDoc, '/results/overridezoomlevel');
            if (zoomOverride != '')
            {
                window.setTimeout(function()
                {
                    map.setZoom(parseInt(zoomOverride,10));
                },100);
            }
        },100);
        
        PageCache.ListingIds      = GetSingleNodeContent(XMLDoc, "/results/listingids");
	    PageCache.Channel         = GetSingleNodeContent(XMLDoc, '/results/breadcrumbs/defaults/channel');
	    //  Should always have value, moved to top
	    //  PageCache.Location        = GetSingleNodeContent(XMLDoc, '/results/querystringendecalocationid');
        
        // Personalization 
        SearchCriteria              = GetSingleNodeContent(XMLDoc, '/results/centerregionname');
        if(GetSingleNodeContent(XMLDoc, '/results/centerregionname') != "" && GetSingleNodeContent(XMLDoc, "/results/searchcriteria")!= "")
        {
            SearchCriteria += ", ";
        }
        SearchCriteria +=  GetSingleNodeContent(XMLDoc, "/results/searchcriteria");
        if (SearchCriteria.length > 50)
        {
            SearchCriteria = SearchCriteria.substr(0, 47) + "...";
        }
        // End of Personalization
        PageCache.QueryString = Query;
        
        //alert(PageCache.TotalRecords);
        
        if (PageCache.TotalRecords > 0)
        {
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            //  Cache the QueryString for a return
            //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            PageCache.LastQueryString = Query; // Cache querystring for return
        }  
             
         ChangeResultUserAction(PageCache.ListingIds);
        
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        //  Reload Advertising Iframes
        //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 

        if (gE("iframetopad") != null)
        {
            gE("iframetopad").contentWindow.location.reload();
        }
        
        if (gE("iframe1") != null)
        {
            gE("iframe1").contentWindow.location.reload();
        }
        
        if (gE("iframerightad2") != null)
        {
            gE("iframerightad2").contentWindow.location.reload();
        }
        
        if (gE("adframe_middle") != null)
        {
            gE("adframe_middle").src = gE("adframe_middle").src;
        }
        
        if (gE("adframe_bottom2") != null)
        {
            gE("adframe_bottom2").src = gE("adframe_bottom2").src;
        }
        
        if (gE("omnitureframe") != null)
        {
            gE("omnitureframe").contentWindow.location.reload();
        }
        
        if (gE("right1frame") != null)
        {
            gE("right1frame").contentWindow.location.reload();
        }
        if (gE("topadframe") != null)
        {
            gE("topadframe").contentWindow.location.reload();
        }
        if (gE("bottomadframe") != null)
        {
            gE("bottomadframe").contentWindow.location.reload();
        }
        if (gE("right2frame") != null)
        {
            gE("right2frame").contentWindow.location.reload();
        }
        
        
}




    
//################################################################
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  Code Archive
//  Code not currently being used, but keep here for reference
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//################################################################
//
//

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  ZoomCache
//  Obsolete
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//var ZoomCache = new Object();
//    ZoomCache.last = 0;
//    ZoomCache.factor = 0;
    
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  markerOff and markerOn Arrays
//  Obsolete
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//	//set up marker blank
//	var markerOff = [];
//	var markerOn = [];
//		
//	markerOff['single']  = 'images/map_markers/singlepoint_off.png';
//	markerOff['featured']  = 'images/map_markers/featured_off.png';
//	markerOff['multi']  = 'images/map_markers/multipoint_off.png';
//		
//	markerOn['single']  = 'images/map_markers/singlepoint_on.png';
//	markerOn['featured']  = 'images/map_markers/featured_on.png';
//	markerOn['multi']  = 'images/map_markers/multipoint_on.png';
//
//

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// A TextualZoomControl is a GControl that displays textual "Zoom In"
// and "Zoom Out" buttons (as opposed to the iconic buttons used in
// Google Maps).
// We define the function first
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  TextualZoomControlBG() is Obsolete.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*
function TextualZoomControlBG() {}

    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // To "subclass" the GControl, we set the prototype object to
    // an instance of the GControl object
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    TextualZoomControlBG.prototype = new GControl();
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // 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.
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    TextualZoomControlBG.prototype.initialize = function(map) 
    {  
        var containerBackground = document.createElement("div"); 
        containerBackground.className = "map_zoom_back_off";
        containerBackground.id = "ZoomContainerBackground";
        
        map.getContainer().appendChild(containerBackground);
        return containerBackground;
    };
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // By default, the control will appear in the top left corner of the
    // map with 7 pixels of padding.
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    TextualZoomControlBG.prototype.getDefaultPosition = function() 
    {  
        return new GControlPosition(G_ANCHOR_TOP_LEFT, new GSize(8, 8));
    };
*/

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  ScrollToMapAboveFold()
//  Scrolls page up to level of map
//  Not currently implemented
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*
function ScrollToMapAboveFold()
{
	WindowBounds = new GetWindowBunds();
	var map = gE("map");
	// determine if map is out of view
	// if it is, scroll to the top of the map
	var Target = (RecurseOffset(map).offsetTop - 15);
	if (WindowBounds.VisibleTop > Target)
	{
		window.scrollTo(0,Target);
	}
	
//	if (WindowBounds.VisibleTop > Target)
//	{
//		var timer = 25;
//		if (document.all)
//		{
//			timer = 2;
//		}
//        
//		var Scroller = window.setInterval(function(){
//			window.scrollBy(0,-10);
//			WindowBounds = new GetWindowBounds();
//			if (WindowBounds.VisibleTop < Target)
//			{
//				window.clearInterval(Scroller);
//			}
//		},timer);
//	}
}
*/


    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    //  setButtonStyle(button) from TextualZoomControl is Obsolete.
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    // Sets the proper CSS for the given button element.
    //    TextualZoomControl.prototype.setButtonStyle = function(button) 
    //    {  
    //        button.style.textDecoration = "none";  
    //        button.style.color = "#000";  
    //        button.style.backgroundColor = "white";  
    //        button.style.font = "bold 12px 'arial black',arial,tahoma,verdana,sans-serif;";  
    //        button.style.border = "2px solid black";  
    //        button.style.padding = "2px";  
    //        button.style.marginBottom = "3px";  
    //        button.style.textAlign = "center";  
    //        button.style.width = "14px";  
    //        button.style.cursor = "pointer";
    //    };
    //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  MUserCacheObject
//  Object that envokes and manages History of map pans and searches
//  Feature allows user to click a "bacK" button to return to their last 
//  map state. Maintains a list of history states in cookie.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  Not currently implemented
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/*
function MUserCacheObject(DivObject)
{
    this.DivObject = DivObject;
    this.Cache = new Array();
    this.Index = 0;

    MUserCacheObject.prototype.Dispose = function()
    {
        this.Cache = new Array();
        this.Index = 0;
        this.SetCookie();
        this.Redraw();
    };

    MUserCacheObject.prototype.LoadCookie = function()
    {
        this.Cache = new Array();
        var cName = "maphistory";
        var begin = document.cookie.indexOf(cName + "="); 
        var cLength = begin + cName.length + 1; 
        if ((!begin) && (cName != document.cookie.substring(0 ,cName.length))) 
        {
            return null; 
        }
        if (begin == -1) 
        {
            return null; 
        }
        var cEnd = document.cookie.indexOf(";", cLength); 
        if (cEnd == -1) 
        {
            cEnd = document.cookie.length; 
        }
        var dataArray = unescape(document.cookie.substring(cLength,cEnd)).split('|'); 
        if (dataArray.length > 0)
        {
            this.Index = dataArray.length-1;
            for (var x=0;x<dataArray.length;x++)
            {
                var Element = dataArray[x].split(':');
                switch (Element[0])
                {
                    case 'pan':
                        this.Cache.push(['pan', parseFloat(Element[1]), parseFloat(Element[2]), eval(Element[3])]);
                        break;
                    case 'qs':
                        this.Cache.push(['qs',Element[1], eval(Element[2])]);
                        break;
                }
            }
        }
    };

    MUserCacheObject.prototype.SetCookie = function()
    {
        var TempData = new Array();
        if (this.Cache.length > 0)
        {
            for (var x=0; x<this.Cache.length; x++)
            {
                var Element = this.Cache[x];
                switch (Element[0])
                {
                    case 'pan':
                        TempData.push(String.format("pan:{0}:{1}:{2}", Element[1], Element[2], Element[3]));
                        break;
                    case 'qs':
                        TempData.push(String.format("qs:{0}:{1}", escape(Element[1]), Element[2]));
                        break;
                }
            }
        }
        var cookieName = "maphistory";
        //DateAdd(theDate, addDays, addMonths, addYears)
        var d = new Date()
        var expires = DateAdd(d, 7, 0, 0);
        var cookieString = String.format("{0}={1};expires={2}", cookieName, TempData.join("|"), expires);
        document.cookie = cookieString; 
    };

    MUserCacheObject.prototype.AddPan = function(GLatLng, Zoom)
    {
        this.Cache.push(['pan', GLatLng.lat(), GLatLng.lng(), Zoom]);
        this.Index = this.Cache.length-1;
        this.Redraw();
        this.SetCookie();
    };

    MUserCacheObject.prototype.AddQuery = function(Query, Recenter)
    {
        this.Cache.push(['qs', Query, Recenter]);
        this.Index = this.Cache.length-1;
        this.Redraw();
        this.SetCookie();
    };

    MUserCacheObject.prototype.Next = function()
    {
        if (this.Index+1 <= this.Cache.length-1)
        {
            this.Index += 1;
            this.ExecuteIndex();
            this.Redraw();
        }
    };

    MUserCacheObject.prototype.Prev = function()
    {
        if (this.Index-1 >= 0)
        {
            this.Index -= 1;
            this.ExecuteIndex();
            this.Redraw();
        }
    };

    MUserCacheObject.prototype.First = function()
    {
        this.Index = 0;
        this.ExecuteIndex();
        this.Redraw();
    };

    MUserCacheObject.prototype.Last = function()
    {
        this.Index = this.Cache.length-1;
        this.ExecuteIndex();
        this.Redraw();
    };

    MUserCacheObject.prototype.DeleteItem = function()
    {
        this.Cache.splice(this.Index,1);
        if (this.Index > this.Cache.length-1)
        {
            this.Index = this.Cache.length-1;
        }
        this.SetCookie();
        this.Redraw();
    };

    MUserCacheObject.prototype.ExecuteIndex = function()
    {
        var Element = this.Cache[this.Index];
        switch (Element[0])
        {
            case 'pan':
                //map.setZoom(Element[3]);
                //map.panTo(new GLatLng(Element[1], Element[2]));
                map.setCenter(new GLatLng(Element[1], Element[2]), Element[3]);
                RequeryOnBounds(false, true, false);
                break;
            case 'qs':
                RunQuery(Element[1], Element[2], false);
                break;
        }
    };

    MUserCacheObject.prototype.Redraw = function()
        {with(this){
            var prev = -1;
            var next = 0;
            var status = "";
            if (Index > 0)
            {
                prev = Index-1;
            }
            else
            {
                prev = 0;
            }
            if (Index < Cache.length-1)
            {
                next = Index+1;
            }
            else
            {
                next = Cache.length-1
            }
    
            var first, last;
            if (Cache.length > 0)
            {
                first= "<a href='javascript:MCO.First();'>first</a>";
                prev = "<a href='javascript:MCO.Prev();'>prev</a>";
                next = "<a href='javascript:MCO.Next();'>next</a>";
                last = "<a href='javascript:MCO.Last();'>last</a>";
                status = String.format("Item {0} of {1} in history",Index+1, Cache.length);
            }
            else
            {
                prev = "prev";
                next = "next";
                first = "first";
                last = "last";
                status = "Your Map History Is Empty";
            }
            var del = "<a href='javascript:MCO.DeleteItem();'>Delete This History Item</a>";
            var delAll = "<a href='javascript:MCO.Dispose();'>Clear History</a>";
    
            DivObject.innerHTML = String.format("{0} -- {1} -- {2} -- {3} ----- {4} -- {5} -- {6}", first, prev, next, last, status, del, delAll);
        }};
    this.LoadCookie();
    this.Redraw();
}
*/
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//  End MUserCacheObject Code
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~