views:

116

answers:

2

I am trying to create a script that finds the closest store/location to a customer using googlemapsAPI. So I've got a json object which is a collection of store objects. Using Jquery's .each to iterate through that object, I am grabbing the driving time from the customer to each store. If it finds the directions, It copies the duration of the drive which is an object with the time in seconds and a human readable value. That appears to work, however when I try to sort through all of those store objects with the drivetime added, I cannot read the object copied from google. If I console.log the whole object, 'closest_store', It shows the values I'm looking for. When I try to read the values directly via closest_store.driveTime, Firebug is outputting undefined in the console. What am I missing here?

$.getJSON('<?php echo Url::base() ?>oldservices/get_locations', {}, function(data){
            $.each(data, function(index, value)
            {
                var end = data[index].address;

                var request = {
                    origin: start,
                    destination: end,
                    travelMode: google.maps.DirectionsTravelMode.DRIVING
                };

                directionsService.route(request, function(response, status)
                {
                    //console.log(response);
                    if (status == google.maps.DirectionsStatus.OK)
                    {
                        value.driveTime = response.trips[0].routes[0].duration.value;
                        //console.log(response.trips[0].routes[0].duration.value);
                    };
                });


            });


            var closest_store;
            $.each(data, function(index, current_store)
            {
                if (index == 0)
                {
                    closest_store = current_store;
                }
                else if (current_store.driveTime.value < closest_store.driveTime.value)
                {
                    closest_store = value
                };
                console.log(current_store.driveTime);
            }
        )



        });
A: 

Why don't you just use value.address, rather than data[index].address ?

SamB
I could, but isn't that synonymous?
Rockinelle
A: 

In your second $.each, I'm not sure what value is that the code is referencing. Try this approach instead:

Do this to set the value:

data[index].driveTime = response.trips[0].routes[0].duration.value;

Use this for your bottom loop:

var closest_store;
$.each(data, function(index, current_store) {
    if (index == 0) {
        closest_store = current_store;
    } else if (current_store.driveTime.value < closest_store.driveTime.value) {
        closest_store = current_store;
    };
    console.log(current_store.driveTime);
});

Update to fix async issue:

$.getJSON('<?php echo Url::base() ?>oldservices/get_locations', {}, function(data){
  var count = 0;
  $.each(data, function(index, value) {
    var end = data[index].address;
    var request = { 
          origin: start,
          destination: end,
          travelMode: google.maps.DirectionsTravelMode.DRIVING
        };
    count++;
    directionsService.route(request, function(response, status) {
      count--;
      if (status == google.maps.DirectionsStatus.OK)
        value.driveTime = response.trips[0].routes[0].duration.value;
      if (count == 0)
        getClosestStore(data);
    });
  });
});


function getClosestStore(data) {
  var closest_store = data[0];
  $.each(data, function(index, current_store) {
    if (current_store.driveTime.value < closest_store.driveTime.value)
      closest_store = current_store;
  });
  //do something with closest_store
}

This counts up before sending a request, and as each request comes back, counts down...when we get back to 0 (last request coming back) it then runs the function that calculates the closest store.

Nick Craver
That was a bug you found, but it never gets that far. During the first iteration where index == 0, it sets the closest_store to the current store and drops down to the console.log output where it returns undefined. The next around, it drops into the else if where it does the comparison and fails there because driveTime is undefined. Like I said, if I change the console.log to output current_store, it lists the driveTime object as one of the properties and I can see the correct values.
Rockinelle
@Rockinelle - This is after changing the assignment up top like in my answer?
Nick Craver
Nick, yes. The comparison of driveTime.values between locations causes an error, 'current_store.driveTime is undefined' as reported by firebug.
Rockinelle
@Rockinelle - It looks like `directionsService.route` an asynchronous request, when you log the response of that in the top loop, does it occur **before** the undefined in the bottom loop? If it's an ajax request, it probably isn't coming back until after the bottom loop runs.
Nick Craver
@Nick, the asynchronous nature of directionsService.route seems to be the issue. When I log value.driveTime inside the callback, it outputs them correctly as their are returned from Google. They are showing AFTER the lower loop logs undefined. So, Is there a way to force it to be synchronous or force the bottom loop to wait for the above call to complete? Otherwise, I'll have to attack this differently.
Rockinelle
@Rockinelle - I posted a solution for this using just a count...I can't test against your data, but try the updated answer and give it a shot.
Nick Craver
@Nick Fabulous, thank you!
Rockinelle