← back to Commercialrealestate
broker-grid.html: add compact-list view (3rd mode) — grid/list/table + all-col sort; contact modal + find-email + facets/search preserved
ca654ac788ae883da0ee8483689427888aca1351 · 2026-08-13 08:16:02 -0700 · steve
Files touched
M public/broker-grid.html
Diff
commit ca654ac788ae883da0ee8483689427888aca1351
Author: steve <steve@designerwallcoverings.com>
Date: Thu Aug 13 08:16:02 2026 -0700
broker-grid.html: add compact-list view (3rd mode) — grid/list/table + all-col sort; contact modal + find-email + facets/search preserved
---
public/broker-grid.html | 23 +++++++++++++++++++----
1 file changed, 19 insertions(+), 4 deletions(-)
diff --git a/public/broker-grid.html b/public/broker-grid.html
index 320a79d..54eeb49 100644
--- a/public/broker-grid.html
+++ b/public/broker-grid.html
@@ -92,6 +92,7 @@
.rail .rsec.collapsed > h4::after { transform:rotate(-90deg); }
.rail .rsec.collapsed > *:not(h4) { display:none !important; }
</style>
+ <link rel="stylesheet" href="/three-view.css">
<link rel="stylesheet" href="/nav-agent/nav-agent.css"><!-- nav-agent -->
</head>
<body>
@@ -100,7 +101,7 @@
<div class="nav"><a href="/crcp.html">← CRCP</a><a href="/">Explorer</a><a href="/mls.html">📋 Listings</a><a href="/gov-agents.html">🏛️ Gov-Licensed</a><a href="/linkedin.html">🔗 LinkedIn</a><a href="/brokers.html">🕸️ Mindmap</a></div>
<span class="spacer"></span>
<input class="search" id="q" type="text" placeholder="search all fields — name, firm, phone, email, license, source… (space = AND)">
- <div class="toggle" id="view"><button data-v="table" class="on">▦ List</button><button data-v="grid">▤ Grid</button></div>
+ <div class="toggle tv-seg" id="view"><button data-v="grid">▦ Grid</button><button data-v="list">☰ List</button><button data-v="table" class="on">▤ Table</button></div>
<select id="sortsel" title="Sort brokers"></select>
<label id="denswrap" title="Card density — grid view">⤢<input type="range" id="density" min="1" max="10" step="1"></label>
<button class="csvbtn" id="csv" title="Export current rows to CSV">⬇ CSV</button>
@@ -120,6 +121,7 @@
<div class="statsbar" id="statsbar"></div>
<div id="tableView" class="tblwrap"><table class="g" data-no-sort><thead id="thead"></thead><tbody id="tbody"></tbody></table></div>
<div id="gridView" class="grid hide"></div>
+ <div id="listView" class="hide"></div>
</div>
</div>
<div id="ov"><div id="modal"><button class="x" aria-label="Close" onclick="document.getElementById('ov').classList.remove('on')">✕</button><div id="mbody"></div></div></div>
@@ -303,8 +305,9 @@ function render(){
const rows=filtered(); const cols=visCols();
$('#count').textContent=`${rows.length} of ${DATA.length} brokers/agents`;
$('#thead').innerHTML='<tr>'+cols.map(c=>`<th data-k="${c.k}" draggable="true" title="Drag to reorder · click to sort" class="dragcol${sortKey===c.k?(sortDir>0?' asc':' desc'):''}">${esc(c.l)}</th>`).join('')+'</tr>';
+ const show=id=>['#tableView','#gridView','#listView'].forEach(s=>$(s).classList.toggle('hide',s!==id));
if(view==='table'){
- $('#tableView').classList.remove('hide'); $('#gridView').classList.add('hide');
+ show('#tableView');
$('#tbody').innerHTML=rows.map(r=>`<tr class="brow" data-id="${r.id}" data-name="${esc(r.name)}" style="cursor:pointer">`+cols.map(c=>{const cls=(c.t==='n')?' class="n"':'';return `<td${cls}>${cell(r,c)}</td>`;}).join('')+'</tr>').join('');
const csig=cols.map(c=>c.k).join(',');
// Column SET/ORDER changed → full colgroup rebuild. Same columns (a sort /
@@ -313,8 +316,18 @@ function render(){
// works on first paint then dies after the first re-render (TK-10088).
if(csig!==lastColSig){ lastColSig=csig; reinitResize(); }
else if(window.ColResize && window.ColResize.reattach){ window.ColResize.reattach(document.querySelector('#tableView table.g')); }
+ } else if(view==='list'){
+ // COMPACT LIST — one scannable row per broker, every VISIBLE column as inline
+ // key/value pairs (reuses cell() so mailto/find-email/DRE/geo HTML matches the
+ // table + cards exactly). TK-10526 additive 3rd view. Rows share the .brow class
+ // so the existing modal/find-email click delegation on document just works.
+ show('#listView');
+ const metaCols=cols.filter(c=>c.k!=='name');
+ $('#listView').innerHTML='<div class="tv-rows">'+rows.map(r=>`<div class="tv-lrow brow" data-id="${r.id}" data-name="${esc(r.name)}">`
+ +`<div class="tv-lmain"><span class="tv-la">${esc(r.name)}</span><span class="tv-lsub">${esc(r.firm||'—')}${r.title?' · '+esc(r.title):''}</span>${r.agent_type==='residential'?'<span class="atype res">Res</span>':'<span class="atype com">Com</span>'}</div>`
+ +`<div class="tv-lmeta">`+metaCols.map(c=>`<span class="tv-lm"><span class="tv-lmk">${esc(c.l)}</span>${cell(r,c)}</span>`).join('')+`</div></div>`).join('')+'</div>';
} else {
- $('#tableView').classList.add('hide'); $('#gridView').classList.remove('hide');
+ show('#gridView');
const skipGrid=new Set(['name','firm','agent_type','phone','email','website','linkedin','title']);
const bodyCols=cols.filter(c=>!skipGrid.has(c.k));
$('#gridView').innerHTML=rows.map(r=>`<div class="gc brow" data-id="${r.id}" data-name="${esc(r.name)}" style="cursor:pointer">
@@ -407,6 +420,8 @@ function exportCSV(){ const rows=filtered(); const cols=visCols(); const cv=(r,c
$('#csv').addEventListener('click',exportCSV);
$('#view').addEventListener('click',e=>{const b=e.target.closest('button');if(!b)return;
document.querySelectorAll('#view button').forEach(x=>x.classList.toggle('on',x===b));view=b.dataset.v;localStorage.setItem('brokView',view);$('#denswrap').style.display=(view==='grid')?'inline-flex':'none';render();});
+// v2 3-view migration (TK-10526): the old 'table' button was labeled "List". Model is
+// now grid/list/table — no key remap needed (stored value 'table' still valid).
// ── sort <select> + density slider (Steve rule: every grid gets sort + density) ──
(function(){
const sel=$('#sortsel'),dz=$('#density');
@@ -432,7 +447,7 @@ $('#view').addEventListener('click',e=>{const b=e.target.closest('button');if(!b
const dv=parseInt(localStorage.getItem('brokDensity'),10),dval=(dv>=1&&dv<=10)?dv:5;
dz.value=dval;applyDensity(dval);
dz.addEventListener('input',()=>{const v=+dz.value;applyDensity(v);localStorage.setItem('brokDensity',v);});
- const pv=localStorage.getItem('brokView'); if(pv==='grid'||pv==='table'){view=pv;document.querySelectorAll('#view button').forEach(x=>x.classList.toggle('on',x.dataset.v===view));}
+ const pv=localStorage.getItem('brokView'); if(pv==='grid'||pv==='table'||pv==='list'){view=pv;document.querySelectorAll('#view button').forEach(x=>x.classList.toggle('on',x.dataset.v===view));}
$('#denswrap').style.display=(view==='grid')?'inline-flex':'none';
window.__syncSortSel=()=>{if(Array.from(sel.options).some(o=>o.value===sortKey)&&sel.value!==sortKey)sel.value=sortKey;};
})();
← badc059 condos.html: add compact-list view (3rd mode) + shared three
·
back to Commercialrealestate
·
mls.html: add compact-list view (3rd mode) — grid/list/table b36efec →