Google Maps Autocomplete and Bounds - google-maps

I want auto complete results only from Mexico, for this I am trying the code below and adding bounds to ensure put Mexico in a rectangle, however I still get resutlts from outside of the country.
How Can I fix this ?
Here is the html and the same code is below:
<!DOCTYPE html>
<html>
<head>
<title>Google Maps JavaScript API v3 Test: Places Autocomplete</title>
<script src="http://maps.googleapis.com/maps/api/js?sensor=false&libraries=places"
type="text/javascript"></script>
<style type="text/css">
body {
font-family: sans-serif;
font-size: 14px;
}
#map_canvas {
height: 1px;
width: 1px;
display:hidden;
}
#searchTextField{
width:500px;
}
</style>
<script type="text/javascript">
function initialize() {
var options = {
bounds: google.maps.LatLngBounds( google.maps.LatLng(33.1613, -118.4766), google.maps.LatLng(14.3770, -84.8145) )
};
var input = document.getElementById('searchTextField');
var autocomplete = new google.maps.places.Autocomplete(input, options);
var infowindow = new google.maps.InfoWindow();
google.maps.event.addListener(autocomplete, 'place_changed', function() {
infowindow.close();
var place = autocomplete.getPlace();
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<input id="searchTextField" type="text" size="50"> <div id="map_canvas"></div>
</body>
</html>

Now you can accomplish what you want with:
componentRestrictions: {country: 'mx'}
in your options argument to build the Autocomplete object.
This is a hard restriction, unlike bounds. It's only for countries, but that's what you want anyway.

var options = {
types: ['geocode'],
componentRestrictions: {country: "mx"}
};

Setting the bounds is not how you do location biasing. See "Location Biasing" in this documentation:
http://code.google.com/apis/maps/documentation/places/autocomplete.html#location_biasing
You may bias results to a specified circle by passing a location and a
radius parameter. Doing so instructs the Place service to prefer
showing results within that circle; results outside of the defined
area may still be displayed.
Also, take a look at this sample here:
http://gmaps-samples-v3.googlecode.com/svn/trunk/places/places-search.html
I should also, note, I don't think it's possible to just specify "Mexico only". You can do searches within a radius, but you can't specify just a country.

As the previous answer suggested and as it says in the API, you can only bias towards a set of results. I would suggest making a smaller bounds based on somewhere in the middle of Mexico or even Mexico City to make the bias stronger.

Related

Google Map layer refresh with Geojson

I am able to plot data onto google maps using geojson. I now want to refresh the markers every 10 seconds. How can I do this? In my example below the json file would refresh on my local server. How can I change the properties/ position of the same marker?
<!DOCTYPE html>
<html>
<head>
<style>
html, body, #map {
height: 100%;
margin: 0px;
padding: 0px
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<script>
var map;
var layer1;
var layer2;
function initialize() {
var mapOptions = {
zoom: 11,
center: new google.maps.LatLng(23.0171240, 72.5330533),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map"), mapOptions);
layer1 = map.data.loadGeoJson('http://localhost/envitia.its.webclient/myjson.json');
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map">
</div>
</body>
</html>
Can you just use the setInterval() function in javascript? In you initialize() function, just wrap the layer1 command in a setInterval() with a time of 10 seconds.
I had a similar question and the comment from Todd is correct. Per the Google Maps API, the GeoJSON functions just load a bunch of features in into the map. To remove them, you can either
Remove every feature and start over
Implement some logic to remove only the features that need to be removed and selectively add ones not already on the map
It varies slightly if you use the .addGeoJson() function vs .loadGeoJson(). If you use the first one, you can do something like
if (mapFeatures != null) {
for (var i = 0; i < mapFeatures.length; i++) {
map.data.remove(mapFeatures[i]);
}
}
geoJSON = jQuery.parseJSON(json.data);
mapFeatures=map.data.addGeoJson(geoJSON);
mapFeatures is an array of Data.Feature objects which are just iterated and removed. If you use the .loadGeoJson() method instead, then you can use the forEach() method to iterate though the collection in the map object.
Have a look at the API reference. There is also a contains() method if you want to implement selective feature removal
https://developers.google.com/maps/documentation/javascript/reference#Data

Styled Maps: How can I control visibility of elements for specific zoom level?

I am trying to create a styled map with map stylers in Goolge Maps API v3. Everything is working fine, except that I can't find a way to add styles for elements at a specific zoom level.
For example, I only want the road.highway displayed at a higher zoom level, otherwise the whole map is cluttered with highways. I have tried to use the weight property, but that makes the highways thinner even if on a high zoom level.
Is there a way how this can be done, if so, could you please show me how to do it?
Many thanks in advance!
It's done by creating different google.maps.StyledMapType objects with different styles, and then setting an event listener to listen to the 'zoom_changed' event of the Map object. This should give you some idea:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Custom Styled Map</title>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false"></script>
<script>
/***
SEE:
https://developers.google.com/maps/documentation/javascript/styling
ALSO, GOOGLES STYLED MAP WIZARD:
http://gmaps-samples-v3.googlecode.com/svn/trunk/styledmaps/wizard/index.html
***/
function initialize() {
var gm = google.maps,
darkStylers = [
{stylers:[{invert_lightness:true}]}
],
lightStylers = [
{stylers:[{saturation:-100}]}
],
darkStyle = new gm.StyledMapType(darkStylers, {name: 'Dark Style'}),
lightStyle = new gm.StyledMapType(lightStylers, {name: 'Light Style'}),
mapOptions = {
zoom: 7,
mapTypeControl:false,
center: new gm.LatLng(32.8297,-96.6486),
mapTypeId: gm.MapTypeId.ROADMAP
},
map = new gm.Map(document.getElementById('map_canvas'), mapOptions);
//add two new MapTypes to the maps mapTypes
map.mapTypes.set('Dark_Map', darkStyle);
map.mapTypes.set('Light_Map', lightStyle);
//set our maps initial style
map.setMapTypeId('Dark_Map');
gm.event.addListener(map, 'zoom_changed', function () {
var zoom = this.getZoom();
if (zoom < 9) {
map.setMapTypeId('Dark_Map');
} else {
map.setMapTypeId('Light_Map');
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map_canvas" style="width:780px; height:600px; margin:10px auto;"></div>
</body>
</html>

How to get the state of a marker?

I am using the the Google Maps JavaScript API v3. I have a map that has markers on each state. When I click the state marker, I need access to the state abbreviation in the callback function. Is there any way native to google maps that I can access the state of a marker?
google.maps.event.addListener(mark,'click',function(event){
// how can I access the state abbreviation (e.g. 'MO') from in here?
}
I know that I can probably accomplish this via reverse geocoding, but is there any simpler (and less error-prone) way?
If this can only be accomplished using reverse geocoding, what is the simplest code to access the state? I assume my code would look something like this:
google.maps.event.addListener(mark,'click',function(event){
geocoder.geocode({'latLng': event.latLng}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
... get state from results ...
}
}
}
What would be the simplest code to get the state from the results? Based on the documentation of the address component types, I assume I would be looking for the "short_name" of the "administrative_area_level_1". Is this correct? Is there an easier way to access it than looping over the results until I find the "administrative_area_level_1"? (I have jquery included on the page and so can code with it if it makes anything simpler)
Here's a working example:
<!DOCTYPE html>
<html>
<head>
<title>http://stackoverflow.com/questions/17144375/how-to-get-the-state-of-a-marker?noredirect=1#comment24816710_17144375</title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0; padding: 0 }
#map_canvas { height: 100%; width:100% }
</style>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var map;
var markers = [
{lat:54.60039, lng:-3.13632, state:"AA"},
{lat:54.36897, lng:-3.07561, state:"ZZ"},
];
function initialize() {
var myOptions = {
zoom: 10,
center: new google.maps.LatLng(54.42838,-2.9623),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var marker;
var infowindow = new google.maps.InfoWindow({
content: ''
});
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
for (var i = 0; i < markers.length; i++) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(markers[i].lat,markers[i].lng),
map: map,
title:"marker " + i,
state: markers[i].state // a custom property of our own
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(this.state);
infowindow.open(map, this);
});
}
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map_canvas"></div>
</body>
</html>

Google Maps API v3: Gray Box, no map

As part of a much bigger project, we're trying to get a Map on a site using Google's Map API v3. I have followed the simplest steps that Google has laid out, I've tried copying code outright from other working maps. But no matter what I do, all we get is a gray box and no map.
Using Firebug, I can see the information trying to populate the map, but it is simply not displaying. I've tried jquery, jquery libraries specifically made for google maps, nothing is working. I have been up and down the internet and all through google's api help files. Plus, the problem is not local as I've uploaded the file to multiple servers and tested it on multiple browsers and computers. Nothing is working.
At this point it's got to be something stupid that I'm overlooking. Here's my code.
<!DOCTYPE html>
<html>
<head>
<title></title>
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script type="text/javascript" src="http://maps.googleapis.com/maps/api/js?&sensor=true">
</script>
<script type="text/javascript">
function load()
{
var mapDiv = document.getElementById("map");
var latlng = new google.maps.LatLng(-34.397, 150.644);
var mapOptions =
{
//zoom: 8,
center:latlng,
//backgroundColor: '#ff0000',
mapTypeId: google.maps.MapTypeId.ROADMAP,
imageDefaultUI: true
};
var map = new google.maps.Map(mapDiv, mapOptions);
function createMarker(point, text, title)
{
var marker =
new GMarker(point,{title:title});
return marker;
}
}
</script>
</head>
<body onload="load()">
<div id="map" style="width: 800px; height: 400px;"></div>
</div>
</body>
</html>
This works for me. You simply have to set zoom parameter:
UPDATE (by #user2652379): You need to set BOTH zoom and center options. Just zoom does not work.
<!DOCTYPE html>
<html>
<head>
<title></title>
<META NAME="ROBOTS" CONTENT="NOINDEX, NOFOLLOW">
<script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>
</script>
<script type="text/javascript">
function load()
{
var mapDiv = document.getElementById("map");
var latlng = new google.maps.LatLng(-34.397, 150.644);
var mapOptions =
{
zoom: 8,
center:latlng,
//backgroundColor: '#ff0000',
mapTypeId: google.maps.MapTypeId.ROADMAP,
//imageDefaultUI: true
};
var map = new google.maps.Map(mapDiv, mapOptions);
// map.addControl(new GSmallMapControl());
// map.addControl(new GMapTypeControl());
// map.addMapType(ROADMAP);
// map.setCenter(
// new GLatLng(37.4419, -122.1419), 13);
}
</script>
</head>
<body onload="load()">
<div id="map" style="width: 800px; height: 400px;"> </div>
</body>
</html>
Another case is when map container is hidden at the moment you initialize the map. E.g. you are doing it inside bootstrap show.bs.modal event, instead of shown.bs.modal
I had the same issue and came across a lot of topics on stackoverflow but none of them had the working solution for me. I eventually found out it was caused to a line of css I had added.
All the elements in the map inherited a
overflow:hidden;
By adding the following line to my CSS it was fixed
#map * {
overflow:visible;
}
I would like to add a quick comment to this since I had the same problem with the zoom parameter set.
I found out that the problem was my theme's css. In my base theme I had the following CSS:
img, embed, object, video {
max-width: 100%;
max-height: 100%;
width: auto;
height: auto;
}
This messed up the rendering of the map and after I removed it, my map renders just fine.
Also beware of having an invalid latitude or longitude value for the map center or your markers. For example, this fiddle shows the Grey Map Of Death because the map center is at latitude 131.044 which is invalid (not from +90:-90).
function initMap() {
var uluru = {lat: 131.044, lng: -25.363};
var map = new google.maps.Map(document.getElementById('map'), {
zoom: 4,
center: uluru
});
var marker = new google.maps.Marker({
position: uluru,
map: map
});
}
In my case, I was working on a map with vue and a modal in the iview library; and during the first render it worked, but any other render displayed the grey screen of death. I fixed the issue by setting a timeout function to display the map after 50 ms to give the modal enough time to render and be visible.
//Time out is crucial for the map to load when opened with vue
setTimeout(() => {
this.showMap(id);
}, 50);
The above example was an earlier fix and a quick hack, i have realized all you need to do is wait for the next tick, on vue you can achieve this by
async mounted(){
await this.$nextTick()
this.showMap(id)
}
or if you are not comfortable with async await you can try the callback option
mounted(){
Vue.nextTick(function () {
this.showMap(id)
})
}
I had the same issue. i was using google maps in Jquery Accordion and when i expand the div the map only consisted a grayed area. I was able to solve this issue by triggering a click event on the specified accordion heading and setting the map container to visible.
Script:
<script type="text/javascript">
var map;
function initMap(lat, lng) {
var myCenter = new google.maps.LatLng(lat, lng);
var mapOptions = {
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: myCenter
};
map = new google.maps.Map(document.getElementById('map'), mapOptions);
}
function ViewMap() {
var latlng = document.getElementById('<%=txt.ClientID%>').value.split(','); // This is where my latlng are placed: 25.12312,55.3212333
$("#showmap").show();
// Sorry for mixing up Jquery and javascript.
initMap(latlng[0], latlng[1]);
}
</script>
ASPX File/Html Markup:
<h3 id="lMap" onclick="ViewMap();"><i class="fa fa-map-o" onclick="ViewMap();"></i>Location Map</h3>
<div style="height:auto" id="showmap">
<div id="map" style="width: 850px; height: 550px; overflow: visible"></div>
</div>
I realise this is an old thread, but this may help someone in the future.
Struggled with this for hours, but after discovering that the Google Map is rendered with a grey box overlay if the map is rendered while not being visible, I used a bit of jQuery to make my application only instantiate and render the map if the map is visible, like such:
if ($("#myHomeMapHolder").is(":visible")) {
if (homemap == null) {
homemap = new google.maps.Map(document.getElementById("myHomeMapHolder"), myOptions);
google.maps.event.addListener(homemap, 'click', function (event) {
placeHomeMarker(event.latLng);
});
} else {
homemap.setCenter(myLatlng);
}
if (homemarker == null) {
homemarker = new google.maps.Marker({
position: myLatlng,
map: homemap,
title: "Home"
});
} else {
homemarker.setPosition(myLatlng);
}
}
And voila, my map is only rendered if the map holder is visible, so it never renders with a grey box.
For anyone wondering, myHomeMapHolder is a div which the map sits inside.
In my case, someone had dropped this little prize in some responsive.css file:
img {
max-width: 100% !important;
}
Removed that and all is fine now.
I had this issue with a site I'm working on too. We're doing some things to all <img> tags for responsiveness. This fix is working for us for the map:
img {max-width: initial !important;}
For those who might be stuck regardless of the nice solutions provided here, try setting the height and width of your container directly in the html markup instead of a stylesheet ie.
<div id="map-container" style="width: 100%; height: 300px;"></div>
happy mapping!
This may not be the case for everyone, but maybe it can help someone.
I was creating markers in my map from data attributes placed on the map element like this: data-1-lat="2" data-1-lon="3" data-text="foo". I was putting them in an array based on the order they were placed in the data attributes.
The problem is that IE and Edge (for some mad reason) invert the order of the data attributes in the HTML tag, therefore I wasn't able to correctly extract them from the data attributes.
None of the existing answers helped me because my problem was that Apollo was adding extra properties ("__typename" fields) to my MapOptions object.
In other words, the JSON looked like this:
mapOptions {"__typename":"MapOptions","center":{"__typename":"GeoCoordinates","lat":33.953056,"lng":-83.9925},"zoom":10}
Once I realized that those extra properties were problematic, this is how I solved it (using TypeScript):
function getCleanedMapOptions(mapOptionsGql: google.maps.MapOptions): google.maps.MapOptions {
const mapOptions = { ...mapOptionsGql };
const lat: number = mapOptions.center.lat as number;
const lng: number = mapOptions.center.lng as number;
const mapOptionsCleaned = {
center: new google.maps.LatLng({ lat, lng }),
zoom: mapOptions.zoom,
};
return mapOptionsCleaned;
}
export function createMap(mapOptions: google.maps.MapOptions): google.maps.Map {
const mapOptionsCleaned = getCleanedMapOptions(mapOptions);
const map = new google.maps.Map(document.getElementById('map') as HTMLElement, mapOptionsCleaned);
return map;
}
In my case (version is 3.30 when submitting this), it was because the div id MUST be "map"
<div id="map"></div>
...
document.getElementById("map")

Is there a way to add an id to the div that is created when you add a marker to a google map?

The question is pretty self-explanatory. When a marker is added to a google map, in the DOM it looks like it is actually a div wrapped around the marker image. It would make it a lot easier for me if those div's could be uniquely identified, e.g. I could grab individual markers on the map with getElementById() or similar. I'm using google maps v3.
Thanks.
Yes there is - you can create a custom Overlay class to include custom markup. Fortunately someone already had that idea and did it. Check out RichMarker and StyledMarker in Google Map Utility Libraries (at the bottom of the page) both allow you to put custom markup/css classes in marker markup.
If you just want to attach tooltips to the marker, you could also simply attach a custom property to the marker at creation (such as tooltip text or something) and add a mouseover event handler to read that property and do something with it.
Example:
<html>
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=yes" />
<meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
<title>Google Maps Markers</title>
<script src="http://code.jquery.com/jquery-1.4.4.js"></script>
<script type="text/javascript" src="http://maps.google.com/maps/api/js?sensor=false"></script>
<script type="text/javascript">
var map;
//your tooltips
msg = ['Yeah Right', 'oompa oompa','I feel good']
var marker;
function initialize() {
var chicago = new google.maps.LatLng(41.875696,-87.624207);
var myOptions = {
zoom: 11,
center: chicago,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"),
myOptions);
marker = new google.maps.Marker({
map:map,
position: chicago,
title: "<h2>Sample Tooltip</h2>", //title can also be used for custom tooltips
myCustomIndex:2 //storing index of a tooltip
})
//if you have multiple markers pls read about event closures http://code.google.com/apis/maps/documentation/javascript/events.html#EventClosures
//attach an event to the marker
google.maps.event.addListener(marker, 'mouseover', function() {
//you could also use the title property of the marker to hold the text of the tooltop
showFakeTooltip(marker.title)
//or you could show it by accessing a custom property
showTooltip(marker.myCustomIndex);
});
}
function showFakeTooltip(title) {
$(".fakeTooltip").html(title);
}
function showTooltip(index) {
alert(msg[index])
}
</script>
</head>
<body onload="initialize()">
<div id="map_canvas" style="width: 900px;height: 600px;"></div>
<div class="fakeTooltip"></div>
</body>
</html>