]> jcornell.net Git - ntbd-parcels.git/commitdiff
Switch from overlay to status bar and add progress indicator
authorJakob Cornell <jakob+gpg@jcornell.net>
Sun, 24 May 2026 17:28:19 +0000 (12:28 -0500)
committerJakob Cornell <jakob+gpg@jcornell.net>
Sun, 24 May 2026 20:01:28 +0000 (15:01 -0500)
main.js
parcels.html

diff --git a/main.js b/main.js
index a7e9c4734b56f0088e0379387e5f17d747b50a7d..e2b06e748f883250210808be5c3c4f590c84cdbb 100644 (file)
--- a/main.js
+++ b/main.js
@@ -21,9 +21,10 @@ function transposeCoordinates(coordList) {
        )));
 }
 
-async function asyncMain() {
-       const overlay = document.getElementById("loading-overlay");
+const statusSpan = document.querySelector("#status > span");
+const progressBar = document.querySelector("#status > progress");
 
+async function asyncMain() {
        const onVersionUpdate = async (db) => {
                const parcelStore = db.createObjectStore("features", {keyPath: "properties.OBJECTID"});
        };
@@ -31,15 +32,17 @@ async function asyncMain() {
        await db.open();
 
        if (!(PARCEL_LOAD_KEY in localStorage)) {
-               overlay.innerText = "downloading parcel data";
+               statusSpan.innerText = "downloading parcel data";
                const geoJsonResponse = await fetch(PARCEL_JSON_PATH);
                if (geoJsonResponse.ok) {
-                       overlay.innerText = "parsing dataset";
+                       statusSpan.innerText = "parsing dataset";
                        const geoJson = await geoJsonResponse.json();
-                       overlay.innerText = "saving parcels to persistent storage";
-                       for (const feature of geoJson.features) {
+                       statusSpan.innerText = "saving parcels to persistent storage";
+                       for (const [i, feature] of geoJson.features.entries()) {
+                               progressBar.value = i / geoJson.features.length;
                                await db.query("features").put(feature);
                        }
+                       progressBar.value = 1;
                        localStorage[PARCEL_LOAD_KEY] = "1";
                } else {
                        console.error(geoJsonResponse);
@@ -47,13 +50,17 @@ async function asyncMain() {
                }
        }
 
+       statusSpan.innerText = "filtering parcels";
+       progressBar.value = 0;
        const store = db.query("features", "readonly");
-       overlay.innerText = "filtering parcels";
+       const featureCount = await store.count();
        const matches = [];
+       let index = 0;
        let noZoningCount = 0;
        let noLotSizeCount = 0;
        // store.getAll doesn't work for some reason.
        for await (const {value: feature} of await store.openCursor()) {
+               progressBar.value = index / featureCount;
                if (feature.geometry.type == "MultiPolygon") {
                        const zoningParts = (feature.properties.ZoningAll ?? "").split(", ");
                        const zoningMatch = zoningParts.length && new Set(zoningParts).intersection(PICK_ZONINGS).size;
@@ -71,10 +78,12 @@ async function asyncMain() {
                else {
                        console.warn("Skipping %s feature geometry", feature.geometry.type);
                }
+               index += 1;
        }
+       progressBar.value = 1;
        console.log(
                "Searched %d parcels: %d matches, %d with no zoning, %d with no size",
-               await store.count(),
+               featureCount,
                matches.length,
                noZoningCount,
                noLotSizeCount,
@@ -107,10 +116,10 @@ async function asyncMain() {
        }
 
        console.log(flyBounds);
-       overlay.style["display"] = "none";
        if (flyBounds !== null) {
                map.flyToBounds(flyBounds);
        }
+       statusSpan.innerText = "ready";
 }
 
 document.getElementById("picked-zones").innerText = [...PICK_ZONINGS].join(", ");
index 69e8c3cbf6ce7869809cc07d8d074372ce94d9cf..c79e8fc988fb5c4fb73c18955f61c8fbca634f51 100644 (file)
                                flex-grow: 1;
                                z-index: 0;
                        }
-                       #controls {
+                       #sidebar {
+                               display: flex;
                                flex-basis: 25rem;
+                               flex-direction: column;
                                padding: 1rem;
                        }
-                       #loading-overlay {
-                               position: absolute;
-                               top: 0;
-                               left: 0;
-                               right: 0;
-                               bottom: 0;
-                               z-index: 1;
-                               background: rgba(0, 0, 0, 0.7);
-                               color: white;
-                               font-size: 2rem;
-                               text-align: center;
-                               padding-top: 3rem;
+                       #controls {
+                               flex-grow: 1;
+                               overflow: auto;
                        }
                </style>
        </head>
                        integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
                        crossorigin=""></script>
                <div id="split">
-                       <div id="map" class="loading"></div>
-                       <div id="controls">
-                               <h2>Zoning</h2>
-                               <p id="picked-zones"></p>
-                               <h2>Lot size</h2>
-                               <p id="lot-size"></p>
+                       <div id="map"></div>
+                       <div id="sidebar">
+                               <div id="controls">
+                                       <h2>Zoning</h2>
+                                       <p id="picked-zones"></p>
+                                       <h2>Lot size</h2>
+                                       <p id="lot-size"></p>
+                               </div>
+                               <div id="status">
+                                       <span style="display: block"></span>
+                                       <progress style="width: 100%"></progress>
+                               </div>
                        </div>
                </div>
-               <div id="loading-overlay">loading</div>
                <script src="main.js" type="module"></script>
        </body>
 </html>