forked from carderne/leaflet-gsheets
-
Notifications
You must be signed in to change notification settings - Fork 0
/
leaflet-gsheets.js
181 lines (156 loc) · 5.95 KB
/
leaflet-gsheets.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/*
* Script to display two tables from Google Sheets as point and polygon layers using Leaflet
* The Sheets are then imported using Tabletop.js and overwrite the initially laded layers
*/
// init() is called as soon as the page loads
function init() {
// PASTE YOUR URLs HERE
// these URLs come from Google Sheets 'shareable link' form
// the first is the polygon layer and the second the points
var polyURL = 'https://docs.google.com/spreadsheets/d/1tafKIXBNgo8bAOYrJglVi1WQs09VqIccXEOnSHX5m1s/edit?usp=sharing';
var pointsURL = 'https://docs.google.com/spreadsheets/d/1KwQtPhOmh7cuLNCLFdRwOZBY0T6FHoe0Et5192eznSU/edit?usp=sharing';
Tabletop.init( { key: polyURL,
callback: addPolygons,
simpleSheet: true } );
Tabletop.init( { key: pointsURL,
callback: addPoints,
simpleSheet: true } ); // simpleSheet assumes there is only one table and automatically sends its data
}
window.addEventListener('DOMContentLoaded', init);
// Create a new Leaflet map centered on the continental US
var map = L.map('map').setView([40, -100], 4);
// This is the Carto Positron basemap
var basemap = L.tileLayer('https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}{r}.png', {
attribution: '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a> © <a href="http://cartodb.com/attributions">CartoDB</a>',
subdomains: 'abcd',
maxZoom: 19
});
basemap.addTo(map);
var sidebar = L.control.sidebar({
container: 'sidebar',
closeButton: true,
position: 'right'
}).addTo(map);
panelID = 'my-info-panel'
var panelContent = {
id: panelID,
tab: '<i class="fa fa-bars active"></i>',
pane: '<p id="sidebar-content"></p>',
title: '<h2 id="sidebar-title">No state selected</h2>',
};
sidebar.addPanel(panelContent);
map.on('click', function (feature, layer) {
sidebar.close(panelID);
});
// These are declared outisde the functions so that the functions can check if they already exist
var polygonLayer;
var pointGroupLayer;
// The form of data must be a JSON representation of a table as returned by Tabletop.js
// addPolygons first checks if the map layer has already been assigned, and if so, deletes it and makes a fresh one
// The assumption is that the locally stored JSONs will load before Tabletop.js can pull the external data from Google Sheets
function addPolygons(data) {
if (polygonLayer != null) {
// If the layer exists, remove it and continue to make a new one with data
polygonLayer.remove()
}
// Need to convert the Tabletop.js JSON into a GeoJSON
// Start with an empty GeoJSON of type FeatureCollection
// All the rows will be inserted into a single GeoJSON
var geojsonStates = {
'type': 'FeatureCollection',
'features': []
};
for (var row in data) {
// The Sheets data has a column 'include' that specifies if that row should be mapped
if (data[row].include == 'y') {
var coords = JSON.parse(data[row].geometry);
geojsonStates.features.push({
'type': 'Feature',
'geometry': {
'type': 'MultiPolygon',
'coordinates': coords
},
'properties': {
'name': data[row].name,
'summary': data[row].summary,
'state': data[row].state,
'local': data[row].local,
}
});
}
}
// The polygons are styled slightly differently on mouse hovers
var polygonStyle = {'color': '#2ca25f', 'fillColor': '#99d8c9', 'weight': 1.5};
var polygonHoverStyle = {'color': 'green', 'fillColor': '#2ca25f', 'weight': 3};
polygonLayer = L.geoJSON(geojsonStates, {
onEachFeature: function (feature, layer) {
layer.on({
mouseout: function(e) {
e.target.setStyle(polygonStyle);
},
mouseover: function(e) {
e.target.setStyle(polygonHoverStyle);
},
click: function(e) {
// This zooms the map to the clicked polygon
// map.fitBounds(e.target.getBounds());
// if this isn't added, then map.click is also fired!
L.DomEvent.stopPropagation(e);
document.getElementById('sidebar-title').innerHTML = e.target.feature.properties.name;
document.getElementById('sidebar-content').innerHTML = e.target.feature.properties.summary;
sidebar.open(panelID);
}
});
},
style: polygonStyle
}).addTo(map);
}
// addPoints is a bit simpler, as no GeoJSON is needed for the points
// It does the same check to overwrite the existing points layer once the Google Sheets data comes along
function addPoints(data) {
if (pointGroupLayer != null) {
pointGroupLayer.remove();
}
pointGroupLayer = L.layerGroup().addTo(map);
for(var row = 0; row < data.length; row++) {
var marker = L.marker([data[row].lat, data[row].long]).addTo(pointGroupLayer);
// UNCOMMENT THIS LINE TO USE POPUPS
//marker.bindPopup('<h2>' + data[row].location + '</h2>There's a ' + data[row].level + ' ' + data[row].category + ' here');
// COMMENT THE NEXT 14 LINES TO DISABLE SIDEBAR FOR THE MARKERS
marker.feature = {
properties: {
location: data[row].location,
category: data[row].category
}
};
marker.on({
click: function(e) {
L.DomEvent.stopPropagation(e);
document.getElementById('sidebar-title').innerHTML = e.target.feature.properties.location;
document.getElementById('sidebar-content').innerHTML = e.target.feature.properties.category;
sidebar.open(panelID);
}
});
// AwesomeMarkers is used to create fancier icons
var icon = L.AwesomeMarkers.icon({
icon: 'info-sign',
iconColor: 'white',
markerColor: getColor(data[row].category),
prefix: 'glyphicon',
extraClasses: 'fa-rotate-0'
});
marker.setIcon(icon);
}
}
// Returns different colors depending on the string passed
// Used for the points layer
function getColor(type) {
switch (type) {
case 'Coffee Shop':
return 'green';
case 'Restaurant':
return 'blue';
default:
return 'green';
}
}