1

I am trying to get the address from the google maps api and display this address in the right column of my table when there is not already a value there. When they have a custom address defined in the code this address is shown, but when it needs to show the address from the google maps api it doesn't show up. What do I need to change to make these show up?

var oTable = $("#example").dataTable({
  "aoColumns": [{
    "sTitle": "Time"
  }, {
    "sTitle": "Lat"
  }, {
    "sTitle": "Long"
  }, {
    "sTitle": "Addr"
  }]
});
var p = [
        ["10:00:00", "78.8807865", "17.8921649", "got Address"]
];
for (var j = 0; j < 400; j++) {
p.push(["10:00:"+j, "78.4807865", "17.4921649", ""]);
}
alert(p.length);
oTable.fnAddData(p);

for (var i = 0; i < p.length; i++) {
  if (p[i][3] == "") {
    var geocoder = new google.maps.Geocoder();
    var latlng = new google.maps.LatLng(p[i][1], p[i][2]);
    function getAddr(i){

  geocoder.geocode({
    "latLng": latlng
  }, function(results, status) {
    var address;
    if (status == 'OVER_QUERY_LIMIT') {
      address = 'Loading...';
      setTimeout(function(){ getAddr(i); }, 1000);
    } else if (status == 'OK') {
      address = results[0].formatted_address;
    } else {
      address = 'Error: ' + status;
    }
    p[i][3] = address;
    oTable.fnUpdate(p[i], i);
  });

}

getAddr(i);}
}
<link href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
<table id="example"></table>

UPDATED CODE

  • with this updated Code BROWSER NOT RESPONDING and BROWSER STRUCK.
  • any advice for more then calls of client side google map api avoid BROWSER NOT RESPONDING and BROWSER STRUCK(if it takes more time not a problem,need solution for without struck the browser),
  • thanks in advance.
Hydrogen
  • 167
  • 3
  • 10
  • Slightly off topic, but very basic Javascript scope - you declare "var i" twice, however scope means that it exists for the entire block even before the first declaration (and the second one is redundant) - stackoverflow.com/a/500459/3328079 - see point 8 specifically – Rycochet Feb 21 '15 at 12:10

3 Answers3

2

When the callback is called, the loop has already finished, so the loop variable i is outside of the array p.

You can use a function expression to create a scope where a copy of the variable i survives until the data arrives:

var oTable = $("#example").dataTable({
  "aoColumns": [{
    "sTitle": "Time"
  }, {
    "sTitle": "Lat"
  }, {
    "sTitle": "Long"
  }, {
    "sTitle": "Addr"
  }]
});
var p = [
  ["10:00:00", "17.4807865", "78.4921649", ""],
  ["10:00:01", "17.5807865", "78.5921649", ""],
  ["10:00:02", "17.6807865", "78.6921649", "Somthing address"],
  ["10:00:03", "17.7807865", "78.7921649", ""],
  ["10:00:04", "17.8807865", "78.8921649", "got Address"],
  ["10:00:05", "17.4807865", "78.4921649", ""],
  ["10:00:06", "17.5807865", "78.5921649", ""],
  ["10:00:07", "17.6807865", "78.6921649", "Somthing address"],
  ["10:00:08", "17.7807865", "78.7921649", ""],
  ["10:00:09", "17.8807865", "78.8921649", "got Address"],
  ["10:00:10", "17.4807865", "78.4921649", ""],
  ["10:00:11", "17.5807865", "78.5921649", ""],
  ["10:00:12", "17.6807865", "78.6921649", "Somthing address"],
  ["10:00:13", "17.7807865", "78.7921649", ""],
  ["10:00:14", "17.8807865", "78.8921649", "got Address"],
  ["10:00:15", "17.4807865", "78.4921649", ""],
  ["10:00:16", "17.5807865", "78.5921649", ""],
  ["10:00:17", "17.6807865", "78.6921649", "Somthing address"],
  ["10:00:18", "17.7807865", "78.7921649", ""],
  ["10:00:19", "17.8807865", "78.8921649", "got Address"],
  ["10:00:19", "17.8807865", "78.8921649", "got Address"],
];

oTable.fnAddData(p);
for (var i = 0; i < p.length; i++) {
  if (p[i][3] == "") {
    var geocoder = new google.maps.Geocoder();
    var latlng = new google.maps.LatLng(p[i][1], p[i][2]);
    
    (function(i){
    
      geocoder.geocode({
        "latLng": latlng
      }, function(results, status) {
        var address;
        if (status == 'OK') {
          address = results[0].formatted_address;
        } else {
          address = 'Error: ' + status;
        }
        p[i][3] = address;
        oTable.fnUpdate(p[i], i);
      });

    })(i);
    
  }
}
<link href="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/css/jquery.dataTables.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="http://ajax.aspnetcdn.com/ajax/jquery.dataTables/1.9.4/jquery.dataTables.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?sensor=false"></script>
<table id="example"></table>

To use a timeout to circumvent the query limit, it looks like this:

    function getAddr(i){

      geocoder.geocode({
        "latLng": latlng
      }, function(results, status) {
        var address;
        if (status == 'OVER_QUERY_LIMIT') {
          address = 'Loading...';
          setTimeout(function(){ getAddr(i); }, 1500);
        } else if (status == 'OK') {
          address = results[0].formatted_address;
        } else {
          address = 'Error: ' + status;
        }
        p[i][3] = address;
        oTable.fnUpdate(p[i], i);
      });

    }

    getAddr(i);
Guffa
  • 687,336
  • 108
  • 737
  • 1,005
  • thanks @Guffa , Nice Solution, but when i get p data from server more then 50 records its showing some address are null. – Hydrogen Jan 10 '15 at 11:25
  • 1
    @acecloudsmaps: You should check the status of the response. It's very possible that the `geocode` can't find any address for some of the coordinates. – Guffa Jan 10 '15 at 11:30
  • thanks @Guffa : i added more data in p i.e. added 20 records,but address showing only 10 records, please once look out above updated code. – Hydrogen Jan 10 '15 at 12:23
  • 1
    @acecloudsmaps: You should check the status of the response, I added code for that above. You are not allowed to geocode that many coordinates at once. You get the status `OVER_QUERY_LIMIT` after the first five calls. – Guffa Jan 10 '15 at 12:58
  • thanks @Guffa, i tried this solution `else if (status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT) { setTimeout(function() { geocoder.geocode({"latLng": latlng}, function(results, status) { aaData[i][4] = (results[0].formatted_address); //alert(aaData[i][1]) console.log(aaData[i][4]) oTable.fnUpdate(aaData[i], i); }); }, 1500); } });` please can you share any other solutions. – Hydrogen Jan 10 '15 at 13:35
  • 2
    @acecloudsmaps: That looks like a working approach, just using the `i` variable for index instead of the hard coded values. You could turn the function expression into a named function, that way the timeout could just call that function. – Guffa Jan 10 '15 at 13:52
  • thanks @Guffa, i try to add this code but did not worked.please can you give me complete solution.`var getAddr = (function(i){etc..else if(status === google.maps.GeocoderStatus.OVER_QUERY_LIMIT){setTimeout(function(){getaddr()},200);}` its not working. – Hydrogen Jan 10 '15 at 14:25
  • 1
    @acecloudsmaps: You can use the `function getAddr(i) { ... }` syntax instead of the function expression. When you call it you should use `getAddr(i)` instead of `getaddr()`. Note the case difference also. – Guffa Jan 10 '15 at 14:34
  • thanks @Guffa, No words for your Solution.., **awesome**, now i got where did i done my mistake(done mistake as place of function calling). – Hydrogen Jan 10 '15 at 15:26
  • Hi @Guffa., i have one more small issue is when in my web browser get data more then 100 records its take(Loading addresses) more time(some time browser shows not responding. ), can you please any solutions for this fast loading address into table. – Hydrogen Jan 15 '15 at 07:13
  • @acecloudsmaps: If you have that many addresses then you should perhaps rethink the way that you make the geocode calls. The web service will only allow you to do a few calls in a specific time, so you are effectively hammering it with hundreds or thousands of calls. You shouldn't make so many calls at the same time, and stop making calls for a while as soon as one call gets rejected. – Guffa Jan 15 '15 at 09:15
  • 1
    Slightly off topic, but very basic Javascript scope - you declare "var i" twice, however scope means that it exists for the entire block even before the first declaration (and the second one is redundant) - http://stackoverflow.com/a/500459/3328079 - see point 8 specifically – Rycochet Feb 20 '15 at 09:18
  • @Guffa: Doh - yes I did, hope it'll get noted though, as your code doesn't have that mistake in it ;-) – Rycochet Feb 20 '15 at 10:42
  • thanks @Rycochet ,@Guffa : Please can you update your changed code. – Hydrogen Feb 20 '15 at 11:20
  • @Hydrogen: There is no change in the code in the answer. What Rycochet is talking about is the two `for (var i = 0; ...` in the code in the question. The variable `i` is only declared for the first one, and the scope for it is the entire code block, not just the code in the `for` block. For the second loop the `var` is ignored and the variable is just reused. This is a minor issue that doesn't cause an error, not even in strict mode. – Guffa Feb 20 '15 at 13:29
  • Exactly - it's just something that confuses people, and when they look for code and find the same coding patterns repeated they don't realise that their assumptions are wrong ;-) – Rycochet Feb 21 '15 at 12:09
0
  • Try this Code.

    oTable.fnUpdate(p[i],i);

Community
  • 1
  • 1
kks
  • 342
  • 5
  • 25
  • thanks i got all rows updated if i was not using google map address.i need google map address also. – Hydrogen Jan 10 '15 at 07:58
0

Why don't you use a reverse geocode service to curate this in your datasource server-side? You're likely to be hitting query api limits for google pretty quickly, and unless you're combining this with a maps display, I'm pretty sure it violates TOS.

There are many free and paid services available. You can also download data sets and roll your own.

Tracker1
  • 19,103
  • 12
  • 80
  • 106