From 17111492dc3305026997e072feac0f011e85f509 Mon Sep 17 00:00:00 2001 From: ZsoltMONOLITE <141682166+ZsoltMONOLITE@users.noreply.github.com> Date: Sat, 2 Dec 2023 13:02:00 +0000 Subject: [PATCH] Update main.js --- main.js | 106 +++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 75 insertions(+), 31 deletions(-) diff --git a/main.js b/main.js index cb61c244..b7be89b8 100644 --- a/main.js +++ b/main.js @@ -1,4 +1,13 @@ +/* global L Papa */ + +/* + * Script to display two tables from Google Sheets as point and geometry layers using Leaflet + * The Sheets are then imported using PapaParse and overwrite the initially laded layers + */ + // PASTE YOUR URLs HERE +// these URLs come from Google Sheets 'shareable link' form +// the first is the geometry layer and the second the points let geomURL = "https://docs.google.com/spreadsheets/d/e/2PACX-1vS4sQJDfJGptqDkY-eNDqcR1xJ_YH-X0qb9BKnYvSf34ArSCPE5ducm_-FaG1cNcO1AgQjsjGxie8Fi/pub?gid=0&single=true&output=csv"; let pointsURL = @@ -10,13 +19,19 @@ let map; let sidebar; let panelID = "my-info-panel"; +/* + * init() is called when the page has loaded + */ function init() { + // Create a new Leaflet map centered on the continental US map = L.map("map").setView([51.5, -0.1], 14); + + // This is the Carto Positron basemap L.tileLayer( "https://cartodb-basemaps-{s}.global.ssl.fastly.net/light_all/{z}/{x}/{y}{r}.png", { attribution: - "© OpenStreetMap © CartoDB", + "© OpenStreetMap © CartoDB", subdomains: "abcd", maxZoom: 19, } @@ -38,42 +53,40 @@ function init() { }; sidebar.addPanel(panelContent); - let namesList = []; - map.on("click", function () { sidebar.close(panelID); }); + // Use PapaParse to load data from Google Sheets + // And call the respective functions to add those to the map. Papa.parse(geomURL, { download: true, header: true, - complete: function (result) { - addGeoms(result, namesList); - }, + complete: addGeoms, }); - Papa.parse(pointsURL, { + Papa.parse(pointsURL, { download: true, header: true, complete: addPoints, }); - - let options = { - valueNames: ["name"], - listClass: "names-list", - searchClass: "names-search", - }; - - let names = new List("sidebar-names", options); - names.add(namesList); } -function addGeoms(data, namesList) { +/* + * Expects a JSON representation of the table with properties columns + * and a 'geometry' column that can be parsed by parseGeom() + */ +function addGeoms(data) { data = data.data; + // Need to convert the PapaParse JSON into a GeoJSON + // Start with an empty GeoJSON of type FeatureCollection + // All the rows will be inserted into a single GeoJSON let fc = { type: "FeatureCollection", features: [], }; + for (let row in data) { + // The Sheets data has a column 'include' that specifies if that row should be mapped if (data[row].include == "y") { let features = parseGeom(JSON.parse(data[row].geometry)); features.forEach((el) => { @@ -82,11 +95,11 @@ function addGeoms(data, namesList) { description: data[row].description, }; fc.features.push(el); - namesList.push(data[row].name); }); } } + // The geometries are styled slightly differently on mouse hovers let geomStyle = { color: "#2ca25f", fillColor: "#99d8c9", weight: 2 }; let geomHoverStyle = { color: "green", fillColor: "#2ca25f", weight: 3 }; @@ -100,7 +113,13 @@ function addGeoms(data, namesList) { e.target.setStyle(geomHoverStyle); }, click: function (e) { - L.DomEvent.stopPropagation(e, click); + // This zooms the map to the clicked geometry + // Uncomment to enable + // 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 = @@ -113,10 +132,23 @@ function addGeoms(data, namesList) { }).addTo(map); } +/* + * addPoints is a bit simpler, as no GeoJSON is needed for the points + */ function addPoints(data) { data = data.data; let pointGroupLayer = L.layerGroup().addTo(map); + + // Choose marker type. Options are: + // (these are case-sensitive, defaults to marker!) + // marker: standard point with an icon + // circleMarker: a circle with a radius set in pixels + // circle: a circle with a radius set in meters let markerType = "marker"; + + // Marker radius + // Wil be in pixels for circleMarker, metres for circle + // Ignore for point let markerRadius = 100; for (let row = 0; row < data.length; row++) { @@ -134,13 +166,14 @@ function addPoints(data) { } marker.addTo(pointGroupLayer); + // UNCOMMENT THIS LINE TO USE POPUPS + //marker.bindPopup('

' + data[row].name + '

There's a ' + data[row].description + ' here'); + + // COMMENT THE NEXT GROUP OF LINES TO DISABLE SIDEBAR FOR THE MARKERS marker.feature = { properties: { name: data[row].name, description: data[row].description, - program: data[row].program, - client: data[row].client, - dropbox: data[row].dropbox, }, }; marker.on({ @@ -150,16 +183,12 @@ function addPoints(data) { e.target.feature.properties.name; document.getElementById("sidebar-content").innerHTML = e.target.feature.properties.description; - document.getElementById("sidebar-content").innerHTML = - e.target.feature.properties.program; - document.getElementById("sidebar-content").innerHTML = - e.target.feature.properties.client; - document.getElementById("sidebar-content").innerHTML = - e.target.feature.properties.dropbox; sidebar.open(panelID); }, }); + // COMMENT UNTIL HERE TO DISABLE SIDEBAR FOR THE MARKERS + // AwesomeMarkers is used to create fancier icons let icon = L.AwesomeMarkers.icon({ icon: "info-circle", iconColor: "white", @@ -173,14 +202,29 @@ function addPoints(data) { } } +/* + * Accepts any GeoJSON-ish object and returns an Array of + * GeoJSON Features. Attempts to guess the geometry type + * when a bare coordinates Array is supplied. + */ function parseGeom(gj) { + // FeatureCollection if (gj.type == "FeatureCollection") { return gj.features; - } else if (gj.type == "Feature") { + } + + // Feature + else if (gj.type == "Feature") { return [gj]; - } else if ("type" in gj) { + } + + // Geometry + else if ("type" in gj) { return [{ type: "Feature", geometry: gj }]; - } else { + } + + // Coordinates + else { let type; if (typeof gj[0] == "number") { type = "Point";