Search code examples
javascriptgoogle-maps-api-3getjsoninfowindow

Two $.getJSON calls for one Google Maps api info window. Scope issue


I am trying to call $.getJSON twice and use the data from both in one info window. This is a mashup to display articles from Google News together with a "fortune" (from an RSS feed) in a Google Maps API infowindow. I put the click event listener and the info window blocks inside the $.getJSON("articles.php") call so this code below works in so far as it will display the articles but I can't figure out the right structure to display the fortune since it's in a separate $.getJSON with it's own scope. Is there a way to make this work?

function addMarker(place)
{

    var image = 'http://maps.google.com/mapfiles/kml/pal2/icon31.png';  
    var myLatlng = new google.maps.LatLng(parseFloat(place.latitude), parseFloat(place.longitude));
    //make markers and push to array. 
    var marker = new MarkerWithLabel({
    position: myLatlng,
    map: map,
    icon: image,
    labelClass: "labels",
    labelContent: place.place_name,
    labelAnchor: new google.maps.Point(20,0),    
    });

    markers.push(marker);

    // getJSON fortune from RSS feed. 
    var fortune = []; 
    $.getJSON("fortunes.php").done(function(data, textStatus, jqXHR) {
        var content = data;
        var len = data.length;
        if (content.length < 1)
        {
            var fortune = "test";
        }
        else
        {
            fortune = content;
        }

    });     
    // getJSON articles from Google News rss feed. 
    var query = place.postal_code;
    var articles = "News service currently unavailable.";
    var parameter = { "geo": query };
    $.getJSON("articles.php", parameter).done(function(data, textStatus, jqXHR) {
        var content = data;
        var len = data.length;
        if (content.length < 1)
        {
            articles = "Slow news day."
        }
        else
        {
            articles = "<ul>";
            // put articles in unordered list
            for (var i = 0; i < len; i++) {
                articles += "<div><li> <a href=\"" + data[i].link + "\" target=\"_blank\">" + data[i].title + "</li></div>";
            }
            articles += "</ul><div><p>FORTUNE</p><p>" + fortune.length + "</p></div>";
        }
        // Listener for info window    
        google.maps.event.addListener(marker, 'click', function() {
            infowindow.open(map,marker);
        });
        // Info window 
        var infowindow = new google.maps.InfoWindow({
            content: articles
        });  
    }); 

}

Solution

  • There are 4 ways to get this done.

    1. Make the AJAX calls sequentially - see code example below or http://jsfiddle.net/xs0oypmd/
    2. Build the marker window content when the user opens it, so move the articles html building code to within the marker click event listener and use the setContent function on the infoWindow. If going with this approach I'd suggest using a flag to indicate the first time the info window is opened so that the articles html is built only once. This approach does have the limitation that you still do not know if fortunes has loaded.
    3. Make the "fortunes" call from within "articles.php" - this assumes ownership over the php scripts. This approach means one AJAX call from the browser.
    4. Use a model binding framework, e.g. knockout, to update the infoWindow content when the data is updated via the json call

    Code Example For Option 1

    $("#btnGetArticles").on("click", function(){
        var fortunes = "test";
    
        $.ajax({
            url: "/echo/json/",
            type: 'post',
            dataType: 'json',
            data: {
                json: '"some fortune"'
            }
        }).done(function(data) {
            fortunes = data;
    
            $.ajax({
                url: "/echo/json/",
                type: 'post',
                dataType: 'json',
                data: {
                    json: '[{"link": "link/to/first/article", "title" : "first article"},{"link": "link/to/second/article", "title" : "second article"},{"link": "link/to/third/article", "title" : "third article"}]'
                }
            }).done(function(articles) {
                var articlesList = $("<ul />");
                $.each(articles, function(i, v) {
                    articlesList.append($("<li />").html(v.title + ' ' + fortunes.length));
                });
    
                $("#output").append(articlesList);
            });
        });
    });