Link to home
Start Free TrialLog in
Avatar of Jason Berry
Jason Berry

asked on

Add json to Google Maps window

I need a solution to add a local json file to the body of an html page, to display data from said file in a Google map window.  So far, all attempts to display data from an external source have failed.  Below, is the code I am using.

<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="viewport" content="initial-scale=1.0, user-scalable=no">
	<title>Info windows</title>
	<style type="text/css">/* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
      #map {
        height: 100%;
      }
      /* Optional: Makes the sample page fill the window. */
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
	</style>
</head>
<body>
<div id="map"></div>
<script>

      // This example displays a marker at the center of Australia.
      // When the user clicks the marker, an info window opens.

      function initMap() {
        var hc = {lat: 40.4512, lng: -85.3700};
        var map = new google.maps.Map(document.getElementById('map'), {
          zoom: 4,
          center: hc
        });

obj = { "table":"customers", "limit":20 };
dbParam = JSON.stringify(obj);
xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
        myObj = JSON.parse(this.responseText);
        txt += "<table border='1'>"
        for (x in myObj) {
            txt += "<tr><td>" + myObj[x].name + "</td></tr>";
        }
        txt += "</table>" 
        document.getElementById("demo").innerHTML = txt;
    }
}
xmlhttp.open("POST", "json_demo_db_post.php", true);
xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xmlhttp.send("x=" + dbParam);


        var infowindow = new google.maps.InfoWindow({
          content: obj
        });

        var marker = new google.maps.Marker({
          position: hc,
          map: map,
          title: 'Hartford City'
        });
        marker.addListener('click', function() {
          infowindow.open(map, marker);
        });
      }
    </script><script async defer
    src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCz672JUYjod6zzfxnBg_rzBNsBfbbjpJc&callback=initMap">
    </script></body>
</html>

Open in new window

Avatar of leakim971
leakim971
Flag of Guadeloupe image

try this :

<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="viewport" content="initial-scale=1.0, user-scalable=no">
	<title>Info windows</title>
	<style type="text/css">/* Always set the map height explicitly to define the size of the div
       * element that contains the map. */
      #map {
        height: 100%;
      }
      /* Optional: Makes the sample page fill the window. */
      html, body {
        height: 100%;
        margin: 0;
        padding: 0;
      }
	</style>
</head>
<body>
<div id="map"></div>
<script>
      // This example displays a marker at the center of Australia.
      // When the user clicks the marker, an info window opens.

      function initMap() {
        var hc = {lat: 40.4512, lng: -85.3700};
        var map = new google.maps.Map(document.getElementById('map'), {
          zoom: 4,
          center: hc
        });

        var infowindow = new google.maps.InfoWindow({
          content: obj
        });

        var marker = new google.maps.Marker({
          position: hc,
          map: map,
          title: 'Hartford City'
        });
        marker.addListener('click', function() {
          infowindow.open(map, marker);
        });
      }

      var downloadJSON = function() {
        obj = { "table":"customers", "limit":20 };
        dbParam = JSON.stringify(obj);
        xmlhttp = new XMLHttpRequest();
        xmlhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                myObj = JSON.parse(this.responseText);
                txt += "<table border='1'>"
                for (x in myObj) {
                    txt += "<tr><td>" + myObj[x].name + "</td></tr>";
                }
                txt += "</table>" 
                document.getElementById("demo").innerHTML = txt;
                initMap();
            }
        }
        xmlhttp.open("POST", "json_demo_db_post.php", true);
        xmlhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
        xmlhttp.send("x=" + dbParam);
      }

</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCz672JUYjod6zzfxnBg_rzBNsBfbbjpJc&callback=downloadJSON"></script>
</body>
</html>

Open in new window


Please note we have : callback=downloadJSON
and not : callback=initMap

Your ajax call is asynchronous, you must run the initMap after loading the JSON data
more info here : https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests
Avatar of Jason Berry
Jason Berry

ASKER

The above code doesn't display a map.

 Since Chrome's privacy policy makes it extremely complicated to display a local json file from within your own domain, I have attempted to take the advice of others and run a local webserver, serve up the file and make the AJAX call to localhost, using the $.getJSON method to display the information, internally.

       <!DOCTYPE html>
        <html>
        <head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="viewport" content="initial-scale=1.0, user-scalable=no">
        	<title>Info windows</title>
        	<style type="text/css">/* Always set the map height explicitly to define the size of the div
               * element that contains the map. */
              #map {
                height: 100%;
              }
              /* Optional: Makes the sample page fill the window. */
              html, body {
                height: 100%;
                margin: 0;
                padding: 0;
              }
        	</style>
        <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
        </head>
        <body>
        <div id="map"></div>
        <script>
        
              // This example displays a marker at the center of Australia.
              // When the user clicks the marker, an info window opens.
        
              function initMap() {
                var hc = {lat: 40.4512, lng: -85.3700};
                var map = new google.maps.Map(document.getElementById('map'), {
                  zoom: 4,
                  center: hc
                });
        
        var obj = $.getJSON( "ajax/GeoObs.json", function( data ) {
          var items = [];
          $.each( data, function( key, val ) {
            items.push( "<li id='" + key + "'>" + val + "</li>" );
          });
         
          $( "<ul/>", {
            "class": "my-new-list",
            html: items.join( "" )
          }).appendTo( "body" );
        });
        
                var infowindow = new google.maps.InfoWindow({
                  content: obj
                });
        
                var marker = new google.maps.Marker({
                  position: hc,
                  map: map,
                  title: 'Hartford City'
                });
                marker.addListener('click', function() {
                  infowindow.open(map, marker);
                });
              }
            </script><script async defer
            src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCz672JUYjod6zzfxnBg_rzBNsBfbbjpJc&callback=initMap">
            </script></body>
        </html>

Open in new window


If you run the code, it displays the marker and creates a window.  However, it does not display any data.  Maybe there is a better way to do this - I'm not sure.

Comments/ suggestions?

Thank you!
could you post the JSON object ?
Using jQuery doesn't resolve your main issue.
Here the new version with the same previous update.
If you are able to share the JSON I can validate it work... or not.
If you've a link to see you code, it's better.
Hope you got my notes after the following code, just like my previous answer.

<!DOCTYPE html>
<html>
<head><meta http-equiv="Content-Type" content="text/html; charset=utf-8"><meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <title>Info windows</title>
    <style type="text/css">/* Always set the map height explicitly to define the size of the div
               * element that contains the map. */
    #map {
        height: 100%;
    }
    /* Optional: Makes the sample page fill the window. */
    html, body {
        height: 100%;
        margin: 0;
        padding: 0;
    }
    </style>
    <script src="https://code.jquery.com/jquery-1.10.2.js"></script>
</head>
<body>
<div id="map"></div>
<script>

    // This example displays a marker at the center of Australia.
    // When the user clicks the marker, an info window opens.

    function initMap() {
        var hc = {lat: 40.4512, lng: -85.3700};
        var map = new google.maps.Map(document.getElementById('map'), {
            zoom: 4,
            center: hc
        });

        var infowindow = new google.maps.InfoWindow({
            content: obj
        });

        var marker = new google.maps.Marker({
            position: hc,
            map: map,
            title: 'Hartford City'
        });
        marker.addListener('click', function() {
            infowindow.open(map, marker);
        });
    }

    var downloadJSON = function() {
        var obj = $.getJSON( "ajax/GeoObs.json", function( data ) {
            var items = [];
            $.each( data, function( key, val ) {
                items.push( "<li id='" + key + "'>" + val + "</li>" );
            });

            $( "<ul/>", {
                "class": "my-new-list",
                html: items.join( "" )
            }).appendTo( "body" );

            initMap();
        });
    }

</script>
<script async defer src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCz672JUYjod6zzfxnBg_rzBNsBfbbjpJc&callback=downloadJSON"></script>
</body>
</html>

Open in new window


Please note we have : callback=downloadJSON
and not : callback=initMap

Your ajax call is asynchronous, you must run the initMap after loading the JSON data
more info here : https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/Synchronous_and_Asynchronous_Requests
so the JSOn is :
{
  features: [
    {
      geometry: {
        coordinates: [
          -85.362709,
          40.466442
        ],
        type: "Point"
      },
      properties: {
        Temp: "30.2 F (-1.0 C)",
        Weather: "Overcast",
        Wind: "From the SE at 4.5 MPH Gusting to 6.9 MPH"
      },
      type: "Feature"
    }
  ],
  type: "FeatureCollection"
}

Open in new window


your code, do a $.each over the json (the data), what do you want to do ? for each feature inside the features array ?
a feature is ?
from that part : "<li id='" + key + "'>" + val + "</li>"
what is supposed to be the key and the value from each feature ?

let me know and I will give your the code
Thank you for the reply!  I would like to show values for both Weather and Temp, as well as Wind.  However, those values should be dynamic, as they will change often.

The output needs to be in list form, like below:

Weather:
Temp:
Wind:
ASKER CERTIFIED SOLUTION
Avatar of leakim971
leakim971
Flag of Guadeloupe image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
THIS LOOKS GREAT - THANK YOU!  Now, if I can only find a way to make the JSON display on my website.  Bringing in the code a you have been so kind to include, above still shows an empty map window on click.  This is obviously something to do with my web server and not the code itself.
give me the link to your website to see how you integrate the code
I will fix it
at the bottom replace :
=initMap
by :
=downloadJSON

        </script><script async defer
        src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCz672JUYjod6zzfxnBg_rzBNsBfbbjpJc&callback=downloadJSON">
        </script></body>
    </html>
Hmmm... Replacing 'initMap' with 'downloadJSON' returns a blank page.  Any other suggestions?  I feel like we're so close, maybe one line of code somewhere I am missing?
I tried and it worked fine
could you let what you did to let me seee that blank page too ?
Certainly!  I saved changes at http://stormtrackerwx.com/index_beta.html
we've a 404 error for the JSON file : ajax/GeoObs.json
404 error is : file not found
you're supposed to palce the GeoObs.json inside an ajax folder
Yep, that's it.  Sounds like my webserver didn't like the ajax import.  I'm going to have to try and figure-out where the problem lies there.  Thank you so much for all the help!
look better now :

User generated image
Thank you for all the help!  The information provided helped tremendously in addressing the problem and expanding my knowledge for future projects.
How'd you make the ajax folder work?
this si your page.... maybe clear your browser cache... I did not create anything
Thanks again!   You've been a tremendous help!
Sorry to keep going with this, but I'm right back to where I was with the JSON not displaying.  If there is anyway you can go back to my index page, above and see if you see anything, that would be greatly appreciated!  Not sure what's going on.  Everything validates.
at the bottom replace :
=initMap
by :
=downloadJSON

        </script><script async defer
        src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCz672JUYjod6zzfxnBg_rzBNsBfbbjpJc&callback=downloadJSON">
        </script></body>
    </html>
Awesome!  Everything is working great... Except, I am getting 'Undefined" when attempting to pass new fields from the JSON into the list.

https://api.myjson.com/bins/10y73l
if you're trying to load  https://api.myjson.com/bins/10y73l from your website, you've a problem : this is not possible.
you must use your backend :
save the following as  geo.php
<?php
   echo file_get_contents("https://api.myjson.com/bins/10y73l");
?>

Open in new window


and replace :
var obj = $.getJSON( "ajax/GeoObs.json", function( data ) {
by :
var obj = $.getJSON( "geo.php", function( data ) {
Correct.  I just used a url to show what my GeoJSON contained.  This is how I am calling that data in my html.

    var downloadJSON = function() {
        $.getJSON( "ajax/GeoObs.json", function( data ) {
            var items = [];
            items.push( "<li id='Weather'>Station: " + data.features[0].properties.Station + "</li>");
            items.push( "<li id='Weather'>Time: " + data.features[0].properties.Time + "</li>");
            items.push( "<li id='Weather'>Weather: " + data.features[0].properties.Weather + "</li>");
            items.push( "<li id='Weather'>Temp: " + data.features[0].properties.Temp + "</li>");
            items.push( "<li id='Weather'>Wind: " + data.features[0].properties.Wind + "</li>");
            obj = $('<div>').append($( "<ul/>", { class: "my-new-list", html: items.join("") })).html();
            initMap();
        });
    }

Not sure where the undefined is coming from on Station and Time.  On a related note, would your time be better suited if I created a project request?
I just checked your site and it work fine, maybe it's not the bad version ? put it in place to let me see what happen
You don't see 'undefined'?

User generated image
my bad...
unlike : https://api.myjson.com/bins/10y73l inside "ajax/GeoObs.json" there's not Station and Time in your json, so your code can't get them
That is so weird.  I checked and they are there, but it's almost like they can't read from them.
Since this is turning into an ongoing thread, would you rather me start a new thread or continue on this one?  I am still needing assistance placing markers from latitude/ longitude coordinates in the JSON, as well as updating each marker to point back to an image path that I will also include on the external JSON.
it's ok now, it's all about browser caching...
to avoid caching issue, replace :
$.getJSON( "ajax/GeoObs.json", function( data ) {
by :
$.getJSON( "ajax/GeoObs.json?_="+new Date().getTime(), function( data ) {

and yes, it's would be great to create a thread by question what is supposed to help people coming here and searching for answer