Skip to content

βœ… Final Template Code

index.html
<!DOCTYPE html>
<html>
    <head>
        <title>Hello World with MapLibreGl</title>
        <!-- hint: remember to change your page title! -->
        <meta charset="utf-8" />
        <link rel="shortcut icon" href="#">
        <link rel="stylesheet" href="styles/style.css">

        <!-- MapLibreGL's css-->
        <link rel="stylesheet" href="https://unpkg.com/maplibre-gl/dist/maplibre-gl.css" />

        <!-- MapLibreGL's JavaScript-->
        <script src="https://unpkg.com/maplibre-gl/dist/maplibre-gl.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.3.0/papaparse.min.js"></script>
    </head>

    <body>
        <header>
            COVID Vaccination Stories
        </header>

        <main>
            <div class="portfolio">
                <div id="contents">
                </div>
                <iframe src="https://docs.google.com/forms/d/e/1FAIpQLSfcElv5dlXInR7XHQz27_OcYJlWcIUr-GBbc-ocefWlGd1uXg/viewform?embedded=true" width="100%" height="100%" frameborder="0" marginheight="0" marginwidth="0">Loading…</iframe>
            </div>
            <div id="map"></div>
        </main>
        <div id="footer">
            Copyright(2024)
        </div>
        <script src="js/init.js"></script>
    </body>
</html>
js/init.js
// declare variables
let mapOptions = {'centerLngLat': [-118.444,34.0709],'startingZoomLevel':5}

const map = new maplibregl.Map({
    container: 'map', // container ID
    style: 'https://api.maptiler.com/maps/streets-v2-light/style.json?key=wsyYBQjqRwKnNsZrtci1', // Your style URL
    center: mapOptions.centerLngLat, // Starting position [lng, lat]
    zoom: mapOptions.startingZoomLevel // Starting zoom level
});

function addMarker(data){
    let popup_message;
    let lng = data['lng'];
    let lat = data['lat'];
    if (data['Have you been vaccinated?'] == "Yes"){
        popup_message = `<h2>Vaccinated</h2> <h3>Location: ${data['Where did you get vaccinated?']}</h3> <p>Zip Code: ${data['What zip code do you live in?']}</p>`
    }
    else{
        popup_message = `<h2>Not Vaccinated</h2><p>Zip Code: ${data['What zip code do you live in?']}</p>`
    }
    new maplibregl.Marker()
        .setLngLat([lng, lat])
        .setPopup(new maplibregl.Popup()
            .setHTML(popup_message))
        .addTo(map)
    createButtons(lat,lng,data['Where did you get vaccinated?']);
}

function createButtons(lat,lng,title){
    const newButton = document.createElement("button");
    newButton.id = "button"+title; 
    newButton.innerHTML = title;
    newButton.setAttribute("lat",lat);
    newButton.setAttribute("lng",lng);
    newButton.addEventListener('click', function(){
        map.flyTo({
            center: [lng,lat],
        })
    })
    document.getElementById("contents").appendChild(newButton);
}

const dataUrl = "https://docs.google.com/spreadsheets/d/e/2PACX-1vSNq8_prhrSwK3CnY2pPptqMyGvc23Ckc5MCuGMMKljW-dDy6yq6j7XAT4m6GG69CISbD6kfBF0-ypS/pub?output=csv"

// When the map is fully loaded, start adding GeoJSON data
map.on('load', function() {
    // Use PapaParse to fetch and parse the CSV data from a Google Forms spreadsheet URL
    Papa.parse(dataUrl, {
        download: true, // Tells PapaParse to fetch the CSV data from the URL
        header: true, // Assumes the first row of your CSV are column headers
        complete: function(results) {
            // Process the parsed data
            processData(results.data); // Use a new function to handle CSV data
        }
    });
});

function processData(results){
    console.log(results) //for debugging: this can help us see if the results are what we want
    results.forEach(feature => {
        //console.log(feature) // for debugging: are we seeing each feature correctly?
        // assumes your geojson has a "title" and "message" attribute
        // let coordinates = feature.geometry.coordinates;
        let longitude = feature['lng']
        let latitude = feature['lat'];
        let title = feature['Where did you get vaccinated?'];
        let message = feature['What zip code do you live in?'];
        addMarker(feature);
    });
};
styles/style.css
/* Global reset to ensure consistency across browsers */
* {
    font-family: Arial, sans-serif; /* Sets a default font for the whole page */
    margin: 0; /* Removes default margins */
    padding: 0; /* Removes default padding */
    box-sizing: border-box; /* Makes sure borders and paddings are included in the element's total width and height */
}

/* Sets the background color of the whole page and ensures content fits the screen height */
html {
    background-color: aqua; /* Sets a light blue background color */
}

/* Applies to both <html> and <body> */
html, body {
    height: 80vh; /* Sets the height to 80% of the viewport height, making sure the content fits on the screen */
    padding: 1rem; /* Adds a bit of space around the content for better readability */
    box-sizing: border-box; /* Ensures padding does not add to the set height */
}

/* Defines the main layout of the page using CSS Grid */
body {
    display: grid; /* Enables CSS Grid layout */
    grid-template-areas: 
        "header" /* Top area for the header */
        "main"   /* Middle area for the main content */
        "footer"; /* Bottom area for the footer */
    grid-template-rows: auto 1fr auto; /* Sizes: auto for header and footer to fit content, 1fr for main to fill remaining space */
}

/* Sets up the layout for the main content area, dividing it into two columns */
main {
    display: grid; /* Enables CSS Grid within the main element */
    grid-template-areas:
        "portfolio map"; /* Divides the main area into portfolio and map sections side by side */
    grid-template-columns: 1fr 1fr; /* Allocates equal width to both sections */
}

/* Grid area assignments for each major section, linking them to their respective areas in the grid */
header { 
    grid-area: header; /* Assigns the header to its grid area */
}

main { 
    grid-area: main; /* Assigns the main content to its grid area */
}

.portfolio {
    grid-area: portfolio;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
}


#map { 
    grid-area: map; /* Assigns the map section to its grid area */
    height: 80vh; /* Sets the map's height to 80% of the viewport height */
}

#footer {
    grid-area: footer;
    padding: 5px; /* Adds padding for better spacing */
    background-color: #4677a0; /* Sets a dark background for contrast */
    color: #fff; /* Ensures text is readable against the dark background */
    text-align: center; /* Centers the footer content */
}