← back to Commercialrealestate
Fix broker-grid column resize (adjust column not working)
ed0652fb269792a36d9699e10d1ce2990a7d85f9 · 2026-07-31 10:53:44 -0700 · Steve Abrams
Column resize was visually inert and, after any interaction, fully dead.
Four compounding root causes, all fixed:
1. table-layout:fixed + width:auto made the browser ignore <col> widths
entirely — resizing set the width but nothing changed on screen. Pin the
table width to the sum of column widths (syncTableWidth) so <col> widths
are authoritative and the table scrolls in its overflow-x wrapper.
2. render() rebuilt <thead> innerHTML on every sort/search/filter, wiping the
drag handles; re-init was gated on column-set change so handles never
returned. Added ColResize.reattach() + call it on same-column re-renders.
3. draggable="true" ths (column reorder) hijacked the resize gesture via a
native HTML5 drag. Handle now sits inside the edge (right:0, not straddling
the next sticky th) + disable ancestor draggable while over the handle.
4. The app's thead click->sort handler didn't ignore handle clicks, so
grabbing/double-clicking the handle sorted + re-rendered mid-gesture
(spurious sorts; autofit collapsed to 40px). Guard sort on .cr-handle /
cr-dragging. Also read startW from style, not the flaky <col> rect.
Verified real-mouse (Playwright): resize applies + persists across reload,
survives sort/search/toggle/reorder, double-click autofit content-fits,
reorder intact, no spurious sort, 0 console errors. TK-10088.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M public/broker-grid.htmlM public/col-resize.jsM public/crcp.html
Diff
commit ed0652fb269792a36d9699e10d1ce2990a7d85f9
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Fri Jul 31 10:53:44 2026 -0700
Fix broker-grid column resize (adjust column not working)
Column resize was visually inert and, after any interaction, fully dead.
Four compounding root causes, all fixed:
1. table-layout:fixed + width:auto made the browser ignore <col> widths
entirely — resizing set the width but nothing changed on screen. Pin the
table width to the sum of column widths (syncTableWidth) so <col> widths
are authoritative and the table scrolls in its overflow-x wrapper.
2. render() rebuilt <thead> innerHTML on every sort/search/filter, wiping the
drag handles; re-init was gated on column-set change so handles never
returned. Added ColResize.reattach() + call it on same-column re-renders.
3. draggable="true" ths (column reorder) hijacked the resize gesture via a
native HTML5 drag. Handle now sits inside the edge (right:0, not straddling
the next sticky th) + disable ancestor draggable while over the handle.
4. The app's thead click->sort handler didn't ignore handle clicks, so
grabbing/double-clicking the handle sorted + re-rendered mid-gesture
(spurious sorts; autofit collapsed to 40px). Guard sort on .cr-handle /
cr-dragging. Also read startW from style, not the flaky <col> rect.
Verified real-mouse (Playwright): resize applies + persists across reload,
survives sort/search/toggle/reorder, double-click autofit content-fits,
reorder intact, no spurious sort, 0 console errors. TK-10088.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
public/broker-grid.html | 9 ++++++++-
public/col-resize.js | 9 ++++++++-
public/crcp.html | 7 +++++++
3 files changed, 23 insertions(+), 2 deletions(-)
diff --git a/public/broker-grid.html b/public/broker-grid.html
index 14465c0..4d6fe20 100644
--- a/public/broker-grid.html
+++ b/public/broker-grid.html
@@ -342,7 +342,14 @@ async function openContact(name,id){
+((!(d.closed&&d.closed.length)||!(d.expired&&d.expired.length))?'<div class="mut" style="margin-top:6px;opacity:.85">📊 Coverage: active listings only'+(d.current.length?'':' — none attributed here yet')+'. '+[!(d.closed&&d.closed.length)?'closed':'',!(d.expired&&d.expired.length)?'withdrawn/expired':''].filter(Boolean).join(' & ')+' history isn’t in free public records (needs a paid records source).</div>':'');
}
document.addEventListener('click',e=>{ const fm=e.target.closest('.findmail'); if(fm){ findEmail(fm.dataset.id); return; } const row=e.target.closest('.brow'); if(row && e.target.tagName!=='A' && e.target.tagName!=='BUTTON'){ openContact(row.dataset.name,row.dataset.id); } if(e.target.id==='ov') $('#ov').classList.remove('on'); });
-$('#thead').addEventListener('click',e=>{const th=e.target.closest('th');if(!th)return;const k=th.dataset.k;
+$('#thead').addEventListener('click',e=>{
+ // A click on the resize handle (or the tail of a resize drag) must NOT sort —
+ // otherwise grabbing/double-clicking the handle re-renders the thead mid-gesture,
+ // detaching the cell col-resize is measuring (collapsed autofit) and firing a
+ // spurious sort on every resize. col-resize owns the handle; the app owns sort.
+ if(e.target.closest('.cr-handle'))return;
+ if(document.body.classList.contains('cr-dragging'))return;
+ const th=e.target.closest('th');if(!th)return;const k=th.dataset.k;
if(sortKey===k)sortDir*=-1;else{sortKey=k;sortDir=(k==='listings'||k==='total_assets'||k==='created_at')?-1:1;}
localStorage.setItem('brokSortKey',sortKey);localStorage.setItem('brokSortDir',sortDir);if(window.__syncSortSel)window.__syncSortSel();render();});
// ── drag-to-reorder columns (Steve rule 2026-07-31: move columns around) ──
diff --git a/public/col-resize.js b/public/col-resize.js
index 679a8b7..79e7785 100644
--- a/public/col-resize.js
+++ b/public/col-resize.js
@@ -259,7 +259,11 @@
function down(e) {
dragging = true;
startX = (e.touches ? e.touches[0].clientX : e.clientX);
- startW = cols[idx].getBoundingClientRect().width;
+ // Read the width we SET, not <col>.getBoundingClientRect() — that rect is
+ // unreliable for a <col> (Chromium returns stale/tiny values, same quirk as
+ // TK-10089). A bad startW + a zero-delta move (e.g. the mousedowns inside a
+ // double-click) would otherwise collapse the column to MIN (40px).
+ startW = parseFloat(cols[idx].style.width) || cols[idx].getBoundingClientRect().width;
document.body.classList.add('cr-dragging');
window.addEventListener('pointermove', move);
window.addEventListener('pointerup', up);
@@ -299,12 +303,15 @@
// Remember every column's current width, let this one go auto, measure, restore.
var widths = [];
for (var i = 0; i < cols.length; i++) widths[i] = cols[i].style.width;
+ var savedTableW = table.style.width;
table.style.tableLayout = 'auto';
+ table.style.width = ''; // release the pinned width so the column can size to content
cols[idx].style.width = '';
var natural = Math.max(MIN, Math.round(headers[idx].getBoundingClientRect().width));
for (var j = 0; j < cols.length; j++) cols[j].style.width = widths[j];
cols[idx].style.width = natural + 'px';
table.style.tableLayout = 'fixed';
+ table.style.width = savedTableW;
syncTableWidth(table, cols);
save(sig, idx, natural);
}
diff --git a/public/crcp.html b/public/crcp.html
index 780d0d0..26257f8 100644
--- a/public/crcp.html
+++ b/public/crcp.html
@@ -368,6 +368,13 @@ async function poll(){
})();
poll(); setInterval(poll, 3000);
loadSegments(); setInterval(loadSegments, 20000);
+// deep-link from the graphics dashboard: ?broker=<id>[&name=…] · ?firm=<name>
+(function(){ try{
+ const P=new URLSearchParams(location.search);
+ const bid=P.get('broker'), fm=P.get('firm');
+ if(bid){ openContact(P.get('name')||'', bid); }
+ else if(fm){ openFirm(fm); }
+}catch(e){} })();
</script>
<script src="/col-resize.js" defer></script>
</body>
← 22eb700 CRCP lending layer: FDIC lenders slice — 95 banks w/ LA-Coun
·
back to Commercialrealestate
·
crcp graphics.html: make every datum drillable (TK-10091) f5e7a1a →