Store Google Maps Marker Info - javascript

I am trying to store the title of a clicked on Marker in a global variable using the following code:
var selectedUser; //returns undefined
function attachSecretMessage(marker, secretMessage) {
var infowindow = new google.maps.InfoWindow({
content: secretMessage
});
marker.addListener('click', function() {
infowindow.open(marker.get('map'), marker);
selectedUser = secretMessage;
console.log(selectedUser); //Gives title of selected marker
});
}
function selectedUser () {
document.write(selectedUser); // returns undefined
}
The following is how I am calling selectedUser() in HTML:
<div class="selectedUsername">
<h2><script type="text/javascript">selectedUser();</script></h2>
</div>
But I am only getting undefined returned. How can I fix this and be able to store the title of the clicked on Marker and access it somewhere else?

It actually does write it in the global var. And your console.log proves it. I think that your selectedUser() function executes before the click happens. That's why you have undefined.. Your click callback isn't executed yet. Try doing this (also changing names):
var selectedUser; //returns undefined
function writeSelectedUser () {
docment.getElementByTagName('h2')[0].innerHTML = secretUser;
}
function attachSecretMessage(marker, secretMessage) {
var infowindow = new google.maps.InfoWindow({
content: secretMessage
});
marker.addListener('click', function() {
infowindow.open(marker.get('map'), marker);
selectedUser = secretMessage;
writeSelectedUser();
console.log(selectedUser); //Gives title of selected marker
});
}

Related

Call function for content of infowindow when opening not only on init

I have some objects with markers. These objects have dynamic data and I would like to output them in the infowindow of the marker of the object.
So far this is what I have:
function createRandomObjectWithAMarker() {
var marker;
var aData = "dataToDisplay";
var infowindow = new google.maps.InfoWindow({
content:callThisFunctionWhenOpenWindow(aData)
});
marker.addListener('click', function() {
infowindow.open(map, marker);
});
randomObject = {
/*
someData
*/
marker: marker
};
return randomObject;
}
And I would like that this function to be called when I click the marker to show the return modifiedData as the content of the infoWindow.
function callThisFunctionWhenOpenWindow(aData){
/*
do some stuff on aData
*/
return modifiedData;
}
But actually, this function is called once: only when I init the randomObject with the call of createRandomObjectWithAMarker(). So if I show the infoWindow after some time, when the datas would not be the same as when the script starter, it will still display the same output.
Is there any way to do that? If yes how?
Try something like this?
This way the infowindow (and it's data) is only created when you click the marker
function createRandomObjectWithAMarker() {
var marker;
var aData = "dataToDisplay";
marker.addListener('click', function() {
var infowindow = new google.maps.InfoWindow({
content:callThisFunctionWhenOpenWindow(aData)
});
infowindow.open(map, marker);
});
randomObject = {
/*
someData
*/
marker: marker
};
return randomObject;
}

Update marker in Leaflet

I have a problem with a marker in leaflet. My code is this:
var updateMarker = function(lat, lng) {
if($('.leaflet-marker-icon').length)
marker.setLatLng([lat, lng]);
else
var marker = L.marker([lat, lng]).addTo(map);
return false;
};
var updateMarkerByInputs = function() {
return updateMarker( $('#latInput').val() , $('#lngInput').val());
}
$('#latInput').on('input', updateMarkerByInputs);
$('#lngInput').on('input', updateMarkerByInputs);
map.on('click', function(e) {
$('#latInput').val(e.latlng.lat);
$('#lngInput').val(e.latlng.lng);
updateMarker(e.latlng.lat, e.latlng.lng);
});
As you can see, on the first click will be add a marker and in the next clicks it should be updated. But I get this error at the second click:
TypeError: i is undefined
..."_leaflet_id";return function(i){return i[e]=i[e]||++t,i[e]}}(),invokeEach:funct...
leaflet.js (line 6, col 603)
What do I wrong?
You are defining your marker variable locally in the updateMarker function, so the reference is lost as soon as the function returns.
Define it outside the function:
var marker;
var updateMarker = function(lat, lng) {
if($('.leaflet-marker-icon').length)
marker.setLatLng([lat, lng]);
else
marker = L.marker([lat, lng]).addTo(map);
return false;
};
This way you don't need to check the DOM with jQuery to find out if your marker is defined, you can check directly the marker variable:
var marker;
var updateMarker = function(lat, lng) {
if (marker) {
marker.setLatLng([lat, lng]);
} else {
marker = L.marker([lat, lng]).addTo(map);
}
return false;
};
(to improve readability I would suggest to always use brackets in your if statements.)

AJAX call in an Infowindow: Scope Issue

Or at least I believe it's a scope issue, correct me if I'm wrong.
I have a for loop that generates markers on my map. Each infowindow loads different content using callbacks to an ajax function.
I've simplified this sample to outline the problem.
var xhr = "";
var infowindow = new google.maps.InfoWindow();
var marker, i;
var polylineCoordinates = [new google.maps.LatLng(78.782762, 17.917843),
new google.maps.LatLng(-0.829439, -91.112473),
new google.maps.LatLng(15.066156, -23.621399),
]
function createHttpRequest() {
try {
xhr = new XMLHttpRequest();
return xhr;
}
catch (e)
{
//assume IE6
try {
xhr = new activeXBbject("microsoft.XMLHTTP");
return xhr;
}
catch (e) {
return alert("Unable to create an XMLHttpRequest object");
}
}
}
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(78.782762,17.917843),
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"),
mapOptions);
}
//I recreated the polylineCoordinates array (see above)
//to try and replicate and real array in the script
for (i = 0; i < polylineCoordinates.length; i++) {
marker = new google.maps.Marker({
position: polylineCoordinates[i],
map: map
});
google.maps.event.addListener(marker, 'click', (function (marker, i) {
return function () {
infowindow.setContent("<div id=\"infowindow\">" + getStationInfo(infoWindowDiv) + "</div>");
infowindow.open(map, marker);
}
})(marker, i));
} //End adding markers loop
function infoWindowDiv(stationInfo) {
var add = document.createTextNode(stationInfo);
document.getElementById("infowindow").appendChild(add);
}
function getStationInfo(callback) {
//createHttpRequest() exists globally
var xhr = createHttpRequest();
var url = "stations.php" //edited out the original URL
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
var stationInfo = "This is a Test";
return callback(stationInfo)
} //end readyState
} //end readystatechange
xhr.open("GET", url, true);
xhr.send(null);
} //end getStationInfo
Small Edit: Moved functions outside of the loop
Edit 2: There is nothing wrong with the ajax call, the url was edited for the sake of the sample code. Notice the final output shows "This is a test" in the infowindow which clearly states a successful callback was performed. Moreover, notice there is no responseText or responseXml. The variable being sent back has nothing to do with the url
The callback works fine but for some reason it's topped with the dreadful 'undefined' on top of it.
Console shows nothing.
Output:
undefined
This is a test
What am I doing wrong? How can it be undefined if it works?
What is happening:
you click on the infowindow
getStationInfo(infoWindowDiv) is called, fires off an AJAX request, but returns nothing useful ("undefined", there is no return statement)
The AJAX function will encounter an error (url "Unnecessary at this point" will not cause the onreadystatechange function to fire). But you tell us that isn't a problem.
The script encounters the javascript error Uncaught TypeError: Cannot call method 'appendChild' of null because the div with id infowindow hasn't been attached to the DOM.
Suggest adding an event listener on the infowindow to not attempt to access the div with id="infowindow" until it has been rendered (domready).
Working code:
var xhr = "";
var infowindow = new google.maps.InfoWindow();
var map = null;
var marker, i;
var polylineCoordinates = [new google.maps.LatLng(78.782762, 17.917843),
new google.maps.LatLng(-0.829439, -91.112473),
new google.maps.LatLng(15.066156, -23.621399)
]
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(78.782762,17.917843),
zoom: 10,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map_canvas"),
mapOptions);
for (i = 0; i < polylineCoordinates.length; i++) {
marker = new google.maps.Marker({
position: polylineCoordinates[i],
map: map
});
google.maps.event.addListener(marker, 'click', (function (marker, i) {
return function () {
infowindow.setContent("<div id=\"infowindow\" style=\"height:50px;width:200px;\"></div>");
infowindow.open(map, marker);
google.maps.event.addListenerOnce(infowindow,"domready", function(){
getStationInfo(infoWindowDiv);
});
})(marker, i));
} //End adding markers loop
}
function infoWindowDiv(stationInfo) {
var add = document.createTextNode(stationInfo);
document.getElementById("infowindow").appendChild(add);
}
function getStationInfo(callback) {
var stationInfo = "This is a Test";
callback(stationInfo)
} //end getStationInfo
google.maps.event.addDomListener(window, 'load', initialize);

close other infowindows nicely

Im currently doing this to create markers for my google map.
function createMarker(posn, title, html) {
var marker = new google.maps.Marker({ position: posn, title: title, draggable: false });
marker['infowindow'] = new google.maps.InfoWindow({ content: html });
infoWindows.push(marker['infowindow']);
google.maps.event.addListener(marker, "click", function () {
for (i = 0; i < infoWindows.length; i++) {
infoWindows[i].close();
}
this['infowindow'].open(map, this);
});
return marker;
}
im not happy with the for loop, for closing the markers, i know something similar to this can be done by using one refernce:
if (infowindow) infowindow.close();
the reason I am using code like above is because i am doing something like
markers[myPoint]['infowindow'].open(map, markers[myPoint]); else where, (myPoint is a number).
how can i avoid this for loop to close open infowindows and do it the nice way?
Just store last opened infoWindow in a global variable:
var activeInfoWindow;
function createMarker(posn, title, html) {
var marker = new google.maps.Marker({ position: posn, title: title, draggable: false });
marker['infowindow'] = new google.maps.InfoWindow({ content: html });
infoWindows.push(marker['infowindow']);
google.maps.event.addListener(marker, "click", function () {
if ( activeInfoWindow == this['infowindow'] ) {
return;
}
if ( activeInfoWindow ) {
activeInfoWindow.close();
}
this['infowindow'].open(map, this);
activeInfoWindow = this['infowindow'];
});
return marker;
}
Another way of doing it is only having one InfoWindow and on the marker click event you call the setContent property of the InfoWindow and then the open event with the map and the marker as parameters.
I have found this method better in my application where I have 10,000+ markers on the map.
see: http://code.google.com/apis/maps/documentation/javascript/reference.html#InfoWindow
infoWindow = new google.maps.InfoWindow();
function createMarker(posn, title, html) {
var marker = new google.maps.Marker({ position: posn, title: title, draggable: false });
marker['content'] = html;
google.maps.event.addListener(marker, "click", function () {
infoWindow.setContent(this['content']);
infoWindow.open(map, this);
});
return marker;
}

InfoWindow doesn't want to close with Google Maps Api V3

i can't close the info window of the marker i'm dragging, any idea ?
Thanks for your help
function mapClick(event) {
createLocationMarker(event.latLng);
}
function createLocationMarker(location) {
var clickedLocation = new google.maps.LatLng(location)
var gMarker = new google.maps.Marker({position:location, map:gMap2, draggable: true});
gMap2.setCenter(location);
displayMarkerPosition(gMarker);
google.maps.event.addListener(gMarker, "dragstart", closeMapInfoWindow );
google.maps.event.addListener(gMarker, "dragend", function() { displayMarkerPosition(gMarker); });
}
function closeMapInfoWindow() {infowindow.close(); }
function displayMarkerPosition(gMarker) {
var message = "my message";
var infowindow = new google.maps.InfoWindow(
{ content : message,
});
infowindow.open(gMap2,gMarker);
}
Yes, you define infowindow in a private scope, but access it outside that scope. Add this to the beginning of your script:
var infowindow;
And remove 'var ' from your constructor line:
infowindow = new google.maps.InfoWindow(
The finished code (from your sample) would look like this.
A little more background
When you define a variable with var, it is tied to that scope. If you define it in a function, only that function and other functions defined in it can access the variable. The only other way to pass it around is as a parameter in a function.
Update I would do this to facilitate multiple infowindows. Notice I have reverted to the original var declaration to keep it scoped to that function. I then return the reference to the object to use it later:
function mapClick(event) {
createLocationMarker(event.latLng);
}
function createLocationMarker(location) {
var clickedLocation = new google.maps.LatLng(location)
var gMarker = new google.maps.Marker({position:location, map:gMap2, draggable: true});
gMap2.setCenter(location);
// Store reference to info window
var info = displayMarkerPosition(gMarker);
google.maps.event.addListener(gMarker, "dragstart", function(){ info.close } );
google.maps.event.addListener(gMarker, "dragend", function() { displayMarkerPosition(gMarker); });
}
function displayMarkerPosition(gMarker) {
var message = "my message";
var infowindow = new google.maps.InfoWindow(
{ content : message }
);
infowindow.open(gMap2,gMarker);
return infowindow; // Return the reference to the infowindow
}

Categories

Resources