how to get the city using Google Maps Geocoder - javascript

I'm developing a website using Wordpress and I'm using a theme that allows to insert custom post called "Property"; this features is handled inside a custom page template. Inside this page I can add the address of the property, which has the autocomplete geocoder suggestion. Here is the code:
this.initAutoComplete = function(){
var addressField = this.container.find('.goto-address-button').val();
if (!addressField) return null;
var that = thisMapField;
$('#' + addressField).autocomplete({
source: function(request, response) {
// TODO: add 'region' option, to help bias geocoder.
that.geocoder.geocode( {'address': request.term }, function(results, status) {
//$('#city').val(results.formatted_address);
response($.map(results, function(item) {
$('#city').val(item.formatted_address);
return {
label: item.formatted_address,
value: item.formatted_address,
latitude: item.geometry.location.lat(),
longitude: item.geometry.location.lng()
};
}));
});
},
select: function(event, ui) {
that.container.find(".map-coordinate").val(ui.item.latitude + ',' + ui.item.longitude);
var location = new window.google.maps.LatLng(ui.item.latitude, ui.item.longitude);
that.map.setCenter(location);
// Drop the Marker
setTimeout(function(){
that.marker.setValues({
position: location,
animation: window.google.maps.Animation.DROP
});
}, 1500);
}
});
}
When an address is clicked, the maps draw a maker with the coordinates received. I would like to extract the city from the address clicked and put that value on another input field. How can I do that? Thanks!

looking at documentation
you need to access address_components and look for type locality, political, so something like this:
var city = '';
item.address_components.map(function(e){
if(e.types.indexOf('locality') !== -1 &&
e.types.indexOf('political') !== -1) {
city = e.long_name;
}
});
$('#city').val(city);

Related

Suggestion box only displays , ,

I am making a mashup website that involves a map, and a search textbox in javascript. So as the title says, no matter what is inputted into the search box, only 2 commas appear in the suggestion box and when the suggestion is clicked on, it turn the map gray and unusable. Whats the problem? This is my javascript file, the function where this is located is in the configure function
// Google Map
var map;
// markers for map
var markers = [];
// info window
var info = new google.maps.InfoWindow();
// execute when the DOM is fully loaded
$(function() {
// styles for map
// https://developers.google.com/maps/documentation/javascript/styling
var styles = [
// hide Google's labels
{
featureType: "all",
elementType: "labels",
stylers: [
{visibility: "off"}
]
},
// hide roads
{
featureType: "road",
elementType: "geometry",
stylers: [
{visibility: "off"}
]
}
];
// options for map
// https://developers.google.com/maps/documentation/javascript/reference#MapOptions
var options = {
center: {lat: 35.7640, lng: -78.7786}, // Cary, North Carolina
disableDefaultUI: true,
mapTypeId: google.maps.MapTypeId.ROADMAP,
maxZoom: 14,
panControl: true,
styles: styles,
zoom: 13,
zoomControl: true
};
// get DOM node in which map will be instantiated
var canvas = $("#map-canvas").get(0);
// instantiate map
map = new google.maps.Map(canvas, options);
// configure UI once Google Map is idle (i.e., loaded)
google.maps.event.addListenerOnce(map, "idle", configure);
});
/**
* Adds marker for place to map.
*/
function addMarker(place)
{
var url = "/search?q=" + place;
$.getJSON(url, function(data){
var location = data.latitude + data.longitude;
mark = new google.maps.marker(location, map);
markers[0] = mark;
});
}
/**
* Configures application.
*/
function configure()
{
// update UI after map has been dragged
google.maps.event.addListener(map, "dragend", function() {
// if info window isn't open
// http://stackoverflow.com/a/12410385
if (!info.getMap || !info.getMap())
{
update();
}
});
// update UI after zoom level changes
google.maps.event.addListener(map, "zoom_changed", function() {
update();
});
// configure typeahead
$("#q").typeahead({
highlight: false,
minLength: 1
},
{
display: function(suggestion) { return null; },
limit: 10,
source: search,
templates: {
suggestion: Handlebars.compile(
"<div>" +
"<p>{{ place_name }}, {{ admin_name1 }}, {{ postal_code }}</p>" +
"</div>"
)
}
});
// re-center map after place is selected from drop-down
$("#q").on("typeahead:selected", function(eventObject, suggestion, name) {
// set map's center
map.setCenter({lat: parseFloat(suggestion.latitude), lng: parseFloat(suggestion.longitude)});
// update UI
update();
});
// hide info window when text box has focus
$("#q").focus(function(eventData) {
info.close();
});
// re-enable ctrl- and right-clicking (and thus Inspect Element) on Google Map
// https://chrome.google.com/webstore/detail/allow-right-click/hompjdfbfmmmgflfjdlnkohcplmboaeo?hl=en
document.addEventListener("contextmenu", function(event) {
event.returnValue = true;
event.stopPropagation && event.stopPropagation();
event.cancelBubble && event.cancelBubble();
}, true);
// update UI
update();
// give focus to text box
$("#q").focus();
}
/**
* Removes markers from map.
*/
function removeMarkers()
{
// TODO
}
/**
* Searches database for typeahead's suggestions.
*/
function search(query, syncResults, asyncResults)
{
// get places matching query (asynchronously)
var parameters = {
q: query
};
$.getJSON(Flask.url_for("search"), parameters)
.done(function(data, textStatus, jqXHR) {
// call typeahead's callback with search results (i.e., places)
asyncResults(data);
})
.fail(function(jqXHR, textStatus, errorThrown) {
// log error to browser's console
console.log(errorThrown.toString());
// call typeahead's callback with no results
asyncResults([]);
});
}
/**
* Shows info window at marker with content.
*/
function showInfo(marker, content)
{
// start div
var div = "<div id='info'>";
if (typeof(content) == "undefined")
{
// http://www.ajaxload.info/
div += "<img alt='loading' src='/static/ajax-loader.gif'/>";
}
else
{
div += content;
}
// end div
div += "</div>";
// set info window's content
info.setContent(div);
// open info window (if not already open)
info.open(map, marker);
}
/**
* Updates UI's markers.
*/
function update()
{
// get map's bounds
var bounds = map.getBounds();
var ne = bounds.getNorthEast();
var sw = bounds.getSouthWest();
// get places within bounds (asynchronously)
var parameters = {
ne: ne.lat() + "," + ne.lng(),
q: $("#q").val(),
sw: sw.lat() + "," + sw.lng()
};
$.getJSON(Flask.url_for("update"), parameters)
.done(function(data, textStatus, jqXHR) {
// remove old markers from map
removeMarkers();
// add new markers to map
for (var i = 0; i < data.length; i++)
{
addMarker(data[i]);
}
})
.fail(function(jqXHR, textStatus, errorThrown) {
// log error to browser's console
console.log(errorThrown.toString());
});
};
Nvm, figured out that in my application.py, I should have put jsonify(value) instead of jsonify([value]).

Automatically fill up the Google Map search bar (Address Picker)

I want to present my users with a text box wherein they can type in their address. As they type their address, there's a new window will open (Google map) and automatically fill up the search box in Google map. I want to provide the users with suggestions/predictions of what address they are trying to type. I'm also concerned about the relevance of this address (e.g. that the address is not an address halfway across the world).
How to automatically fill the search box in Google map from the inputted address text box from another website?
E.g In my website, there's a text box and I input an address in that text box and when I click enter in that text box there's a new window appear and display the Google Map with search bar (in that search bar, the address is already there)
Is this possible in javascript and jquery? Please help me. I'm newbie in those PL. Thank you
Here's the code:
(function($, window, document, undefined){
var defaults = {
bounds: true,
country: null,
map: false,
details: false,
detailsAttribute: "name",
autoselect: true,
location: false,
mapOptions: {
zoom: 14,
scrollwheel: false,
mapTypeId: "roadmap"
},
markerOptions: {
draggable: false
},
maxZoom: 16,
types: ['geocode'],
blur: false
};
var componentTypes = ("street_address route intersection political " +
"country administrative_area_level_1 administrative_area_level_2 " +
"administrative_area_level_3 colloquial_area locality sublocality " +
"neighborhood premise subpremise postal_code natural_feature airport " +
"park point_of_interest post_box street_number floor room " +
"lat lng viewport location " +
"formatted_address location_type bounds").split(" ");
var placesDetails = ("id url website vicinity reference name rating " +
"international_phone_number icon formatted_phone_number").split(" ");
// The actual plugin constructor.
function GeoComplete(input, options) {
this.options = $.extend(true, {}, defaults, options);
this.input = input;
this.$input = $(input);
this._defaults = defaults;
this._name = 'geocomplete';
this.init();
}
// Initialize all parts of the plugin.
$.extend(GeoComplete.prototype, {
init: function(){
this.initMap();
this.initMarker();
this.initGeocoder();
this.initDetails();
this.initLocation();
},
// Initialize the map but only if the option `map` was set.
// This will create a `map` within the given container
// using the provided `mapOptions` or link to the existing map instance.
initMap: function(){
if (!this.options.map){ return; }
if (typeof this.options.map.setCenter == "function"){
this.map = this.options.map;
return;
}
this.map = new google.maps.Map(
$(this.options.map)[0],
this.options.mapOptions
);
// add click event listener on the map
google.maps.event.addListener(
this.map,
'click',
$.proxy(this.mapClicked, this)
);
google.maps.event.addListener(
this.map,
'zoom_changed',
$.proxy(this.mapZoomed, this)
);
},
// Add a marker with the provided `markerOptions` but only
// if the option was set. Additionally it listens for the `dragend` event
// to notify the plugin about changes.
initMarker: function(){
if (!this.map){ return; }
var options = $.extend(this.options.markerOptions, { map: this.map });
if (options.disabled){ return; }
this.marker = new google.maps.Marker(options);
google.maps.event.addListener(
this.marker,
'dragend',
$.proxy(this.markerDragged, this)
);
},
// Associate the input with the autocompleter and create a geocoder
// to fall back when the autocompleter does not return a value.
initGeocoder: function(){
var options = {
types: this.options.types,
bounds: this.options.bounds === true ? null : this.options.bounds,
componentRestrictions: this.options.componentRestrictions
};
if (this.options.country){
options.componentRestrictions = {country: this.options.country};
}
this.autocomplete = new google.maps.places.Autocomplete(
this.input, options
);
this.geocoder = new google.maps.Geocoder();
// Bind autocomplete to map bounds but only if there is a map
// and `options.bindToMap` is set to true.
if (this.map && this.options.bounds === true){
this.autocomplete.bindTo('bounds', this.map);
}
// Watch `place_changed` events on the autocomplete input field.
google.maps.event.addListener(
this.autocomplete,
'place_changed',
$.proxy(this.placeChanged, this)
);
// Prevent parent form from being submitted if user hit enter.
this.$input.keypress(function(event){
if (event.keyCode === 13){ return false; }
});
// Listen for "geocode" events and trigger find action.
this.$input.bind("geocode", $.proxy(function(){
this.find();
}, this));
// Trigger find action when input element is blured out.
// (Usefull for typing partial location and tabing to the next field
// or clicking somewhere else.)
if (this.options.blur === true){
this.$input.blur($.proxy(function(){
this.find();
}, this));
}
},
// Prepare a given DOM structure to be populated when we got some data.
// This will cycle through the list of component types and map the
// corresponding elements.
initDetails: function(){
if (!this.options.details){ return; }
var $details = $(this.options.details),
attribute = this.options.detailsAttribute,
details = {};
function setDetail(value){
details[value] = $details.find("[" + attribute + "=" + value + "]");
}
$.each(componentTypes, function(index, key){
setDetail(key);
setDetail(key + "_short");
});
$.each(placesDetails, function(index, key){
setDetail(key);
});
this.$details = $details;
this.details = details;
},
// Set the initial location of the plugin if the `location` options was set.
// This method will care about converting the value into the right format.
initLocation: function() {
var location = this.options.location, latLng;
if (!location) { return; }
if (typeof location == 'string') {
this.find(location);
return;
}
if (location instanceof Array) {
latLng = new google.maps.LatLng(location[0], location[1]);
}
if (location instanceof google.maps.LatLng){
latLng = location;
}
if (latLng){
if (this.map){ this.map.setCenter(latLng); }
if (this.marker){ this.marker.setPosition(latLng); }
}
},
// Look up a given address. If no `address` was specified it uses
// the current value of the input.
find: function(address){
this.geocode({
address: address || this.$input.val()
});
},
// Requests details about a given location.
// Additionally it will bias the requests to the provided bounds.
geocode: function(request){
if (this.options.bounds && !request.bounds){
if (this.options.bounds === true){
request.bounds = this.map && this.map.getBounds();
} else {
request.bounds = this.options.bounds;
}
}
if (this.options.country){
request.region = this.options.country;
}
this.geocoder.geocode(request, $.proxy(this.handleGeocode, this));
},
// Get the selected result. If no result is selected on the list, then get
// the first result from the list.
selectFirstResult: function() {
//$(".pac-container").hide();
var selected = '';
// Check if any result is selected.
if ($(".pac-item-selected")['0']) {
selected = '-selected';
}
// Get the first suggestion's text.
var $span1 = $(".pac-container .pac-item" + selected + ":first span:nth-child(2)").text();
var $span2 = $(".pac-container .pac-item" + selected + ":first span:nth-child(3)").text();
// Get the inputted address from LAP
var
// Adds the additional information, if available.
var firstResult = $span1;
if ($span2) {
firstResult += " - " + $span2;
}
this.$input.val(firstResult);
return firstResult;
},
// Handles the geocode response. If more than one results was found
// it triggers the "geocode:multiple" events. If there was an error
// the "geocode:error" event is fired.
handleGeocode: function(results, status){
if (status === google.maps.GeocoderStatus.OK) {
var result = results[0];
this.$input.val(result.formatted_address);
this.update(result);
if (results.length > 1){
this.trigger("geocode:multiple", results);
}
} else {
this.trigger("geocode:error", status);
}
},
// Triggers a given `event` with optional `arguments` on the input.
trigger: function(event, argument){
this.$input.trigger(event, [argument]);
},
// Set the map to a new center by passing a `geometry`.
// If the geometry has a viewport, the map zooms out to fit the bounds.
// Additionally it updates the marker position.
center: function(geometry){
if (geometry.viewport){
this.map.fitBounds(geometry.viewport);
if (this.map.getZoom() > this.options.maxZoom){
this.map.setZoom(this.options.maxZoom);
}
} else {
this.map.setZoom(this.options.maxZoom);
this.map.setCenter(geometry.location);
}
if (this.marker){
this.marker.setPosition(geometry.location);
this.marker.setAnimation(this.options.markerOptions.animation);
}
},
// Update the elements based on a single places or geoocoding response
// and trigger the "geocode:result" event on the input.
update: function(result){
if (this.map){
this.center(result.geometry);
}
if (this.$details){
this.fillDetails(result);
}
this.trigger("geocode:result", result);
},
// Populate the provided elements with new `result` data.
// This will lookup all elements that has an attribute with the given
// component type.
fillDetails: function(result){
var data = {},
geometry = result.geometry,
viewport = geometry.viewport,
bounds = geometry.bounds;
// Create a simplified version of the address components.
$.each(result.address_components, function(index, object){
var name = object.types[0];
data[name] = object.long_name;
data[name + "_short"] = object.short_name;
});
// Add properties of the places details.
$.each(placesDetails, function(index, key){
data[key] = result[key];
});
// Add infos about the address and geometry.
$.extend(data, {
formatted_address: result.formatted_address,
location_type: geometry.location_type || "PLACES",
viewport: viewport,
bounds: bounds,
location: geometry.location,
lat: geometry.location.lat(),
lng: geometry.location.lng()
});
// Set the values for all details.
$.each(this.details, $.proxy(function(key, $detail){
var value = data[key];
this.setDetail($detail, value);
}, this));
this.data = data;
},
// Assign a given `value` to a single `$element`.
// If the element is an input, the value is set, otherwise it updates
// the text content.
setDetail: function($element, value){
if (value === undefined){
value = "";
} else if (typeof value.toUrlValue == "function"){
value = value.toUrlValue();
}
if ($element.is(":input")){
$element.val(value);
} else {
$element.text(value);
}
},
// Fire the "geocode:dragged" event and pass the new position.
markerDragged: function(event){
this.trigger("geocode:dragged", event.latLng);
},
mapClicked: function(event) {
this.trigger("geocode:click", event.latLng);
},
mapZoomed: function(event) {
this.trigger("geocode:zoom", this.map.getZoom());
},
// Restore the old position of the marker to the last now location.
resetMarker: function(){
this.marker.setPosition(this.data.location);
this.setDetail(this.details.lat, this.data.location.lat());
this.setDetail(this.details.lng, this.data.location.lng());
},
// Update the plugin after the user has selected an autocomplete entry.
// If the place has no geometry it passes it to the geocoder.
placeChanged: function(){
var place = this.autocomplete.getPlace();
if (!place || !place.geometry){
if (this.options.autoselect) {
// Automatically selects the highlighted item or the first item from the
// suggestions list.
var autoSelection = this.selectFirstResult();
this.find(autoSelection);
}
} else {
// Use the input text if it already gives geometry.
this.update(place);
}
}
});
// A plugin wrapper around the constructor.
// Pass `options` with all settings that are different from the default.
// The attribute is used to prevent multiple instantiations of the plugin.
$.fn.geocomplete = function(options) {
var attribute = 'plugin_geocomplete';
// If you call `.geocomplete()` with a string as the first parameter
// it returns the corresponding property or calls the method with the
// following arguments.
if (typeof options == "string"){
var instance = $(this).data(attribute) || $(this).geocomplete().data(attribute),
prop = instance[options];
if (typeof prop == "function"){
prop.apply(instance, Array.prototype.slice.call(arguments, 1));
return $(this);
} else {
if (arguments.length == 2){
prop = arguments[1];
}
return prop;
}
} else {
return this.each(function() {
// Prevent against multiple instantiations.
var instance = $.data(this, attribute);
if (!instance) {
instance = new GeoComplete( this, options );
$.data(this, attribute, instance);
}
});
}
};
})( jQuery, window, document );
AFIK, the search bar which is used in Google maps search api is a simple textbox (input type="text") and its id is pac-input
$('#pac-input').val($('your address element').val()); //copy the value
$('#pac-input').focus(); //focus might trigger automatically
JSfiddle
Read document for geocoder = new google.maps.Geocoder();
and try this:
var input_address = $('your address element').val();
geocoder.geocode({address: input_address}, reverseGeocodeResult);
function reverseGeocodeResult(results, status) {
currentReverseGeocodeResponse = results;
if (status == 'OK') {
if (results.length == 0) {
document.getElementById('cong_viec_dia_chi').innerHTML = 'None';
} else {
document.getElementById('cong_viec_dia_chi').innerHTML = results[0].formatted_address;
}
} else {
document.getElementById('cong_viec_dia_chi').innerHTML = 'can't get address';
}
}
Update: demo here
http://jsfiddle.net/HoangHieu/x8dSP/3626/
http://jsfiddle.net/HoangHieu/x8dSP/3631/

angular too much recursion error in firefox

I am working on an application and need to convert an address supplied by user to lat lng and update a google map. I am using angular js version 1.0.0 Problem is in firefox i keep getting a too much recursion error.
app.controller("BasicMapController", function($scope, $timeout){
.......
angular.extend($scope, {
.......
checking_address: false// curently trying to get lat long from address
});
......
I had to create an ngBlur directive since 1.0.0 didn't have it and upgrading is not an option since too much other code breaks.
app.directive('ngBlur', function() {
return function( scope, elem, attrs ) {
elem.bind('blur', function() {
scope.$apply(attrs.ngBlur);
});
};
});
On my page i add ng-blur="onblur_()" to the relevant text area and then in my controller i define the relevant function:
$scope.onblur_ = function ($event) {
if ($scope.checking_address)
return;
var map_scope = angular.element($('.google-map')).scope();
var address = document.getElementById("id_address").value;
if ( !! !address)
return;
$scope.checking_address = true;
var geocoder = new google.maps.Geocoder();
geocoder.geocode({
'address': address
}, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map_scope.map._instance.panTo(results[0].geometry.location);
if ($scope.markers[0] == undefined) {
$scope.markers[0] = new google.maps.Marker({
map: map_scope.map._instance,
position: results[0].geometry.location
});
} else
$scope.markers[0].setPosition(results[0].geometry.location);
}
$scope.checking_address = false;
});
}
The code works fine in Opera and Chromium. Any ideas on what could be wrong or how i could get around the problem?

Geocoder not returning results

This is my first JavaScript I have tried to put together but I am not having a lot of luck.
This is what the script should do: Geocode an address either by clicking on an autosuggested location or by clicking search button if we do not have the result already from clicking autosuggestion. Then submit the form.
I am not having much luck, it seems I have mucked up my bracketing on the script because no matter what I do it complains about exceptions.
This is my code:
geocode();
// SET COOKIE FOR TESTING PURPOSES
$.cookie("country", "US");
// GEOCODE FUNCTION
function geocode() {
var coded = false;
var input = document.getElementById('loc');
var options = {
types: ['geocode']
};
var country_code = $.cookie('country');
if (country_code) {
options.componentRestrictions = {
'country': country_code
};
}
var autocomplete = new google.maps.places.Autocomplete(input, options);
google.maps.event.addListener(autocomplete, 'place_changed', function() {
processLocation();
});
// ON SUBMIT - WORK OUT IF WE ALREADY HAVE THE RESULTS FROM AUTOCOMPLETE FUNCTION
$('#searchform').on('submit', function(e) {
e.preventDefault();
if(coded = false;) {
processLocation();
}
else {
$('#searchform').submit();
}
});
// CHECK TO SEE IF INPUT HAS CHANGED SINCE BEING GEOCODED
// IF "CODED" VAR IS FALSE THEN WE WILL GEOCODE WHEN SEARCH BUTTON HIT
$("#loc").bind("change paste keyup", function() {
var coded = false;
});
};
// GEOCODE THE LOCATION
function processLocation(){
var geocoder = new google.maps.Geocoder();
var address = document.getElementById('loc').value;
$('#searchform input[type="submit"]').attr('disabled', true);
geocoder.geocode({
'address': address
},
// RESULTS - STORE COORDINATES IN FIELDS OR ERROR IF NOT SUCCESSFUL
function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var coded = true;
$('#lat').val(results[0].geometry.location.lat());
$('#lng').val(results[0].geometry.location.lng());
} else {
var coded = false;
$('#searchform input[type="submit"]').attr('disabled', false);
alert("We couldn't find this location")
}
});
}
Where have I gone wrong?
PS: Because this is my first script, I am happy to receive feedback if I have made any poor choices in the design of it. I really want to make my first script as cleanly coded as possible.
There is an syntax error
if(coded = false;) {
should be
if(coded == false) {
Checking the console would have told you such a thing and also the place WHERE the error occured.... Here's your fixed fiddle

Google Map Autosuggest - Trigger Geocode on click of autosuggest

Currently when you click on the autosuggest suggestion in the location field it just loads it into the input box. I want to make an adjustment to it, so when you click on the result in the autosuggest box, not only does it load its value into the input box but it also triggers the geocode. I cant get my head around how I would do this though, so I would appreciate some help.
This is the code: http://jsfiddle.net/njDvn/130/
<!-- Geocode -->
$(document).ready(function () {
var GeoCoded = { done: false };
autosuggest();
$('#myform').on('submit', function (e) {
if (GeoCoded.done) return true;
e.preventDefault();
var geocoder = new google.maps.Geocoder();
var address = document.getElementById('location').value;
$('#myform input[type="submit"]').attr('disabled', true);
geocoder.geocode({
'address': address
},
function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var latLng = results[0].geometry.location;
$('#lat').val(results[0].geometry.location.lat());
$('#lng').val(results[0].geometry.location.lng());
GeoCoded.done = true;
$('#myform').submit();
} else {
console.log("Geocode failed: " + status);
//enable the submit button
$('#myform input[type="submit"]').attr('disabled', false);
}
});
});
});
And the autosuggest:
<!-- AutoSuggest -->
function autosuggest() {
var input = document.getElementById('location');
var options = {
types: [],
};
var autocomplete = new google.maps.places.Autocomplete(input, options);
}
What you could do instead is use only Places API library and simply listen for place_changed event like in this sample here:
https://developers.google.com/maps/documentation/javascript/places#getting_place_information
You can get the Geocode using: place.geometry.location

Categories