I am using a gmap autocomplete and sometimes the user doesn't hit any choice in the suggestion list. For example he types "Paris" in the input field and believes the search will be performed with Paris, however has the 'place_changed' of the gmap autcomplete was never called, the search cannot be perfomed.
How can I select by default the first choice of the suggestion list when the user doesn't make any choice ? I believe I could adapt the solution provided for the "enter issue" described here (Google maps Places API V3 autocomplete - select first option on enter) with a blur event handling, however this doesn't work.
Any hint ?
I think this is kind of defeating the purpose of the auto complete.
You could just retrieve the autocomplete predictions pro grammatically like so:
function initialize()
{
var service = new google.maps.places.AutocompleteService();
service.getQueryPredictions({ input: 'some address' }, callback);
}
function callback(predictions, status)
{
if (status != google.maps.places.PlacesServiceStatus.OK)
{
alert(status);
return;
}
// Take the first result
var result = predictions[0]
// do as you wish with the result
}
Hope that helps
Related
I have a weird problem when dealing with Google Maps Autocomplete / Places API, it autocompletes the given address just fine:
Street Streetnumber, City, Country = Römerstraße 101, Reith bei Seefeld, Österreich
With the autocompleted value, I am trying to get the address_component data.
const autocomplete = new this.api.places.Autocomplete(
options.input,
{types: ['address'], sessiontoken: sessionToken}
),
inputObj = $(options.input);
inputObj.prop('placeholder', inputObj.data('geocode-autocomplete-placeholder'));
autocomplete.setFields(['address_component']);
autocomplete.addListener('place_changed', () => {
try {
callback(options, {'queryResult': {'res': [autocomplete.getPlace()]}}, this);
} catch (e) {
this.disableGeocoding();
console.log(e);
}
});
Problem is with the returned result, where "city" is missing:
I would expect every information that has been autocompleted to be in the "address_components" data.
Questions:
Why is city missing, and not found in another node, although autocompleted?
How can/should i get the city information?
According to these two links,
https://developers.google.com/maps/documentation/javascript/examples/places-autocomplete-addressform
https://developers.google.com/places/web-service/details
It says locality of response is represents the city part of the address.
So you can see locality part in the response.
Refer those links to get more information.
Is there any parameter I can add to a request such as the one in this function to display a name for an opened location, instead of showing the coordinates?
url(loc, label) {
const prefix = "https://www.google.com/maps/search/?api=1&query=";
url = prefix + `${loc.latitude},${loc.longitude}`;
return url;
}
For example this is possible in Apple Maps with the label in the function below:
url(loc, label) {
const latLng = `${loc.latitude},${loc.longitude}`;
return `maps:0,0?q=${latLng}(${label})`;
}
Maps URLs for Search only support two parameters; query and the optional query_place_id. There is no label parameter at this time. You can use query_place_id to show a textual name though, and Google specifically recommends this when querying lat/lng coordinates.
See this example: https://www.google.com/maps/search/?api=1&query=47.5951518,-122.3316393&query_place_id=ChIJKxjxuaNqkFQR3CK6O1HNNqY
Android intents do support using a label parameter.
Hope this answers your question.
I have a simple distance calculator on a page I'm making, and the distance is calculated between 2 points from an input field using data from google maps (Places Autocomplete).
I load the info from google using this:
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?sensor=false&libraries=places">
I've also tried adding the adsense and geometery libraries seperated by comma, but from the documentation it doesn't seem like I really need those for this problem. Without them the places I want to see do appear, it's just that sometimes they aren't used.
The dropdown does function and I can see the results I want to use. Most of the time it will, but for certain vague places it does not. For example, the distance from X to "Tufts University, Medford, MA, United States" (autocompleted by google) will calculate just fine. However, from X to "Foxwoods Resort Casino, Ledyard, CT, United States" (also autocompleted by google) will not. These are both large campus-style layouts, and I understand that it's not an exact address, but in most cases the broadest name for a large multi-address destination will work fine. So why not on Foxwoods, for example? It appears in the autocomplete drop down menu provided by google, so why doesn't it have some kind of address value?
The options I'm using for the map are pretty standard, I have it restricted to the US but that's about it. Except:
travelMode: google.maps.DirectionsTravelMode.DRIVING
That's how it uses the points to get the mileage, unsure if it's related but that's the only other thing I can find that might change behavior.
If there's any more info I need to provide let me know, I'm wondering how to lick this and I just can't. I'm hoping that it's possible without going into a whole geolocation thing :P
Thanks!
edit: here's the distance calculation function using the "start" and "end" autocompleted inputs:
var fromText = document.getElementById('start');
var fromAuto = new google.maps.places.Autocomplete(fromText);
var toText = document.getElementById('end');
var toAuto = new google.maps.places.Autocomplete(toText);
function calcRoute() {
var start = document.getElementById("start").value;
var end = document.getElementById("end").value;
var distanceInput = document.getElementById("distance");
var request = {
origin:start,
destination:end,
travelMode: google.maps.DirectionsTravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsDisplay.setDirections(response);
distanceinkm = response.routes[0].legs[0].distance.value / 1000;
distanceinmiles = (distanceinkm * 0.621371);
distanceinmiles = distanceinmiles.toFixed(2);
distanceInput.value = distanceinmiles;
}
});
"Foxwoods Resort Casino, Ledyard, CT, United States" is a place, it can't be found by the geocoder or the directions service. The autocomplete service returns the coordinates associated with the result. Use those to compute the route.
Example of getting coordinates from the documentation (as pointed out by Scott Selby in the comments)
I have been making a script using a fusion table's layer in google maps.
I am using geocoder and get the coordinates of a point that I need.
I put a script that changes the style of a polygon from the fusion table when you click on it, using the google.maps.event.addListener(layer, "click", function(e) {});
I would like to use the same function that I call in the case of a click on the layer, but this time with a click with the coordinates that I got.
I have tried google.maps.event.trigger(map, 'click', {latLng: new google.maps.LatLng(42.701487,26.772308)});
As well as the example here > Google Fusion Table Double Click (dblClick)
I have tried changing map with layer...
I am sorry if my question is quite stupid, but I have tried many options.
P.S. I have seen many post about getting the info from the table, but I do not need that. I want to change the style of the KML element in the selected row, so I do not see it happening by a query.
Here is the model of my script:
function initialize()
{
geocoder = new google.maps.Geocoder();
map = new google.maps.Map(document.getElementById("map_canvas"),myOptions);
layer = new google.maps.FusionTablesLayer({
suppressInfoWindows:true,
map : map,
query : {
select: 'Местоположение',
from: '12ZoroPjIfBR4J-XwM6Rex7LmfhzCDJc9_vyG5SM'
}
});
google.maps.event.addListener(layer, "click", function(e) {
SmeniStilRaionni(layer,e);
marker.setMap(null);
});
}
function SmeniStilRaionni(layer,e)
{
...
}
function showAddress(address)
{
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var point = results[0].geometry.location;
//IMITATE THE CLICK
}
});
}
In response to geocodezip
This way you hide all the other elements... I do not wish that. It is like if I want to change the border of the selected element. And I do not wish for a new layer.
In the function that I use now I push the style of the options of the layer and then set the option. I use the e from google.maps.event.addListener(layer, "click", function(e)); by inserting e.row['Name'].value inside the where rule.
I would like to ask you if there is any info on the e variable in google.maps.event.addListener(layer, "click", function(e));
I found out how to get the results I wanted:
For my query after I get the point I use this:
var queryText ="SELECT 'Районен съд','Окръжен съд','Апелативен съд','Местоположение' FROM "+FusionTableID+" WHERE ST_INTERSECTS(\'Местоположение\', CIRCLE(LATLNG(" + point.toUrlValue(6) + "),0.5));";
queryText = encodeURIComponent(queryText);
document.getElementById("vij query").innerHTML = queryText;
var query = new google.visualization.Query('http://www.google.com/fusiontables/gvizdata?tq=' + queryText);
And then I get these results:
var rsyd = response.getDataTable().getValue(0,0);
var osyd = response.getDataTable().getValue(0,1);
var apsyd = response.getDataTable().getValue(0,2);
And then, I use the following:
where: "'Районен съд' = '"+rsyd+"'",
Which is the same as:
where: "'Районен съд' = '"+e.row['Районен съд'].value+"'",
in the click function.
This is a working solution for my problem.
But still, I cannot find a way to Imitate a Mouse click.
The issue is this: the data(row) for the layers will be requested via AJAX when you click on a layer.
In theory it's possible to select a geometry(polygon) by a given LatLng, the geometry-library has a method for this: google.maps.geometry.poly.containsLocation().
Unfortunately the FusionTableAPI does not support such queries(ST_CONTAINS), you cannot select a row by supplying a LatLng and selecting the rows where the geometry contains the LatLng.
So what you can do: create a copy of the table that contains the columns needed to select a row(Община...the distinct value, and Местоположение.... the geometry). This copy may be requested via AJAX, but when the FusionTable will not be modified anymore I would suggest to use a hardcoded copy.
What to do now when you want to simulate the click:
Iterate over all rows of the copy, use the mentioned containsLocation()-method to check if the geometry(Местоположение) contains the LatLng and when it does apply the query by using the value of the distinct column Община .
Of course it would take some time to check all the geometries, but the FusionTable is not very large, it should be a possible approach in your case.
Here is a demo: http://jsfiddle.net/doktormolle/sSwj3/
The size of the stored data is approximately 500kb, you should store the data in an external script, so they may be cached.
You may notice that the highligthning of the selected layer will be much faster when triggered via the links, because there will no data be requested via AJAX. When the highlightning of the selected feature is the only thing you need you may ommit the observation of the layer-click completely and observe the map-click instead. Use the returned LatLng to retrieve the selected row from the data and set the style:
Demo: http://jsfiddle.net/doktormolle/swdX8/
I have a Knockout object mapped from a JSON object. A value of that knockout object is databound to an input element.
I have also bound a google places autocomplete to that same input element.
The value referenced by the knockout object tells me the value of what I have typed in (not selected, so it would be 'bar').
The value of the input box is the correct value (the location I have chosen, 'Barnet, United Kingdom').
Here is a JSFiddle that demonstrates the problem...
http://jsfiddle.net/twistedinferno/CPEMk/
Why do the two values differ and can I get the selected value as my bound value? (preferably without the need of another property on my KO object)
Updated JSFiddle here
This is normal behavior. Knockout registers its value bindings to events it is aware of such as afterkeypress or blur. It cannot 'detect' changes made by other frameworks such Google Places API by default. So, in order to work, you need to write some code that pushes events from the other framework to Knockout.
In this case, Google Places Autocomplete API supports a place_changed event. I've incorporated this event in my updated Fiddle to showcase a working example. See the Google documentation for more information about this event. The most important bit is:
google.maps.event.addListener(autocomplete, 'place_changed', function() {
var place = autocomplete.getPlace();
koObj.StartDescription(place.formatted_address);
koObj.Name(place.name);
koObj.Address(place.formatted_address);
});
However, if you intend to use this functionality more than once, I strongly suggest you wrap this behavior in a custom Knockout binding.
Here's an excellent article about custom Knockout bindings. If you scroll all the way down to the last chapter, you will see an example of a Knockout binding that wraps around a third party control. You will want to do the same for Google Places Autocomplete, so you can handle three aspects of working with this control:
Initializing the control (with optional config options for the widget)
Responding to updates made in the UI by setting up an event handler. This is achieved by wrapping around the place_changed event.
Responding to updates made to the view model. This might not be necessary for your scenario.
Using a custom knockout binding will look something like this:
<input id="startDescription" type="text" data-bind="googleAutoComplete: StartDescription, googleAutoCompleteOptions: { componentRestrictions: { country: 'uk' } }" />
Good luck!
Here is a bare bones custom binding that I wrote for this in case anyone is searching for this:
ko.bindingHandlers.addressAutocomplete = {
init: function (element, valueAccessor, allBindingsAccessor) {
var value = valueAccessor(), allBindings = allBindingsAccessor();
var options = { types: ['geocode'] };
ko.utils.extend(options, allBindings.autocompleteOptions)
var autocomplete = new google.maps.places.Autocomplete(element, options);
google.maps.event.addListener(autocomplete, 'place_changed', function () {
result = autocomplete.getPlace();
value(result.formatted_address);
});
},
update: function (element, valueAccessor, allBindingsAccessor) {
ko.bindingHandlers.value.update(element, valueAccessor);
}
};
You can use it like this:
<input type="text" data-bind="addressAutocomplete: Address" />
Or if you want to specify options of the google places autocomplete ( eg. Limiting your search to one country):
<input type="text" data-bind="addressAutocomplete: Address, autocompleteOptions: { componentRestrictions: { country: 'au' } }" />
Hope it helps.
(Note. I have limited my autocomplete to the geocode type by default.)
also if you want to bind to specific components of the address see this gist https://gist.github.com/chadedrupt/5974524