← back to Commercialrealestate
Adopt column-manager.js in gov-agents + sales (TK-10120 sweep)
a01bf5ea00acb0cbb4fbbdd480ee3a4c81b50732 · 2026-08-01 22:25:21 -0700 · Steve Abrams
The 2 CRCP grid pages that share mls's exact column-state pattern get the shared
column-manager panel (grouped by their real c.g + in-panel search + drag-reorder),
wired as a view over each page's own VISCOL/COLORDER. Same 4-edit swap as mls:
replace buildFieldToggles, remove the now-duplicate #fFields change handler,
refresh the panel after a thead reorder, load the script. Graceful fallback to the
old grouped toggle list if the module hasn't loaded.
Verified live (:9943, real-mouse) on BOTH: panel mounts with real groups
(gov-agents Identity/License/Location; sales Property/Sale/Unit/Details), toggle
re-renders the grid, sort works (confirmed on a varied column), resize works,
0 console errors.
Survey finding: of the ~14 surveyed CRCP pages, only these 2 + mls share the
retrofittable pattern — the rest use different column systems (lending-grid.js
engine, COLORDER-without-VISCOL, or no column manager), so the '18-page sweep' was
a false premise; a blind sweep would have broken them.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M public/gov-agents.htmlM public/sales.html
Diff
commit a01bf5ea00acb0cbb4fbbdd480ee3a4c81b50732
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Sat Aug 1 22:25:21 2026 -0700
Adopt column-manager.js in gov-agents + sales (TK-10120 sweep)
The 2 CRCP grid pages that share mls's exact column-state pattern get the shared
column-manager panel (grouped by their real c.g + in-panel search + drag-reorder),
wired as a view over each page's own VISCOL/COLORDER. Same 4-edit swap as mls:
replace buildFieldToggles, remove the now-duplicate #fFields change handler,
refresh the panel after a thead reorder, load the script. Graceful fallback to the
old grouped toggle list if the module hasn't loaded.
Verified live (:9943, real-mouse) on BOTH: panel mounts with real groups
(gov-agents Identity/License/Location; sales Property/Sale/Unit/Details), toggle
re-renders the grid, sort works (confirmed on a varied column), resize works,
0 console errors.
Survey finding: of the ~14 surveyed CRCP pages, only these 2 + mls share the
retrofittable pattern — the rest use different column systems (lending-grid.js
engine, COLORDER-without-VISCOL, or no column manager), so the '18-page sweep' was
a false premise; a blind sweep would have broken them.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
public/gov-agents.html | 27 ++++++++++++++++++++-------
public/sales.html | 27 ++++++++++++++++++++-------
2 files changed, 40 insertions(+), 14 deletions(-)
diff --git a/public/gov-agents.html b/public/gov-agents.html
index 4ecfaf3..83fb79b 100644
--- a/public/gov-agents.html
+++ b/public/gov-agents.html
@@ -144,12 +144,24 @@ function cell(a,c){
if(k==='name') return '<b>'+esc(a[k])+'</b>';
const v=a[k]; return v==null||v===''?'<span class="miss">—</span>':esc(v);
}
+// Column show/hide + in-panel search & drag-reorder via the shared column-manager.js
+// drop-in (TK-10120), as a VIEW over this page's own VISCOL/COLORDER state.
+let __cm=null;
function buildFieldToggles(){
- const groups={};
- COLS.forEach(c=>{ (groups[c.g||'Other']=groups[c.g||'Other']||[]).push(c); });
- $('#fFields').innerHTML=Object.entries(groups).map(([g,cs])=>
- `<div class="fgrp">${esc(g)}</div>`+cs.map(c=>`<label class="ftog"><input type="checkbox" data-ck="${c.k}" ${colVis(c.k)?'checked':''}><span>${esc(c.l)}</span></label>`).join('')
- ).join('');
+ if(!window.ColumnManager){ // fallback if the module hasn't loaded (keeps page usable)
+ const groups={};
+ COLS.forEach(c=>{ (groups[c.g||'Other']=groups[c.g||'Other']||[]).push(c); });
+ $('#fFields').innerHTML=Object.entries(groups).map(([g,cs])=>
+ `<div class="fgrp">${esc(g)}</div>`+cs.map(c=>`<label class="ftog"><input type="checkbox" data-ck="${c.k}" ${colVis(c.k)?'checked':''}><span>${esc(c.l)}</span></label>`).join('')
+ ).join(''); return; }
+ const cols=COLS.map(c=>({k:c.k,l:c.l,g:c.g||'Other'}));
+ if(!__cm){
+ __cm=ColumnManager.init({ mount:'#fFields', footer:false, hint:false, cols,
+ state:{ visible:k=>colVis(k), setVisible:(k,v)=>{VISCOL[k]=v;saveCols();},
+ order:()=>{syncColOrder();return COLORDER.slice();}, setOrder:a=>{COLORDER=a;saveColOrder();},
+ reset:()=>{VISCOL={};saveCols();COLORDER=[];saveColOrder();} },
+ onChange:()=>render() });
+ } else { __cm.setCols(cols); }
}
function filtered(){
let rows=AGENTS.slice();
@@ -240,13 +252,13 @@ $('#thead').addEventListener('drop',e=>{ if(!dragKey) return; const th=e.target.
const r=th.getBoundingClientRect(), after=(e.clientX-r.left)>r.width/2;
syncColOrder(); const from=COLORDER.indexOf(dragKey); if(from>=0){
COLORDER.splice(from,1); let to=COLORDER.indexOf(tgt); if(after) to+=1; COLORDER.splice(to,0,dragKey);
- saveColOrder(); lastColSig=''; render();
+ saveColOrder(); lastColSig=''; render(); if(__cm)__cm.refresh();
}
}
dragKey=null; });
$('#thead').addEventListener('dragend',()=>{ document.querySelectorAll('#thead th.dragging,#thead th.dropL,#thead th.dropR').forEach(x=>x.classList.remove('dragging','dropL','dropR')); dragKey=null; });
// ── left-rail column show/hide toggles ──
-$('#fFields').addEventListener('change',e=>{const cb=e.target.closest('input[data-ck]');if(!cb)return;VISCOL[cb.dataset.ck]=cb.checked;saveCols();render();});
+// (#fFields change is handled inside column-manager.js now — its onChange calls render)
$('#fAll').addEventListener('click',()=>{COLS.forEach(c=>VISCOL[c.k]=true);saveCols();buildFieldToggles();render();});
$('#fNone').addEventListener('click',()=>{COLS.forEach(c=>VISCOL[c.k]=false);saveCols();buildFieldToggles();render();});
// Reset the whole table layout back to the tight default: visibility, order, widths.
@@ -259,6 +271,7 @@ if(railEl){ railEl.addEventListener('click',e=>{ const h=e.target.closest('h4');
buildSortSel(); buildFieldToggles();
loadIndex();
</script>
+ <script src="/column-manager.js" defer></script>
<script src="/col-resize.js" defer></script>
</body>
</html>
diff --git a/public/sales.html b/public/sales.html
index 5cf91dd..c46a529 100644
--- a/public/sales.html
+++ b/public/sales.html
@@ -193,12 +193,24 @@ function buildRail(){
$('#fBeds').innerHTML=Object.entries(bc).sort((a,b)=>b[1]-a[1]).map(([k,c])=>`<span class="chip" data-bd="${esc(k)}">${esc(k)}<span class="ct">${c}</span></span>`).join('');
buildFieldToggles();
}
+// Column show/hide + in-panel search & drag-reorder via the shared column-manager.js
+// drop-in (TK-10120), as a VIEW over this page's own VISCOL/COLORDER state.
+let __cm=null;
function buildFieldToggles(){
- const groups={};
- COLS.forEach(c=>{ (groups[c.g||'Other']=groups[c.g||'Other']||[]).push(c); });
- $('#fFields').innerHTML=Object.entries(groups).map(([g,cs])=>
- `<div class="fgrp">${esc(g)}</div>`+cs.map(c=>`<label class="ftog"><input type="checkbox" data-ck="${c.k}" ${colVis(c.k)?'checked':''}><span>${esc(c.l)}</span></label>`).join('')
- ).join('');
+ if(!window.ColumnManager){ // fallback if the module hasn't loaded (keeps page usable)
+ const groups={};
+ COLS.forEach(c=>{ (groups[c.g||'Other']=groups[c.g||'Other']||[]).push(c); });
+ $('#fFields').innerHTML=Object.entries(groups).map(([g,cs])=>
+ `<div class="fgrp">${esc(g)}</div>`+cs.map(c=>`<label class="ftog"><input type="checkbox" data-ck="${c.k}" ${colVis(c.k)?'checked':''}><span>${esc(c.l)}</span></label>`).join('')
+ ).join(''); return; }
+ const cols=COLS.map(c=>({k:c.k,l:c.l,g:c.g||'Other'}));
+ if(!__cm){
+ __cm=ColumnManager.init({ mount:'#fFields', footer:false, hint:false, cols,
+ state:{ visible:k=>colVis(k), setVisible:(k,v)=>{VISCOL[k]=v;saveCols();},
+ order:()=>{syncColOrder();return COLORDER.slice();}, setOrder:a=>{COLORDER=a;saveColOrder();},
+ reset:()=>{VISCOL={};saveCols();COLORDER=[];saveColOrder();} },
+ onChange:()=>render() });
+ } else { __cm.setCols(cols); }
}
function passFacets(r){
if(F.city.size && !F.city.has(r.city)) return false;
@@ -294,7 +306,7 @@ $('#thead').addEventListener('drop',e=>{ if(!dragKey) return; const th=e.target.
const r=th.getBoundingClientRect(), after=(e.clientX-r.left)>r.width/2;
syncColOrder(); const from=COLORDER.indexOf(dragKey); if(from>=0){
COLORDER.splice(from,1); let to=COLORDER.indexOf(tgt); if(after) to+=1; COLORDER.splice(to,0,dragKey);
- saveColOrder(); lastColSig=''; render();
+ saveColOrder(); lastColSig=''; render(); if(__cm)__cm.refresh();
}
}
dragKey=null; });
@@ -339,7 +351,7 @@ $('#view').addEventListener('click',e=>{const b=e.target.closest('button');if(!b
$('#fCity').addEventListener('click',e=>{const c=e.target.closest('.chip');if(!c)return;tog(F.city,c.dataset.ci);c.classList.toggle('active');render();});
$('#fYear').addEventListener('click',e=>{const c=e.target.closest('.chip');if(!c)return;tog(F.year,c.dataset.yr);c.classList.toggle('active');render();});
$('#fBeds').addEventListener('click',e=>{const c=e.target.closest('.chip');if(!c)return;tog(F.beds,c.dataset.bd);c.classList.toggle('active');render();});
-$('#fFields').addEventListener('change',e=>{const cb=e.target.closest('input[data-ck]');if(!cb)return;VISCOL[cb.dataset.ck]=cb.checked;saveCols();render();});
+// (#fFields change is handled inside column-manager.js now — its onChange calls render)
$('#fAll').addEventListener('click',()=>{COLS.forEach(c=>VISCOL[c.k]=true);saveCols();buildFieldToggles();render();});
$('#fNone').addEventListener('click',()=>{COLS.forEach(c=>VISCOL[c.k]=false);saveCols();buildFieldToggles();render();});
// Reset the whole table layout back to the tight default: visibility, order, widths.
@@ -369,6 +381,7 @@ fetch('/api/closed-sales?limit=5000').then(r=>r.json()).then(d=>{
autoCols(); if(window.__buildSortSel)window.__buildSortSel(); buildRail(); render(); drawCharts(d);
}).catch(()=>{ $('#count').textContent='failed to load /api/closed-sales'; $('#stat').textContent='sold-comps load error.'; });
</script>
+ <script src="/column-manager.js" defer></script>
<script src="/col-resize.js" defer></script>
</body>
</html>
← 3b9663c column-manager: add external-state + footer/hint opts; adopt
·
back to Commercialrealestate
·
auto-save: 2026-08-01T22:40:01 (1 files) — public/lending-gr 4ba8f30 →