diff options
| -rw-r--r-- | scripts/park-editor.html | 50 | ||||
| -rw-r--r-- | src/data/parks-rows.ts | 9 |
2 files changed, 50 insertions, 9 deletions
diff --git a/scripts/park-editor.html b/scripts/park-editor.html index 7d6ac56..6c4605a 100644 --- a/scripts/park-editor.html +++ b/scripts/park-editor.html @@ -87,6 +87,9 @@ <option value="done">確認済み</option> <option value="todo">未確認</option> </select> + <select id="type-filter" hidden title="種別で絞り込む"> + <option value="">種別: すべて</option> + </select> <span id="checked-count" class="checked-count"></span> <span class="check-note" title="確認チェックはこのブラウザにのみ保存され、JSONには入りません">このブラウザのみ</span> <button id="clear-checks" title="このデータの確認チェックをすべて外す">確認をクリア</button> @@ -179,9 +182,11 @@ const DATASETS = { facilities: { label: "市内の公共施設", fields: [ - FIELD("name", "名称"), FIELD("type", "種別"), FIELD("address", "住所"), - FIELD("hours", "開館時間"), FIELD("closed", "休館日"), FIELD("toilet", "トイレ"), - FIELD("water", "給水"), FIELD("note", "備考"), FIELD("source", "出典URL"), + FIELD("name", "名称"), FIELD("type", "種別"), + FIELD("toilet", "トイレ"), FIELD("water", "給水"), + FIELD("address", "住所"), + FIELD("hours", "開館時間"), FIELD("closed", "休館日"), + FIELD("note", "備考"), FIELD("source", "出典URL"), FIELD("lat", "緯度"), FIELD("lon", "経度"), FIELD("city", "市"), FIELD("distance_m", "距離(m)"), ], @@ -190,9 +195,11 @@ const DATASETS = { label: "周辺の公共施設", warning: "周辺の公共施設は update-nearby-facilities.py で再生成すると上書きされます。編集内容は別途保存してください。", fields: [ - FIELD("name", "名称"), FIELD("type", "種別"), FIELD("address", "住所"), - FIELD("hours", "開館時間"), FIELD("closed", "休館日"), FIELD("toilet", "トイレ"), - FIELD("water", "給水"), FIELD("note", "備考"), FIELD("source", "出典URL"), + FIELD("name", "名称"), FIELD("type", "種別"), + FIELD("toilet", "トイレ"), FIELD("water", "給水"), + FIELD("address", "住所"), + FIELD("hours", "開館時間"), FIELD("closed", "休館日"), + FIELD("note", "備考"), FIELD("source", "出典URL"), FIELD("lat", "緯度"), FIELD("lon", "経度"), FIELD("city", "市"), FIELD("distance_m", "距離(m)"), ], @@ -306,6 +313,7 @@ const statusEl = document.getElementById("status"); const warningEl = document.getElementById("warning"); const tabsEl = document.getElementById("tabs"); const checkFilter = document.getElementById("check-filter"); +const typeFilter = document.getElementById("type-filter"); const checkedCount = document.getElementById("checked-count"); const clearChecksBtn = document.getElementById("clear-checks"); const STORAGE_KEY = "park-editor-checks-v1"; @@ -451,6 +459,7 @@ async function load(id) { data = await res.json(); isFC = data.type === "FeatureCollection"; rows = isFC ? data.features : data; + populateTypeFilter(); render(); showCorruptKeys(); statusEl.textContent = `${DATASETS[id].label}: ${rows.length}件`; @@ -459,6 +468,29 @@ async function load(id) { } } +// 公共施設では種別(地域センター・文化施設など)で絞り込めるようにする。 +function populateTypeFilter() { + if (!typeFilter) return; + const show = currentId === "facilities" || currentId === "nearbyFacilities"; + typeFilter.hidden = !show; + typeFilter.innerHTML = '<option value="">種別: すべて</option>'; + if (!show) return; + const counts = new Map(); + rows.forEach((row) => { + const props = isFC ? row.properties || {} : row; + const type = String(props.type || "").trim(); + if (type) counts.set(type, (counts.get(type) || 0) + 1); + }); + [...counts.entries()] + .sort((a, b) => a[0].localeCompare(b[0], "ja")) + .forEach(([type, n]) => { + const opt = document.createElement("option"); + opt.value = type; + opt.textContent = `${type} (${n})`; + typeFilter.appendChild(opt); + }); +} + function render() { const COL_CLASS = { 緯度: "c-coord", @@ -542,6 +574,7 @@ function render() { tr.appendChild(td); }); + tr.dataset.type = String(props.type || "").trim(); tr.dataset.search = fields.map((f) => f.toy ? toys[f.toy] : String(props[f.key] != null ? props[f.key] : "")).join(" ") + " " + String(props["遊具"] || ""); tbody.appendChild(tr); }); @@ -553,13 +586,15 @@ function render() { function filter() { const s = q.value.trim().toLowerCase(); const checkMode = checkFilter ? checkFilter.value : ""; + const type = typeFilter ? typeFilter.value : ""; let shown = 0; Array.prototype.forEach.call(tbody.children, (tr) => { const cb = tr.querySelector("input[data-check]"); const checked = Boolean(cb && cb.checked); const okCheck = !checkMode || (checkMode === "done" ? checked : !checked); const okText = !s || tr.dataset.search.toLowerCase().indexOf(s) >= 0; - const ok = okText && okCheck; + const okType = !type || (tr.dataset.type || "") === type; + const ok = okText && okCheck && okType; tr.hidden = !ok; if (ok) shown++; }); @@ -756,6 +791,7 @@ document.getElementById("revert").onclick = function () { q.addEventListener("input", filter); checkFilter.addEventListener("change", filter); +if (typeFilter) typeFilter.addEventListener("change", filter); tbody.addEventListener("focusin", (event) => { const target = event.target; if (!(target instanceof Element)) return; diff --git a/src/data/parks-rows.ts b/src/data/parks-rows.ts index 832ea28..6f1add7 100644 --- a/src/data/parks-rows.ts +++ b/src/data/parks-rows.ts @@ -84,8 +84,13 @@ function facilityRow(f: any, nearby: boolean): Park { : name.startsWith("小平市") ? name : `小平市${name}`; - const toilet = f.toilet === "○" ? "○" : ""; - const water = f.water === "○" ? "○" : ""; + // ○以外の「あり」「1階」なども表示に反映する(「未確認」などは除外)。 + const facilityFlag = (value: unknown) => { + const text = String(value ?? "").trim(); + return text && !/未確認|なし|無|×|✕/.test(text) ? text : ""; + }; + const toilet = facilityFlag(f.toilet); + const water = facilityFlag(f.water); return { "公園名": name, "住所": address, |
