So I am trying to make a simple application that will allow the user to search for restaurants and have the results show as markers on the map and as text below. The results object that returns from the textSearch doesn't provide detailed information like: phone number, pictures, etc. So i decided to create an array of place id's pushed from the results object, get the place details for each id, then push that into an array. The problem I get is a message from google saying I'm over my quota and I think it's because I'm requesting the place details for every single search result.
Is there a way I can request the place details only for the marker I click? Or is there a better solution to my problem? Thank you in advance for your help.
<!DOCTYPE html>
<html>
<head>
<title>gMap test</title>
<style type="text/css">
#map-canvas{
height:500px;
}
</style>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?libraries=places&sensor=false"></script>
<script type="text/javascript">
function performSearch(){
var locationBox;
var address = document.getElementById("address").value;
var searchRadius = metricConversion(document.getElementById("radius").value);
//gMaps method to find coordinates based on address
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
});
var latitude = results[0].geometry.location.A;
var longitude = results[0].geometry.location.F;
locationBox = new google.maps.LatLng(latitude, longitude);
}else{
errorStatus(status);
return;
}
//search request object
var request = {
query: document.getElementById('keyword').value,
location: locationBox,
radius: searchRadius,
//minPriceLvl: minimumPrice,
//maxPriceLvl: maximumPrice,
types: ["restaurant"]
}
//search method. sending request object and callback function
service.textSearch(request, handleSearchResults);
});
};
var latLngArray = [];
var placeIdArray = [];
//callback function
function handleSearchResults(results,status){
if( status == google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
placeIdArray.push(results[i].place_id)
latLngArray.push(results[i].geometry.location);
};
for(var j = 0; j<placeIdArray.length; j++){
service.getDetails({placeId: placeIdArray[j]},getDetails)
};
}
else{errorStatus(status)};
};
var detailedArray = [];
function getDetails(results,status){
if (status == google.maps.places.PlacesServiceStatus.OK) {
detailedArray.push(results);
for(var i = 0; i<detailedArray.length; i++){
createMarker(detailedArray[i],i);
}
}
else{
errorStatus(status)
};
}
//array of all marker objects
var allMarkers = [];
//creates markers and info windows for search results
function createMarker(place, i) {
var image = 'images/number_icons/number_'+(i+1)+'.png';
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location,
html:
"<div class = 'markerPop'>" + "<h3>" + (i+1) + ". " + place.name + "</h3><br>" + "<p>Address: "
+ place.formatted_address + "</p><br>" + "<p> Price Range: "+ priceLevel(place.price_level)
+ "</p>" + "</div>",
icon: image
});
allMarkers.push(marker);
marker.infowindow = new google.maps.InfoWindow();
//on marker click event do function
google.maps.event.addListener(marker, 'click', function() {
//service.getDetails({placeId: placeIdArray[j]},getDetails)
//sets infowindow content and opens infowindow
infowindow.setContent(this.html);
infowindow.open(map,this);
});
//create new bounds object
var bounds = new google.maps.LatLngBounds();
//iterates through all coordinates to extend bounds
for(var i = 0;i<latLngArray.length;i++){
bounds.extend(latLngArray[i]);
};
//recenters map around bounds
map.fitBounds(bounds);
};
var map;
var service;
var geocoder;
var infowindow;
function initialize(location){
var mapOptions = {
center: new google.maps.LatLng(37.804, -122.271),
zoom: 8,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
geocoder = new google.maps.Geocoder();
map = new google.maps.Map(document.getElementById("map-canvas"),mapOptions);
service = new google.maps.places.PlacesService(map)
infowindow = new google.maps.InfoWindow();
};
$(document).ready(function(){
initialize();
$('#search').on('click', function(){
removeMarkers();
performSearch();
});
});
//::::::Random Functions:::::::
//Clears all markers between searches
function removeMarkers(){
for(var i = 0; i<allMarkers.length;i++){
allMarkers[i].setMap(null);
};
};
//converts miles to meters for search object
function metricConversion(miles){
var meters;
meters = miles * 1609.34;
return meters;
}
//converts number value to $ sign
function priceLevel(number){
var moneySigns = ""
for(var i =0;i<=number;i++){
moneySigns += "$";
};
return moneySigns;
}
//errors for search results
function errorStatus(status){
switch(status){
case "ERROR": alert("There was a problem contacting Google Servers");
break;
case "INVALID_REQUEST": alert("This request was not valid");
break;
case "OVER_QUERY_LIMIT": alert("This webpage has gone over its request quota");
break;
case "NOT_FOUND": alert("This location could not be found in the database");
break;
case "REQUEST_DENIED": alert("The webpage is not allowed to use the PlacesService");
break;
case "UNKNOWN_ERROR": alert("The request could not be processed due to a server error. The request may succeed if you try again");
break;
case "ZERO_RESULTS": alert("No result was found for this request. Please try again");
break;
default: alert("There was an issue with your request. Please try again.")
};
};
</script>
</head>
<body>
<div id="map-canvas"></div>
<div id="searchBar">
<h3>search options</h3>
Location:<input type="text" id="address" value="enter address here" /><br>
Keyword<input type="text" id="keyword" value="name or keyword" /><br>
Advanced Filters:<br>
Search Radius:<select id="radius">
<option>5</option>
<option>10 </option>
<option>15 </option>
<option>20 </option>
<option>25 </option>
</select>miles<br>
<div id="minMaxPrice">
Min Price<select id="minPrice">
<option>$</option>
<option>$$</option>
<option>$$$</option>
<option>$$$$</option>
</select>
Max Price<select id="maxPrice">
<option>$</option>
<option>$$</option>
<option>$$$</option>
<option>$$$$</option>
</select>
</div>
<input type="button" id="search" value="Submit Search"/><br>
</div>
<div id='searchResults'>
</div>
</body>
</html>
The radarSearch example in the documentation requests the details of the marker on click.
code snippet:
var map;
var infoWindow;
var service;
function initialize() {
map = new google.maps.Map(document.getElementById('map-canvas'), {
center: new google.maps.LatLng(-33.8668283734, 151.2064891821),
zoom: 15,
styles: [{
stylers: [{
visibility: 'simplified'
}]
}, {
elementType: 'labels',
stylers: [{
visibility: 'off'
}]
}]
});
infoWindow = new google.maps.InfoWindow();
service = new google.maps.places.PlacesService(map);
google.maps.event.addListenerOnce(map, 'bounds_changed', performSearch);
}
function performSearch() {
var request = {
bounds: map.getBounds(),
keyword: 'best view'
};
service.radarSearch(request, callback);
}
function callback(results, status) {
if (status != google.maps.places.PlacesServiceStatus.OK) {
alert(status);
return;
}
for (var i = 0, result; result = results[i]; i++) {
createMarker(result);
}
}
function createMarker(place) {
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location,
icon: {
// Star
path: 'M 0,-24 6,-7 24,-7 10,4 15,21 0,11 -15,21 -10,4 -24,-7 -6,-7 z',
fillColor: '#ffff00',
fillOpacity: 1,
scale: 1 / 4,
strokeColor: '#bd8d2c',
strokeWeight: 1
}
});
google.maps.event.addListener(marker, 'click', function() {
service.getDetails(place, function(result, status) {
if (status != google.maps.places.PlacesServiceStatus.OK) {
alert(status);
return;
}
var htmlStr = "<b>"+result.name+"</b><br>";
if (result.website) htmlStr += "<a href='"+result.website+"'>"+result.website+"</a><br>";
if (result.adr_address) htmlStr += result.adr_address+"<br>";
infoWindow.setContent(htmlStr);
infoWindow.open(map, marker);
});
});
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#map-canvas {
height: 100%;
margin: 0px;
padding: 0px
}
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp&signed_in=true&libraries=places"></script>
<div id="map-canvas"></div>
I had the same issue some time ago. The geocoding function by google is done in order to avoid the user executing it on a large set of data (and then, avoid you to get a large amount of geocoded address easily).
My solution was to execute the geocoding function only when the user choose a particular place, and then, display this particular data (handled by the click on the pin).
I think it would be very useful to initiate a jsfiddle with a working version of your code.
Basically on your function :
google.maps.event.addListener(marker, 'click', function() {
//Execute geocoding function here on marker object
//Complete your html template content
infowindow.setContent(this.html);
infowindow.open(map,this);
});
Related
This is my code, When i am calling removeMarkers(), it's not removing the markers.
function receiver(data, textStatus, XMLHttpRequest) {
var json = JSON.parse(data);
for (var i = 0; i < json.length; i++) {
var lat = json[i]["lat"];
var lng = json[i]["lng"];
// push object into features array
features.push({ position: new google.maps.LatLng(lat,lng) });
}
features.forEach(function(feature) {
var marker1 = new google.maps.Marker({
position: feature.position,
//icon: icons[feature.type].icon,
map: map
});
});
gmarkers.push(marker1);
}
function removeMarkers(){
for(i=0; i<gmarkers.length; i++){
gmarkers[i].setMap(null);
}
}
This is my full code. For displaying places(church) that which i saved in my database along the route from origin to destination. If i changed the origin and destination i want to remove old markers and displaying new markers without refreshing the page.
css
<style>
#map {
height: 100%;
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
</style>
html
<div id="map" height="460px" width="100%"></div>
<input type="text" id="distance" value="3" size="2">
<input type="text" id="from" />to
<input type="text" id="to" />
<input type="submit" onClick="route()" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js?key=api_ key&libraries=places"></script>
<script src="https://cdn.rawgit.com/googlemaps/v3-utility-library/master/routeboxer/src/RouteBoxer.js" type="text/javascript"></script>
javascript
<script>
var map;
var marker;
var infowindow;
var messagewindow;
var boxpolys = null;
var directions = null;
var routeBoxer = null;
var distance = null; // km
var service = null;
var gmarkers = [];
var boxes = null;
var coordinates=null;
var features = [];
var gmarkers = [];
<?php
echo "
var lat={$lat};
var lng={$lng};
"
?>
function initialize() {
var location = {lat: 10.525956868983068, lng:76.21387481689453};
map = new google.maps.Map(document.getElementById('map'), {
center: location,
zoom: 13
});
service = new google.maps.places.PlacesService(map);
routeBoxer = new RouteBoxer();
directionService = new google.maps.DirectionsService();
directionsRenderer = new google.maps.DirectionsRenderer({
map: map
});
}
function route() {
removeMarkers()
clearBoxes();
distance = parseFloat(document.getElementById("distance").value) * 0.1;
var request = {
origin: document.getElementById("from").value,
destination: document.getElementById("to").value,
travelMode: google.maps.DirectionsTravelMode.DRIVING
}
directionService.route(request, function(result, status) {
if (status == google.maps.DirectionsStatus.OK) {
directionsRenderer.setDirections(result);
var path = result.routes[0].overview_path;
boxes = routeBoxer.box(path, distance);
drawBoxes();
findPlaces(0);
} else {
alert("Directions query failed: " + status);
}
});
}
function drawBoxes() {
boxpolys = new Array(boxes.length);
for (var i = 0; i < boxes.length; i++) {
boxpolys[i] = new google.maps.Rectangle({
bounds: boxes[i],
fillOpacity: 0,
strokeOpacity: 1.0,
strokeColor: '#000000',
strokeWeight: 0,
map: map
});
}
}
function findPlaces(searchIndex) {
var request = {
bounds: boxes[searchIndex],
};
coordinates = boxes[searchIndex].toString().match(/[0-9]+\.[0-9]+/g);
$.ajax({
url:"http://localhost/church_finder/index.php/MapController/search_church",
type:'POST',
data:{coordinates:coordinates},
//dataType:'json',
success: receiver
});
if (status != google.maps.places.PlacesServiceStatus.OVER_QUERY_LIMIT) {
searchIndex++;
if (searchIndex < boxes.length)
findPlaces(searchIndex);
} else {
setTimeout("findPlaces(" + searchIndex + ")", 1000);
}
}
function clearBoxes() {
if (boxpolys != null) {
for (var i = 0; i < boxpolys.length; i++) {
boxpolys[i].setMap(null);
}
}
boxpolys = null;
}
function receiver(data, textStatus, XMLHttpRequest) {
var json = JSON.parse(data);
for (var i = 0; i < json.length; i++) {
var lat = json[i]["lat"];
var lng = json[i]["lng"];
features.push({ position: new google.maps.LatLng(lat,lng) });
}
features.forEach(function(feature) {
var marker1 = new google.maps.Marker({
position: feature.position,
map: map
});
});
gmarkers.push(marker1);
}
function removeMarkers(){
for(i=0; i<gmarkers.length; i++){
gmarkers[i].setMap(null);
}
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
enter image description here
function removeMarkers(){
features.length=0;
if (gmarkers != []) {
for(var i=0; i<gmarkers.length; i++){
gmarkers[i].setMap(null);
}
}
gmarkers =[];
}
Your app throws loads of errors in the console and this is just a temporary fix to what you are asking for:
change the origin and destination, I want to remove old markers and
displaying new markers without refreshing the page
call your initialize() function with a script tag in your HTML file. This is where you include your API key for the project:
<script defer async src="https://maps.googleapis.com/maps/api/js?
key=YOUR_KEY&callback=initialize">
Where is the map element passed in the map constructor?
Create a div element in your HTML to contain the map and add CSS style to it
#map {
height: 100%;
}
html, body {
margin: 0;
padding: 0;
height: 100%;
}
This is actually in the Google Maps API documentation;
Always set the map height explicitly to define the size of the div
element that contains the map.
Now into your JS code...
What are you using var service for? var service is firstly declared in the global scope with a null value and then assigned to a PlacesService constructor...but service is not defined simply because you have not included the places library in your script tag:
ADD PLACES LIBRARY IF YOU WANT TO USE PLACES API
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?
key=YOUR_API_KEY&_ADD_libraries=places_PLEASE_"></script>
Because var service cannot be run, just remove it (it actually does not do anything but adding lines in your code right now) along with the RouteBoxer()
REMOVE THESE LINES - THEY ARE USELESS RIGHT NOW
service = new google.maps.places.PlacesService(map);
routeBoxer = new RouteBoxer();
If you do this, without refreshing the page, you clear the markers for each subsequent requests. You get loads of errors still because you have both syntax and logic bugs in your app.
Get a BIN here
The code below display a map and display the results in UL. I have 2 buttons that display train station and shopping mall.Initially, it will display the results correctly but If I click the other button, it will display duplicate values.
Javascript
var map;
var pos;
var distance;
var distancearray = [];
var markers = [];
//=================================================================
function initialize() {
googleMapsLoaded = false;
map = new google.maps.Map(document.getElementById('map'), {
zoom: 13
});
// Try HTML5 geolocation
if(navigator.geolocation) {
navigator.geolocation.getCurrentPosition(function(position) {
pos = new google.maps.LatLng(position.coords.latitude,position.coords.longitude);
var request = {
location:pos,
radius:3000, //3000 Meters
type:initialtype
};
infowindow = new google.maps.InfoWindow();
var service = new google.maps.places.PlacesService(map);
service.nearbySearch(request,callback);
infowindow = new google.maps.InfoWindow({
map: map,
position: pos,
content: 'You Are Here',
});
map.setCenter(pos);
}, function() {
handleNoGeolocation(true);
});
} else {
// Browser doesn't support Geolocation
handleNoGeolocation(false);
}
function callback(results, status) {
if (status !== google.maps.places.PlacesServiceStatus.OK) {
return;
}
else{
for (var i = 0; i < results.length; i++)
markers.push(createMarker(results[i]));
}
} //end callback function
/* listen to the tilesloaded event
if that is triggered, google maps is loaded successfully for sure */
google.maps.event.addListener(map, 'tilesloaded', function() {
googleMapsLoaded = true;
// document.getElementById("mapnotification").innerHTML = "Map Loaded!";
$("#mapnotification").hide();
$("#map-loaded").show();
$("#map-loaded").css('visibility', 'hidden');
$("#map-notloaded").hide();
//clear the listener, we only need it once
google.maps.event.clearListeners(map, 'tilesloaded');
});
setTimeout(function() {
if (!googleMapsLoaded) {
//we have waited 7 secs, google maps is not loaded yet
document.getElementById("mapnotification").innerHTML = "Map NOT Loaded! Make sure you have stable internet connnection";
$("#mapnotification").hide();
$("#map-notloaded").show();
$("#map-loaded").hide();
}
}, 7000);
function createMarker(place) { // Create Marker and the Icon of the marker
// var bounds = new google.maps.LatLngBounds();
var markerlat;
var markerlon;
var p2;
var output="";
var placesList = document.getElementById('places');
placeLoc = place.geometry.location;
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location,
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 8,
fillColor:'00a14b',
fillOpacity:0.3,
fillStroke: '00a14b',
strokeWeight:4,
strokeOpacity: 0.7
}, // end icon
}); //end of marker variable
markerlat = marker.getPosition().lat()
markerlon = marker.getPosition().lng()
console.log("Markers Lat" + markerlat);
console.log("Markers Lon" + markerlon );
p2 = new google.maps.LatLng(markerlat, markerlon);
distance = [calcDistance(pos, p2)];
//calculates distance between two points in km's
function calcDistance(p1, p2) {
return (google.maps.geometry.spherical.computeDistanceBetween(p1, p2) / 1000).toFixed(2);
}
distancearray.push([distance, place.name]);
distancearray.sort();
console.log("distancearraylength" + distancearray.length);
console.log("Summary" + distancearray);
for(var i = 0; i < distancearray.length; i++){
output += '<li>' + distancearray[i][1] + " " + distancearray[i][0]+ " " + "km" + '</li>';
placesList.innerHTML = output;
}
google.maps.event.addListener(marker, 'click', function() { //show place name when marker clicked
infowindow.setContent(place.name);
infowindow.open(map, marker);
}); // end of marker show place name
} // end createMarker function
function handleNoGeolocation(errorFlag) {
if (errorFlag) {
var content = 'Error: The Geolocation service failed.';
} else {
var content = 'Error: Your browser doesn\'t support geolocation.';
}
var options = {
map: map,
position: new google.maps.LatLng(60, 105),
content: content
};
var infowindow = new google.maps.InfoWindow(options);
map.setCenter(options.position);
} // End handleNoGeolocation function
} //End function initialize
//==========================================================================================================//
$(document).on('pagebeforeshow','#itemPanel2', function(e, data){ // Loading of Nearest Place Options
bindchoicesclick();
function bindchoicesclick(){
$("#subway_station").on("click",function(){
// alert("subway");
markers = [];
pos="";
while(distancearray.length > 0) {
distancearray.pop();
}
while(markers.length > 0) {
markers.pop();
}
//$("#places").empty();
initialtype = ['subway_station'];
buttonholder = "Nearest Station";
$("#find").val(buttonholder);
$("#find").button("refresh");
initialize();
});
$("#shopping_mall").on("click",function(){
// alert("stores");
markers = [];
pos="";
while(distancearray.length > 0) {
distancearray.pop();
}
while(markers.length > 0) {
markers.pop();
}
// distancearray.splice(0).
// $("#places").empty();
initialtype = ['shopping_mall'];
buttonholder = "Nearest Mall";
$("#find").val(buttonholder);
$("#find").button("refresh");
initialize();
});
}
});
HTML
<h1 id="headerField">Nearby Search</h1>
</div>
Search Nearest Train Station
Search Nearest Mall
</div>
<!--Train Stations -->
<div id="globa_map" data-role="page">
<div data-role="header">
Back
Refresh
<h1 id="headerField">Global</h1>
</div>
<div data-role="content">
<!-- <input type="button" id="refreshmap" value="Refresh"> -->
<p id="mapnotification">Please wait while the map is loading...</p>
<p id="map-loaded">Map Loaded!</p>
<p id="map-notloaded">Map NOT Loaded! Make sure you have stable internet connnection</p>
<h2>Results</h2>
<ul id="places"></ul>
<button id="more">More results</button>
<div id="map" style="height:400px;">
</div>
</div>
I am trying to add pins to a Google Map using postcodes stored in a Google Sheet. So far I have been able to access to the Postcodes in the spreadsheet using JSON:
$.getJSON('http://cors.io/?u=https://spreadsheets.google.com/feeds/list/1pksFEATRRWfOU27kylZ1WLBJIC-pMVxKk9YlCcDG0Kk/od6/public/values?alt=json', function(data) {
$.each(data.feed.entry, function(i, v) {
var data = $('<div class="listing">').append('<h4 id="bandb">' + v.gsx$postcode.$t + '</h4>');
$('body').append(data);
});
});
I am also able to add pins to a Google Map using the postcodes.
Example: http://codepen.io/aljohnstone/pen/eJOyrP
I am having trouble combining the two. I would like the postcodes variable in the Codepen to take the postcodes from my Google Sheet.
Working example using the Google Maps Javascript API v3:
$(document).ready(function() {
var geocoder = new google.maps.Geocoder();
var map = new google.maps.Map(document.getElementById("map_canvas"), {
center: {
lat: 54,
lng: -3
},
zoom: 5
});
var i;
var postcodes = [];
$.getJSON('http://cors.io/?u=https://spreadsheets.google.com/feeds/list/1pksFEATRRWfOU27kylZ1WLBJIC-pMVxKk9YlCcDG0Kk/od6/public/values?alt=json', function(data) {
$.each(data.feed.entry, function(i, v) {
postcodes.push(v.gsx$postcode.$t);
});
}).done(function() {
map.setCenter(new google.maps.LatLng(54.00, -3.00));
map.setZoom(5);
var bounds = new google.maps.LatLngBounds();
for (i = 0; i < postcodes.length; i++) {
geocoder.geocode({
'address': "" + postcodes[i]
}, (function(i) {
return function(results, status) {
if (status === google.maps.GeocoderStatus.OK) {
var marker = new google.maps.Marker({
position: results[0].geometry.location,
map: map,
title: postcodes[i]
});
bounds.extend(marker.getPosition());
map.fitBounds(bounds);
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
}
})(i));
}
});
});
html,
body,
#map_canvas {
height: 100%;
width: 100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maps.googleapis.com/maps/api/js" type="text/javascript"></script>
<div id="map_canvas"></div>
Try this
<script src="http://maps.google.com/maps?file=api&v=2&sensor=false" type="text/javascript"></script>
<div id="map_canvas" style="width: 600px; height: 350px"></div>
<script type="text/javascript">
$(document).ready(function()
{
var geocoder = new GClientGeocoder();
var map = new GMap2(document.getElementById("map_canvas"));
var i;
var postcodes = [];
$.getJSON('http://cors.io/?u=https://spreadsheets.google.com/feeds/list/1pksFEATRRWfOU27kylZ1WLBJIC-pMVxKk9YlCcDG0Kk/od6/public/values?alt=json', function(data) {
$.each(data.feed.entry, function(i, v)
{
postcodes.push(v.gsx$postcode.$t);
});
}).done(function()
{
map.setCenter(new GLatLng(54.00, -3.00), 5);
for (i = 0; i < postcodes.length; i++) {
geocoder.getLatLng(postcodes[i] + ', UK', function(point) {
if (point) {
map.addOverlay(new GMarker(point));
}
});
}
});
});
</script>
Working example http://codepen.io/snm/pen/eJOVMY?editors=101
I have implemented Google Maps JavaScript API v3 to contrive a custom store locator for my company's website. Let me start by saying that the code I have works for the two stores, but it would not be efficient or feasible if I added any more stores because of the "hacky" code used to make it work.
I am using the Google Maps Places Library to send "place details" requests to Google using the getDetails() method. On the callback, I am receiving the InfoWindow information (name, address, location) for each of my store locations.
I create a marker for each place, then use google.maps.event.addListener to coordinate the Place, Marker, and InfoWindow objects. This is where I encounter problems. The place details requests are not always received in the same order they are sent which throws off the indexing of my buttons that have a data-marker attribute set to 0 and 1, respectively, to correlate to the map markers.
Is there anyway to delay the second request until the first is finished? or write the script in a way that maintains ordinal integrity?
The first snippet of code below is my event handler to bind the click listener to each button using the .place.placeId property of the marker rather than the preferred technique of using the index of the markers array (the markers array holds the place details for the two stores).
None of the demos or examples in the Google Maps API documentation (Places Library) delineate the procedure for multiple places. Any tips, resources, or suggestions will be much appreciated
Website: http://m.alliancepointe.com/locate.html
Event Handler
$(".loc-btn").on('click', function () {
var me = $(this).data('marker');
var place1 = markers[0].place.placeId;
var myIndex = me == place1 ? 0 : 1;
google.maps.event.trigger(markers[myIndex], 'click');
});
Full JS
var markers = [];
var map;
var infowindow;
var service;
function initialize() {
var index;
var daddr;
var idVA = 'ChIJKezXgqmxt4kRXrAnqIwIutA';
var geoVA = '38.80407,-77.062881/Alliance+Pointe,+LLC';
var idDC = 'ChIJDQlqOLG3t4kRqDU3uNoy4hs';
var geoDC = '38.90188,-77.049161/Alliance+Pointe,+LLC';
var bounds = new google.maps.LatLngBounds();
var mapOptions = {
center: {lat: 38.90188, lng: -77.049161},
zoom: 10,
mapTypeControlOptions: {style: google.maps.MapTypeControlStyle.DROPDOWN_MENU}
};
map = new google.maps.Map(document.getElementById('map'),
mapOptions);
var request = [
{placeId: idVA, location: {lat: 38.80407, lng: -77.062881}},
{placeId: idDC, location: {lat: 38.90188, lng: -77.049161}}
];
var office = [
"Main Office",
"Principal Office"
];
infowindow = new google.maps.InfoWindow();
service = new google.maps.places.PlacesService(map);
for (var i = 0; i < request.length; i++) {
service.getDetails(request[i], function (placeResult, status) {
if (status == google.maps.places.PlacesServiceStatus.OK) {
var id = placeResult.place_id;
var location = placeResult.geometry.location;
var trimAddr = placeResult.formatted_address.split(", ");
var image = {
url: 'images/icons/AP-marker_large.png',
scaledSize: new google.maps.Size(32, 54)
};
var marker = new google.maps.Marker({
map: map,
place: {
placeId: id,
location: location
},
icon: image,
title: "Get directions"
});
google.maps.event.addListener(marker, 'click', function () {
if (id == idVA) {
index = 0;
daddr = geoVA;
trimAddr[0] = "1940 Duke St #200";
} else {
index = 1;
daddr = geoDC;
trimAddr[0] = "2200 Pennsylvannia Ave NW";
}
infowindow.setContent('<div class="info-window title">' + placeResult.name + "</div><div class='info-window sub-title'>" + office[index] + '</div><div class="info-window">' + trimAddr[0] + '<br>' + trimAddr[1] + ", " + trimAddr[2] + '</div><div class="info-window direction-div"><div class="direction-icon"></div><a class="google-link save-button-link" target="_blank" href="https://www.google.com/maps/dir/Current+Location/' + daddr + '">Get Directions</a></div>');
infowindow.open(map, marker);
});
markers.push(marker);
//bounds.extend(location);
}
});
}
if (!bounds.isEmpty()) {
map.fitBounds(bounds);
}
$(".loc-btn").on('click', function () {
var me = $(this).data('marker');
var place1 = markers[0].place.placeId;
var myIndex = me == place1 ? 0 : 1;
google.maps.event.trigger(markers[myIndex], 'click');
//console.log("PlaceId = " + me);
//console.log("Adj index = " + myIndex);
//console.log("0:VA array index = " + markers[0].place.placeId);
//console.log("1:DC array index = " + markers[1].place.placeId);
});
google.maps.event.addListenerOnce(map, 'idle', function () {
$.mobile.loading("hide");
$(".loc-btn").prop("disabled",false);
});
}
google.maps.event.addDomListener(window, 'load', initialize);
HTML: Map & Buttons
<div data-role="content" class="full-width">
<figure id="map"></figure>
<div class="loc-btn-set">
<button disabled data-role="none" data-theme="a" data-marker="ChIJKezXgqmxt4kRXrAnqIwIutA" class="loc-btn nightly-button">VA <span>- Alexandria</span></button>
<button disabled data-role="none" data-theme="b" data-marker="ChIJDQlqOLG3t4kRqDU3uNoy4hs" class="loc-btn nightly-button">DC <span>- Washington</span></button>
</div>
</div>
The simpliest approach based on the given code would be to add the click-handler for the buttons inside the getDetails-callback.
Add this after the creation of the marker:
$('.loc-btn[data-marker="'+id+'"]').click(function(){
google.maps.event.trigger(marker,'click');
});
I'm sure this is really simple but I haven't had much luck figuring out what's wrong. I'm creating an empty array (locations), filling it with location objects in the getPartnerLocations function and then trying to plot the locations on the map with the drop function. The problem I'm having is that inside the drop function the locations array which has stuff in it is returning a length of zero so the loop in the isn't working. Any tips or ideas about what's going on here would be greatly appreciated.
var markers = [];
var locations = [];
var iterator = 0;
var map;
var geocoder;
var newYork = new google.maps.LatLng(40.7143528, -74.0059731);
function initialize() {
var mapOptions = {
zoom: 12,
mapTypeId: google.maps.MapTypeId.ROADMAP,
center: newYork
};
map = new google.maps.Map(document.getElementById("map_canvas"),mapOptions);
}
function getPartnerLocations() {
geocoder = new google.maps.Geocoder();
$('.partner').each(function(index){
var street = $('.partner-streetaddress',this).text();
var city = $('.partner-city',this).text();
var state = $('.partner-state',this).text();
var country = $('.partner-country',this).text();
var address = street + ', ' + city + ', ' + state + ', ' + country;
geocoder.geocode( { 'address': address}, function(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
locations.push( results[0].geometry.location );
console.log(locations[index]);
}
else
{
console.log('failed to geocode address: ' + address);
}
});
});
initialize();
drop();
}
function addMarker() {
console.log('add marker function');
markers.push(new google.maps.Marker({
position: locations[iterator],
map: map,
draggable: false,
animation: google.maps.Animation.DROP
}));
iterator++;
}
function drop()
{
console.log(locations.length);
for (var i = 0; i < locations.length; i++) {
setTimeout(function() {
addMarker();
}, i * 200);
}
}
getPartnerLocations();
geocode is an asynchronous function.
The callback doesn't execute until some time after you call drop.
Therefore, when you call drop, the array is still empty.
You need to call initialize and drop after the last AJAX call replies, in the geocode callback.