diff --git a/public/modules/dynamic/editors/cultures-editor.js b/public/modules/dynamic/editors/cultures-editor.js index 5c2b9b5b4..3ceeec7c4 100644 --- a/public/modules/dynamic/editors/cultures-editor.js +++ b/public/modules/dynamic/editors/cultures-editor.js @@ -4,6 +4,18 @@ let culturesManualHistory = []; const cultureTypes = ["Generic", "River", "Lake", "Naval", "Nomadic", "Hunting", "Highland"]; +const culturesPage = {page: 1}; +const CULTURES_SORT_ACCESSORS = { + name: c => c.name, + type: c => c.type || "", + base: c => c.base, + cells: c => c.cells, + expansionism: c => c.expansionism || 0, + area: c => c.area, + population: c => c.rural * populationRate + c.urban * populationRate * urbanization, + emblems: c => c.shield +}; + export function open() { closeDialogs("#culturesEditor, .stable"); if (!layerIsOn("toggleCultures")) toggleCultures(); @@ -12,6 +24,7 @@ export function open() { if (layerIsOn("toggleReligions")) toggleReligions(); if (layerIsOn("toggleProvinces")) toggleProvinces(); + culturesPage.page = 1; refreshCulturesEditor(); $("#culturesEditor").dialog({ @@ -77,6 +90,10 @@ function insertEditorHtml() { function addListeners() { applySortingByHeader("culturesHeader"); + bindEditorSortReset(ensureEl("culturesHeader"), () => { + culturesPage.page = 1; + culturesEditorAddLines(); + }); ensureEl("culturesEditorRefresh").on("click", refreshCulturesEditor); ensureEl("culturesEditStyle").on("click", () => editStyle("cults")); @@ -120,15 +137,25 @@ function culturesCollectStatistics() { function culturesEditorAddLines() { const unit = getAreaUnit(); - let lines = ""; - let totalArea = 0; - let totalPopulation = 0; const emblemShapeGroup = ensureEl("emblemShape").selectedOptions[0]?.parentNode?.label; const selectShape = emblemShapeGroup === "Diversiform"; - for (const c of pack.cultures) { - if (c.removed) continue; + const allCultures = pack.cultures.filter(c => !c.removed); + sortDataByActiveHeader(ensureEl("culturesHeader"), allCultures, CULTURES_SORT_ACCESSORS); + + // footer totals over the full set + let totalArea = 0; + let totalPopulation = 0; + for (const c of allCultures) { + totalArea += getArea(c.area); + totalPopulation += rn(c.rural * populationRate + c.urban * populationRate * urbanization); + } + + const pageInfo = getEditorPage(allCultures, culturesPage); + let lines = ""; + + for (const c of pageInfo.items) { const area = getArea(c.area); const rural = c.rural * populationRate; const urban = c.urban * populationRate * urbanization; @@ -136,8 +163,6 @@ function culturesEditorAddLines() { const populationTip = `Total population: ${si(population)}. Rural population: ${si(rural)}. Urban population: ${si( urban )}. Click to edit`; - totalArea += area; - totalPopulation += population; if (!c.i) { // Uncultured (neutral) line @@ -231,6 +256,11 @@ function culturesEditorAddLines() { ensureEl("culturesFooterArea").dataset.area = totalArea; ensureEl("culturesFooterPopulation").dataset.population = totalPopulation; + renderEditorPagination(ensureEl("culturesFooter"), pageInfo, page => { + culturesPage.page = page; + culturesEditorAddLines(); + }); + // add listeners $body.querySelectorAll(":scope > div").forEach($line => { $line.on("mouseenter", cultureHighlightOn); @@ -258,7 +288,6 @@ function culturesEditorAddLines() { $body.dataset.type = "absolute"; togglePercentageMode(); } - applySorting($culturesHeader); $("#culturesEditor").dialog({ width: fitContent() }); } @@ -578,12 +607,12 @@ function drawCultureCenters() { .attr("cy", d => pack.cells.p[d.center][1]) .on("mouseenter", d => { tip(tooltip, true); - $body.querySelector(`div[data-id='${d.i}']`).classList.add("selected"); + $body.querySelector(`div[data-id='${d.i}']`)?.classList.add("selected"); cultureHighlightOn(event); }) .on("mouseleave", d => { tip("", true); - $body.querySelector(`div[data-id='${d.i}']`).classList.remove("selected"); + $body.querySelector(`div[data-id='${d.i}']`)?.classList.remove("selected"); cultureHighlightOff(event); }) .call(d3.drag().on("start", cultureCenterDrag)); @@ -682,6 +711,8 @@ function recalculateCultures(force) { function enterCultureManualAssignent() { if (!layerIsOn("toggleCultures")) toggleCultures(); customization = 4; + culturesPage.page = 1; + culturesEditorAddLines(); cults.append("g").attr("id", "temp"); document.querySelectorAll("#culturesBottom > *").forEach(el => (el.style.display = "none")); ensureEl("culturesManuallyButtons").style.display = "inline-block"; @@ -718,8 +749,10 @@ function selectCultureOnMapClick() { const assigned = cults.select("#temp").select("polygon[data-cell='" + i + "']"); const culture = assigned.size() ? +assigned.attr("data-culture") : pack.cells.culture[i]; - $body.querySelector("div.selected").classList.remove("selected"); - $body.querySelector("div[data-id='" + culture + "']").classList.add("selected"); + const $row = $body.querySelector("div[data-id='" + culture + "']"); + if (!$row) return; // clicked culture's row is on another page; ignore to avoid a crash + $body.querySelector("div.selected")?.classList.remove("selected"); + $row.classList.add("selected"); } function dragCultureBrush() { @@ -794,7 +827,7 @@ function exitCulturesManualAssignment(close) { ensureEl("culturesManuallyButtons").style.display = "none"; culturesEditor.querySelectorAll(".hide").forEach(el => el.classList.remove("hidden")); - culturesFooter.style.display = "block"; + culturesFooter.style.display = "flex"; $body.querySelectorAll("div > input, select, span, svg").forEach(e => (e.style.pointerEvents = "all")); if (!close) $("#culturesEditor").dialog({ position: { my: "right top", at: "right-10 top+10", of: "svg" } }); @@ -858,15 +891,16 @@ function addCulture() { function downloadCulturesCsv() { const unit = getAreaUnit("2"); const headers = `Id,Name,Color,Cells,Expansionism,Type,Area ${unit},Population,Namesbase,Emblems Shape,Origins`; - const lines = Array.from($body.querySelectorAll(":scope > div")); - const data = lines.map($line => { - const { id, name, color, cells, expansionism, type, area, population, emblems, base } = $line.dataset; - const namesbase = nameBases[+base].name; - const { origins } = pack.cultures[+id]; - const originList = origins.filter(origin => origin).map(origin => pack.cultures[origin].name); - const originText = '"' + originList.join(", ") + '"'; - return [id, name, color, cells, expansionism, type, area, population, namesbase, emblems, originText].join(","); - }); + const data = pack.cultures + .filter(c => !c.removed) + .map(c => { + const area = getArea(c.area); + const population = rn(c.rural * populationRate + c.urban * populationRate * urbanization); + const namesbase = nameBases[c.base].name; + const originList = (c.origins || []).filter(origin => origin).map(origin => pack.cultures[origin].name); + const originText = '"' + originList.join(", ") + '"'; + return [c.i, c.name, c.color || "", c.cells, c.i ? (c.expansionism ?? "") : "", c.type || "", area, population, namesbase, c.shield, originText].join(","); + }); const csvData = [headers].concat(data).join("\n"); const name = getFileName("Cultures") + ".csv"; diff --git a/public/modules/dynamic/editors/religions-editor.js b/public/modules/dynamic/editors/religions-editor.js index b3d151635..543dc6ec2 100644 --- a/public/modules/dynamic/editors/religions-editor.js +++ b/public/modules/dynamic/editors/religions-editor.js @@ -1,6 +1,18 @@ const $body = insertEditorHtml(); addListeners(); +const religionsPage = {page: 1}; +const RELIGIONS_SORT_ACCESSORS = { + name: r => r.name, + type: r => r.type || "", + form: r => r.form || "", + deity: r => r.deity || "", + area: r => r.area, + population: r => r.rural * populationRate + r.urban * populationRate * urbanization, + expansion: r => r.expansion || "", + expansionism: r => r.expansionism || 0 +}; + export function open() { closeDialogs("#religionsEditor, .stable"); if (!layerIsOn("toggleReligions")) toggleReligions(); @@ -9,6 +21,7 @@ export function open() { if (layerIsOn("toggleCultures")) toggleCultures(); if (layerIsOn("toggleProvinces")) toggleProvinces(); + religionsPage.page = 1; refreshReligionsEditor(); drawReligionCenters(); @@ -92,6 +105,10 @@ function insertEditorHtml() { function addListeners() { applySortingByHeader("religionsHeader"); + bindEditorSortReset(ensureEl("religionsHeader"), () => { + religionsPage.page = 1; + religionsEditorAddLines(); + }); ensureEl("religionsEditorRefresh").on("click", refreshReligionsEditor); ensureEl("religionsEditStyle").on("click", () => editStyle("relig")); @@ -129,17 +146,27 @@ function religionsCollectStatistics() { } } -// add line for each religion +// add line for each religion (current page only; sort + totals span all religions) function religionsEditorAddLines() { const unit = " " + getAreaUnit(); - let lines = ""; + + const allReligions = pack.religions.filter( + r => !r.removed && !(r.i && !r.cells && $body.dataset.extinct !== "show") + ); + sortDataByActiveHeader(ensureEl("religionsHeader"), allReligions, RELIGIONS_SORT_ACCESSORS); + + // footer totals over the full (visible) set let totalArea = 0; let totalPopulation = 0; + for (const r of allReligions) { + totalArea += getArea(r.area); + totalPopulation += rn(r.rural * populationRate + r.urban * populationRate * urbanization); + } - for (const r of pack.religions) { - if (r.removed) continue; - if (r.i && !r.cells && $body.dataset.extinct !== "show") continue; // hide extinct religions + const pageInfo = getEditorPage(allReligions, religionsPage); + let lines = ""; + for (const r of pageInfo.items) { const area = getArea(r.area); const rural = r.rural * populationRate; const urban = r.urban * populationRate * urbanization; @@ -147,8 +174,6 @@ function religionsEditorAddLines() { const populationTip = `Believers: ${si(population)}; Rural areas: ${si(rural)}; Urban areas: ${si( urban )}. Click to change`; - totalArea += area; - totalPopulation += population; if (!r.i) { // No religion (neutral) line @@ -233,6 +258,11 @@ function religionsEditorAddLines() { ensureEl("religionsFooterArea").dataset.area = totalArea; ensureEl("religionsFooterPopulation").dataset.population = totalPopulation; + renderEditorPagination(ensureEl("religionsFooter"), pageInfo, page => { + religionsPage.page = page; + religionsEditorAddLines(); + }); + // add listeners $body.querySelectorAll(":scope > div").forEach($line => { $line.on("mouseenter", religionHighlightOn); @@ -258,7 +288,6 @@ function religionsEditorAddLines() { togglePercentageMode(); } - applySorting(religionsHeader); $("#religionsEditor").dialog({ width: fitContent() }); } @@ -640,6 +669,7 @@ async function showHierarchy() { } function toggleExtinct() { + religionsPage.page = 1; $body.dataset.extinct = $body.dataset.extinct !== "show" ? "show" : "hide"; religionsEditorAddLines(); drawReligionCenters(); @@ -648,6 +678,8 @@ function toggleExtinct() { function enterReligionsManualAssignent() { if (!layerIsOn("toggleReligions")) toggleReligions(); customization = 7; + religionsPage.page = 1; + religionsEditorAddLines(); relig.append("g").attr("id", "temp"); document.querySelectorAll("#religionsBottom > *").forEach(el => (el.style.display = "none")); ensureEl("religionsManuallyButtons").style.display = "inline-block"; @@ -683,8 +715,10 @@ function selectReligionOnMapClick() { const assigned = relig.select("#temp").select("polygon[data-cell='" + i + "']"); const religion = assigned.size() ? +assigned.attr("data-religion") : pack.cells.religion[i]; - $body.querySelector("div.selected").classList.remove("selected"); - $body.querySelector("div[data-id='" + religion + "']").classList.add("selected"); + const $row = $body.querySelector("div[data-id='" + religion + "']"); + if (!$row) return; // clicked religion's row is on another page; ignore to avoid a crash + $body.querySelector("div.selected")?.classList.remove("selected"); + $row.classList.add("selected"); } function dragReligionBrush() { @@ -760,7 +794,7 @@ function exitReligionsManualAssignment(close) { ensureEl("religionsEditor") .querySelectorAll(".hide") .forEach(el => el.classList.remove("hidden")); - ensureEl("religionsFooter").style.display = "block"; + ensureEl("religionsFooter").style.display = "flex"; $body.querySelectorAll("div > input, select, span, svg").forEach(e => (e.style.pointerEvents = "all")); if (!close) $("#religionsEditor").dialog({ position: { my: "right top", at: "right-10 top+10", of: "svg" } }); @@ -809,15 +843,28 @@ function addReligion() { function downloadReligionsCsv() { const unit = getAreaUnit("2"); const headers = `Id,Name,Color,Type,Form,Supreme Deity,Area ${unit},Believers,Origins,Potential,Expansionism`; - const lines = Array.from($body.querySelectorAll(":scope > div")); - const data = lines.map($line => { - const { id, name, color, type, form, deity, area, population, expansion, expansionism } = $line.dataset; - const deityText = '"' + deity + '"'; - const { origins } = pack.religions[+id]; - const originList = (origins || []).filter(origin => origin).map(origin => pack.religions[origin].name); - const originText = '"' + originList.join(", ") + '"'; - return [id, name, color, type, form, deityText, area, population, originText, expansion, expansionism].join(","); - }); + const data = pack.religions + .filter(r => !r.removed && !(r.i && !r.cells && $body.dataset.extinct !== "show")) + .map(r => { + const area = getArea(r.area); + const population = rn(r.rural * populationRate + r.urban * populationRate * urbanization); + const deityText = '"' + (r.deity || "") + '"'; + const originList = (r.origins || []).filter(origin => origin).map(origin => pack.religions[origin].name); + const originText = '"' + originList.join(", ") + '"'; + return [ + r.i, + r.name, + r.color || "", + r.type || "", + r.form || "", + deityText, + area, + population, + originText, + r.expansion || "", + r.i ? (r.expansionism ?? "") : "" + ].join(","); + }); const csvData = [headers].concat(data).join("\n"); const name = getFileName("Religions") + ".csv"; diff --git a/public/modules/dynamic/editors/states-editor.js b/public/modules/dynamic/editors/states-editor.js index 1433aac92..2548ebb1b 100644 --- a/public/modules/dynamic/editors/states-editor.js +++ b/public/modules/dynamic/editors/states-editor.js @@ -1,6 +1,19 @@ const $body = insertEditorHtml(); addListeners(); let statesManualHistory = []; +const statesPage = {page: 1}; +const STATES_SORT_ACCESSORS = { + name: s => s.name, + form: s => s.formName, + capital: s => (s.i ? pack.burgs[s.capital].name : ""), + culture: s => (s.i ? pack.cultures[s.culture].name : ""), + burgs: s => s.burgs, + area: s => s.area, + population: s => s.rural * populationRate + s.urban * populationRate * urbanization, + type: s => s.type || "", + expansionism: s => s.expansionism || 0, + cells: s => s.cells +}; export function open() { closeDialogs("#statesEditor, .stable"); @@ -10,6 +23,7 @@ export function open() { if (layerIsOn("toggleBiomes")) toggleBiomes(); if (layerIsOn("toggleReligions")) toggleReligions(); + statesPage.page = 1; refreshStatesEditor(); $("#statesEditor").dialog({ @@ -96,6 +110,10 @@ function insertEditorHtml() { function addListeners() { applySortingByHeader("statesHeader"); + bindEditorSortReset(ensureEl("statesHeader"), () => { + statesPage.page = 1; + statesEditorAddLines(); + }); ensureEl("statesEditorRefresh").on("click", refreshStatesEditor); ensureEl("statesEditStyle").on("click", () => editStyle("regions")); @@ -156,17 +174,28 @@ function refreshStatesEditor() { statesEditorAddLines(); } -// add line for each state +// add line for each state (current page only; sort + totals span all states) function statesEditorAddLines() { const unit = getAreaUnit(); const hidden = ensureEl("statesRegenerateButtons").style.display === "block" ? "" : "hidden"; // toggle regenerate columns - let lines = ""; + + const allStates = pack.states.filter(s => !s.removed); + sortDataByActiveHeader(ensureEl("statesHeader"), allStates, STATES_SORT_ACCESSORS); + + // footer totals over the full set let totalArea = 0; let totalPopulation = 0; let totalBurgs = 0; + for (const s of allStates) { + totalArea += getArea(s.area); + totalPopulation += rn(s.rural * populationRate + s.urban * populationRate * urbanization); + totalBurgs += s.burgs; + } - for (const s of pack.states) { - if (s.removed) continue; + const pageInfo = getEditorPage(allStates, statesPage); + let lines = ""; + + for (const s of pageInfo.items) { const area = getArea(s.area); const rural = s.rural * populationRate; const urban = s.urban * populationRate * urbanization; @@ -174,9 +203,6 @@ function statesEditorAddLines() { const populationTip = `Total population: ${si(population)}; Rural population: ${si(rural)}; Urban population: ${si( urban )}. Click to change`; - totalArea += area; - totalPopulation += population; - totalBurgs += s.burgs; const focused = defs.select("#fog #focusState" + s.i).size(); if (!s.i) { @@ -283,6 +309,11 @@ function statesEditorAddLines() { ensureEl("statesFooterPopulation").innerHTML = si(totalPopulation); ensureEl("statesFooterPopulation").dataset.population = totalPopulation; + renderEditorPagination(ensureEl("statesFooter"), pageInfo, page => { + statesPage.page = page; + statesEditorAddLines(); + }); + // add listeners $body.querySelectorAll(":scope > div").forEach($line => { $line.on("mouseenter", stateHighlightOn); @@ -294,7 +325,6 @@ function statesEditorAddLines() { $body.dataset.type = "absolute"; togglePercentageMode(); } - applySorting(statesHeader); $("#statesEditor").dialog({ width: fitContent() }); } @@ -873,7 +903,8 @@ function randomizeStatesExpansion() { if (!s.i || s.removed) return; const expansionism = rn(Math.random() * 4 + 1, 1); s.expansionism = expansionism; - $body.querySelector("div.states[data-id='" + s.i + "'] > input.statePower").value = expansionism; + const $power = $body.querySelector("div.states[data-id='" + s.i + "'] > input.statePower"); + if ($power) $power.value = expansionism; }); recalculateStates(true, true); } @@ -892,6 +923,8 @@ function exitRegenerationMenu() { function enterStatesManualAssignent() { if (!layerIsOn("toggleStates")) toggleStates(); customization = 2; + statesPage.page = 1; + statesEditorAddLines(); statesBody.append("g").attr("id", "temp"); document.querySelectorAll("#statesBottom > button").forEach(el => (el.style.display = "none")); ensureEl("statesManuallyButtons").style.display = "inline-block"; @@ -930,8 +963,10 @@ function selectStateOnMapClick() { const assigned = statesBody.select("#temp").select("polygon[data-cell='" + i + "']"); const state = assigned.size() ? +assigned.attr("data-state") : pack.cells.state[i]; - $body.querySelector("div.selected").classList.remove("selected"); - $body.querySelector("div[data-id='" + state + "']").classList.add("selected"); + const $row = $body.querySelector("div[data-id='" + state + "']"); + if (!$row) return; // clicked state's row is on another page; ignore to avoid a crash + $body.querySelector("div.selected")?.classList.remove("selected"); + $row.classList.add("selected"); } function dragStateBrush() { @@ -1171,7 +1206,7 @@ function exitStatesManualAssignment(close) { ensureEl("statesEditor") .querySelectorAll(".hide:not(.show)") .forEach(el => el.classList.remove("hidden")); - statesFooter.style.display = "block"; + statesFooter.style.display = "flex"; $body.querySelectorAll("div > input, select, span, svg").forEach(e => (e.style.pointerEvents = "all")); if (!close) $("#statesEditor").dialog({ position: { my: "right top", at: "right-10 top+10", of: "svg", collision: "fit" } }); @@ -1491,31 +1526,33 @@ function openStateMergeDialog() { function downloadStatesCsv() { const unit = getAreaUnit("2"); const headers = `Id,State,Full Name,Form,Color,Capital,Culture,Type,Expansionism,Cells,Burgs,Area ${unit},Total Population,Rural Population,Urban Population`; - const lines = Array.from($body.querySelectorAll(":scope > div")); - const data = lines.map($line => { - const { id, name, form, color, capital, culture, type, expansionism, cells, burgs, area, population } = - $line.dataset; - const { fullName = "", rural, urban } = pack.states[+id]; - const ruralPopulation = Math.round(rural * populationRate); - const urbanPopulation = Math.round(urban * populationRate * urbanization); - return [ - id, - name, - fullName, - form, - color, - capital, - culture, - type, - expansionism, - cells, - burgs, - area, - population, - ruralPopulation, - urbanPopulation - ].join(","); - }); + const data = pack.states + .filter(s => !s.removed) + .map(s => { + const area = getArea(s.area); + const ruralPopulation = Math.round(s.rural * populationRate); + const urbanPopulation = Math.round(s.urban * populationRate * urbanization); + const population = ruralPopulation + urbanPopulation; + const capital = s.i ? pack.burgs[s.capital].name : ""; + const culture = s.i ? pack.cultures[s.culture].name : ""; + return [ + s.i, + s.name, + s.fullName || "", + s.formName || "", + s.color || "", + capital, + culture, + s.type || "", + s.expansionism ?? "", + s.cells, + s.burgs, + area, + population, + ruralPopulation, + urbanPopulation + ].join(","); + }); const csvData = [headers].concat(data).join("\n"); const name = getFileName("States") + ".csv"; diff --git a/public/modules/ui/burgs-overview.js b/public/modules/ui/burgs-overview.js index ce922e22b..e78dd4ea4 100644 --- a/public/modules/ui/burgs-overview.js +++ b/public/modules/ui/burgs-overview.js @@ -1,4 +1,19 @@ "use strict"; + +const burgsPage = {page: 1}; +const BURGS_SORT_ACCESSORS = { + name: b => b.name || "", + province: b => { + const p = pack.cells.province[b.cell]; + return p ? pack.provinces[p]?.name || "" : ""; + }, + state: b => pack.states[b.state]?.name || "", + culture: b => pack.cultures[b.culture]?.name || "", + group: b => b.group || "", + population: b => b.population * populationRate * urbanization, + features: b => (b.capital && b.port ? "a-capital-port" : b.capital ? "c-capital" : b.port ? "p-port" : "z-burg") +}; + function overviewBurgs(settings = {stateId: null, cultureId: null}) { if (customization) return; closeDialogs("#burgsOverview, .stable"); @@ -8,6 +23,7 @@ function overviewBurgs(settings = {stateId: null, cultureId: null}) { const body = ensureEl("burgsBody"); updateFilter(); updateLockAllIcon(); + burgsPage.page = 1; burgsOverviewAddLines(); $("#burgsOverview").dialog(); @@ -26,9 +42,9 @@ function overviewBurgs(settings = {stateId: null, cultureId: null}) { ensureEl("burgsOverviewRefresh").addEventListener("click", refreshBurgsEditor); ensureEl("burgsGroupsEditorButton").addEventListener("click", editBurgGroups); ensureEl("burgsChart").addEventListener("click", showBurgsChart); - ensureEl("burgsFilterState").addEventListener("change", burgsOverviewAddLines); - ensureEl("burgsFilterCulture").addEventListener("change", burgsOverviewAddLines); - ensureEl("burgsSearch").addEventListener("input", burgsOverviewAddLines); + ensureEl("burgsFilterState").addEventListener("change", resetAndRender); + ensureEl("burgsFilterCulture").addEventListener("change", resetAndRender); + ensureEl("burgsSearch").addEventListener("input", resetAndRender); ensureEl("regenerateBurgNames").addEventListener("click", regenerateNames); ensureEl("addNewBurg").addEventListener("click", enterAddBurgMode); ensureEl("burgsExport").addEventListener("click", downloadBurgsData); @@ -39,8 +55,17 @@ function overviewBurgs(settings = {stateId: null, cultureId: null}) { ensureEl("burgsLockAll").addEventListener("click", toggleLockAll); ensureEl("burgsRemoveAll").addEventListener("click", triggerAllBurgsRemove); + // re-render on column sort so sorting applies across all pages, not just the visible one + bindEditorSortReset(ensureEl("burgsHeader"), resetAndRender); + + function resetAndRender() { + burgsPage.page = 1; + burgsOverviewAddLines(); + } + function refreshBurgsEditor() { updateFilter(); + burgsPage.page = 1; burgsOverviewAddLines(); } @@ -62,14 +87,13 @@ function overviewBurgs(settings = {stateId: null, cultureId: null}) { culturesSorted.forEach(c => cultureFilter.options.add(new Option(c.name, c.i, false, c.i == selectedCulture))); } - // add line for each burg - function burgsOverviewAddLines() { + // collect the burgs matching the current search + state/culture filters (all pages) + function getFilteredBurgs() { const searchText = ensureEl("burgsSearch").value.toLowerCase().trim(); const selectedStateId = +ensureEl("burgsFilterState").value; const selectedCultureId = +ensureEl("burgsFilterCulture").value; - const validBurgs = pack.burgs.filter(b => b.i && !b.removed); - let filtered = validBurgs; + let filtered = pack.burgs.filter(b => b.i && !b.removed); if (searchText) { // filter by search text @@ -90,14 +114,25 @@ function overviewBurgs(settings = {stateId: null, cultureId: null}) { } 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 + return filtered; + } + + // add line for each burg (current page only; sort, totals and footer span the full filtered set) + function burgsOverviewAddLines() { + const validCount = pack.burgs.filter(b => b.i && !b.removed).length; + const filtered = getFilteredBurgs(); + sortDataByActiveHeader(ensureEl("burgsHeader"), filtered, BURGS_SORT_ACCESSORS); + + let totalPopulation = 0; + for (const b of filtered) totalPopulation += b.population * populationRate * urbanization; + + const pageInfo = getEditorPage(filtered, burgsPage); body.innerHTML = ""; let lines = ""; - let totalPopulation = 0; - for (const b of filtered) { + for (const b of pageInfo.items) { const population = b.population * populationRate * urbanization; - totalPopulation += population; const features = b.capital && b.port ? "a-capital-port" : b.capital ? "c-capital" : b.port ? "p-port" : "z-burg"; const state = pack.states[b.state].name; const prov = pack.cells.province[b.cell]; @@ -140,10 +175,15 @@ function overviewBurgs(settings = {stateId: null, cultureId: null}) { if (!filtered.length) body.innerHTML = /* html */ `