Google maps with multiple markers from a php array - google-maps-api-3

Hi have an array of cities and want to create a google map using the javascript api v3 .
When the page loads the map keeps jumping to each marker. Also the the map becomes very small even though i have set a height and width to it .Here is my code for generating the map
<script>
var geocoder;
var map;
var timeout = 600;
var address_position = 0;
var address = [
<?php
foreach($cities_in_country as $item)
{
echo '"'.$item['name'].'",';
}
?>
];
function addMarker(position)
{
geocoder.geocode({'address': address[position]}, function(results, status)
{
address_position++;
if (address_position < address.length)
{
setTimeout(function() { addMarker(address_position); }, (timeout));
}
if (status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT)
{
setTimeout(function() { addMarker(position); }, (timeout * 3));
}
else if (status == google.maps.GeocoderStatus.OK)
{ map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
position: results[0].geometry.location,
map: map,
icon:"<?=base_url()?>assets/goo/images/icons/marker.png",
});
}
});
}
function codeaddress() {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(-34.397, 150.644);
var myOptions = {
zoom: 6,
center: latlng,
navigationControlOptions: {style: google.maps.NavigationControlStyle.SMALL},
mapTypeId: google.maps.MapTypeId.ROADMAP,
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
addMarker(address_position);
}
$(document).ready(function() {
codeaddress();
});
</script>
and
<div id="map_canvas" style="width: 640px; height: 420px;"></div>

"the map keeps jumping to each marker." - that's because you call map.setCenter(results[0].geometry.location); within the addMarker function you're looping over. Remove that line and it'll stop recentering the map.
Also, you should change this; there's a danger that if you go over the query limit then you'll keep calling addMarker just with a longer timeout.
if (address_position < address.length)
{
setTimeout(function() { addMarker(address_position); }, (timeout));
}
if (status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT)
{
setTimeout(function() { addMarker(position); }, (timeout * 3));
}
should maybe be
if (address_position < address.length)
{
if (status == google.maps.GeocoderStatus.OVER_QUERY_LIMIT)
{
setTimeout(function() { addMarker(position); }, (timeout * 3));
} else {
setTimeout(function() { addMarker(address_position); }, (timeout));
}
}

Related

Implementing google place autocomplete

This is my code for places autocomplete and search.
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=places">
</script>
<script>
var geocoder;
var map;
function initialize() {
var input = document.getElementById('address');
var options = {
componentRestrictions: {country: "in"}
};
var autocomplete = new google.maps.places.Autocomplete(input,options);
geocoder = new google.maps.Geocoder();
//var latlng = new google.maps.LatLng(18.52043030000, 73.85674369999);
var mapOptions = {
zoom: 15,
//center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
}
map = new google.maps.Map(document.getElementById('googleMap'), mapOptions);
}
function codeAddress() {
var address = document.getElementById('address').value;
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
This is my html code.
<input id="address" type="textbox" size="30">
<input type="button" value="Search" onclick="codeAddress()">
It is working fine but I dont want to user to click the button. When suggestions appeared, and when user select any of suggestion options, map will have to navigate to that place. How do I do this???
When User select any option from dropdown, map should navigate to that place.
Take a look at this example and the implementation of the place_changed event.
var place = autocomplete.getPlace();
// If the place has a geometry, then present it on a map.
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
}
This way you can pan the map to the location of the autocomplete result.
This is my working code..
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=places">
</script>
<script>
var geocoder;
var map;
function initialize() {
var input = document.getElementById('address');
var options = {
componentRestrictions: {country: "in"}
};
var autocomplete = new google.maps.places.Autocomplete(input,options);
geocoder = new google.maps.Geocoder();
//var latlng = new google.maps.LatLng(18.52043030000, 73.85674369999);
var mapOptions = {
zoom: 15,
//center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP,
}
map = new google.maps.Map(document.getElementById('googleMap'), mapOptions);
var infowindow = new google.maps.InfoWindow();
var marker = new google.maps.Marker({
map: map,
anchorPoint: new google.maps.Point(0, -29)
});
google.maps.event.addListener(autocomplete, 'place_changed', function() {
infowindow.close();
marker.setVisible(false);
var place = autocomplete.getPlace();
if (!place.geometry) {
return;
}
if (place.geometry.viewport) {
map.fitBounds(place.geometry.viewport);
} else {
map.setCenter(place.geometry.location);
map.setZoom(17); // Why 17? Because it looks good.
}
marker.setIcon(/** #type {google.maps.Icon} */({
url: place.icon,
size: new google.maps.Size(71, 71),
origin: new google.maps.Point(0, 0),
anchor: new google.maps.Point(17, 34),
scaledSize: new google.maps.Size(35, 35)
}));
marker.setPosition(place.geometry.location);
marker.setVisible(true);
var address = '';
if (place.address_components) {
address = [
(place.address_components[0] && place.address_components[0].short_name || ''),
(place.address_components[1] && place.address_components[1].short_name || ''),
(place.address_components[2] && place.address_components[2].short_name || '')
].join(' ');
}
infowindow.setContent('<div><strong>' + place.name + '</strong><br>' + address);
infowindow.open(map, marker);
});
}
function codeAddress() {
var address = document.getElementById('address').value;
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location
});
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
Now user can select option from dropdown and map will navigate to that place. And also on search button click.
Hope this might help you
function initialize(){
var mapOptions = {//Map Properties
zoom:12,
center: Bangalore
};
googleMap = new google.maps.Map(document.getElementById('map-holder'),mapOptions);//map-holder is a div which holds map in my html
var defaultBounds = new google.maps.LatLngBounds(//bounds for Bengaluru
new google.maps.LatLng(12.7342888,77.3791981),
new google.maps.LatLng(13.173706,77.8826809)
);
googleMap.fitBounds(defaultBounds);
var input = (document.getElementById('searchInput'));//search input element
googleMap.controls[google.maps.ControlPosition.TOP_LEFT].push(input);//binding it to map
var searchBox = new google.maps.places.SearchBox((input));
google.maps.event.addListener(searchBox, 'places_changed', function() {//triggers when search is performed
var places = searchBox.getPlaces();
if (places.length == 0) {
return;
}
var bounds = new google.maps.LatLngBounds();
for (var i = 0, place; place = places[i]; i++) {
bounds.extend(place.geometry.location);
//googleMap.fitBounds(place.geometry.viewport);
}
googleMap.fitBounds(bounds);
});
google.maps.event.addListener(googleMap, 'bounds_changed', function() {
var bounds = googleMap.getBounds();
searchBox.setBounds(bounds);
})
}

Can I modify this code to detect whether a street view image is available in Google Maps API?

I have to admit, I wing it a bit with Google Maps API. A lot of copy and pasting and basic edits. This code works really well unless a street view image is not available. What is the easiest way to detect no image and hid the pano div? Or the other way round, display it if there is an image:
function googleMap() {
var geocoder = new google.maps.Geocoder();
if (geocoder) {
alert('<?php echo $phoneDirectory->Address; ?>');
geocoder.geocode({ 'address': '<?php echo $phoneDirectory->Address; ?>' }, function (results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var googleLat = results[0].geometry.location.lat();
var googleLong = results[0].geometry.location.lng();
//alert(googleLat + ", " + googleLong);
var fenway = new google.maps.LatLng(googleLat,googleLong);
var mapOptions = {
center: fenway,
zoom: 14,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(
document.getElementById('map_canvas'), mapOptions);
var panoramaOptions = {
position: fenway,
pov: {
heading: 0,
pitch: 0
}
};
var panorama = new google.maps.StreetViewPanorama(document.getElementById('pano'),panoramaOptions);
map.setStreetView(panorama);
// **** ADDED TO GET WORKING!!! *****
var client = new google.maps.StreetViewService();
client.getPanoramaByLocation(fenway, 50, function(result, status) {
if (status == "ZERO_RESULTS") {
// Hide street view div
$('#pano').css("display", "none");
}
});
googleMapLoaded = true;
}
else {
alert('No results found: ' + status);
}
});
}
}
Check this
If there are no nearby panoramas the result is ZERO_RESULTS

Google maps v3 geocode multiple custom markers by address or latlng

I need to plot multiple custom map markers using MapsV3 api either by an address or lat/lon. I put together the following code which works ok for lon/lat, but if the data contains an address the geocoder returns nothing. Any ideas on how to fix this.
$(document).ready(function () { initialize(); });
function initialize() {
var centerMap = new google.maps.LatLng(-27.0,133.0);
var options = {
panControl: false,
zoomControl: true,
scaleControl: false,
mapTypeControl: false,
streetViewControl: false,
zoom: 3,
center: centerMap,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
var map = new google.maps.Map(document.getElementById("map"), options);
var data = [
{
'title':'F C Building Construction ...',
'address':'',
'zindex':20,
'lat':'-33.797847',
'lon':'151.259928',
'marker_number':1,
'marker_html':' html content...',
'image': {
url:'//localhost/assets/images/markers/marker_1.png',
size: new google.maps.Size(24, 29),
origin: new google.maps.Point(0,0),
anchor: new google.maps.Point(10, 29)
}
}];
setMarkers(map, data);
var infowindow = new google.maps.InfoWindow();
}
function showMapPin(i) { }
function setMarkers(map,data) {
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < data.length; i++) {
setMarker(map, data[i], bounds);
}
map.fitBounds(bounds);
}
function setMarker(map, m, bounds) {
if(m["address"]!="") {
var geocoder = new google.maps.Geocoder();
geocoder.geocode( { "address": m["address"] }, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var siteLatLng = results[0].geometry.location;
}
});
} else {
var siteLatLng = new google.maps.LatLng(m["lat"], m["lon"]);
}
if(siteLatLng) {
var marker = new google.maps.Marker({
position: siteLatLng,
map: map,
//shadow: shadow,
icon: m["image"],
title: m["title"],
zIndex: m["zindex"],
html: m["marker_html"]
});
bounds.extend(siteLatLng);
google.maps.event.addListener(marker, "click", function() {
infowindow.setContent(this.html);
infowindow.open(map, this);
});
} // if latlng
}//]]>
After looking back over the code I realized that the variable siteLatLng is within geocode function scope so it never gets passed and it can't be returned. Setting the marker within this function works.

close InfoWindow before open another

I have a problem with InfoWindow. I have an ajax function that retrieves data via JSON, but I can not get close InfoWindow automatically when you open another.
My code is this:
var mapOptions = {
center: new google.maps.LatLng(44.49423583832911, 11.346244544982937),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("mappa_locali"),mapOptions);
$.ajax({
type:'GET',
url:"locali_json.php"+urlz,
success:function(data){
var json = JSON.parse(data);
for (var i=0; i<json.length; i++) {
point = new google.maps.LatLng(json[i].latitudine,json[i].longitudine);
var infowindow = new google.maps.InfoWindow;
infowindow.setContent(''+json[i].nome_locale+'<br>'+json[i].address);
addMarkerz(point,infowindow);
}
}
})
}
function addMarkerz(point,infowindow) {
position: point,
map: map
});
google.maps.event.addListener(marker,'mouseover',infoCallback(infowindow, marker));
markers.push(marker);
infos.push(infowindow);
}
function infoCallback(infowindow, marker) {
return function() {
infowindow.close();
infowindow.open(map, marker);
};
}
Does anyone know where decreased mistake? Or do you have any advice for me?
The suggestion is only create one infowindow (in the global scope), reuse it and change its contents when a marker is clicked, close it if the user clicks on the map.
code snippet (removes the dependency on the AJAX call):
// global variables
var map;
var markers = [];
var infowindow = new google.maps.InfoWindow();
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(44.49423583832911, 11.346244544982937),
zoom: 13,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("mappa_locali"), mapOptions);
var json = JSON.parse(data);
for (var i = 0; i < json.length; i++) {
point = new google.maps.LatLng(json[i].latitudine, json[i].longitudine);
var infowindowHtml = '' + json[i].nome_locale + '<br>' + json[i].address;
addMarkerz(point, infowindowHtml);
}
}
function addMarkerz(point, infowindowHtml) {
var marker = new google.maps.Marker({
position: point,
map: map
});
google.maps.event.addListener(marker, 'mouseover', infoCallback(infowindowHtml, marker));
markers.push(marker);
}
function infoCallback(infowindowHtml, marker) {
return function() {
infowindow.close();
// update the content of the infowindow before opening it
infowindow.setContent(infowindowHtml)
infowindow.open(map, marker);
};
}
var data = JSON.stringify([{
latitudine: 44.494887,
longitudine: 11.3426163,
id_locale: "0",
nome_locale: "Bologna",
address: "Bologna, Italy"
}, {
latitudine: 44.4946615,
longitudine: 11.314634999999953,
id_locale: "0",
nome_locale: "Quartiere Saragozza",
address: "Quartiere Saragozza, Bologna, Italy"
}]);
google.maps.event.addDomListener(window, "load", initialize);
html,
body,
#mappa_locali {
height: 100%;
width: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
<div id="mappa_locali"></div>
function infoCallback(infowindow, marker) {
return function() {
infowindow.close();
infowindow.open(map, marker);
};
}
should be changed to
function infoCallback(infowindow, marker) {
return function() {
//Close active window if exists
if (activeWindow != null) {
activeWindow.close();
}
//Open new window
infowindow.open(map,marker);
//Store new window in global variable
activeWindow = infowindow;
};
}
and declare activeWindow as a global variable in your .js file as var activeWindow.
I think I have a simple solution. I just save the last open mark. On the next click first of all I close the last mark.
var markers = [];
var infowindows = [];
function addMarkes(facilityID) {
var bounds = new google.maps.LatLngBounds();
for (var i = 0; i < variants.length; i++) {
var v = variants[i];
var position = new google.maps.LatLng(v.Lat, v.Long);
bounds.extend(position);
markers[i] = new google.maps.Marker({
position: position,
title: v.Title,
map: map,
animation: google.maps.Animation.DROP,
icon: v.Icon,
infoWindowIndex: i //synchronize with infoWindows
});
var localContent = '<div><span class="address">' + v.Address + '</span></div>';
infowindows[i] = new google.maps.InfoWindow({
content: localContent
});
//Just for multiple marks.
if (variants.length > 0) {
var lastOpen = -1; //Save the last open mark
google.maps.event.addListener(markers[i], 'click', function (innerKey) {
return function () {
//Close the last mark.
if (lastOpen > -1) {
infowindows[lastOpen].close();
}
infowindows[innerKey].open(map, markers[innerKey]);
lastOpen = innerKey;
}
}(i));
}
}
map.fitBounds(bounds);
}

Google Maps API geocode function problem

Ok, I'm fooling around with Google Maps API v3 and I bumped into a problem. I don't know if its the API or just some JS error i made.
Problem:
addMarkerFromAdress() function calls on geocodeFromAdress() which returns coordinates back to addMarkerFromAdress(). But returned value is "undefined".
As a debug i added two alert outputs, one in addMarkerFromAdress() and one in geocodeFromAdress(). What troubles me is that the alert() in addMarkerFromAdress() seems to fire off before any value is returned. Why?
Source:
<script type="text/javascript">
var geocoder;
var map;
function initializeGoogleMaps() {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(0, 0);
var myOptions = {
zoom: 1,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
}
function geocodeFromAdress(address) {
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var latLng = results[0].geometry.location;
alert(latLng); //Outputs coordinates, but is for some reason outputted 2nd
return latLng;
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
function addMarkerFromAdress(address, title){
var latLng = geocodeFromAdress(address);
alert(latLng); //Outputs "undefined", but is for some reason outputted 1st
map.setCenter(latLng);
var marker = new google.maps.Marker({
map: map,
position: latLng
});
}
window.onload = function () {
initializeGoogleMaps();
addMarkerFromAdress('Berlin, Germany', 'Berlin');
}
</script>
See that function passed as the second argument to geocoder.geocode()? that is where you should be calling addMarkerFromAddress. Due to the asynchronous nature of the geocode request, the alert after var latLng = geocodeFromAdress(address); is firing before the response is returned with the lat long values.
Something like this should do it
<script type="text/javascript">
var geocoder;
var map;
function initializeGoogleMaps() {
geocoder = new google.maps.Geocoder();
var latlng = new google.maps.LatLng(0, 0);
var myOptions = {
zoom: 1,
center: latlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
}
map = new google.maps.Map(document.getElementById("map_canvas"), myOptions);
}
function geocodeFromAdress(address, title) {
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
var latLng = results[0].geometry.location;
addMarkerFromAdress(latLng, title);
} else {
alert("Geocode was not successful for the following reason: " + status);
}
});
}
function addMarkerFromAdress(latLng, title){
map.setCenter(latLng);
var marker = new google.maps.Marker({
map: map,
position: latLng
});
}
window.onload = function () {
initializeGoogleMaps();
geocodeFromAdress('Berlin, Germany', 'Berlin');
}
</script>

Resources