Sidebar on Google Maps reacting to map - google-maps

I have a Google Map (API v3) populated with markers that indicate data from a database. I would like to add a sidebar that checks which markers are currently visible on the map and adds them to a sidebar, adjusting whenever map is moved. Is something like that possible?

I have a GitHub project which loads a KML file containing placemarks, puts them in the sidebar, and uses the Google Maps API to dim / brighten the locations when changing the map. The relevant portion is this snippet:
google.maps.event.addListener(mapInstance, 'bounds_changed', function() {
currentBounds = mapInstance.getBounds();
for (i = 0; i < parser.docs[0].placemarks.length; i++) {
var myLi = $("#p" + i);
if (currentBounds.contains(parser.docs[0].placemarks[i].marker.getPosition())) {
myLi.css("color","#000000");
} else {
myLi.css("color","#CCCCCC");
}
}
});
The abbreviated version of that is:
google.maps.event.addListener(mapInstance, 'bounds_changed', function() {
currentBounds = mapInstance.getBounds();
/*
Loop over Google map placemarks and check the placemark by doing:
if (currentBounds.contains(currentPlacemark.getPosition())) {
// Change CSS to make sidebar entry visible
} else {
// Change CSS to make sidebar entry invisible
}
*/
});
In my examples, mapInstance is an instance of google.maps.Map, and currentPlacemark is an instance of one of your google.maps.Marker objects.

Related

clearing a kml from google maps

I have a google map and I am wanting to show this KML file, I can load the KML but I haven't yet figured out how to clear it off the map. I load the KML on the map when the user click a check box, but whe they uncheck the box the KML wont go away. Here is the code that I am using to load the KML.
var isShowData = false;
//showEMSz(null);
var tileEMSz;
function showEMSz(obj) {
isShowData = !isShowData;
if (isShowData) {
tileEMSz = new google.maps.KmlLayer({
url: '/ELTSCAD.kml'
});
tileEMSz.setMap(map);
}
else
{
// remove Option
tileEMSz = null;
}
}
set the map-property of the layer to null:
if(tileEMSz){tileEMSz.setMap(null);}

Google Maps KMZ file not rendering in IE8 and IE7

I have a web app with a map in it. I've added a nice little custom map control to turn on and off different layers on the map. Currently there are only two layers, and it all works nice and fine in most browsers.
Except for IE8+7. None of the layers are showing on the map when turned on. As far as I can tell the map is loading the kmz/kml files (when preserveViewport is set to false, the map moves to the right location) but they're just not appearing. One layer contains polylines, and the other contains markers. The code I use is below:
function someFunction() {
//code to initialise map etc goes here...
var layers = [];
//Create 1st layer
var exchangeslayer = new google.maps.KmlLayer('http://link.to.file/exchanges.kmz'
suppressInfoWindows: true,
preserveViewport: true
});
layers.push({name: "Exchanges", layer: exchangeslayer});
//Code to create second layer
var nyclayer = new google.maps.KmlLayer('http://www.nyc.gov/html/dot/downloads/misc/cityracks.kml'
suppressInfoWindows: true,
preserveViewport: false
});
layers.push({name: "NY City Tracks", layer: nyclayer});
addCustomLayerControls(layers);
}
function addCustomLayerControls(layers) {
//there is code here that would generate the divs for the custom map control
var container; //container is a div element created via javascript
for (var i = 0; i < layers.length; i++) {
this.addLayerLabelToContainer(layers[i], container);
}
//some more code
}
function addLayerLabelToContainer(layer, container) {
var map; //Assume I get a reference to the map
//some code here to make pretty labels for the map controls...
var layerLabel; // layerLabel is a div element created via javascript
google.maps.event.addDomListener(layerLabel, 'click', function() {
if(layer.layer.map == null) {
layer.layer.setMap(map);
} else {
layer.layer.setMap(null);
}
});
}
So as it turns out my problem related to CSS. One of my stylesheets was applying max-width: 100% to all img tags. This was playing havok with the map markers/polylines.
Its obvious now that I see it, but when you think the problem is to do with the javascript its not so obvious. As such, I'll leave this answer here for anyone else who makes the same mistake as me.
If you modify addLayerLabelToContainer() like this then it works in IE as expected. Verified it loads KMZ correctly in IE 8 and 9.
function addLayerLabelToContainer(layer, container) {
// var map; //Assume I get a reference to the map
//some code here to make pretty labels for the map controls...
var layerLabel; // layerLabel is a div element created via javascript
if(layer.layer.map == null) {
layer.layer.setMap(map);
} else {
layer.layer.setMap(null);
}
}
Don't need to invoke addDomListener(). Also note the API syntax:
addDomListener(instance:Object, eventName:string, handler:Function)
Also minor fix of syntax errors in someFunction as follows:
function someFunction() {
// var map; //assume map is initialised, I've just removed that code
var layers = [];
// see https://developers.google.com/maps/documentation/javascript/layers
//Create 1st layer
var exchangeslayer = new google.maps.KmlLayer(
'http://kml-samples.googlecode.com/svn/trunk/kml/kmz/simple/big.kmz',
{ suppressInfoWindows: true, preserveViewport: true
});
layers.push( {name: "Exchanges", layer: exchangeslayer} );
// ...
addCustomLayerControls(layers);
}

How to make the infowindow appear depending upon the space it already have and not move the map

I am displaying few locations in google maps. I refresh these locations if a user zoom in/out or drags the map. Now the issue is if i click on the marker of a location then the info window opens up and drags the map if it doesn't have any space to show. This dragging causes my locations to be refreshed and hence my marker vanishes.
I tried disableAutoPan: true but then the info window is not seen only. Is there any way that the info window auto adjust itself. is there any way to sort this out?
Use a global variable to indicate when the refresh should be ignored, for example:
// Global var
var ignoreRefresh = false;
google.maps.addListener(marker,'click', function(){
ignoreRefresh = true;
infoWindow.setContent('Hello');
infoWindow.open(map,marker);
})
function refresh(){
if (ignoreRefresh) {
ignoreRefresh = false;
return;
}
//...
//do your normal refresh of data
//...
}

Open Google Maps InfoWindow based on certain criteria

I want to open a Google Maps InfoWindow based on whether or not one of my buildings is throwing a building alarm. The buildings I have the markers on all have alarm states (on or off), and if they are in alarm state, I am changing the color of the marker to yellow or red, depending on the severity of the alarm. When the alarms are "red" alarms, the marker is animated with the google.maps.Animation.BOUNCE effect.
The bounce effect is sometimes not enough to garner attention (we leave this screen open on a wall, and the data in the $(this).children(".alarm-count") div below changes dynamically due to another script we have running on the site in the background.
I already know how to change the markers based on the alarm state, can I also open an InfoWindow within the same condition? I have tried this:
google.maps.event.addListener(map,'idle',(function(marker,i){
return function(){
infowindow.setContent(
'<div class="infowindow-inner">'+
'<a href="'+bldgGfx[i]+'" onclick="window.open('+bldgGfx[i]+');return false;" target="_blank" title="'+bldgName[i]+' ('+bldgAddr[i]+')">'+
'<h2>'+bldgName[i]+'</h2>'+
'<h4>'+bldgAddr[i]+'</h4>'+
'<p>'+mainMeter[i]+' kW</p>'+
'<p>'+alarmCount[i]+' Alarms</p>'+
'</div>'
);infowindow.open(map,marker);
}
})(marker,i));
but it doesn't seem to be working.
The long and short of it is I need to evaluate one value per marker in my page, and open (or not open) the InfoWindow for each building based on that value.
Here is my code:
$(".building").each(function(i){
bldgNo[i] = $(this).children(".bldg-no").html().slice(1);
bldgName[i] = $(this).children(".bldg-name").html();
bldgAddr[i] = $(this).children(".bldg-address").html();
bldgGfx[i] = $(this).children(".bldg-graphic").html();
mainMeter[i] = $(this).children(".main-meter").html();
alarmCount[i] = $(this).children(".alarm-count").html();
latitude[i] = $(this).children(".latitude").html();
longitude[i] = $(this).children(".longitude").html();
if (alarmCount[i]!="N/A"){alarmCount[i]=alarmCount[i].slice(0,-3);}
if (alarmCount[i]>"0" && alarmCount[i]!="N/A"){
marker=new google.maps.Marker({position:new google.maps.LatLng(latitude[i],longitude[i]),map:map,shadow:shadow,icon:redIcon,title:bldgName[i]+" \n"+bldgAddr[i],optimized:false});marker.setAnimation(google.maps.Animation.BOUNCE);
////
//// THE COMMAND TO OPEN THE INFOWINDOW WILL GO HERE, RIGHT?
////
}
else if ($(this).hasClass("new")||(mainMeter[i]=="N/A")||(!isNumber(mainMeter[i]))) {
marker=new google.maps.Marker({position:new google.maps.LatLng(latitude[i],longitude[i]),map:map,shadow:shadow,icon:yellowIcon,title:bldgName[i]+" \n"+bldgAddr[i],optimized:false});marker.setAnimation(google.maps.Animation.NULL);}
else {
marker=new google.maps.Marker({position:new google.maps.LatLng(latitude[i],longitude[i]),map:map,shadow:shadow,icon:greenIcon,title:bldgName[i]+" \n"+bldgAddr[i],optimized:false});marker.setAnimation(google.maps.Animation.NULL);}
markersArray.push(marker);
google.maps.event.addListener(marker,'click',(function(marker,i){
return function(){
infowindow.setContent(
'<div class="infowindow-inner">'+
'<a href="'+bldgGfx[i]+'" onclick="window.open('+bldgGfx[i]+');return false;" target="_blank" title="'+bldgName[i]+' ('+bldgAddr[i]+')">'+
'<h2>'+bldgName[i]+'</h2>'+
'<h4>'+bldgAddr[i]+'</h4>'+
'<p>'+mainMeter[i]+' kW</p>'+
'<p>'+alarmCount[i]+' Alarms</p>'+
'</div>'
);infowindow.open(map,marker);
}
})(marker,i));
i++;
});
Since many buildings may be "on alert", you'll want a InfoWindow array (in my demo it's a global because I use an inline call); however, the screen may get cluttered very easily. I wrote a Z-Index routine to bring a clicked InfoWindow to front. You might also want to consider MarkerWithLabel or InfoBubble because in my opinion they look better than the vanilla InfoWindow.
Please see the demo
demo side-by-side with code
I'll only copy some of the parts that are very different.
var infowindows = [];
function initialize() {
map = new google.maps.Map(document.getElementById("map_canvas"), mapOptions);
// MANY LINES SKIPPED
// ...
$(this).children(".longitude").html();
infowindows[i] = new google.maps.InfoWindow({
content:'<div class="infowindow"
onclick="bringToFront('+i+')">'+bldgName[i]+'</div>'});
if (alarmCount[i]>0 && alarmCount[i]!="N/A"){
// marker=new google.maps.Marker({position:new google.maps.LatLng(latitude[i],longitude[i]),map:map,shadow:shadow,icon:redIcon,title:bldgName[i]+" \n"+bldgAddr[i],optimized:false});marker.setAnimation(google.maps.Animation.BOUNCE);
marker = new google.maps.Marker({position:new google.maps.LatLng(latitude[i],longitude[i]),map:map,title:"red"});
infowindows[i].open(map,marker);
//// THE COMMAND TO OPEN THE INFOWINDOW WILL GO HERE, RIGHT?
}
...
google.maps.event.addListener(marker,'click',(function(marker,i){
return function(){
infowindows[i].open(map,marker);
bringToFront(i);
}
})(marker,i));
});
}
function bringToFront(windowIndex) {
console.log(windowIndex);
for (var i = infowindows.length-1, n = 0; i >= n; i--) {
infowindows[i].setZIndex(0);
}
infowindows[windowIndex].setZIndex(1);
}

How to get markers after calling drive directions in Google Maps API?

I just started working using Google Maps API yesterday, and trying to set up drive directions to my map. My problem is: when I call the function load,
// [...]
gdir = new GDirections(map, directionsPanel);
// [...]
gdir.load("from: " + fromAddress + " to: " + toAddress);
it returns a map whose markers are not draggable. So, I need to make them draggable in order to recalculate the directions, but I can't get the markers objects.
Someone knows how can I do it?
You need to add a handler on the GDirections object for the addoverlay event:
GEvent.addListener(gdir, "addoverlay", onGDirectionsAddOverlay);
When your onGDirectionsAddOverlay handler is called you can iterate through the new markers and replace them with draggable copies:
for (var i = 0; i <= gdir.getNumRoutes(); i++)
{
var originalMarker = gdir.getMarker(i);
latLngs[i] = originalMarker.getLatLng();
icons[i] = originalMarker.getIcon();
newMarkers[i] = new GMarker(latLngs[i], { icon: icons[i], draggable: true, title: 'Kan flyttes' });
map.addOverlay(newMarkers[i]);
// add stuff to your newMarkers[i] drag end event...
// ...
//Bind 'click' event to original markers 'click' event
copyClick(newMarkers[i], originalMarker);
// Now we can remove the original marker safely
map.removeOverlay(originalMarker);
}
You can find a working example of this here (source).