Hello and welcome to our community! Is this your first visit?
Register
Enjoy an ad free experience by logging in. Not a member yet? Register.
Results 1 to 10 of 10
  1. #1
    New to the CF scene
    Join Date
    Jun 2013
    Posts
    5
    Thanks
    3
    Thanked 0 Times in 0 Posts

    Smile Plotting JSON data from URL onto Google Maps

    Hello all,
    First time posting here. Looks like a pretty cool community. Anyways, I have a pretty solid foundation of JS, but I've run into a problem that is pretty confusing. Essentially, I need to take user input data from Google Maps (i.e. a location) and reference a URL that is simply a JSON file (e.g. http://ws.geonames.org/earthquakesJS...ate=2013-06-30). Then, I must plot every individual JSON object in that file, onto google maps. This is quite the challenge for me and the first part I want to know about involves reading and plotting the JSON file (I'll worry about the dynamic URL later). Anyways, here's the sample code that does something similar with a different file (taken from Google directly).
    [CODE]
    // Create a <script> tag and set the USGS URL as the source.
    var script = document.createElement('script');
    // (In this example we use a locally stored copy instead.)
    script.src = 'http://earthquake.usgs.gov/earthquakes/feed/geojsonp/2.5/week';
    document.getElementsByTagName('head')[0].appendChild(script);
    }

    // Loop through the results array and place a marker for each
    // set of coordinates.
    window.eqfeed_callback = function(results) {
    for (var i = 0; i < results.features.length; i++) {
    var coords = results.features[i].geometry.coordinates;
    var latLng = new google.maps.LatLng(coords[1],coords[0]);
    var marker = new google.maps.Marker({
    position: latLng,
    map: map
    });
    };
    };
    [CODE]

    What I don't really understand is the for loop. More specifically, it is gathering locations and geotagging these Earthquakes on Google Maps. However, I see no specific indicator of "coordinates" in the JSON file. Only city locations. I would like to understand this better as I need help adjusting the script to read from this JSON file (http://ws.geonames.org/earthquakesJSON?north=22.5&south=0.0&east=-22.4&west=33.2&date=2013-06-30), and plotting the appropriate earthquakes around the given point. Thank you in advance for any help you can give me.

    P.S. This is only the first part of the problem, the other issue I'm running into is in regards to the dynamic URL (you'll notice the above link has specific coordinates, those coordinates need to change based on the city user inputs in the google maps search bar).

  • #2
    Senior Coder xelawho's Avatar
    Join Date
    Nov 2010
    Posts
    2,930
    Thanks
    56
    Thanked 552 Times in 549 Posts
    you can paste those urls into the JSON data URL input on this page:
    http://jsonformatter.curiousconcept.com/

    to get a more humanly-readable format.

    for the earthquake.usgs.gov, scroll down 'til you see "geometry" - that's where the coordinates are stored

    in the geonames ones they are stored at the first level, in the "lat" and "lng" keys

    but there is a difference in the results that will make your implementation vary from google's - note that the usgs results come wrapped in a callback function - eqfeed_callback, whereas the geonames ones get served up as raw JSON. This means that you can call the callback after appending the usgs script and once the results are ready you can access that data.

    But if geonames doesn't wrap their results in a callback (which I'm sure they do, you just have to find the parameter on their webpage) you would have to find some other way of accessing that info, maybe with a cross-domain ajax request (which will be annoying... I strongly recommend looking for a callback parameter first)

    the second part of your problem will require you to geocode the address supplied:
    https://developers.google.com/maps/d...ocoding-simple

    then get the surrounding points (because the urls seem accept a box for the cardinal points - the bounds property of the geocode result will be useful for this:
    https://developers.google.com/maps/d...rence#Geocoder)

    and add them to the url before requesting it from geonames (or wherever)

  • Users who have thanked xelawho for this post:

    Sockle (06-30-2013)

  • #3
    Senior Coder xelawho's Avatar
    Join Date
    Nov 2010
    Posts
    2,930
    Thanks
    56
    Thanked 552 Times in 549 Posts
    just had a look at the geonames page... you can add an optional callback, so the url would look like this:
    http://ws.geonames.org/earthquakesJS...lback="showMe"

    where showMe is the function that processes the results once they come back to you.

  • Users who have thanked xelawho for this post:

    Sockle (06-30-2013)

  • #4
    New to the CF scene
    Join Date
    Jun 2013
    Posts
    5
    Thanks
    3
    Thanked 0 Times in 0 Posts
    Great Xelawho,
    You're amazing! Thank you so much.

    Anyways, I've corrected the code to look more like this:

    [CODE]
    // Create a <script> tag and set the USGS URL as the source.
    var script = document.createElement('script');
    //script.src = 'http://earthquake.usgs.gov/earthquakes/feed/geojsonp/2.5/week';
    script.src = 'http://ws.geonames.org/earthquakesJSON?north=22.5&south=0.0&east=-22.4&west=33.2&date=2013-06-30&callback=showMe';
    document.getElementsByTagName('head')[0].appendChild(script);
    }

    // Loop through the results array and place a marker for each
    // set of coordinates.
    window.showMe = function(results) {
    for (var i = 0; i < results.earthquakes.length; i++) {
    //var coords = results.features[i].geometry.coordinates;
    //var latLng = new google.maps.LatLng(coords[1],coords[0]);
    var coords = results.earthquakes[i];
    var latLng = new google.maps.LatLng(coords[6],coords[2]);
    var marker = new google.maps.Marker({
    position: latLng,
    map: map
    });
    };
    };
    [CODE]

    I've appended the callback tag onto the URL and changed the for loop appropriately (at least I think so). For some reason the markers are still not popping up on the map and I'm not sure why. Any input you can give would be great. Also, if you would like to see the rest of the code (including the HTML) let me know.
    - Thanks!

  • #5
    Senior Coder xelawho's Avatar
    Join Date
    Nov 2010
    Posts
    2,930
    Thanks
    56
    Thanked 552 Times in 549 Posts
    here's a quick example... you may want to adjust the zoom level of the map (or do some other calculation to get the n,s,e,w variables) before it calculates the bounds - if the user is zoomed right out it will show everything...

    Code:
    <!DOCTYPE html>
    <html>
      <head>
        <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
        <meta charset="utf-8">
        <title>Earthquake finder</title>
    	<style>
    body,html{height:100%}
    #map-canvas{height:100%}
    </style>
        <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
        <script>
    var geocoder;
    var map;
    function initialize() {
      geocoder = new google.maps.Geocoder();
      var latlng = new google.maps.LatLng(-34.397, 150.644);
      var mapOptions = {
        zoom: 8,
        center: latlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
      }
      map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
    }
    
    function codeAddress() {
      var address = document.getElementById('address').value;
      geocoder.geocode( { 'address': address}, function(results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
    	if(document.getElementById("eqscript")){
    	document.getElementsByTagName('head')[0].removeChild(document.getElementById("eqscript"));
    	}
    	  map.setCenter(results[0].geometry.location);
    	  var script = document.createElement('script');
    	  script.id="eqscript"
    	var bnds=map.getBounds(); 
    		var n=bnds.getNorthEast().lat();
    		var e=bnds.getNorthEast().lng();
    		var w=bnds.getSouthWest().lng();
    		var s=bnds.getSouthWest().lat();
    		script.src = "http://ws.geonames.org/earthquakesJSON?north="+n+"&south="+s+"&east="+e+"&west="+w+"&date=2013-06-30&callback=showMe";
    		document.getElementsByTagName('head')[0].appendChild(script);
        } else {
          alert('Geocode was not successful for the following reason: ' + status);
        }
      });
    }
    
    function showMe(o){
    var eqs=o.earthquakes;
    for (var i = 0; i < eqs.length; i++) {
    var marker = new google.maps.Marker({
              map: map,
              position: new google.maps.LatLng(eqs[i].lat, eqs[i].lng),
    		  title:"Time: "+eqs[i].datetime+" Magnitude: "+eqs[i].magnitude
          });
    	}
    }
    
    google.maps.event.addDomListener(window, 'load', initialize);
    
        </script>
      </head>
      <body>
        <div id="panel">
          <input id="address" type="textbox" value="Sydney, NSW">
          <input type="button" value="Find Earthquakes" onclick="codeAddress()">
        </div>
        <div id="map-canvas"></div>
      </body>
    </html>
    Last edited by xelawho; 06-30-2013 at 04:33 PM. Reason: added remove script to avoid cluttering

  • Users who have thanked xelawho for this post:

    Sockle (06-30-2013)

  • #6
    New to the CF scene
    Join Date
    Jun 2013
    Posts
    5
    Thanks
    3
    Thanked 0 Times in 0 Posts

    Smile

    Holy geez this is amazing, Xelawho!
    Thank you so much for going above and beyond for what I asked for.
    I'm going to try to recreate this code myself so that I can understand it better. You have my eternal gratitude!

  • #7
    Senior Coder xelawho's Avatar
    Join Date
    Nov 2010
    Posts
    2,930
    Thanks
    56
    Thanked 552 Times in 549 Posts
    no worries - I just frankensteined a couple of bits of pre-existing code. feel free to ask if you don't understand something.

    one thing you might want to look at... if you make various queries, the markers just keep getting added to the map - if you wanted to avoid that you would have to push the markers onto an array, then every time a new query is made, loop through that array and call setMap(null) on each of the markers (which removes them from the map)

  • #8
    New to the CF scene
    Join Date
    Jun 2013
    Posts
    5
    Thanks
    3
    Thanked 0 Times in 0 Posts
    Thanks for all of your help. I took your advice and pushed everything through an array, it seems to be working alright now. The final issue I have with this code is that I'm trying to implement a separate button that shows the most destructive Earthquakes of the past year. To do this I'm reading off of this list:

    http://ws.geonames.org/earthquakesJS...allback=TopTen

    and calling back an almost identical function that only parses the first ten entries. Anyways, I can get all of this to display just fine, however I can't figure the appropriate function to separate it from the original "CodeAddress()" function. What I have so far is:

    [CODE]
    function SevereQuakes() {
    var address = document.getElementById('address').value;
    geocoder.geocode({'address': address}, function(results, status) {
    if (status == google.maps.GeocoderStatus.OK) {
    map.setCenter(results[0].geometry.location);
    map.setZoom(2);
    var script = document.createElement('script');
    script.src = "http://ws.geonames.org/earthquakesJSON?north=180&south=-180.0&east=90&west=-90&date=2013-06-30&minMagnitude=6.4&maxRows=25&callback=TopTen";
    document.getElementsByTagName('head')[0].appendChild(script);
    }
    });
    }
    [CODE]

    Essentially I'm trying to figure out a way to remove all ties to the search bar, such that if I click the 2nd button, the top ten earthquakes will simply appear on the map. Any input that could be offered would be very helpful, thanks again!

  • #9
    Senior Coder xelawho's Avatar
    Join Date
    Nov 2010
    Posts
    2,930
    Thanks
    56
    Thanked 552 Times in 549 Posts
    you don't need the address and geocoder stuff if you're querying worldwide, and you can reuse the showMe function - it seems to me that if you want the top ten you should specify maxRows as 10, no?

    you can use the bounds object to center and zoom the map according to your query, too, which seems to make more sense than setting a static zoom level...

    Code:
    <!DOCTYPE html>
    <html>
      <head>
        <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
        <meta charset="utf-8">
        <title>Earthquake finder</title>
    	<style>
    body,html{height:100%}
    #map-canvas{height:100%}
    </style>
        <script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
    
      </head>
      <body>
        <div id="panel">
          <input id="address" type="textbox" value="Sydney, NSW">
          <input type="button" value="Find Earthquakes" id="all">
    	  <input type="button" value="Show top 10" id="top">
        </div>
        <div id="map-canvas"></div>
        <script>
    var geocoder;
    var map;
    var mkrs = [];
    
    function initialize() {
      geocoder = new google.maps.Geocoder();
      var latlng = new google.maps.LatLng(-34.397, 150.644);
      var mapOptions = {
        zoom: 8,
        center: latlng,
        mapTypeId: google.maps.MapTypeId.ROADMAP
      }
      map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);
      document.getElementById("all").onclick = codeAddress;
      document.getElementById("top").onclick = topTen;
    }
    
    function codeAddress() {
      var address = document.getElementById('address').value;
      geocoder.geocode({
        'address': address
      }, function (results, status) {
        if (status == google.maps.GeocoderStatus.OK) {
          if (document.getElementById("eqscript")) {
            document.getElementsByTagName('head')[0].removeChild(document.getElementById("eqscript"));
          }
          map.setCenter(results[0].geometry.location);
          map.setZoom(8);
          var script = document.createElement('script');
          script.id = "eqscript";
          var bnds = map.getBounds();
          var n = bnds.getNorthEast().lat();
          var e = bnds.getNorthEast().lng();
          var w = bnds.getSouthWest().lng();
          var s = bnds.getSouthWest().lat();
          script.src = "http://ws.geonames.org/earthquakesJSON?north=" + n + "&south=" + s + "&east=" + e + "&west=" + w + "&date=2013-06-30&callback=showMe";
          document.getElementsByTagName('head')[0].appendChild(script);
        } else {
          alert('Geocode was not successful for the following reason: ' + status);
        }
      });
    }
    
    function showMe(o) {
      var LLbnds = new google.maps.LatLngBounds();
      clearIt();
      var eqs = o.earthquakes;
      for (var i = 0; i < eqs.length; i++) {
        var marker = new google.maps.Marker({
          map: map,
          position: new google.maps.LatLng(eqs[i].lat, eqs[i].lng),
          title: "Time: " + eqs[i].datetime + " Magnitude: " + eqs[i].magnitude
        });
        mkrs.push(marker);
        LLbnds.extend(marker.getPosition())
      }
      map.fitBounds(LLbnds);
    }
    
    function clearIt() {
      for (var i = 0; i < mkrs.length; i++) {
        mkrs[i].setMap(null);
      }
    }
    
    function topTen() {
      if (document.getElementById("eqscript")) {
        document.getElementsByTagName('head')[0].removeChild(document.getElementById("eqscript"));
      }
      var script = document.createElement('script');
      script.id = "eqscript";
      script.src = "http://ws.geonames.org/earthquakesJSON?north=180&south=-180.0&east=90&west=-90&date=2013-06-30&minMagnitude=6.4&maxRows=10&callback=showMe";
      document.getElementsByTagName('head')[0].appendChild(script);
    }
    
    google.maps.event.addDomListener(window, 'load', initialize);
        </script>
    	</body>
    </html>

  • #10
    New to the CF scene
    Join Date
    Jun 2013
    Posts
    5
    Thanks
    3
    Thanked 0 Times in 0 Posts
    Hey I just want to say thank you for all your help. The code is up and running now and everything seems to be working great. You were extremely helpful in all of this. Cheers, buddy!


  •  

    Tags for this Thread

    Posting Permissions

    • You may not post new threads
    • You may not post replies
    • You may not post attachments
    • You may not edit your posts
    •