Last week I shared my initial experiences with Leaflet and I thought I'd share a small demo I built with it - a general purpose GeoJSON viewer.

GeoJSON and Leaflet

As I mentioned at the end of my last post, GeoJSON is a specification for encoding ad hoc geographic data. Here's an example:

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "id": 0,
            "properties": {
                "Code": "FRLA",
                "Name": "Frederick Law Olmsted National Historic Site"
            },
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -71.13112956925647,
                    42.32550867371509
                ]
            }
        },
        {
            "type": "Feature",
            "id": 1,
            "properties": {
                "Code": "GLDE",
                "Name": "Gloria Dei Church National Historic Site"
            },
            "geometry": {
                "type": "Point",
                "coordinates": [
                    -75.14358360598474,
                    39.93437740957208
                ]
            }
        },
	]
}

GeoJSON can encode points, lines, polygons, and more, and support a properties section that can have anything in it. Leaflet makes it easy to use GeoJSON. Here's the example I used in that last post:

let dataReq = await fetch('https://assets.codepen.io/74045/national-parks.geojson');
let data = await dataReq.json();

L.geoJSON(data).bindPopup(function (layer) {
		return layer.feature.properties.Name;
}).addTo(map);

That's literally it. Given how easy this, I thought I'd build a demo where the data was provided by the user.

The Application

My application is built with simple vanilla JavaScript, no Alpine even, and lets you drop a file into the browser to load the information.

The Leaflet demo

My code waits for DOMContentLoaded and then registers event handlers for dragdrop support:

document.addEventListener('dragover', e => e.preventDefault());
document.addEventListener('drop', handleDrop);

When you drop a file, I then use a bit of code to read it in.

function handleDrop(e) {
		e.preventDefault();
		let droppedFiles = e.dataTransfer.files;
		if(!droppedFiles) return;
		let myFile = droppedFiles[0];
		let ext = myFile.name.split('.').pop();
		if(ext !== 'geojson') {
			alert('Drag/drop a .geojson file only.');
			return;
		}
		
		let reader = new FileReader();
		reader.onload = e => {
			loadGeoJSON(JSON.parse(e.target.result));
		};
		
		updateStatus('Reading .geojson');
		reader.readAsText(myFile);	
}

The loadGeoJSON function handles adding the data to Leaflet:

async function loadGeoJSON(data) {
	updateStatus(`.geojson loaded with ${data.features.length} features. Adding to map now.`);

	L.geoJSON(data, {
	}).bindPopup(function (layer) {
			return `
			<p>
			<b>Properties:</b><br>
			<pre style='white-space:pre-wrap'><code>
${JSON.stringify(layer.feature.properties,null,'  ')}
			</code></pre>
			</p>
			`;
	},{minWidth:450}).addTo(map);

}

This is pretty much the same code as before, except that my popup uses a basic dump (stringify) of the properties key. Note that this will not work for all files, especially if there's a lot of data there. I could get fancier with my output there and perhaps add a max height with overflow. That being said, here is how it looks after adding America's parks to it (and clicking one feature):

The Leaflet demo - with data

You can test it out here (full screen): https://codepen.io/cfjedimaster/full/GRbxVVR

And here's the full code:

See the Pen Leaflet geojson viewer (v2) by Raymond Camden (@cfjedimaster) on CodePen.