Skip to content

Instantly share code, notes, and snippets.

@boazsender
Last active August 24, 2022 16:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save boazsender/9cbb8a600e05574b09c767873f01c755 to your computer and use it in GitHub Desktop.
Save boazsender/9cbb8a600e05574b09c767873f01c755 to your computer and use it in GitHub Desktop.
An example of a webpage rendering information from a google form as both a list and a map. Demo sheet is here: https://docs.google.com/spreadsheets/d/1l6FZYfeMx5nSz3diE60PeFrvJmJtC3_9W5BvhNhd7fA/edit?resourcekey#gid=64148024
<!DOCTYPE html>
<html lang="en">
<head>
<title> google form backed list and map</title>
<meta name="description" content="a google form backed map.">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<meta name="keywords" content="map">
<!-- included the leaflet CSS -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.8.0/dist/leaflet.css"/>
<!-- include the various leaflet and esri scripts you-->
<script src="https://unpkg.com/leaflet@1.8.0/dist/leaflet.js"></script>
<script src="https://unpkg.com/esri-leaflet@3.0.8/dist/esri-leaflet.js"></script>
<script src="https://unpkg.com/@esri/arcgis-rest-request@4.0.0/dist/bundled/request.umd.js"></script>
<script src="https://unpkg.com/@esri/arcgis-rest-geocoding@4.0.0/dist/bundled/geocoding.umd.js"></script>
<script type='text/javascript'>
// Wrapp everything in a DOMContentLoaded callback so we don't start trying
// to run code before the document is ready
window.addEventListener('DOMContentLoaded', ()=> {
// Setup your Esri ReST API Key, and google Sheet ID
const config = {
esrikey: "your Esri api key", // get one from https://developers.arcgis.com/documentation/mapping-apis-and-services/security/api-keys/
googlesheet: "1l6FZYfeMx5nSz3diE60PeFrvJmJtC3_9W5BvhNhd7fA/Responses" // the scheme is "sheetID/tabName" get this from the URL of your google sheet. You can use this demo to get started.
};
// Initialize the map
var map = L.map('map').setView([40, -95], 2);
// Add the open streetmap tile set. This is the base example from
// https://leafletjs.com/examples/mobile/
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
maxZoom: 19,
attribution: '&copy; OpenStreetMap'
}).addTo(map);
// Create an authentication object for the esri ReST API
// You'll need to register your own and pass it into the fromKey method
const authentication = arcgisRest.ApiKeyManager.fromKey(config.esrikey);
// Fetch the google spreadhseet data from the elk.sh json proxy
// more info here https://benborgers.com/posts/google-sheets-json
// you'll need to pass in your own sheet ID and sheet name
// use the full doc ID + / + tab name. Make sure the doc is also
// published to the web. Here's a template for you to get started with:
// https://docs.google.com/spreadsheets/d/e/2PACX-1vQp2Mq32XQ3Y_WhVYmTR765HkotbVIZi1_Ld-gugxQ8gcmp9k3k-t1xKkIYdDVYYQiC5uoWxdww9gBZ/pubhtml
fetch("https://opensheet.elk.sh/" + config.googlesheet).then((res) => res.json())
.then((data) => {
// Itererate over the data
data.forEach((row) => {
// Check to see if there is a "TRUE" string in the "Approved" column
if (row['Approved'] === "TRUE") {
// Create an off DOM figure element
let fig = document.createElement('figure')
// Fill that figure elemement with the content of the sheet using a
// template. You can adjust as needed.
fig.innerHTML = `
<h2>${row['Title']} </h2>
<sub>${row['Date']}</sub>
<p>${row['Description']} <a href="${row['Call to action link']}"> ${row['Call to action']}</a></p>
`;
// Select the parent element to add this row of the sheet to and add it.
document.querySelectorAll('#list')[0].prepend(fig);
// Look up the latitude and longitude of the city and state from
// the sheet. You can adjust as needed.
arcgisRest.geocode({
params: {
address: row['City'] + " " + row['State'],
maxLocations: 1
},
outFields: ["PlaceName", "Place_addr", "Phone"],
authentication
}).then((places) => {
// When you get the data back, plot it on a map and add the
// figure we made above to the popup.
L.marker([places.candidates[0].location.y, places.candidates[0].location.x]).addTo(map)
.bindPopup(fig);
});
}
});
});
// Grab references to the list and map container elements
let listEl = document.querySelectorAll("#list")[0];
let mapEl = document.querySelectorAll("#mapcontainer")[0];
// Grab a reference to the element we'll use to switch between
// list and map, note that we start with a hidden (display: none)
// map container, and a visible (display:block) list.
document.querySelectorAll("#uichanger")[0].onpointerdown = (e) => {
// use the text in the element we're using to chang UIs as the source
// of truth for which UI is currently shown.
let state = e.target.innerHTML;
// If it's a list, change over to map.
if (state === "list") {
e.target.innerHTML = 'map';
mapEl.style.display = 'none';
listEl.style.display = 'block';
}
// If its a map, change over to list.
if( state==="map" ) {
e.target.innerHTML = 'list';
listEl.style.display = 'none';
mapEl.style.display = 'block';
map.invalidateSize()
}
}
});
</script>
<style>
html, body {
height: 100%;
width: 100vw;
padding: 0px;
margin: 0px;
}
#uichanger {
text-decoration: underline;
color: blue;
cursor: pointer;
}
section, header, footer {
width: 400px;
margin: 0 auto;
padding: 0px;
}
p, footer, header {
line-height: 1.15;
font-size: 16px;
}
p {
margin-top: 6px;
margin-bottom: 15px;
}
section .leaflet-popup-content p {
font-size: 12px;
}
header {
height: 145px;
padding-top: 40px;
}
footer {
padding-top: 30px;
height: 20px;
font-size: 12px;
text-align: center;
}
footer nav {
font-size: 16px;
margin-bottom: 15px;
}
figure {
margin: 0px;
}
section#mapcontainer {
padding: 0;
}
#mapcontainer, #map {
width: 100%;
}
#map {
height: 100%;
}
#mapcontainer, #list {
height: 60%;
width: 400px;
overflow: scroll;
}
#mapcontainer {
display: none;
}
@media (max-width: 600px) {
header, footer {
width: 94%;
}
section#mapcontainer, section#list {
width: 72%;
padding-left: 14%;
padding-right: 14%;
font-size: 14px;
height: 60%;
}
}
</style>
</head>
<body>
<header>
<h1>A google form backed list and map</h1>
<nav>
view this as a <span id="uichanger" role="button">map</span>.
</nav>
</header>
<section id="mapcontainer">
<div id="map"></div>
</section>
<section id="list"></section>
<footer>
<nav>
<a href="https://forms.gle/FCUpuHP3MesL4GxZ8">submit an point</a>
</nav>
</footer>
</body>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment