so I'm making a website using leaflet with dozens of base maps. I want to incorporate information about each map that is only visible if the user wants it. To do this, I would like to make an overlay map with popups, but I want the popups to change depending on the base map selected by the user.
How would I go about doing this?
Thank You So Much
You need to either use a plugin that keeps track of the base maps for you (like active layers) or you need to do it yourself.
If you are using the Leaflet layers control, you can subscribe to the basemapchange event to do this easily.
You need two things: active base layer management (easy) and dynamic popups (not too hard)
To wit:
First, here is the event handler to track active base layer when it changes.
map.on("baselayerchange",
function(e) {
// e.name has the layer name
// e.layer has the layer reference
map.activeBaseLayer = e.layer;
console.log("base map changed to " + e.name);
});
Because using L.marker().bindPopup() creates the popup content right there and does not support callbacks, you must manually create the popups in response to click event by calling map.openPopup() with your dynamic html (dynamic because it uses a variable: the active basemap name)
marker.on("click", function(e) {
var html = "Current base layer: <br/><b>" + map.activeBaseLayer.options.name + "<b>";
map.openPopup(html,
e.latlng, {
offset: L.point(1, -24)
});
});
Here is a working example on JS fiddle: http://jsfiddle.net/4caaznsc/
Working code snippet also below (relies on Leaflet CDN):
// Create the map
var map = L.map('map').setView([39.5, -0.5], 5);
// Set up the OSM layer
var baseLayer1 = L.tileLayer(
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
name: "Base layer 1"
});
var baseLayer2 = L.tileLayer(
'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 18,
name: "Base layer 2"
});
// add some markers
function createMarker(lat, lng) {
var marker = L.marker([lat, lng]);
marker.on("click", function(e) {
var html = "Current base layer: <br/><b>" + map.activeBaseLayer.options.name + "<b>";
map.openPopup(html,
e.latlng, {
offset: L.point(1, -24)
});
});
return marker;
}
var markers = [createMarker(36.9, -2.45), createMarker(36.9, -2.659), createMarker(36.83711, -2.464459)];
// create group to hold markers, it will be added as an overlay
var overlay = L.featureGroup(markers);
// show overlay by default
overlay.addTo(map);
// show features
map.fitBounds(overlay.getBounds(), {
maxZoom: 11
});
// make up our own property for activeBaseLayer, we will keep track of this when it changes
map.activeBaseLayer = baseLayer1;
baseLayer1.addTo(map);
// create basemaps and overlays collections for the layers control
var baseMaps = {};
baseMaps[baseLayer1.options.name] = baseLayer1;
baseMaps[baseLayer2.options.name] = baseLayer2;
var overlays = {
"Overlay": overlay
};
// create layers control
var layersControl = L.control.layers(baseMaps, overlays).addTo(map);
// update active base layer when changed
map.on("baselayerchange",
function(e) {
// e.name has the name, but it may be handy to have layer reference
map.activeBaseLayer = e.layer;
map.closePopup(); // any open popups will no longer be correct; take easy way out and hide 'em
});
#map {
height: 400px;
}
<script src="https://npmcdn.com/leaflet#0.7.7/dist/leaflet.js"></script>
<link href="https://npmcdn.com/leaflet#0.7.7/dist/leaflet.css" rel="stylesheet"/>
<div id="map"></div>
Related
I have a leaflet map that displays the area around where the person currently is (currentlocation), and typically I want the map to 'follow' the person as they travel. I am using a mymap.panTo command for this. This much is working fine. It updates the map every 5 seconds and pans to centre on the current person perfectly.
Occasionally though the person may want to scroll the map further afield to see something. This works ... until the 5 second counter kicks in and pans the map back to their location again. Annoying.
I have seen on various map apps a button/toggle on the map that the person can click on to stop the map following them. In fact usually it turns off if the map is shifted manually and then they'd click the toggle to pan back to their current location. Please see the image attached of a google map highlighting what they call a "Show Your Location" button. That's what I want.
But how is this done? Is this some sort of custom leaflet control that I cannot find? Or is it done fully programmatically somehow (and any sample code snippets?).
any help appreciated.
Below is the bit of code I use to display my map.
var streetmap = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
attribution: 'Map data © OpenStreetMap contributors, Imagery © Mapbox',
id: 'mapbox/streets-v11',
accessToken: 'token code here' //redacted token
}),
satellite = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
attribution: 'Map data © OpenStreetMap contributors, Imagery © Mapbox',
id: 'mapbox/satellite-v9',
accessToken: 'token code here' //redacted token });
var baseMaps = {
"Streetmap": streetmap,
"Satellite": satellite
};
var mymap = L.map('mapid', {
center: [latitude,longitude],
zoom: 17,
layers: [streetmap] //default layer
});
var personicon = L.icon({
iconUrl: '/js/personicon.png',
iconSize: [20, 20]
});
var playerLoc = new L.marker([latitude,longitude], {icon: personicon}) // set player location marker as a declared variable but don't put it on the map yet
elsewhere I have code to start the map (once variables are populated) and then keep updating location
const interval = setInterval(function() {
if (is_running) { // we need to know that there is data populated before showing or updating the map with it
if (!map_started) { //start the map only once
L.control.layers(baseMaps).addTo(mymap); //show choice of layer views
L.control.scale().addTo(mymap); //show scale bar
console.log("Create current player marker:",MYID,latitude,longitude);
playerLoc.setLatLng([latitude,longitude]).addTo(mymap).bindPopup(MYID); //update current player marker, and now show it on the map
map_started=true;
}; //start the map only once
updatemap(); // for current player location and circle colour.
}; //update only if is_running
mymap.invalidateSize(); //reset map view
}, 5000); // update map every 5 seconds
function updatemap() { // Update the current player location on map
playerLoc.setLatLng([latitude,longitude]); //update current player marker instead of creating new ones
mymap.panTo([latitude,longitude]); // pan the map to follow the player (TODO: Can we toggle pan mode?)
}; // end updatemap
this code all works fine. the mymap.panTo([latitude,longitude]); line is what needs to be wrapped in a condition "If pan is allowed, then do mymap.panTo([latitude,longitude]);" But surely there's a standard leaflet control or approach to this? I see this thing all the time elsewhere
You need to listen on the movestart event, to detect if the user moves the map. But this event is also triggered from the panTo function, so you need a flag to indicate if movestart is fired by interval or by the user.
var currentAutoMove = false; // needed to check in `movestart` event-listener if moved from interval or by user
var pauseAutoMove = false; // if true -> Stops moving map
var latitude,longitude;
setInterval(()=>{
latitude = playerLoc.getLatLng().lat + 0.001;
longitude = playerLoc.getLatLng().lng + 0.001;
updatemap();
}, 1000)
function updatemap() { // Update the current player location on map
playerLoc.setLatLng([latitude,longitude]);
if(!pauseAutoMove){
currentAutoMove = true; // Set flag, that currently map is moved by interval
map.panTo([latitude,longitude]);
currentAutoMove = false; // Remove flag, that currently map is moved by interval
}
}
map.on('movestart',(e)=>{
console.log(e, currentAutoMove);
if(!currentAutoMove){ // Check if map is moved by interval or by user
pauseAutoMove = true; // set flag, to stop moving map
}
})
// Start auto move again, if button clicked
L.DomEvent.on(document.getElementById('toPos'),'click',(e)=>{
pauseAutoMove = false; // reset flag, to stop moving map -> start moving map
map.panTo([latitude,longitude]);
})
To create a Control / button to start auto move you only need to search in Google there are many examples, else you can use L.easybutton.
Demo: https://jsfiddle.net/falkedesign/8akw3ust/
With much thanks to Falke Design I have used the suggestions in the answer above. My code now looks like this for the button I wanted:
var panbtn = L.easyButton({
states: [{
stateName: 'pauseAutoMove',
icon: 'fa-sign-in fa-lg',
title: 'Centre display at current Player', //Tooltip
onClick: function(btn, map) {
console.log("AutoMoveButton pressed");
panbtn.state('AutoMove');
mymap.panTo([latitude,longitude]);
}
}, {
stateName: 'AutoMove',
icon: 'fa-crosshairs fa-lg',
}]
}).addTo(mymap);
mymap.on("zoomstart", function (e) { currentAutoMove = true }); //Set flag, that currently map is moved by a zoom command
mymap.on("zoomend", function (e) { currentAutoMove = false }); //Remove flag again
mymap.on('movestart',(e)=>{ //Check if map is being moved
if(!currentAutoMove){ //ignore if it was a natural PlayerLoc Auto update
pauseAutoMove = true; //set flag to stop Auto moving map
console.log("Map moved");
panbtn.state('pauseAutoMove'); //change button style to remove crosshairs
}
});
and inside the updatemap function the code:
if(!pauseAutoMove){ //pan the map to follow the player unless it is on pause
currentAutoMove = true; //Set flag, that currently map is moved by a normal PlayerLoc Auto update
mymap.panTo([latitude,longitude]);
currentAutoMove = false; //Remove flag again
};
much thanks.
I am using leaflet js with openstreetmap in my project.
I have multiple circlemarkers at same place in my map.
I want to store some Id in that circlemarkers so that I can Identify that which data should be refereed when circlemarker is clicked.
My circlemarker is
var myMarker = L.circleMarker(myPoint, { title: 'unselected', radius: 20 });
myMarker.addTo(map);
Here I am using title for other purpose that's why I cant use it.
Can any one tell me some way to do this.
It sounds like you would like to add new functionality (functions, properties, etc) to an existing class. It would make sense to use object-oriented principals for this. For this purpose, I'd recommend you extending the CircleMarker class to add those properties.
customCircleMarker = L.CircleMarker.extend({
options: {
someCustomProperty: 'Custom data!',
anotherCustomProperty: 'More data!'
}
});
Now when you create your circle marker, create an instance of your extended object instead.
var myMarker = new customCircleMarker(myPoint, {
title: 'unselected',
radius: 20,
someCustomProperty: 'Adding custom data to this marker!',
anotherCustomProperty: 'More custom data to this marker!'
});
myMarker.addTo(map);
Now you can get the properties like you would any other option from the marker. This is just a simple case of extending, and you can do more as needed, such as adding other properties or functions to the object.
JSFiddle example: JSFiddle
With the current version of leaflet (0.8-dev) you can just set your custom properties on the marker object itself, without having to create a custom marker class...
function map() {
return L.map('leaflet-canvas',
{
maxZoom: 10,
minZoom: 0,
crs: L.CRS.Simple
});
}
var map = map().setView([0, 0], 10).on('click', onMapClick);
function onMapClick(e) {
var marker = L.circleMarker(e.latlng, {draggable:true});
marker.myCustomID = Math.floor((Math.random() * 100) + 1);
marker.on('click', onMarkerClick);
map.addLayer(marker);
// 'click' the new marker to show the ID when marker created
marker.fireEvent('click');
}
function onMarkerClick(e) {
alert(e.target.myCustomID);
}
Here is a TypeScript friendly way:
DataMarker.ts
import * as L from 'leaflet';
export class DataMarker extends L.Marker {
data: any;
constructor(latLng: L.LatLngExpression, data: any, options?: L.MarkerOptions) {
super(latLng, options);
this.setData(data);
}
getData() {
return this.data;
}
setData(data: any) {
this.data = data;
}
}
SomeOtherFile.ts
import { DataMarker } from './DataMarker';
const marker = new DataMarker([ lat, lng ], anyData, markerOptions);
--
Note 1: I decided not to merge the marker options with the data property
Note 2: Adjust the type of data if you need something more specific
marker is basically javascript object rite.
Below snippet solve my case simply.
var marker = new L.marker([13.0102, 80.2157]).addTo(mymap).on('mouseover', onClick);
marker.key = "marker-1";
var marker2 =new L.marker([13.0101, 80.2157]).addTo(mymap).on('mouseover', onClick);
marker2.key = "marker-2";
function onClick(e) {
alert(this.key); // i can expect my keys here
}
just to complete the picture , to create a handler which will respond to a mouse click on a marker and provide access the new options
function onMarkerClick(e) {
console.log("You clicked the marker " + e.target.options.someCustomProperty);
console.log("You clicked the marker " + e.target.options.anotherCustomProperty);
}
marker.on('click', onMarkerClick);
Try this Uniquely identifying Leaflet Markers , its working for me.
//Handle marker click
var onMarkerClick = function(e){
alert("You clicked on marker with customId: " +this.options.myCustomId);
}
//Create marker with custom attribute
var marker = L.marker([36.83711,-2.464459], {myCustomId: "abc123"});
marker.on('click', onMarkerClick);
I would recommend to structure in your data for your markers in the standard GeoJSON format, which makes it compatible for direct saving as shapefile, etc.
var myMarker = L.circleMarker(myPoint, { title: 'unselected', radius: 20 });
myMarker.properties.id = your_Id;
myMarker.addTo(map);
To retrieve the stored information and do things with it or pass it on to other parts of your program, showing a sample onclick function:
myMarker.on('click',markerOnClick);
function markerOnClick(e) {
my_ID = e.layer.properties.id;
console.log(my_ID, e.latlng);
// do whatever you want with my_ID
}
It took me a while to find out the e.layer.properties way to access the clicked marker's properties, so hope this helps someone. Most other examples only focused on yielding the lat-long of the marker, e.latlng.
Note that you can use this same code even with a whole layer / group of markers. The function will work on each individual marker.
I have a easy solution. options property in each circleMarker is the good place to store custom value.
var myMarker = L.circleMarker(myPoint, { custom_id: 'gisman', radius: 20 });
myMarker.addTo(map);
You can easily retrive the value in options.
function markerOnClick(e) {
var id = e.options.custom_id;
}
I'm currently trying to learn the Bing Maps API and currently trying to build a map with multiple pins that can be hovered to reveal a info window with that pins data. At the moment I'm experiencing a few problems. If anyone could help with the following points that would be great:
When I mouseleave a pin the info window doesn't get removed?
How can I use the data I retrieve in the addPin() to populate the
required info window?
In createInfoBox() I want to hide any active info window when the
map gets moved but this seems to get triggered even if the map isn't
moved?
If there are any improvements i can make please let me know
jsfiddle: http://jsfiddle.net/kyllle/vpepD/23/ and JS below
JS
var dealerMap = {
createInfoBox: function(infobox) {
var instance = this,
pushpin = infobox;
// Now create infowindows
var NewWindow = new Microsoft.Maps.Infobox(pushpin.getLocation(), {
title: 'title',
offset: new Microsoft.Maps.Point(-3, pushpin.getHeight() - 5),
zIndex: 999,
visible: true
});
//Display infowindow
instance.displayInfoBox(NewWindow, pushpin);
//Hide infowindow if map is moved - currently gets run without moving map
//Microsoft.Maps.Events.addHandler(dealerMap.myMap, 'viewchange', instance.hideInfoBox(NewWindow));
},
displayInfoBox: function(infobox, pin) {
var instance = this;
//Show updated infowindow
dealerMap.myMap.entities.push(infobox);
//Mouse out handler to remove window
Microsoft.Maps.Events.addHandler(pin, 'mouseleave', function() {
instance.hideInfoBox(NewWindow);
});
},
hideInfoBox: function(infobox) {
var instance = this;
console.log('this was called');
dealerMap.myMap.entities.remove(infobox);
},
addPin: function() {
var instance = this;
//make $.ajax json call
var response = data.dummy;
//on success make each pin with returned data
for (var i = 0, len = response.length; i < len; i++) {
var responseItem = response[i],
pinLocation = new Microsoft.Maps.Location(responseItem.lat, responseItem.long);
//Create new pin
var NewPin = new Microsoft.Maps.Pushpin(pinLocation, {
icon: 'http://www.kylehouston.com/testing/sportscar_' + responseItem.id +'.png',
width: 32,
height: 37
});
//Push new pin onto map
this.myMap.entities.push(NewPin);
//Event handlers to show and hide requested infowindow information
Microsoft.Maps.Events.addHandler(NewPin, 'mouseover', function(e) {
console.log(this);
dealerMap.createInfoBox(e.target);
});
}
},
init: function() {
var instance = this;
var mapOptions = {
credentials: "AvGoKWSuMorGQb5h4UyyatCBGmGzSZe7-dWQMzXt4qqz6mV_WCC5m-paxvQhednd",
center: new Microsoft.Maps.Location(37.09024, -95.712891),
zoom: 5,
enableClickableLogo: false,
enableSearchLogo: false
}
dealerMap.myMap = new Microsoft.Maps.Map(document.getElementById('mapDiv'), mapOptions);
//now add some pins
instance.addPin();
}
}
dealerMap.init();
});
I highly recommend only showing one infobox at a time on the map. Showing multiple infoboxes can crowd the map and make for a bad user experience. It also uses up a lot more resources. A better approach is to create a single infobox and reuse it for each pushpin as you want to display content. I wrote a blog post that shows how to do this here: http://rbrundritt.wordpress.com/2011/10/13/multiple-pushpins-and-infoboxes-in-bing-maps-v7/
I'm working on functionality to take snapshot of google map with polylines and open popup window on polyline click on google map.
The snapshot of google map with polylines is working
but it will not able to take snapshot open popup window on polyline.
polyline are showing on sanpshot picture but info window are not showing .
Here is code to take snapshot.
This code is to initialize the code control on javascript onload :
var snapShotControlOptions = { hidden: true };
snapShotControlOptions.buttonLabelHtml="<snap id='snap' style='display:none' >snap</span>"
snapShotControl = new SnapShotControl(snapShotControlOptions);
map.addControl(snapShotControl);
here is the method take snap to take the sanp shot of google map .
function takeSnap() {
//static map size
var sizeStr = "640x640";
var imgSize = "";
if (sizeStr != "") {
var sizeArray = sizeStr.split("x");
imgSize = new GSize(sizeArray[0], sizeArray[1]);
}
snapShotControl.setMapSize(imgSize);
var format = "jpg";
snapShotControl.setFormat(format);
var url = snapShotControl.getImage();
// document.getElementById("snapshot_canvas").src = url;
SaveImage(url);
//
}
//this will add polyline overlay to draw line on google map with different color of polyline on google map .
var polyline = directionsArray[num].getPolyline();
polyline.setStrokeStyle({ color: streetColor, weight: 3, opacity: 0.7 });
polyline.ssColor=streetColor;
map.addOverlay(polyline);
///this code will open the pop info window on polyline those polyline created on google map
and problem is their these pop window not included on sanpshot when i take sanpshot of google map.
var MousePoint = "";
var marker;
GEvent.addListener(map, "mousemove", function (point) {
MousePoint = new GLatLng(point.lat(), point.lng());
});
GEvent.addListener(polyline, "click", function () {
map.openInfoWindowHtml(MousePoint, headMarkerHtml);
});
GEvent.addListener(polyline, "mouseout", function () {
// map.closeInfoWindow();
});
can you please tell who i pass popup window in polyline overlay .
i have use javascript file snapshotcontrol.js to take the snapshot.
from the snapshotcontrol source
This library makes it easy to generate an image "snapshot" of your
interactive map, using the Google Static Maps API.
Static maps doesn't support info windows or anything like adding custom text to the map
https://developers.google.com/maps/documentation/staticmaps/index
You could draw the map on a canvas within the browser then
draw the info window on top of that using this http://html2canvas.hertzen.com/
and then download the canvas content
Short version of my question:
How do I integrate a pair of Google Maps fusion tables (polygons and markers) with GroundOverlays from a KML file? Everything clickable.
Background:
I am working on an interactive history mapping project that uses 2 layers of fusion tables (one layer is polygons, the other is location markers).
I also want to overlay old maps via GroundOverlay -- which is not presently possible with fusion tables -- and so I have been experimenting with GroundOverlay in a KML file.
I've complicated it by adding listeners on both the pages to control click boxes.
I have two webpages:
1. the fusion tables and
2. the KML groundoverlays,
both working fine.
What I want to do is integrate them into a single page. I am not a programmer and don't understand JS well enough to make this happen.
The scripting used was all adapted from examples found online.
Here is my first working page:
http://wendysmithtoronto.com/mapping/townofyork-fusiontables2.html
You'll find a link to the second page there.
Your help would be greatly appreciated.
Thank you.
Wendy
Update:
Here's my effort to merge my two sets of data:
http://wendysmithtoronto.com/mapping/townofyork-merged.html
I tried to do this by adding bits of script from the kmlmaps page into the fusiontables page, but clearly I didn't put things in the right place. Or am missing bits of punctuation (or mixing up different types of scripting, or?)
The map appears, with the polygons and the markers both properly appearing. But now (1) the fusion table icons aren't clickable, and (2) the history maps don't appear. However, the fusion table checkboxes (in blue table) DO work.
I don't understand JS well enough to figure it out.
The two sets of controls from the two pages are both here (in the blue and grey boxes, just above the map). Each set of controls (listeners & click boxes) worked fine in its own wepage but now only the fusion tables controls work.
Eric, thanks for having a look at this! (I just now found your reply. I've been watching for a reply notification but wasn't checking the right place.)
Cheers,
Wendy
Your html file had significant errors in the javascript portions. You really should study up on same basic javascript and in particular using JS with the GMap API.
You created 2 global map objects. You did not encapsulate all your map and layer creations within you initialize function(). All map and layer creation must be done within the initialize (on body load) function. You must set globals outside your initialize function, e.g. the map, all the layers, etc. Finally you were failing to call layer.setMap(map) on 2 of your KML layers.
Despite all this I fixed your file, really just re-arranging things. This is just the section I had to fix. Moved everything into the initialize()
function showbuildings(buildingcheck) {
if (buildingcheck.checked == true)
{
campusmap.setMap(map);
} else {
campusmap.setMap(null);
}
}
function showphilpotts(philpottscheck) {
if (philpottscheck.checked == true)
{
philpotts.setMap(map);
} else {
philpotts.setMap(null);
}
}
function showbeartrail(beartrailcheck) {
if (beartrailcheck.checked == true)
{
beartrail.setMap(map);
} else {
beartrail.setMap(null);
}
}
var infoWindow = new google.maps.InfoWindow();
function openIW(FTevent) {
// infoWindow.setContent(FTevent.infoWindowHtml);
// infoWindow.setPosition(FTevent.latLng);
infoWindow.setOptions(
{
content: FTevent.infoWindowHtml,
position: FTevent.latLng,
pixelOffset: FTevent.pixelOffset
});
infoWindow.open(map);
}
// Globals
//Begin map parameters
var map;
var layer_2;
var layer_1;
var tableid_1 = 2920040; // polygons
var tableid_2 = 3189980; // houses
var zoom = 12;
var center = new google.maps.LatLng(43.652417455515476, -79.37926607055226);
var campusmap;
var philpotts;
var beartrail;
function initialize() {
map = new google.maps.Map(document.getElementById('map_canvas'), {
center: center,
zoom: zoom,
mapTypeId: google.maps.MapTypeId.ROADMAP
});
//End map parameters
campusmap = new google.maps.KmlLayer('http://wendysmithtoronto.com/mapping/1851mapshoreline.kml', {preserveViewport:true, suppressInfoWindows:true});
campusmap.setMap(map);
google.maps.event.addListener(campusmap, 'click', function(kmlEvent) {
document.getElementById('sidebarinfo').innerHTML = kmlEvent.featureData.description;
});
philpotts = new google.maps.KmlLayer('http://wendysmithtoronto.com/mapping/1818maplieutphilpottsd.kml', {preserveViewport:true, suppressInfoWindows:true});
google.maps.event.addListener(philpotts, 'click', function(kmlEvent) {
document.getElementById('sidebarinfo').innerHTML = kmlEvent.featureData.description;
});
philpotts.setMap(map);
beartrail = new google.maps.KmlLayer('http://wendysmithtoronto.com/mapping/1842map-jamescaneb.kml', {preserveViewport:true, suppressInfoWindows:true});
google.maps.event.addListener(beartrail, 'click', function(kmlEvent) {
document.getElementById('sidebarinfo').innerHTML = kmlEvent.featureData.description;
});
beartrail.setMap(map);
layer_2 = new google.maps.FusionTablesLayer({
suppressInfoWindows:true,
query: {
select: 'Location',
from: '3189980'
},
styles: [
{where: "'style' = 14", markerOptions:{ iconName:"star"}},
{where: "'style' = 13", markerOptions:{ iconName:"wht_pushpin"}},
{where: "'style' = 11", markerOptions:{iconName:"red_blank"}}, //town houses
{where: "'style' = 12", markerOptions:{ iconName:"orange_blank"}}, //country homes
{where: "'style' = 15", markerOptions:{ iconName:"target"}},
]});
layer_1 = new google.maps.FusionTablesLayer({
suppressInfoWindows:true,
query: {
select: 'Location',
from: '2920040'
}}),
google.maps.event.addListener(layer_1, "click", openIW);
google.maps.event.addListener(layer_2, "click", openIW);
google.maps.event.addListener(map, "click", function() { infoWindow.close();});
layer_1.setMap(map);
layer_2.setMap(map);
} // end initialize