    var clusterer;
    
    function load() {
        if (!GBrowserIsCompatible()) {
            return;
        }
        G_DEFAULT_ICON.shadow = "";
        var map = new GMap2(document.getElementById("map"));
        map.addControl(new GSmallMapControl());
        if ( defaultLatitude == 0 && defaultLongitude == 0 ) {
          map.setCenter(new GLatLng(40, -20), 3);
        } else {
          map.setCenter(new GLatLng(defaultLatitude, defaultLongitude), 11);
        }
        map.enableDoubleClickZoom();

        clusterer = new Clusterer(map);
        clusterer.SetMaxVisibleMarkers(50);
        clusterer.SetMaxLinesPerInfoBox(5);

        reloadMap();
    }

    function parsePoints(data, responsecode) {
        var xml = GXml.parse(data);
        var markers = xml.documentElement.getElementsByTagName("marker");
        for (var i = 0; i < markers.length; i++) {
            var lat = markers[i].getAttribute("lat");
            var lng = markers[i].getAttribute("lng");
            lat = lat == null || lat.length == 0 ? 0 : parseFloat(lat);
            lng = lng == null || lng.length == 0 ? 0 : parseFloat(lng);
            var city = markers[i].getAttribute("city");
            var country = markers[i].getAttribute("country");
            var name = markers[i].getAttribute("name");
            var id = markers[i].getAttribute("id");
            var age = markers[i].getAttribute("age");
            var photo = markers[i].getAttribute("photo");
            var label = "<div style='height: 100;'><a href='view.jsp?id=" + id + "'>";
            if ( photo != "" ) {
                label += "<img src='photos/"+photo+"' style='float:left;' border='0'>";
            }
            label += name + ": " + age + ", " + city + ", " + country + "</a></div>";
            var title = "<a href='view.jsp?id=" + id + "'>" + name + "</a>";
            var point;
            if ( lat != 0 && lng != 0 ) { // if coordinates found, use that point
                point = new GLatLng(lat, lng);
                clusterer.AddMarker(createMarker(point, label), title); // name is title in cluster list
            } else { // geolocate
                var geocoder = new GClientGeocoder();
                var func = geocodeMarker(label, title); // must put into a new function and copy label or else anonymous function would 
                // use the last value in the loop!
                geocoder.getLatLng(city + ", " + country, func);
            }
        }
    }
    
    function geocodeMarker(label, name) {
        // we have to pass a reference to a function to geocodeMarker, but we also have to copy the value of label.
        // using the anonymous function inline would always use the last value of 'label' in the loop
        return function(point) {
            if (point) {
                clusterer.AddMarker(createMarker(point, label), name);
            }
        };
    }
    
    // Creates a marker at the given point with the given number label
    function createMarker(point, label) {
        var marker = new GMarker(point);
        GEvent.addListener(marker, "click", function() {
            marker.openInfoWindowHtml(label);
        });
        return marker;
    }

    var timeoutId;
    function refreshMap(millis) {
        clearTimeout(timeoutId);
        if (millis == undefined) {
            millis = 2000;
        }
        timeoutId = setTimeout('reloadMap()', millis);
    }

    function reloadMap() {
        //<%-- 
        // Download the data in data.xml and load it on the map. The format we
        // expect is:
        // <markers>
        //   <marker lat="37.441" lng="-122.141"/>
        //   <marker lat="37.322" lng="-121.213"/>
        // </markers>
        // pass parsePoints as a function reference
        //--%>

        clusterer.RemoveAll();
        clusterer.map.closeInfoWindow();
        var gender;
        var genderArray = document.mapForm.gender;
        for (var i = 0; i < genderArray.length; i++) {
            if ( genderArray[i].checked == true ) {
                gender = genderArray[i].value;
            }
        }
        var ageMin = document.mapForm.ageMin.value;
        var ageMax = document.mapForm.ageMax.value;
        var url = "/servlet/ajaxMapQuery?gender="+escape(gender)+"&ageMin="+
            escape(ageMin)+"&ageMax="+escape(ageMax);
        //alert(url);
        GDownloadUrl(url, parsePoints);
    }
