In my app I am trying to get a Region (city) to store in my Location model along with lngLat and address.
The thing is that for new locations it would be easy as when I would create I would do that. For old locations I wrote this bit of code
function geocodeLatLng(geocoder, latlngStr, callback) {
var latlng = { lat: parseFloat(latlngStr.split(',')[0]), lng: parseFloat(latlngStr.split(',')[1]) };
var city;
geocoder.geocode({ 'location': latlng }, function (results, status) {
if (status === google.maps.GeocoderStatus.OK) {
var address = results[0].address_components;
for (var p = address.length - 1; p >= 0; p--) {
if (address[p].types.indexOf("locality") != -1) {
console.log(address[p].long_name);
city = address[p].long_name;
callback(city);
}
}
}
});
}
And I am calling it like this
self.getRegion = function () {
for (var i = 0; i < self.rawLocations().length; i++) {
var location = self.rawLocations()[i];
setTimeout(
geocodeLatLng(geocoder, location.systemRepresentation(), function (res) {
}), 250);// End of setTimeOut Function - 250 being a quarter of a second.
}
}
The issue is that I get over_query_limit after 5 calls. I will store the Location it self in the database for now I would have to do this to fix the old locations.
Any headers?
Google maps javascript library has a maximum calls per second as well as an hourly rate, are you trying to geocode at a rate faster than their per second rate possibly?
5 does seem low as their own documents inform users that it is 50 per second (https://developers.google.com/maps/documentation/geocoding/usage-limits)
Also have you signed up for a key and are using it? This could make a difference (if the google account is old as signed up for maps API sometime you can use the system without a key)
Related
I'm trying to make a function that takes in a users location and then loops through a JSON file of station locations to determine which is the closest station. The issue I am having is with how to include both the location object and the JSON file as arguments in the function.
I am getting the location by using:
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(findNearestStation);
} else {
return "James Street";
}
}
I then want to use the function findNearestStation to take in a JSON as an argument and use the location passed by getLocation to find the nearest station. Something like this:
function findNearestStation(position, json) {
var UserLat = position.coords.latitude;
var UserLong = position.coords.longitude;
for (var i = 0; i < json.stations.length; i++) {
compare and find the min distance...
}
}
Any help would be hugely appreciated. Thanks.
Try an anonymous function:
function getLocation() {
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(pos) {
findNearestStation(pos, json);
});
} else {
return "James Street";
}
}
The Senario:
I have a google map and one of its functions is to show routing information from a central point to several diffrent locations on the same map.
I know that each direction object can only show one set of routes at time so I have a function that create a render object each time it is called and places the route on the map and call it for each location.
The code:
the function to calculate and display the route:
function calculateRoot (startLocation,wayPoints,endLocation) {
var selectedMode = $("#travelMode").val();
// create a new directions service object to handle directions requests
var directionsService = new google.maps.DirectionsService();
// create a directions display to display route info on the map
var directionsDisplay = new google.maps.DirectionsRenderer();
directionsDisplay.setMap(map);
// Stops the default googlemarkers from showing
directionsDisplay.suppressMarkers = true;
directionsDisplay.setPanel(document.getElementById("directions"));
// create a request object
var request = {
origin:startLocation,
waypoints: wayPoints,
destination:endLocation,
travelMode: google.maps.TravelMode[selectedMode],
optimizeWaypoints:true,
provideRouteAlternatives:true,
transitOptions: {
departureTime: new Date()
}
};
directionsService.route(request, function(result,status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(result);
return directionsDisplay;
}
else if (status == google.maps.DirectionsStatus.ZERO_RESULTS){
alert ('No routing can be found for this Journey');
return -1;
}
else {
alert ('The following error occoured while attempting to obtain directions information:'+'\n'+status + '\n' + 'For:'+ ' '+ request.destination);
return -1;
}
});
}
The all locations function:
function showAllRoutes(){
if ( ! directionsArray.length < 1) {
// if directions are already displayed clear the route info
clearRoots();
}
$('#directions').empty();
// craete an empty waypoint array just to pass to the function
var wayPoints = [];
for (var i = 0; i< markerArray.length; i++) {
var directions = calculateRoot(startLatLng,wayPoints,markerArray[i].position);
directionsArray.push(directions);
}
sizeMap();
$('#directions').show();
}
The function to clear the route(s)
function clearRoutes() {
if (directionsArray.length <1 ) {
alert ("No directions have been set to clear");
return;
}
else {
$('#directions').hide();
for (var i = 0;i< directionsArray.length; i ++) {
if (directionsArray [i] !== -1) {
directionsArray [i].setMap(null);
}
}
directionsArray.clear();
map.setZoom(5);
return;
}
}
The problem:
While generating and displaying the routes seems to work fine no matter what I do I cant clear the routes from the map unless I refresh.
Am I missing something simple or can what I need to do not be done in this way, I've been trying to get this working for more than a day now and I'm stumped.
Can anyone help?
Thanks in advance
The directions service is asynchronous, calculateRoot (or calculateRoute or whatever it is really called) can't return anything, you need to push the routes into a global array in the callback function.
This is your callback function:
function(result,status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(result);
return directionsDisplay;
}
change it to something like:
function(result,status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(result);
directionsArray.push(directionsDisplay);
}
I have an array:
var markerArray = [];//global var
var markerCnt = 0;//global var
for(var x=0;x<10;x++){
markerArray[markerCnt] = new Array(agency, address, marker, onMarkerClick);
//agency and agency = string
//marker = google maps marker
//onMarkerClick = function
markerCnt++;
}
How do I call a specified onMarkerClick function?
Would I just do:
markerArray[0][3]();
As an alternative solution, you can also do this:
var markerArray = [];
var markerCnt = 0;
for(var x=0;x<10;x++){
markerArray[markerCnt] = {
'agency' : agency,
'address' : address,
'marker' : marker,
'click' : onMarkerClick
};
markerCnt++;
}
//To call the click
markerArray[0].click();
The answer to your question is yes.
You can execute any function stored in an array, no matter how many dimensions.
// perfectly valid
markerArray[0][3]()
// as is this
someArray[0][1][7][2]()
To go a little bit beyond than just answering your question, I would suggest using an array of objects so you don't have to execute an array member. This will increase readability of your code and saves you a few hours if you look at it in 6 months trying to figure out what you did.
var markerArray = [];//global var
var markerCnt = 0;//global var
for(var x=0;x<10;x++){
markerArray[markerCnt] = {
agency: agency
address: address
marker: marker
onMarkerClick: onMarkerClick
};
//agency and agency = string
//marker = google maps marker
//onMarkerClick = function
markerCnt++;
}
// then reference your function
markerArray[0].onMarkerClick();
I am trying to extend the google maps marker example from the this website by adding the extraction of the country name.
Since google maps returns an array with details to each address, I need to iterate over the array to find the entry e.g. for "country". Since I would like to reuse the piece of code, I create a function.
But I am not sure how to call this function (here call find(components, item)) correctly.
I do not get any return from the find function. How do I call the find function correctly from within the select function?
*Could there be a different mistake why I get an empty return?*
Thank you for your thoughts and suggestions!
$(document).ready(function() {
initialize();
$(function() {
$("#address").autocomplete({
//This bit uses the geocoder to fetch address values
source: function(request, response) {
geocoder.geocode( {'address': request.term }, function(results, status) {
response($.map(results, function(item) {
return {
label: item.formatted_address,
value: item.formatted_address,
components: item.address_components,
latitude: item.geometry.location.lat(),
longitude: item.geometry.location.lng()
}
}));
})
},
// address_component selection
find: function(components, item) {
for(var j=0;j < components.length; j++){
for(var k=0; k < components[j].types.length; k++){
if(components[j].types[k] == "country"){
return components[j].long_name;
}
}
}
},
//This bit is executed upon selection of an address
select: function(event, ui) {
$("#latitude").val(ui.item.latitude);
$("#longitude").val(ui.item.longitude);
$("#country").val(this.find(ui.item.components, "country"));
var location = new google.maps.LatLng(ui.item.latitude, ui.item.longitude);
marker.setPosition(location);
map.setCenter(location);
}
});
});
The find() function is defined in the autocomplete options object.
If you want to access your find function you'll have to define it outside the autocomplete options or to get a pointer to it :
var find = $(event.target).data("autocomplete").options.find;
This is because jQuery changes the context of functions with the element that is attached to the listener.
I'm trying to sort through an array of distances generated by google maps. I need to order my list, closest to furthest. I can get all of the directions and distances displayed just fine with the directionsService api example, but I cannot figure out how to retrieve that info outside of the function so that I can sort it.
function calcDistances() {
for (var x = 0; x < wineries.length; x++) {
var winery = wineries[x];
var trdistances = [];
var request = {
origin: map.getCenter(),
destination: new google.maps.LatLng(winery[1], winery[2]),
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
var route = response.routes[0];
var summaryPanel = document.getElementById("tasting_rooms_panel");
// For each route, display summary information.
for (var i = 0; i < route.legs.length; i++) {
//this works fine and displays properly
summaryPanel.innerHTML += route.legs[i].distance.text;
//I want to store to this array so that I can sort
trdistances.push(route.legs[i].distance.text);
}
}
});
alert(trdistances[0]);//debug
}
}
As commented in the code, I can populate summaryPanel.innerHTML, but when I populate the array trdistances, the alert gives me "undefined". Is this some rookie javascript coding error? I read up on the scope of variables and this should work. Help me oh wise ones.
function calcDistances() {
for (var x = 0; x < wineries.length; x++) {
var winery = wineries[x];
var trdistances = [];
var request = {
origin: map.getCenter(),
destination: new google.maps.LatLng(winery[1], winery[2]),
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
//Using Closure to get the right X and store it in index
(function(index){
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
var route = response.routes[0];
var summaryPanel = document.getElementById("tasting_rooms_panel");
// For each route, display summary information.
for (var i = 0; i < route.legs.length; i++) {
//this works fine and displays properly
summaryPanel.innerHTML += route.legs[i].distance.text;
//I want to store to this array so that I can sort
trdistances.push(route.legs[i].distance.text);
}
if(index == wineries.length-1){ //check to see if this is the last x callback
console.log(trdistances); //this should print the result
//or in your case you can create global function that gets called here like sortMahDistance(trdistances); where the function does what you want.
printMyDistances(trdistances); //calls global function and prints out content of trdistances console.log();
}
}
});
})(x); //pass x into closure as index
}
}
//on global scope
function printMyDistances(myArray){
console.log(myArray);
}
The problem is scope to keep track of the for loop's X. Basically, you have to make sure all the callbacks are done before you can get the final result of trdistances. So, you'll have to use closure to achieve this. By storing first for loops' X into index within closure by passing X in as index, you can check to see if the callback is the last one, and if it is then your trdistances should be your final result. This mod of your code should work, but if not please leave comment.
Furthermore, I marked up my own version of google map using closure to resolve using async directionServices within for loop, and it worked. Here is my demo jsfiddle. Trace the output of console.log(); to see X vs index within the closure.