← back to All Designerwallcoverings
microsites.html: density slider 1-30 with live readout + sort every field (products/name/slug/type both dirs, catalog/live/gated)
7f71cd113bd1328d8b3f4a8a1225d545af21aadb · 2026-07-06 16:28:25 -0700 · Steve Abrams
Files touched
Diff
commit 7f71cd113bd1328d8b3f4a8a1225d545af21aadb
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Mon Jul 6 16:28:25 2026 -0700
microsites.html: density slider 1-30 with live readout + sort every field (products/name/slug/type both dirs, catalog/live/gated)
---
public/microsites.html | 45 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 34 insertions(+), 11 deletions(-)
diff --git a/public/microsites.html b/public/microsites.html
index 3ee2982..3a083e9 100644
--- a/public/microsites.html
+++ b/public/microsites.html
@@ -99,12 +99,19 @@
<button id="fAll">All Live Sites</button>
</div>
<select id="sort" aria-label="Sort">
- <option value="products">Most Products</option>
- <option value="az">Name A→Z</option>
- <option value="za">Name Z→A</option>
- <option value="status">Catalog First</option>
+ <option value="products">Products: Most</option>
+ <option value="products_asc">Products: Fewest</option>
+ <option value="az">Name: A→Z</option>
+ <option value="za">Name: Z→A</option>
+ <option value="slug">Slug: A→Z</option>
+ <option value="slug_desc">Slug: Z→A</option>
+ <option value="type">Type: A→Z</option>
+ <option value="type_desc">Type: Z→A</option>
+ <option value="catalog">Has Catalog First</option>
+ <option value="live">Live First</option>
+ <option value="gated">Trade-Gated First</option>
</select>
- <label class="dens">Density <input type="range" id="density" min="2" max="8" step="1" value="4"></label>
+ <label class="dens">Density <input type="range" id="density" min="1" max="30" step="1" value="4"><span id="densN">4</span></label>
</div>
<main class="grid" id="grid"></main>
@@ -125,6 +132,7 @@ const state = {
document.documentElement.style.setProperty('--cols', state.cols);
density.value = state.cols;
+densN.textContent = state.cols;
sort.value = state.sort;
setSeg();
@@ -160,15 +168,30 @@ fetch('/api/microsites').then(r=>r.json()).then(d=>{
apply();
}).catch(()=>{ fresh.textContent='crawl snapshot not ready — check back shortly'; });
+// Every field on a microsite record gets a sorter. Ties break on name so order is stable.
+const nm = s => displayName(s);
+const str = v => String(v == null ? '' : v); // nulls sink to the end on A→Z
+const gated = s => (s.status === 401 ? 1 : 0);
+const SORTERS = {
+ products: (a,b)=> (b.productCount-a.productCount) || nm(a).localeCompare(nm(b)),
+ products_asc: (a,b)=> (a.productCount-b.productCount) || nm(a).localeCompare(nm(b)),
+ az: (a,b)=> nm(a).localeCompare(nm(b)),
+ za: (a,b)=> nm(b).localeCompare(nm(a)),
+ slug: (a,b)=> str(a.slug).localeCompare(str(b.slug)),
+ slug_desc: (a,b)=> str(b.slug).localeCompare(str(a.slug)),
+ type: (a,b)=> str(a.type).localeCompare(str(b.type)) || nm(a).localeCompare(nm(b)),
+ type_desc: (a,b)=> str(b.type).localeCompare(str(a.type)) || nm(a).localeCompare(nm(b)),
+ catalog: (a,b)=> (b.feed-a.feed) || (b.productCount-a.productCount) || nm(a).localeCompare(nm(b)),
+ live: (a,b)=> (gated(a)-gated(b)) || (b.productCount-a.productCount) || nm(a).localeCompare(nm(b)),
+ gated: (a,b)=> (gated(b)-gated(a)) || nm(a).localeCompare(nm(b)),
+};
+
function apply(){
let v = state.all;
if (state.filter==='feeds') v = v.filter(x=>x.feed);
if (state.q){ const q=state.q.toLowerCase();
- v = v.filter(x=> (x.slug||'').includes(q) || displayName(x).toLowerCase().includes(q) || (x.vendor||'').toLowerCase().includes(q)); }
- if (state.sort==='az') v=[...v].sort((a,b)=>displayName(a).localeCompare(displayName(b)));
- else if (state.sort==='za') v=[...v].sort((a,b)=>displayName(b).localeCompare(displayName(a)));
- else if (state.sort==='status') v=[...v].sort((a,b)=>(b.feed-a.feed)||(b.productCount-a.productCount)||displayName(a).localeCompare(displayName(b)));
- else v=[...v].sort((a,b)=>(b.productCount-a.productCount)||displayName(a).localeCompare(displayName(b)));
+ v = v.filter(x=> (x.slug||'').includes(q) || nm(x).toLowerCase().includes(q) || (x.vendor||'').toLowerCase().includes(q)); }
+ v = [...v].sort(SORTERS[state.sort] || SORTERS.products);
state.view = v; state.rendered = 0; grid.innerHTML=''; renderMore();
}
@@ -210,7 +233,7 @@ new IntersectionObserver(es=>{ if(es[0].isIntersecting) renderMore(); }, {rootMa
q.addEventListener('input', e=>{ state.q=e.target.value.trim(); apply(); });
sort.addEventListener('change', e=>{ state.sort=e.target.value; localStorage.setItem('adwm_sort',state.sort); apply(); });
density.addEventListener('input', e=>{ state.cols=e.target.value; localStorage.setItem('adwm_cols',state.cols);
- document.documentElement.style.setProperty('--cols', state.cols); });
+ densN.textContent=state.cols; document.documentElement.style.setProperty('--cols', state.cols); });
fFeeds.onclick=()=>{ state.filter='feeds'; localStorage.setItem('adwm_filter','feeds'); setSeg(); apply(); };
fAll.onclick=()=>{ state.filter='all'; localStorage.setItem('adwm_filter','all'); setSeg(); apply(); };
</script>
← ce4838d untrack data/microsites.json (live crawl artifact) + restore
·
back to All Designerwallcoverings
·
api: carry series (Book) facet + website/internal_url per pr 3876a0d →