mirror of
https://github.com/Azgaar/Fantasy-Map-Generator.git
synced 2026-02-04 17:41:23 +01:00
feat: add search functionality to overview components
This commit is contained in:
parent
d0395624af
commit
3e339b78d4
5 changed files with 93 additions and 16 deletions
32
index.html
32
index.html
|
|
@ -5369,12 +5369,22 @@
|
||||||
|
|
||||||
<div id="burgsBody" class="table"></div>
|
<div id="burgsBody" class="table"></div>
|
||||||
|
|
||||||
<div id="burgsFilters" data-tip="Apply a filter" style="padding-block: 0.1em">
|
<div
|
||||||
<label for="burgsFilterState">State:</label>
|
id="burgsFilters"
|
||||||
<select id="burgsFilterState" style="width: 28%"></select>
|
data-tip="Apply a filter"
|
||||||
|
style="padding-block: 0.1em; display: flex; gap: 0.5em; width: 100%"
|
||||||
|
>
|
||||||
|
<label for="burgsSearch">Search: <input id="burgsSearch" type="search" /></label>
|
||||||
|
|
||||||
<label for="burgsFilterCulture">Culture:</label>
|
<label for="burgsFilterState"
|
||||||
<select id="burgsFilterCulture" style="width: 28%"></select>
|
>State:
|
||||||
|
<select id="burgsFilterState"></select
|
||||||
|
></label>
|
||||||
|
|
||||||
|
<label for="burgsFilterCulture"
|
||||||
|
>Culture:
|
||||||
|
<select id="burgsFilterCulture"></select
|
||||||
|
></label>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="burgsFooter" class="totalLine">
|
<div id="burgsFooter" class="totalLine">
|
||||||
|
|
@ -5456,6 +5466,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div style="padding: 0.3em 0.5em">
|
||||||
|
<input id="routesSearch" type="text" placeholder="Search by name or group..." style="width: 100%" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="routesBody" class="table"></div>
|
<div id="routesBody" class="table"></div>
|
||||||
|
|
||||||
<div id="routesFooter" class="totalLine">
|
<div id="routesFooter" class="totalLine">
|
||||||
|
|
@ -5506,6 +5520,10 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div style="padding: 0.3em 0.5em">
|
||||||
|
<input id="riversSearch" type="text" placeholder="Search by name, type, or basin..." style="width: 100%" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="riversBody" class="table"></div>
|
<div id="riversBody" class="table"></div>
|
||||||
|
|
||||||
<div id="riversFooter" class="totalLine">
|
<div id="riversFooter" class="totalLine">
|
||||||
|
|
@ -5705,6 +5723,10 @@
|
||||||
></div>
|
></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div style="padding: 0.3em 0.5em">
|
||||||
|
<input id="markersSearch" type="text" placeholder="Search by type..." style="width: 100%" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<div id="markersBody" class="table"></div>
|
<div id="markersBody" class="table"></div>
|
||||||
|
|
||||||
<div id="markersFooter" class="totalLine">
|
<div id="markersFooter" class="totalLine">
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ function overviewBurgs(settings = {stateId: null, cultureId: null}) {
|
||||||
byId("burgsChart").addEventListener("click", showBurgsChart);
|
byId("burgsChart").addEventListener("click", showBurgsChart);
|
||||||
byId("burgsFilterState").addEventListener("change", burgsOverviewAddLines);
|
byId("burgsFilterState").addEventListener("change", burgsOverviewAddLines);
|
||||||
byId("burgsFilterCulture").addEventListener("change", burgsOverviewAddLines);
|
byId("burgsFilterCulture").addEventListener("change", burgsOverviewAddLines);
|
||||||
|
byId("burgsSearch").addEventListener("input", burgsOverviewAddLines);
|
||||||
byId("regenerateBurgNames").addEventListener("click", regenerateNames);
|
byId("regenerateBurgNames").addEventListener("click", regenerateNames);
|
||||||
byId("addNewBurg").addEventListener("click", enterAddBurgMode);
|
byId("addNewBurg").addEventListener("click", enterAddBurgMode);
|
||||||
byId("burgsExport").addEventListener("click", downloadBurgsData);
|
byId("burgsExport").addEventListener("click", downloadBurgsData);
|
||||||
|
|
@ -65,9 +66,22 @@ function overviewBurgs(settings = {stateId: null, cultureId: null}) {
|
||||||
function burgsOverviewAddLines() {
|
function burgsOverviewAddLines() {
|
||||||
const selectedStateId = +byId("burgsFilterState").value;
|
const selectedStateId = +byId("burgsFilterState").value;
|
||||||
const selectedCultureId = +byId("burgsFilterCulture").value;
|
const selectedCultureId = +byId("burgsFilterCulture").value;
|
||||||
|
const searchText = (byId("burgsSearch").value || "").toLowerCase().trim();
|
||||||
let filtered = pack.burgs.filter(b => b.i && !b.removed); // all valid burgs
|
let filtered = pack.burgs.filter(b => b.i && !b.removed); // all valid burgs
|
||||||
if (selectedStateId !== -1) filtered = filtered.filter(b => b.state === selectedStateId); // filtered by state
|
if (selectedStateId !== -1) filtered = filtered.filter(b => b.state === selectedStateId); // filtered by state
|
||||||
if (selectedCultureId !== -1) filtered = filtered.filter(b => b.culture === selectedCultureId); // filtered by culture
|
if (selectedCultureId !== -1) filtered = filtered.filter(b => b.culture === selectedCultureId); // filtered by culture
|
||||||
|
|
||||||
|
// filter by search text
|
||||||
|
if (searchText) {
|
||||||
|
filtered = filtered.filter(b => {
|
||||||
|
const name = (b.name || "").toLowerCase();
|
||||||
|
const state = (pack.states[b.state]?.name || "").toLowerCase();
|
||||||
|
const prov = pack.cells.province[b.cell];
|
||||||
|
const province = prov ? (pack.provinces[prov]?.name || "").toLowerCase() : "";
|
||||||
|
const culture = (pack.cultures[b.culture]?.name || "").toLowerCase();
|
||||||
|
return name.includes(searchText) || state.includes(searchText) || province.includes(searchText) || culture.includes(searchText);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
body.innerHTML = "";
|
body.innerHTML = "";
|
||||||
let lines = "";
|
let lines = "";
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ function overviewMarkers() {
|
||||||
position: {my: "right top", at: "right-10 top+10", of: "svg", collision: "fit"}
|
position: {my: "right top", at: "right-10 top+10", of: "svg", collision: "fit"}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const markersSearch = document.getElementById("markersSearch");
|
||||||
|
|
||||||
const listeners = [
|
const listeners = [
|
||||||
listen(body, "click", handleLineClick),
|
listen(body, "click", handleLineClick),
|
||||||
listen(markersInverPin, "click", invertPin),
|
listen(markersInverPin, "click", invertPin),
|
||||||
|
|
@ -36,7 +38,8 @@ function overviewMarkers() {
|
||||||
listen(markersGenerationConfig, "click", configMarkersGeneration),
|
listen(markersGenerationConfig, "click", configMarkersGeneration),
|
||||||
listen(markersRemoveAll, "click", triggerRemoveAll),
|
listen(markersRemoveAll, "click", triggerRemoveAll),
|
||||||
listen(markersExport, "click", exportMarkers),
|
listen(markersExport, "click", exportMarkers),
|
||||||
listen(markerTypeSelector, "click", toggleMarkerTypeMenu)
|
listen(markerTypeSelector, "click", toggleMarkerTypeMenu),
|
||||||
|
listen(markersSearch, "input", addLines)
|
||||||
];
|
];
|
||||||
|
|
||||||
const types = [{type: "empty", icon: "❓"}, ...Markers.getConfig()];
|
const types = [{type: "empty", icon: "❓"}, ...Markers.getConfig()];
|
||||||
|
|
@ -67,7 +70,19 @@ function overviewMarkers() {
|
||||||
}
|
}
|
||||||
|
|
||||||
function addLines() {
|
function addLines() {
|
||||||
const lines = pack.markers
|
const searchInput = document.getElementById("markersSearch");
|
||||||
|
const searchText = (searchInput?.value || "").toLowerCase().trim();
|
||||||
|
let markers = pack.markers;
|
||||||
|
|
||||||
|
// filter by search text
|
||||||
|
if (searchText) {
|
||||||
|
markers = markers.filter(marker => {
|
||||||
|
const type = (marker.type || "").toLowerCase();
|
||||||
|
return type.includes(searchText);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const lines = markers
|
||||||
.map(({i, type, icon, pinned, lock}) => {
|
.map(({i, type, icon, pinned, lock}) => {
|
||||||
return /* html */ `
|
return /* html */ `
|
||||||
<div class="states" data-i=${i} data-type="${type}">
|
<div class="states" data-i=${i} data-type="${type}">
|
||||||
|
|
@ -91,7 +106,7 @@ function overviewMarkers() {
|
||||||
.join("");
|
.join("");
|
||||||
|
|
||||||
body.innerHTML = lines;
|
body.innerHTML = lines;
|
||||||
markersFooterNumber.innerText = pack.markers.length;
|
markersFooterNumber.innerText = markers.length;
|
||||||
|
|
||||||
applySorting(markersHeader);
|
applySorting(markersHeader);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -26,14 +26,28 @@ function overviewRivers() {
|
||||||
document.getElementById("riversBasinHighlight").addEventListener("click", toggleBasinsHightlight);
|
document.getElementById("riversBasinHighlight").addEventListener("click", toggleBasinsHightlight);
|
||||||
document.getElementById("riversExport").addEventListener("click", downloadRiversData);
|
document.getElementById("riversExport").addEventListener("click", downloadRiversData);
|
||||||
document.getElementById("riversRemoveAll").addEventListener("click", triggerAllRiversRemove);
|
document.getElementById("riversRemoveAll").addEventListener("click", triggerAllRiversRemove);
|
||||||
|
document.getElementById("riversSearch").addEventListener("input", riversOverviewAddLines);
|
||||||
|
|
||||||
// add line for each river
|
// add line for each river
|
||||||
function riversOverviewAddLines() {
|
function riversOverviewAddLines() {
|
||||||
body.innerHTML = "";
|
body.innerHTML = "";
|
||||||
let lines = "";
|
let lines = "";
|
||||||
const unit = distanceUnitInput.value;
|
const unit = distanceUnitInput.value;
|
||||||
|
const searchText = (document.getElementById("riversSearch").value || "").toLowerCase().trim();
|
||||||
|
let filteredRivers = pack.rivers;
|
||||||
|
|
||||||
for (const r of pack.rivers) {
|
// filter by search text
|
||||||
|
if (searchText) {
|
||||||
|
filteredRivers = filteredRivers.filter(r => {
|
||||||
|
const name = (r.name || "").toLowerCase();
|
||||||
|
const type = (r.type || "").toLowerCase();
|
||||||
|
const basin = pack.rivers.find(river => river.i === r.basin);
|
||||||
|
const basinName = basin ? (basin.name || "").toLowerCase() : "";
|
||||||
|
return name.includes(searchText) || type.includes(searchText) || basinName.includes(searchText);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const r of filteredRivers) {
|
||||||
const discharge = r.discharge + " m³/s";
|
const discharge = r.discharge + " m³/s";
|
||||||
const length = rn(r.length * distanceScale) + " " + unit;
|
const length = rn(r.length * distanceScale) + " " + unit;
|
||||||
const width = rn(r.width * distanceScale, 3) + " " + unit;
|
const width = rn(r.width * distanceScale, 3) + " " + unit;
|
||||||
|
|
@ -63,12 +77,12 @@ function overviewRivers() {
|
||||||
body.insertAdjacentHTML("beforeend", lines);
|
body.insertAdjacentHTML("beforeend", lines);
|
||||||
|
|
||||||
// update footer
|
// update footer
|
||||||
riversFooterNumber.innerHTML = pack.rivers.length;
|
riversFooterNumber.innerHTML = filteredRivers.length;
|
||||||
const averageDischarge = rn(d3.mean(pack.rivers.map(r => r.discharge)));
|
const averageDischarge = rn(d3.mean(filteredRivers.map(r => r.discharge)));
|
||||||
riversFooterDischarge.innerHTML = averageDischarge + " m³/s";
|
riversFooterDischarge.innerHTML = averageDischarge + " m³/s";
|
||||||
const averageLength = rn(d3.mean(pack.rivers.map(r => r.length)));
|
const averageLength = rn(d3.mean(filteredRivers.map(r => r.length)));
|
||||||
riversFooterLength.innerHTML = averageLength * distanceScale + " " + unit;
|
riversFooterLength.innerHTML = averageLength * distanceScale + " " + unit;
|
||||||
const averageWidth = rn(d3.mean(pack.rivers.map(r => r.width)), 3);
|
const averageWidth = rn(d3.mean(filteredRivers.map(r => r.width)), 3);
|
||||||
riversFooterWidth.innerHTML = rn(averageWidth * distanceScale, 3) + " " + unit;
|
riversFooterWidth.innerHTML = rn(averageWidth * distanceScale, 3) + " " + unit;
|
||||||
|
|
||||||
// add listeners
|
// add listeners
|
||||||
|
|
|
||||||
|
|
@ -25,13 +25,25 @@ function overviewRoutes() {
|
||||||
byId("routesExport").on("click", downloadRoutesData);
|
byId("routesExport").on("click", downloadRoutesData);
|
||||||
byId("routesLockAll").on("click", toggleLockAll);
|
byId("routesLockAll").on("click", toggleLockAll);
|
||||||
byId("routesRemoveAll").on("click", triggerAllRoutesRemove);
|
byId("routesRemoveAll").on("click", triggerAllRoutesRemove);
|
||||||
|
byId("routesSearch").addEventListener("input", routesOverviewAddLines);
|
||||||
|
|
||||||
// add line for each route
|
// add line for each route
|
||||||
function routesOverviewAddLines() {
|
function routesOverviewAddLines() {
|
||||||
body.innerHTML = "";
|
body.innerHTML = "";
|
||||||
let lines = "";
|
let lines = "";
|
||||||
|
const searchText = (byId("routesSearch").value || "").toLowerCase().trim();
|
||||||
|
let filteredRoutes = pack.routes;
|
||||||
|
|
||||||
for (const route of pack.routes) {
|
// filter by search text
|
||||||
|
if (searchText) {
|
||||||
|
filteredRoutes = filteredRoutes.filter(route => {
|
||||||
|
const name = (route.name || "").toLowerCase();
|
||||||
|
const group = (route.group || "").toLowerCase();
|
||||||
|
return name.includes(searchText) || group.includes(searchText);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const route of filteredRoutes) {
|
||||||
if (!route.points || route.points.length < 2) continue;
|
if (!route.points || route.points.length < 2) continue;
|
||||||
route.name = route.name || Routes.generateName(route);
|
route.name = route.name || Routes.generateName(route);
|
||||||
route.length = route.length || Routes.getLength(route.i);
|
route.length = route.length || Routes.getLength(route.i);
|
||||||
|
|
@ -58,8 +70,8 @@ function overviewRoutes() {
|
||||||
body.insertAdjacentHTML("beforeend", lines);
|
body.insertAdjacentHTML("beforeend", lines);
|
||||||
|
|
||||||
// update footer
|
// update footer
|
||||||
routesFooterNumber.innerHTML = pack.routes.length;
|
routesFooterNumber.innerHTML = filteredRoutes.length;
|
||||||
const averageLength = rn(d3.mean(pack.routes.map(r => r.length)) || 0);
|
const averageLength = rn(d3.mean(filteredRoutes.map(r => r.length)) || 0);
|
||||||
routesFooterLength.innerHTML = averageLength * distanceScale + " " + distanceUnitInput.value;
|
routesFooterLength.innerHTML = averageLength * distanceScale + " " + distanceUnitInput.value;
|
||||||
|
|
||||||
// add listeners
|
// add listeners
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue