)));
}
-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"});
};
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);
}
}
+ 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;
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,
}
console.log(flyBounds);
- overlay.style["display"] = "none";
if (flyBounds !== null) {
map.flyToBounds(flyBounds);
}
+ statusSpan.innerText = "ready";
}
document.getElementById("picked-zones").innerText = [...PICK_ZONINGS].join(", ");
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>