function latLonInput({
geo = nepalGeo,
provincePath = "properties.Province",
districtPath = "properties.DISTRICT",
provinceInputLabel = "Province",
districtInputLabel = "District",
width = 600,
height = 400,
margin = 10,
stroke = "#999",
strokeWidth,
strokeOpacity,
strokeLinecap = "round",
strokeLinejoin = "round", // stroke line join for borders
fill = "#f4f4f4"
} = {}) {
let latlon;
geo = normalizeWinding(geo);
const projection = d3.geoTransverseMercator().rotate([-80, 0, 0]);
const svg = DOM.svg(width, height);
const id = `${prefix}-${generateRandomSeed()}`;
const districtOptionsId = `${id}-dist-options`;
const districts = d3.rollup(
geo.features,
(v) => v.map((d) => getValueByPath(d, districtPath)),
(d) => getValueByPath(d, provincePath)
);
const provinceInput = autoSelect({
options: Array.from(districts.keys()),
title: provinceInputLabel
});
let districtInput;
const districtInputHolder = htl.html`<div>`;
const form = htl.html`<form class=${blockClass} data-state="idle">
${provinceInput}
${districtInputHolder}
${svg}
</form>`;
function dispatchInputEvent() {
form.dispatchEvent(new Event("input", { bubbles: true }));
}
let currentProvince = "";
let currentDistrict = "";
function onDistrictChange() {
currentProvince = provinceInput.value;
currentDistrict = districtInput.value;
updateMap();
}
function populateDistrictOptions(options) {
districtInputHolder.innerHTML = null;
if (options == null) return;
districtInput = autoSelect({
options,
title: districtInputLabel,
list: districtOptionsId
});
districtInput.oninput = onDistrictChange;
districtInputHolder.appendChild(districtInput);
}
function updateMap() {
svg.innerHTML = null;
const filteredGeo = filterGeo(geo, currentProvince, currentDistrict, {
provincePath,
districtPath
});
projection.fitExtent(
[
[margin, margin],
[width - margin, height - margin]
],
filteredGeo
);
const path = d3.geoPath(projection);
const shapes = d3
.select(svg)
.selectAll(".boundary")
.data(filteredGeo.features)
.join("path")
.attr("class", "boundary")
.attr("stroke", stroke)
.attr("stroke-linecap", strokeLinecap)
.attr("stroke-linejoin", strokeLinejoin)
.attr("stroke-width", strokeWidth)
.attr("stroke-opacity", strokeOpacity)
.attr("fill", fill)
.attr("d", path);
const marker = d3
.select(svg)
.append("circle")
.attr("r", 4)
.attr("fill", "transparent");
shapes.on("click", function (e) {
const m = d3.pointer(e);
latlon = projection.invert(m).reverse();
marker.call(function () {
marker.attr("cx", m[0]).attr("cy", m[1]).attr("fill", "red");
});
dispatchInputEvent();
});
}
function onProvinceChange() {
currentProvince = provinceInput.value;
currentDistrict = "";
populateDistrictOptions(districts.get(currentProvince));
updateMap();
}
form.onchange = preventDefault;
form.onsubmit = preventDefault;
provinceInput.oninput = onProvinceChange;
attachStyles(invalidation);
updateMap();
return Object.defineProperty(form, "value", {
get() {
return latlon;
}
});
}