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

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
}

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;
}

Google Map AddListener issue

I have written following code.. which fires Add Listener event on Place_change but i want to fire that event on page load.. which is copied from google and i have made some changes.
function _initMap(latlng){
// google map
$map = $(".lwizard-step1-map");
_latlng = latlng || new google.maps.LatLng(41.3833333,2.1833333);
if (!_STEP1_LOCATION_MAP) {
_STEP1_LOCATION_MAP = new google.maps.Map($map[0],{
center: _latlng,
zoom:11,
mapTypeId:google.maps.MapTypeId.ROADMAP,
streetViewControl:false,
scrollwheel:false
});
} else {
_STEP1_LOCATION_MAP.setCenter(_latlng);
}
if (!_STEP1_LOCATION_MARKER) {
_STEP1_LOCATION_MARKER = new google.maps.Marker({
position: _latlng,
map: _STEP1_LOCATION_MAP,
draggable: true
});
google.maps.event.addListener(_STEP1_LOCATION_MARKER, "dragend", function(event) {
var lat = event.latLng.lat();
var lng = event.latLng.lng();
$("#lwizard-step1-location-autocomplete").val('');
STEP1_PLACE.latLng = [lat,lng];
STEP1_PLACE.address = null;
$.ajax({
url: 'http://maps.googleapis.com/maps/api/geocode/json?latlng='+lat+','+lng+'&sensor=false',
success: function(response){
if ((response) && (response.results) && (response.results.length)){
$(".lwizard-step1-chosen-address").parent().show();
var $address = $(".lwizard-step1-chosen-address");
$address.text(response.results[0].formatted_address);
$("#lwizard-step1-adjust-onmap").data("location", response.results[0].geometry.location);
STEP1_PLACE.address = nc.utils.convertGoogleAddressComponents(response.results[0].address_components);
}
}
})
});
} else {
_STEP1_LOCATION_MARKER.setPosition(_latlng);
}
}
// autocomplete
$input = $("#lwizard-step1-location-autocomplete");
_STEP1_LOCATION_GA = new google.maps.places.Autocomplete($input[0],{ types: [] });
google.maps.event.addListener(_STEP1_LOCATION_GA, 'place_changed', function () {
var place = _STEP1_LOCATION_GA.getPlace();
console.log(place)
var $where = $(".lwizard-step1-chosen-address");
var found = ((place) && (place.formatted_address) && (place.geometry) && (place.id));
if (place && found) {
$("#lwizard-step1-adjust-onmap").data("location", place.geometry.location);
STEP1_PLACE.address = nc.utils.convertGoogleAddressComponents(place.address_components);
STEP1_PLACE.latLng = [place.geometry.location.lat(),place.geometry.location.lng()];
STEP1_PLACE.location = place.geometry.location;
$where.parent().show();
$where.text(place.formatted_address);
$("#lwizard-step1-right-1").show();
$("#lwizard-step1-right-2").hide();
_initMap(place.geometry.location);
} else {
$where.parent().hide();
$("#lwizard-step1-right-1").show();
$("#lwizard-step1-right-2").hide();
_initMap();
}
});
I have one textbox named lwizard-step1-location-autocomplete which shows value from session named SessionLocation on page load.
but i also want to show the map on page load of the location specified in textbox.
But the problem is the addlistener fires only on textbox change means Place_changed event.
pls. Give some suggestions or new method for it.
You can just call change event on load and than it will fired.
$('#lwizard-step1-location-autocomplete').trigger("change");
Or with js;
document.getElementById('lwizard-step1-location-autocomplete').fireEvent("onchange");

Store Google Maps Marker Info

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
});
}

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);

How can I add multiple functions to one file?

I'm trying to create a mash Up of sorts... I want the functions to be in one file but when I add my Ajax functions (half way down ) nothing displays.
Also I want to display them with jQuery, and the top function(Google maps with marker and info) all works a treat until I add the bottom functions.
Should I add them in the (function () {} ) like Google has and what is the (); on the end of the googlemap function?
and when I call my functions in my code how will I call the ajax for the preview as the window.onload has been called in the Google one.
I know that I can use the $.ready function(){} but do I just put the function names in the .ready function { }
I am unsure how to add all the functions in one file and make them work. Basically
this is the code:
(function() {
//define global variables
var map, geocoder, marker, infowindow;
window.onload = function() {
//creating the map
var options = {
zoom: 5,
center: new google.maps.LatLng(53.383, -1.483),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById('map'), options);
//code for catching the form submit event goes here
//Getting the reference to the HTML form
var form = document.getElementById('addressForm');
//Catching the forms submit event
form.onsubmit = function () {
//getting the address from the text input
var address = document.getElementById('address').value;
//Making the geocode call
getAddress(address);
//Preventing the form from doing a page submit
return false;
}
}
//Function Stub
function getAddress(address) {
//Check to see if we already have a geocode object.
//If not we create one
if(!geocoder) {
geocoder = new google.maps.Geocoder();
}
//Creating the geoCoderRequest Object
var geocoderRequest = {
address: address
}
//Making the geocode request
geocoder.geocode(geocoderRequest, function (results, status) {
//Check if status is ok beofre proceeding
if (status == google.maps.GeocoderStatus.OK){
//Center the map on the returned location
map.setCenter(results[0].geometry.location);
//Check to see if already a Marker there
if (!marker){
//Create a new marker and add it to the map
marker = new google.maps.Marker({
map: map
});
}
//Setting position of the Marker to returned location
marker.setPosition(results[0].geometry.location);
//Check to see if we've already an info window
if(!infowindow) {
//Creating a new info window
infowindow = new google.maps.InfoWindow();
}
//Creating the content of the info window to the Address
//and the returned position
var content = '<strong>' + results[0].formatted_address + '</strong><br />';
content += 'Lat: ' + results[0].geometry.location.lat() + '<br />';
content += 'Lng: ' + results[0].geometry.location.lng();
//Adding the content to the info window
infowindow.setContent(content);
//Opening the infoWindow
infowindow.open(map, marker);
}
});
}
})();
// beginning of new function
var xhr = false;
var xPos, yPos;
function prev(){
var link = document.getElementByTagName("a").onmouseover = showPreview;
}
function showPreview(evt) {
if (evt) {
var url = evt.target;
}
else{
evt = window.event;
var url = evt.srcElement;
}
xPos = evt.clientX;
yPos = evt.clientY;
if (window.XMLHttpRequest) {
xhr = new XMLHttpRequest();
}
else {
if (window.ActiveXObject) {
try {
xhr = new ActiveXObject("Microsoft.XMLHTTP");
}
catch (e) { }
}
}
if (xhr) {
xhr.onreadystatechange = showContents;
xhr.open("GET", url, true);
xhr.send(null);
}
else {
alert("Sorry, but I couldn't create an XMLHttpRequest");
}
return false;
}
function showContents() {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
var outMsg = xhr.responseText;
}
else {
var outMsg = "There was a problem with the request " + xhr.status;
}
var preview = document.getElementById('preview');
preview.innerHTML = outMsg;
preview.style.top = parseInt(yPos)+2 + "px";
preview.style.left = parseInt(xPos)+2 + "px";
preview.style.visibility = "visible";
preview.onmouseout = function(){
document.getElementById('preview').style.visibility = "hidden";
}
}
It depends on why you're adding functions. but here is a simple formula. If you want you're functions to be called on document ready only and want them to be called once when the document is loaded. Then you add them as "anonymous functions"
EXAMPLE:
$(function () {
//you code
...............
// you can call your named functions also here.
//like
somefunction();
});
But if you expect them to be called later on as well, when the document has already been loaded. Then add the "named functions"
EXAMPLE:
function somename()
{
............
}
In both cases you can have them in one file and regarding the (); at the end of the function, it is a way of calling anonymous functions immediately in JavaScript, like document.ready in jQuery.

Categories

Resources