views:

2599

answers:

4

I'm having a dilemma with the Google Maps API - I'm using the GDirections object to get the time needed to travel between two points.

I've tested the following code in Firebug, so that the chances of the rest of my code affecting this one call is low (I can't link to the actual map; it's on a local computer).

var start = "NY, USA";
var end = "CA, USA";
var searchString = "from: " + start + " to: " + end;

C.console(searchString);

var myDir = new GDirections(); 

GEvent.addListener(myDir,"load",C.console(myDir,getDuration()));
myDir.load(searchString);

C.console is just a function I wrote to print its arguments to the Firebug debug log. When I run that code, it outputs the searchString from: NY, USA to: CA, USA and the callback function is called. However, it outputs null rather than the duration of the GDirections object.

Next, I run

C.console(myDir.getDuration())

and it ouputs

Object seconds=157994 html=1 day 20 hours

as desired. Does anyone know why it takes two calls for this to work? I think it's time dependent, because in the code if I simply call it twice it'll give me null two times in a row, which wasn't quite surprising. I already use the event listener, though, to wait for it to finish loading. I've also tried using the addoverlay event instead of the load event, but that won't work either.

Has anyone seen this before or has ideas as to how I can fix it? Any help would be greatly appreciated!

A: 

I remembered i had a similar problem but it was of a different nature, however the problem structure was the same.

I had to click it twice for it to work. I finally figured it out and here is the code, My Original Post on google API (http://groups.google.com/group/Google-AJAX-Search-API/browse_thread/thread/c6c46cc8a0435eb0/f697b028bbce18db#f697b028bbce18db)

<script type='text/javascript'>
google.load('search', '1');
google.load('maps', '2');

//Define our Globals
var map;                        //Map API
var gdir;                       //Direction API
var gFirstSearch;       //The From Local Search
var gSecondSearch;      //The To Local Search

var fromAddress;        //From Address The user inputs
var toAddress;          //To Address the user inputs

var first;                      //First Set of Results for From Search
var second;             //Second Set of Results for To Search

//On Load, Load all the Details Needed
function OnLoad(){

        //Set up the Map and the Globals
        //If the Browser Supports its
        if (GBrowserIsCompatible()) {
                map = new GMap2(document.getElementById("map"));
                map.setCenter(new GLatLng(52.037366,-0.703726), 7);
                map.removeMapType(G_HYBRID_MAP);

                var mapControl = new GMapTypeControl();
                map.addControl(mapControl);
                map.addControl(new GLargeMapControl());

                gdir = new GDirections(map);
                GEvent.addListener(gdir, "load", onGDirectionsLoad);
                GEvent.addListener(gdir, "error", handleErrors);

                gFirstSearch = new google.search.LocalSearch();
                gFirstSearch.setCenterPoint(map);
                gFirstSearch.setSearchCompleteCallback(null, FirstSearch);

                gSecondSearch = new google.search.LocalSearch();
                gSecondSearch.setCenterPoint(map);
                gSecondSearch.setSearchCompleteCallback(null, SecondSearch);
        }

}

//Run the From Search
//Runs after the gFirstSearch.execute has finished
//Reference: setSearchCompleteCallback
function FirstSearch(){

        if (!gFirstSearch.results.length){ alert("Could Not Find: " +
fromAddress + "\n Please Try Refining your 'From' Address Field");
return; }
        //Return the First Result into a Variable
        first = gFirstSearch.results[0];

        //Execute the Second
        gSecondSearch.execute(toAddress);

}

//Run the To Search
//Runs after the gSecondSearch.execute has finished
//Reference: setSearchCompleteCallback
function SecondSearch(){

        if (!gSecondSearch.results.length){ alert("Could Not Find: " +
toAddress + "\n Please Try Refining your 'To' Address Field");
return; }

        //Returns the Second results into a Variable
        second = gSecondSearch.results[0];

        //Plot our Graph
        gdir.load("from: " + (first.lat + ", " + first.lng) + " to: " +
(second.lat + ", " + second.lng));

}

//Use to Execite our Form Commands
function setDirections(ifromAddress, itoAddress) {

        //Initiate the inputs into our Global Variables
        fromAddress = ifromAddress;
        toAddress = itoAddress;

        //Execute our Search
        gFirstSearch.execute(fromAddress);

        //Return False so our broweser dosent Refresh
        return false;

}

//Set the Values in our HTML after Direction has loaded
function onGDirectionsLoad(){

        var miles = gdir.getDistance().meters * 0.000621371192; //Convert to
Miles
        document.getElementById("distance").innerHTML = "Distance: " + miles
+ " ml";

        // and yada yada yada...
}

</script>

By looking at this i remember that the first Get Direction is Run as a Thread and then the Second one is also run as a thread, So why it takes 2 clicks is because when you do the gdirection the second one is not loaded hense the value is still null. Therefore you need to some how have to make gdirection wait till the first and second has returned its value

Note: the two callBacks in the above code

gFirstSearch.setSearchCompleteCallback(null, FirstSearch);
gSecondSearch.setSearchCompleteCallback(null, SecondSearch);

Note: the function gSecondSearch.execute(toAddress) is being run inside the function firstSearch()

//Run the From Search
//Runs after the gFirstSearch.execute has finished
//Reference: setSearchCompleteCallback
function FirstSearch(){

    if (!gFirstSearch.results.length){ 
        alert("Could Not Find: " + fromAddress);
        return; 
    }

    //Return the First Result into a Variable
    first = gFirstSearch.results[0];

    //Execute the Second
    gSecondSearch.execute(toAddress);

}

The way i solved it was to put it into callback function. A callback function is called when a process is finished

So here are the steps

  1. Get the First Location (NY)
  2. After you get the First location (NY) Get the Second location(CA) by running the find function inside the callback of the first location
  3. And finaly map these 2 which you seem to do ok up there but the only difference is that you map it in the callback of the second function

If you are still lost on the concept let me know.. il edit it and split it a bit more so you can understand but it should solve your problem

Shahmir Javaid
I appreciate the response - it doesn't seem like my problem's the same though. I have only one process, getting the directions - I think the GDirections object is able to take a query like "from: NY, USA to: CA, USA" and be able to get the directions. The locations have already been found and saved from a previous function - one is user-inputted and the other is reverse-geocoded.
munchybunch
:D great you fixed it.. but i suppose just be carefull when you run two functions on this API, cause it threads all the function and its annoying when you want to do things sequentially :D
Shahmir Javaid
A: 

This has truly boggled me. I played with the code, and this works:

var start = "NY, USA";
var end = "CA, USA";
var searchString = "from: " + start + " to: " + end;

C.console(searchString);

var directions = new GDirections();
GEvent.addListener(directions,"load",function() {
    C.console(directions.getDuration());
});

directions.load(searchString);

Apart from a variable change (myDir is now directions), I used an anonymous function for the callback function. It seems it was a scope problem before, and maybe the second time through the variable had been defined and so it wasn't null anymore. Anyhow, this seems to work properly now - I hope this helps others too.

munchybunch
+2  A: 

Your problem is that this line

GEvent.addListener(myDir,"load",C.console(myDir,getDuration()));

causes C.console to be executed immediately, and whatever it returns is to be used as the callback function. That's not what you want. What you want is for C.console to be called when the callback occurs. One way to do that is

GEvent.addListener(myDir,"load",function() {
  C.console(myDir,getDuration())
});
Mike Williams
A: 

How to use GDirections ?

     var dir=new GDirections(map);
var queryString="from: "+ map.getCenter()+"to: "+marker.getLatLng();
dir.load(queryString);
alert(dir.getDistance().meters);

error:dir.getDistance() is not defined ....

jackchan