Rollbase selectQuery and Google maps callstack

Posted by alexanderg@qbcon.com on 29-Jul-2014 07:04

I'm struggling with this extremely weird error. I have this piece of javascript code:

<script>
var mapOptions = {zoom : 16};
var map;
var address;
var marker;
var geocoder;

$("#map-canvas").css({
           width : String($(window).width()) + "px",
           height : String($(window).height()) + "px"
});

rbf_selectQuery("SELECT name, streetAddr1, city, country FROM flag",999, //AJAX
function(values)
{   
 geocoder = new google.maps.Geocoder();
 map = new google.maps.Map(document.getElementById("map-canvas"),mapOptions);

 for (var k = 0; k < values.length; ++k)
 {
    address = values[k][1] + " " + values[k][2];

    geocoder.geocode({'address':address},
    function(results,status)
    {
        console.log(k);
        if (status != google.maps.GeocoderStatus.OK )
        {
            console.log("Error " + status);
            return;
        }

        if(k==0)
        {
            map.setCenter(results[0].geometry.location);
            map.setZoom(16);
        }

        marker = new google.maps.Marker({
            map : map,
            position : results[0].geometry.location,
            title : values[k][0],
            visible : true
        });
    });
 }
});

</script>

What I'm trying to do is draw all markers from the addresses that I received from the query unto the map. I know that the query is returning the correct data into the 2-d array. Now the error I'm getting is this:

Uncaught TypeError: Cannot read property '0' of undefined 

Somehow (and this is when it gets weird), the statement "console.log(k)" outputs "2", now, to me this is impossible because I know for a fact that the "values.length" is 2, I have a console.log on my side that tests it and I know for a fact the length is 2. What might also be of importance is the fact that there is literally only that one line of output.

Any thoughts?

All Replies

Posted by alexanderg@qbcon.com on 29-Jul-2014 08:46

Okay well I figured out why this happens, the geocoder.geocode function is called asynchronously so the loop finishes before the method executes.

Now I might need help to think of a workaround :)

Posted by Gian Torralba on 29-Jul-2014 10:18

Hi  alexanderg,

Any particular reasons to use the client side API to query the data? If not you can create a formula field that returns the needed values so that the value is generated via server side and then you can just use the formula field token to render the values and put it in the geocode function.

Another approach that I would suggest is to use a better Google map plugin. Gmap.js is a very good Google map plugin which simplifies the code needed to generate a map.

Let me know if you have anymore questions.

Thanks,

Gian

Posted by Santosh Patel on 29-Jul-2014 10:27
Posted by pvorobie on 29-Jul-2014 10:46

Try using server-side API in EVAL[ ] block instead of client-side API. That would be much simpler - you don't need callback.

Posted by romain.pennes@foederis.fr on 29-Jul-2014 10:48

Hello,

We have done the exact same implementation in our Rollbase apps and encountered the same problems.

What we ended up doing (which is one possible solution) is we created a Rollbase "HTTP GET" trigger in our object that calls Google Maps Geocoder, retrieves the result, and saves latitude and longitude into two Rollbase Text Fields that we created. (A faster way to do this, would be to use a Object Script type of trigger and the rbv_api.sendHttpGet function)

Then in our client-side JavaScript, we use rbf_selectQuery to retrive latitudes and longitudes, instead of the adresses, and create Google Maps markers, before putting them onto the map.

Don't hesitate to contact me should you want some more info or code samples.

Cheers,

Romain.

Posted by alexanderg@qbcon.com on 30-Jul-2014 03:06

Hi guys, thanks for your help.

I'm currently creating formula fields for the latitude and longitude but I don't know where to include the google maps API in my application server side? The formula that I entered doesn't recognize the "google" keyword of course so that tells me that the API isn't included

Posted by alexanderg@qbcon.com on 30-Jul-2014 07:09

bump

Posted by alexanderg@qbcon.com on 30-Jul-2014 08:52

So I've been trying out the rbv_api.sendHttpGet method also to no avail, getting some very in-concise errors that I dont understand

Posted by Gian Torralba on 30-Jul-2014 09:58

Hi Alexander,

You can include the scripts in the formula field by creating a hosted file.  Go to Settings -> Application Settings -> Hosted Files.

After creating a hosted file, include the hosted file token in the formula field you created.

Thanks,

Gian

Posted by alexanderg@qbcon.com on 31-Jul-2014 01:09

Hi Gian, can I actually load the google maps API as a hosted file?

The error I'm getting with the "rbv_api.sendHttpGet" method is:

Error  http://maps.googleapis.com/maps/api/geocode/json?address=28+3rd+Street+Menlopark+Pretoria+ZA&key={API-KEY} (line #11) in formula:
var rbv_api = new Packages.com.rb.core.services.api.ServerSideAPI(1, 5790);

function getLat()
{
  var city = ", " + "Pretoria";
  var country = ", " + "ZA";
  var address = "28 3rd Street Menlopark" + " " + "Pretoria" + " " + "ZA";
  address = address.replace(/ /g,"+");

This is the original formula that I've entered:

function getLat()
{
  var city = ", " + "{!city#value}";
  var country = ", " + "{!country#code}";
  var address = "{!streetAddr1#value}" + " " + "{!city#value}" + " " + "{!country#code}";
  address = address.replace(/ /g,"+");
 
  var result = rbv_api.sendHttpGet("http://maps.googleapis.com/maps/api/geocode/json?address="+address+"&key=AIzaSyCQBMnqH-q8etEl3CDOQHQaosd1LSXz_GM");

  return result.results[0].geometry.location.lat;
}

getLat();

Posted by romain.pennes@foederis.fr on 31-Jul-2014 07:34

Hi,

Your request ends up calling:

maps.googleapis.com/.../json

Which doesn't work (because it requires SSL and your key seems wrong).

If you call this instead:

maps.googleapis.com/.../json

It seems to work fine.

Then, I think you also need to call the "rbv_api.stringToJson" function.

The following works:

function getLat()

{

 var result = rbv_api.stringToJson(rbv_api.sendHttpGet("maps.googleapis.com/.../json));

 return result.results[0].geometry.location.lat;

}

getLat();

Posted by alexanderg@qbcon.com on 31-Jul-2014 07:48

Hi Romain

Would you mind posting the those full URLS?

It seems the forums have shorted them somehow

Posted by alexanderg@qbcon.com on 31-Jul-2014 07:53

Romain I've run through the combinations on that url and I keep getting the same error as previous?

I copy pasted the urls you posted(at least what comes up when I click on them in my browser), I used the other method and put a "+" in between as well.

Posted by alexanderg@qbcon.com on 31-Jul-2014 07:56

Also, if it means anything, I manually removed my api key from the url I posed here but I use the correct one on my side

Posted by romain.pennes@foederis.fr on 31-Jul-2014 08:11

Hello,

This works fine in my Rollbase trigger(hopefully the adress isn't shortened):

var result = rbv_api.stringToJson(rbv_api.sendHttpGet("maps.googleapis.com/.../json));

rbv_api.println(result.results[0].geometry.location.lat);

Have you added the "rbv_api.stringToJson" call?

Cheers,

Romain.

Posted by alexanderg@qbcon.com on 01-Aug-2014 02:27

Hey guys

Thanks for all your help.

After much investigation and reacting on my own hunch I decided to test if it was our proxy server denying these requests and indeed it was.

The error in Rollbase had no indication to this and neither did the Catalina logs(at least for how far my Tomcat knowledge reaches).

I suspect it has something to do with the combination of Rollbase and Tomcat or either one alone because the geocoder requests do work through Javascript ran on the browser's side.

Again thanks for all your help

This thread is closed