JavaScript google maps API - one one infowindow open at a time.. - javascript

This questions relating to infowindow in the google maps API v3..
Currently I loop this function and place markers..
function addPostCode(zip, html)
{
geocoder.geocode( { 'address': zip}, 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,
name: zip
});
});
Now I would like to add an info windows with unique HTML, however I would like the following behaviour..
When an infowindow is opened by an event, any current infowindows will close leaving only the new one present..
Is this possible and how would I go about it? Finding documentation on this issue is proving difficult..

Create a single infowindow in your initialization. In your event/listener where you want to open the infowindow, you'd set the content and open the infowindow on the marker/location on the map.
// Initialize infowindow
var infowindow = new google.maps.InfoWindow({content: ''});
function add_marker(point, name, content)
{
var marker = new google.maps.Marker({
map: map,
position: point,
dragable: false,
clickable: true,
name: name
});
marker.content = content;
google.maps.event.addListener(marker, 'click', function()
{
infowindow.content = marker.content;
infowindow.open(map, marker);
});
return marker;
};
function addPostCode(zip, html)
{
geocoder.geocode( { 'address': zip}, function(results, status)
{
if (status == google.maps.GeocoderStatus.OK)
{
map.setCenter(results[0].geometry.location);
var marker = add_marker(results[0].geometry.location, zip, html)
});
});
This question and answer helped me out quite a bit with the single or multiple Info Window issue:
Google Maps API v3 adding an InfoWindow to each marker

var currentInfoWindow = ''; //Global variable
google.maps.event.addListener(marker, 'click', function()
{
if(currentInfoWindow != '')
{
currentInfoWindow.close();
currentInfoWindow = '';
}
var infoWindow = new google.maps.InfoWindow({content: 'COntent'});
infowindow.open(map, marker);
currentInfoWindow = infowindow;
});

You are probably better off asking the Google Groups for the Google Maps API v3 about this one, and any other related questions.
I haven't used API v3, but as far as I know, you can only have one info window open at a time, so this would happen automatically.

There are two ways to do this ... the first is to create a single info window and just use the .setOptions method of the info window to update the content.
The second way to do it is to simply set a module-level variable in your code to contain the "active" window ... and then if any infoWindow is open, call it's .close method before you open the new one.

Related

Google Places API show schools and stores

Using the Google Maps API with the places library I am able to show nearby schools using the recommended method shown here.
var map;
var infowindow;
function initMap() {
var pyrmont = {lat: -33.867, lng: 151.195};
map = new google.maps.Map(document.getElementById('map'), {
center: pyrmont,
zoom: 15
});
infowindow = new google.maps.InfoWindow();
var service = new google.maps.places.PlacesService(map);
service.nearbySearch({
location: pyrmont,
radius: 500,
type: ['store']
}, callback);
}
function callback(results, status) {
if (status === google.maps.places.PlacesServiceStatus.OK) {
for (var i = 0; i < results.length; i++) {
createMarker(results[i]);
}
}
}
function createMarker(place) {
var placeLoc = place.geometry.location;
var marker = new google.maps.Marker({
map: map,
position: place.geometry.location
});
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(place.name);
infowindow.open(map, this);
});
}
Here's a working fiddle: https://jsfiddle.net/api/post/library/pure/
The problem is that if I also want to show nearby stores as well as schools, everyone seems to recommend simply doing this:
type: ['store', 'school']
While this technically works, the problem is the map just shows a bunch of meaningless default markers with no way of knowing what it what.
So my question is: How can I change the icon for the schools and stores? Ideally I would show a different icon for each different type.
It's no different than adding custom marker in regular map.Only thing is that you need to make api calls separately for each type.So even type: ['store', 'school'] would work and you get results but there is no type specifier in the results to tell whether it's a school or shop .Also you would need to create their separate callbacks for setting their separate icons
function createMarker(place) {
var placeLoc = place.geometry.location;
var marker = new google.maps.Marker({
icon:"http://example.com/icon.png", //<-- only this line is enough for icon
map: map,
position: place.geometry.location
});
go through this for a better understanding
Moreover every result will have a default icon (as icon property), that can also be used
var marker = new google.maps.Marker({
icon:place.icon,
map: map,
position: place.geometry.location
});

How to define multiple locations Using Google Maps API to drop pin for every post in a list of posts generated by a loop

This question might be answered in other posts, but I haven't found the specific answer and I'm having trouble discerning how to logically think through this. I have a site where each post has an address. On each post page I've used the Google Maps API to translate the address into a map location and to show a map with a pin at that address. Works great.
What I need to do now is to show a map at the top of my archive/category/etc pages (pages with a list of posts generated by a query and a loop) and to list a pin for every post that shows up in that particular query. I also need the map to automatically resize to show all of the pins, and not show extraneous map outside of the pins boundaries.
The way it seems that this would happen is that I could create the markers with a script that's inside the loop, so that each time the loop runs, it would generate a new marker and add it to the map.
Another possible method that seems like it has potential would be to add the location to an array for each turn of the loop, and then show the array of pins when the loop is done.
Can anyone give me some advice on how to accomplish this? At this point I'm using the following code which gives me a map and the location of the last post in the list generated by the loop. This code is outside of the loop. I need to know which part I should move inside the loop, and how to adjust it so that I won't simply rewrite the marker during every iteration of the loop.
<script type="text/javascript">
function initialize() {
geocoder = new google.maps.Geocoder();
var mapOptions = {
zoom: 3,
}
var myAddress = document.getElementById('theAddress');
var address = myAddress.textContent;
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);
}
});
var map = new google.maps.Map(document.getElementById("map-canvas"), mapOptions);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
You need to add markers in a loop. this was taken from a project i was working.
var locations = ["Denver, CO, United States"];
var markers = [];
var iterator = 0;
for (var i = 0; i < locations.length; i++) {
setTimeout(function() {
geocoder.geocode({'address': locations[iterator]}, function(results, status){
if (status == google.maps.GeocoderStatus.OK) {
var marker = new google.maps.Marker({
map: map,
position: results[0].geometry.location,
animation: google.maps.Animation.DROP
});
bounds.extend(marker.getPosition());
map.fitBounds(bounds);
} else {
log('Geocode was not successful for the following reason: ' + status);
}
});
iterator++;
}, i * 250);
}

Google map api v3 - remove old marker when doing geocoding

I am new in Javascript and google map api and I have been follow this link to remove a marker but some how I cannot make it work.
Basically I want to use a button to generate the marker when user enter an address and click on the button. When the user enter a new address and click on the button again, the old marker will be removed and the new marker pin on the new address. The marker also draggable.
Here is my js code:
$('#geocode').live('click',function() {
codeAddress();
return false;
});
function codeAddress() {
var address = document.getElementById('location').value;
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
map.setCenter(results[0].geometry.location);
if (marker) marker.setMap(null);
if (marker) delete marker;
var marker = new google.maps.Marker({
draggable:true,
map: map,
position: results[0].geometry.location
});
var newlat = results[0].geometry.location.lat();
var newlng = results[0].geometry.location.lng();
document.getElementById('mwqsflatlng').value = (newlat+' , '+newlng);
draggeablemarker(marker);
} else {
alert('Geocode was not successful for the following reason: ' + status);
}
});
}
Update
When I check on the inspect element, it gave me this error:
Uncaught TypeError: Cannot call method 'setMap' of undefined
You need to have a reference to your marker object to be able to access it at a later time. If you want to restrict the map to one marker showing at a time you can update the markers Position property instead of deleting and recreating it.
Here is a function that can change the markers position or create a new marker if one does not exist on the map. The location parameter is a Google LatLng object which is the same as the object returned by the Geocoder results[0].geometry.location.
Notice the marker variable is defined outside of the function scope. This is what allows you to refer to the marker at a later time.
var marker;
function placeMarker(location) {
if (marker) {
//if marker already was created change positon
marker.setPosition(location);
} else {
//create a marker
marker = new google.maps.Marker({
position: location,
map: map,
draggable: true
});
}
}
So for your geocode success function you should only have to pass the result to this function.
geocoder.geocode( { 'address': address}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
placeMarker(results[0].geometry.location);
}
...
Here is a fiddle of of the concept. You can click on the map and the marker will move to the desired location.

geocoder is returning previously stored value when click on a marker

I'm implementing geocoder using google map api v3 (javascript). I'm putting mutiple markers and when i click on marker i want the corresponding address to come in the info-window. But when i click on the marker, initially the default value of address(As per code Geo-Address Unavailable!) is coming and when i click the second marker it is having the address of the previously clicked marker. I'm attaching the piece of code.
var addr=" Geo-Address Unavailable!";
var geocoder = new google.maps.Geocoder();
for(var i = 0; i < latLngs.length-1; i++){ //latLngs is the array of latlongs
marker = new google.maps.Marker({
position: latlng,
id:markerId,
icon: image,
map: map,
animation : google.maps.Animation.DROP,
});
}
markers[markerId] = marker;
var infowindow = new google.maps.InfoWindow({
content: "loading..."
});
google.maps.event.addListener(marker, "click", function () {
geocoder.geocode({'latLng': this.getPosition()}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
addr = results[0].formatted_address;
}
});
infowindow.setContent(addr);
infowindow.open(map, this);
});
Geocoding is asynchronous. You have to use the returned value inside the callback from the geocoder.
What is happening:
you send off a request to the geocoder.
you display the response
the response comes back from the geocoder
you send off another request to the geocoder
you display the response to the first request
the response comes back from the geocoder to the second request

Setting infoWindow for a list of markers created inside a callback function (directionsService)

I'm trying to set infoWindows for markers that are created in the callback function of a directionsService (Google Maps API V3). I tried many different ways to do that without any luck..
Here is a skeleton of how my code looks like:
for(i=0;i<markersList.length;i++){
map = someMap
var request = myRequestObject;
var directionsService = new google.maps.DirectionsService();
var directionsDisplay = new google.maps.DirectionsRenderer();
directionsDisplay.setMap(map);
directionsService.route(request, (function (address) {
return function(response, status) {
//Use the directions service to do some stuff
//..Then create markers
var marker = new google.maps.Marker({
map: map,
title: address['title']
});
//push the marker to a list of markers attached to the map
//this can be useful to delete all markers in a later step
map.markers.push(marker);
//Creating multiple instances of infoWindows works fine though..
//However, Creating 1 info window for the whole map doesn't work from here
//If I try that, I'd set the same content for all info windows
//which is not what I want.
}
}
)(markersList[i])
);
}
I tried doing this, which didn't work either:
//add setInfo as a custom function to my map
//then call it to iterate over all markers and add info windows
google.maps.Map.prototype.setInfo = function() {
for(var i=0; i < this.markers.length; i++){
infowindow.setContent(this.markers[i].getTitle());
google.maps.event.addListener(this.markers[i], 'click', function(){
infowindow.close();
infowindow.open(map,this.markers[i]);
});
}
};
Then I'd call this function after I'm done with directionsService.route (check the first code block), outside my main for-loop. However, it never finds any markers attached to the map for some reason..
Any thoughts on how to assign the right infoWindows to the map markers?
I want to have 1 infoWindow instance so that I could close it when a new infoWindow is clicked (infoWindow.close()).
Thanks!
Here is how I do it within a geocoder callback function (a little different than the directionService, but still using a callback function, so the methodology should be the same) using only one infowindow. I would use this in a loop when geocoding a bunch of addresses.
var infowindow = new google.maps.InfoWindow();
geocoder.geocode( { 'address': value}, function(results, status) {
if (status == google.maps.GeocoderStatus.OK) {
//create and add marker to map based off geocode result
var marker = new google.maps.Marker({
map: map,
title: results[0].formatted_address,
position: results[0].geometry.location
});
//add marker to array so we can clear it later
markersArray.push(marker);
//create listener for marker infowindow and set content
google.maps.event.addListener(marker, 'click', function() {
infowindow.close();
infowindow.setContent(results[0].formatted_address);
infowindow.open(map,marker);
});
}
});
One way to do this is have an external function that sets the content on the infowindow, and as you add your markers, you call that function instead of having the event listener declared inline within your loop. The problem is that after all the markers are created, when you click one, it will just use whatever the value of results[0].formatted_address is, which is whatever it was last set to at the end of the loop.
var marker = new google.maps.Marker({
map: map,
title: address['title']
});
//push the marker to a list of markers attached to the map
//this can be useful to delete all markers in a later step
map.markers.push(marker);
// add an event listener for this marker
bindInfoWindow(marker, map, infowindow, address['title']);
And that function is simply:
function bindInfoWindow(marker, map, infowindow, html) {
google.maps.event.addListener(marker, 'click', function() {
infowindow.setContent(html);
infowindow.open(map, marker);
});
}
PS: You shouldn't need to call infowindow.close() prior to calling infowindow.open(). As there's only one infowindow, the API will automatically close it before reopening it at the new location.

Categories

Resources