Loading animation in Google maps infowindow - javascript

I have developed this http://weathermap.cloudcontrolled.com/ from where you can click on a place and get the current weather details in it. Everything is working properly but its getting small delay after click on a place to show weather. For that I would like to show a small loading animation inside the infowindow and after the weather data available it will show the weather in the same infowindow. How to do this. (this is pure html/js site, you can view source code by pressing ctrl+u)

Yes. Get an animated icon from http://www.ajaxload.info/, call it ajaxicon.gif
Change your map click event to :
google.maps.event.addListener(map, 'click', function(event) {
//call function to create marker
if (marker) {
marker.setMap(null);
marker = null;
}
// why do you recreate the marker over and over ??
marker = createMarker(event.latLng, 'name', '<img src="ajaxicon.gif">');
getWeather(event.latLng.lat(),event.latLng.lng(),function (data) {
infowindow.setContent("<b>"+data.list[0].name+"</b><br>"+data.list[0].weather[0].description+"<br><center><img src=http://www.openweathermap.com/img/w/"+data.list[0].weather[0].icon+".png></center>");
});
});
create the marker, place animated ajax-icon in the infoWindow through your createMarker function
on success / callback, replace infowindow content with actual weather content

You could also try the following
google.maps.event.addListener('click', showLoading);
function showLoading(event) {
var contentString = '<img src="images/loading.gif">';
infoWindow.setContent(contentString);
infoWindow.setPosition(event.latLng);
getWeather(event.latLng.lat(),event.latLng.lng(),function (data) {
contentString = "<b>"+data.list[0].name+"</b><br>"+data.list[0].weather[0].description+"<br><center><img src=http://www.openweathermap.com/img/w/"+data.list[0].weather[0].icon+".png></center>"
infowindow.setContent(contentString);
});
infoWindow.open(map);
};

Related

Map not adding click event handlers to markers

The code below will add markers to my map. But the add Listener event never gets added to each marker.
var mapDiv = document.getElementById("google-map");
var infowindow = new google.maps.InfoWindow({
content: 'test'
});
var map = new google.maps.Map(mapDiv);
map.setCenter(new GLatLng(53.635784, 6.943359));
map.setZoom(5);
for (var i = 0; i < data.length; i++) {
var dataMarker = data[i];
var marker = new GLatLng(dataMarker.Latitude, dataMarker.Longitude);
map.addOverlay(new google.maps.Marker(marker, {
title: dataMarker.Name,
html: dataMarker.HtmlAttributes[0]
}));
google.maps.event.addListener(marker, 'click', function () {
infoWindow.setContent(this.html);
infoWindow.open(map, this);
});
}
What am I doing wrong?
Oh and I am using Maps v2.
You did not add any listener to marker.
var marker = new GLatLng(dataMarker.Latitude, dataMarker.Longitude);
marker is not a google.maps.Marker , it's a google.maps.LatLng , which will not respond to mouse-events, because it's not an UI-element, it's just a javascript-object
You created event listeners which are most probably connected with last marker.
You have to link info window with marker in separate function. Last part of your code should be written as:
addEventListener(marker, infoWindow, map);
}
function addEventListener(marker, infoWindow, map) {
google.maps.event.addListener(marker, 'click', function () {
infoWindow.setContent(marker.html);
infoWindow.open(map, marker);
});
}
See also An array of infoWindow in Google maps api and link with explanation about closures.
It looks like you have a mix of v2 and v3 code in that snippet, and so the whole thing is unlikely to work.
For example, you're using new google.maps.Infowindow (v3) in the same place as GLatLng.
My suggestion would be to change the bootstrap on the page to v3, and delete any references to v2 objects (like GLatLng). Make sure you're loading the API like this:
<script src="//maps.googleapis.com/maps/api/js?…"></script>

Gmaps API v3 -> infoWindow Content not showing

I am using Google Maps API v3 on my website and am trying to display markers from a markersArray.
Here's the relevant code:
var map;
var markersArray = [];
var infowindow;
var marker;
Then I am adding the markers in a loop to the array, calling the following function
function addMarker(location, name) {
marker = new google.maps.Marker({
position: location,
map: map,
company: name,
title: name
});
markersArray.push(marker);
}
I am then trying to display the markers, which works like a charm, using this function:
function showOverlays() {
if (markersArray) {
for (var i in markersArray) {
markersArray[i].setMap(map);
google.maps.event.addListener(markersArray[i], 'click', function () {
infowindow.setContent('<div style="height:300px; color:black">' + this.title + '</div>');
infowindow.open(map, this);
});
}
}
}
Now comes my problem: The content of the infoWindows is not showing up. It opens up, but nothing is being displayed...
If I put a 300px high div in it, the infoWindow actually resizes properly.... but no content is being displayed.
I've searched the web up and down and tried fiddling with it, but to no avail.
Has anybody experienced this and might give me a hint as to how to resolve this?
Thanks in advance!
Chris
I just found the error!
I've had the parent div (the DIV that the map canvas is in) styled with CSS... and set the z-index to 11. Apparently that prevented the content of the infowindow to be on top...
Hope that helps some people who might have done the same "mistake" :)
Thanks to kevmc for trying to help
I'm thinking that the marker object doesn't have a title attribute, you need to retrieve it using getTitle():
function showOverlays() {
if (markersArray) {
for (var i in markersArray) {
markersArray[i].setMap(map);
google.maps.event.addListener(markersArray[i], 'click', function () {
infowindow.setContent('<div style="height:300px; color:black">' + this.getTitle() + '</div>');
infowindow.open(map, this);
});
}
}
}

How to get some information in google maps without click event on marker and show this in a div, other than infoWindow

Hi I am showing some markers on my google map and on click of the marker, I am calling the click event and showing some info about that place to the right side(area other than Map and not as an infoWindow). Now this event gets fired on click, and by default when page loads my div remains blank, How can I have the div the basic information being shown up once the map loads up. I need to show the information that corresponds to the marker that is the center point of the map, and later when the users click the marker icons the info should change and correspond to the particular marker being clicked
I have tried something but it doesn't work:
function loadMap() {
var myLatlng = new google.maps.LatLng(40.46998, -3.68705);
var myOptions = {
zoom: 3,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map"), myOptions);
var places = [];
places.push(new google.maps.LatLng(51.43581, -0.51744));
places.push(new google.maps.LatLng(48.87187, 2.31764));
places.push(new google.maps.LatLng(45.45979, 9.19681));
var infowindow;
for(var i = 0; i<places.length; i++) {
var marker= new google.maps.Marker({
position: places[i],
map: map,
title: 'Place' + i
});
(function (i,marker){
google.maps.event.addListener(marker, 'click' , function() {
infowindow.setContent('PLace Number' + i)
infowindow.open(i, marker)
});
});(i, marker);
}
}
$("document").ready(function () {
loadMap();
});
UPDATE EDITED
Basically I need something like Layer KML features
But the info should come on the right hand side by default for the first time. Later on when the marker is clicked, the info should change. I am also not adamant that I need this info in a kml file(xml is fine with me as well). I can just have a marker and info should popup on click and for the first time be default as well depending on the location of the user.
Bottom Line: I need the info to appear on click of a marker and by default when the page loads the info should appear corresponding to the center point of the map. which means users coming from different locations will see different info's corresponding to their location from where they are coming.(I am centering the map based on users location)
You can use the addDomListener event of the google maps api. Something like this:
<script>
function initialize() {
// Map initialization
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
<body>
<div id="map_canvas"></div>
</body>
Although the above code is Maps Javascript API code, the addDomListener() method binds to the window object of the browser and allows the API to communicate with objects outside of the API's normal domain.
further reading
Actually the basic Idea is that you need to read an XMl and parse the data and and show this in a seperate div on right side., This div you can create dynamically when you load the map e-g:
$("#body").append("<div class='newdiv'></div>")
From the google Docs in the section about InfoWindow:
Note that if you call open() without passing a marker, the InfoWindow
will use the position specified upon construction through the
InfoWindow options object.
So in your code, why don't you simply init your infoWindow and call the open() method? I am not particularly familiar with the api, but how about:
var infowindow = new google.maps.InfoWindow({
content: 'your initial text'
});
infowindow.open();
Or if you need the marker for special purposes on the infowindow, init an marker with the center position and use that in the infowindow.open(your_initial_pos) call.
You can use jQuery to .triger() a click event on the first marker on document.ready:
$(marker).trigger('click');
This will run the code you have already written and make it so when the page loads your div will be populated with data from whatever element you trigger the click on.
When you bind to document.ready you don't need encapsulate document in quotes:
$(document).ready(function () {...});
Or you could use the short-hand if you're into that sort of thing:
$(function () {...});
UPDATE
You can place the trigger function call after your for loop where you are setting up the markers:
for(var i = 0; i<places.length; i++) {
var marker= new google.maps.Marker({
position: places[i],
map: map,
title: 'Place' + i
});
(function (i,marker){
google.maps.event.addListener(marker, 'click' , function() {
infowindow.setContent('PLace Number' + i)
infowindow.open(i, marker)
});
});(i, marker);
//only run on the first marker
if (i === 0) {
//trigger a click event to show the first info-window
$(marker).trigger('click');
}
}
You can fire a tilesloaded event on the map object. Check out the Map reference for events
tilesloaded waits until the map tiles are actually loaded before firing. Using your code, you could do something like this:
function loadMap() {
var myLatlng = new google.maps.LatLng(40.46998, -3.68705);
var myOptions = {
zoom: 3,
center: myLatlng,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById("map"), myOptions);
google.maps.event.addListener(map, 'tilesloaded', function() {
doSomething();
});

Google Maps API v3: Close infowindow when DOM element is clicked

I'm playing around with Google maps for the first time, so I looked at a nice tutorial over at CSS Tricks: http://css-tricks.com/google-maps-slider/ I like working with jQuery better than pure JS, and this tutorial makes a nice way to click on a place in a list to display the marker in the map.
I liked it that way, but I need to add infowindows to the marker. Which I did, but when I click on a place on the list and the map pans away, the infowindow stays open! I think it's because I need to attach the infowindow.close() to the event of clicking on a "#locations li".
Here's my code, which runs on document.ready:
$(function() {
var chicago = new google.maps.LatLng(41.924832, -87.697456),
pointToMoveTo,
first = true,
curMarker = new google.maps.Marker({}),
$el;
var myOptions = {
zoom: 10,
center: chicago,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map($("#map_canvas")[0], myOptions);
$("#locations li").click(function() {
$el = $(this);
if (!$el.hasClass("hover")) {
$("#locations li").removeClass("hover");
$el.addClass("hover");
if (!first) {
// Clear current marker
curMarker.setMap();
// Set zoom back to Chicago level
// map.setZoom(10);
}
// Move (pan) map to new location
function move(){
pointToMoveTo = new google.maps.LatLng($el.attr("data-geo-lat"), $el.attr("data-geo-long"));
map.panTo(pointToMoveTo);
}
move();
// Add new marker
curMarker = new google.maps.Marker({
position: pointToMoveTo,
map: map
});
// Infowindow: contenido
var contentString = '<p>'+$el.find("h3").html()+'</p>';
contentString += 'hola' ;
var infowindow = new google.maps.InfoWindow(
{
size: new google.maps.Size(150,50),
content: contentString
});
// On click, zoom map
google.maps.event.addListener(curMarker, 'click', function() {
//map.setZoom(14);
infowindow.open(map,curMarker);
});
It looks like you're creating a new InfoWindow for each marker. Quoting from the Google Maps API Docs:
If you only want one info window to display at a time (as is the behavior on Google Maps), you need only create one info window, which you can reassign to different locations or markers upon map events (such as user clicks).
Therefore, you may simply want to create one InfoWindow object just after you initialize your map, and then handle the click event handler as follows:
google.maps.event.addListener(curMarker, 'click', function() {
infowindow.setContent(contentString);
infowindow.open(map, curMarker);
});
Then the InfoWindow should automatically close when you click on a new marker without having to call the close() method.

Have just one InfoWindow open in Google Maps API v3

I need to have only one InfoWindow open on my Google Map. I need to close all other InfoWindows before I open a new one.
Can someone show me how to do this?
You need to create just one InfoWindow object, keep a reference to it, and reuse if for all the markers. Quoting from the Google Maps API Docs:
If you only want one info window to display at a time (as is the behavior on Google Maps), you need only create one info window, which you can reassign to different locations or markers upon map events (such as user clicks).
Therefore, you may simply want to create the InfoWindow object just after you initialize your map, and then handle the click event handlers of your markers as follows. Let's say you have a marker called someMarker:
google.maps.event.addListener(someMarker, 'click', function() {
infowindow.setContent('Hello World');
infowindow.open(map, this);
});
Then the InfoWindow should automatically close when you click on a new marker without having to call the close() method.
Create your infowindow out of the scope so that you can share it.
Here is a simple example:
var markers = [AnArrayOfMarkers];
var infowindow = new google.maps.InfoWindow();
for (var i = 0, marker; marker = markers[i]; i++) {
google.maps.event.addListener(marker, 'click', function(e) {
infowindow.setContent('Marker position: ' + this.getPosition());
infowindow.open(map, this);
});
}
I had the same problem but the best answer didn't solve it completely, what I had to do in my for statement was using the this relating to my current marker. Maybe this helps someone.
for(var i = 0; i < markers.length; i++){
name = markers[i].getAttribute("name");
address = markers[i].getAttribute("address");
point = new google.maps.LatLng(parseFloat(markers[i].getAttribute("lat")), parseFloat(markers[i].getAttribute("lng")));
contentString = '<div style="font-family: Lucida Grande, Arial, sans-serif;>'+'<div><b>'+ name +'</b></div>'+'<div>'+ address +'</div>';
marker = new google.maps.Marker({
map: map,
position: point,
title: name+" "+address,
buborek: contentString
});
google.maps.event.addListener(marker, 'click', function(){
infowindow.setContent(this.buborek);
infowindow.open(map,this);
});
marker.setMap(map);
}
a tad late, but I managed to have only one infowindow open by maken infowindow a global variable.
var infowindow = new google.maps.InfoWindow({});
then inside the listner
infowindow.close();
infowindow = new google.maps.InfoWindow({
content: '<h1>'+arrondissement+'</h1>'+ gemeentesFiltered
});
infowindow.open(map, this);
Declare a globar var selectedInfoWindow; and use it to hold the opened info window:
var infoWindow = new google.maps.InfoWindow({
content: content
});
// Open the infowindow on marker click
google.maps.event.addListener(marker, "click", function() {
//Check if there some info window selected and if is opened then close it
if (selectedInfoWindow != null && selectedInfoWindow.getMap() != null) {
selectedInfoWindow.close();
//If the clicked window is the selected window, deselect it and return
if (selectedInfoWindow == infoWindow) {
selectedInfoWindow = null;
return;
}
}
//If arrive here, that mean you should open the new info window
//because is different from the selected
selectedInfoWindow = infoWindow;
selectedInfoWindow.open(map, marker);
});
You need to keep track of your previous InfoWindow object and call the close method on it when you handle the click event on a new marker.
N.B It is not necessary to call close on the shared info window object, calling open with a different marker will automatically close the original. See Daniel's answer for details.
Basically you want one function that keeps reference to one new InfoBox() => delegate the onclick event.
While creating your markers (in a loop) use bindInfoBox(xhr, map, marker);
// #param(project): xhr : data for infoBox template
// #param(map): object : google.maps.map
// #param(marker): object : google.maps.marker
bindInfoBox: (function () {
var options = $.extend({}, cfg.infoBoxOptions, { pixelOffset: new google.maps.Size(-450, -30) }),
infoBox = new window.InfoBox(options);
return function (project, map, marker) {
var tpl = renderTemplate(project, cfg.infoBoxTpl); // similar to Mustache, Handlebars
google.maps.event.addListener(marker, 'click', function () {
infoBox.setContent(tpl);
infoBox.open(map, marker);
});
};
}())
var infoBox is assigned asynchronously and kept in memory. Every time you call bindInfoBox() the return function will be called instead. Also handy to pass the infoBoxOptions only once!
In my example I've had to add an extra param to the map as my initialization is delayed by tab events.
InfoBoxOptions
Here is a solution that doesn't need to create only one infoWindow to reuse it. You can continue creating many infoWindows, the only thing you need is to build a closeAllInfoWindows function, and call it before open a new infowindow.
So, keeping your code, you just need to:
Create a global array to store all the infoWindows
var infoWindows = [];
Store each new infoWindow in the array, just after the infoWindow = new...
infoWindows.push(infoWindow);
Create the closeAllInfoWindows function
function closeAllInfoWindows() {
for (var i=0;i<infoWindows.length;i++) {
infoWindows[i].close();
}
}
In your code, call to closeAllInfoWindows() just before open the infoWindow.
Regards,
One smart easy way to do this with jQuery is the following :
google.maps.event.addListener(marker, 'click', function (e) {
jQuery(".gm-ui-hover-effect").click();
marker.info.open(map, this);
});
It will click on all the closing buttons amongst your tooltips.
My approach allows you to toggle the infoWindow as well.
Global space
var infoWindow = new google.maps.InfoWindow();
infoWindow.setContent(contentString);
var lastInfoWindow;
Local space
marker.addListener("click", (e) => {
if (lastInfoWindow === e.domEvent.srcElement) {
infoWindow.close();
lastInfoWindow = null;
} else {
infoWindow.open({
anchor: marker,
map,
shouldFocus: false,
});
lastInfoWindow = e.domEvent.srcElement;
}
});
Solved it this way:
function window(content){
google.maps.event.addListener(marker,'click', (function(){
infowindow.close();
infowindow = new google.maps.InfoWindow({
content: content
});
infowindow.open(map, this);
}))
}
window(contentHtml);
Google Maps allows you to only have one info window open. So if you open a new window, then the other one closes automatically.

Categories