← back to Bestwallpaperplace
viewer standard: add Grid/List toggle + per-field on/off menu (Fields) to product grid
1ab731c089f1968ebbbc20325a40345c9a5a8f14 · 2026-08-12 08:33:42 -0700 · Steve
Files touched
Diff
commit 1ab731c089f1968ebbbc20325a40345c9a5a8f14
Author: Steve <steve@designerwallcoverings.com>
Date: Wed Aug 12 08:33:42 2026 -0700
viewer standard: add Grid/List toggle + per-field on/off menu (Fields) to product grid
---
public/index.html | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 84 insertions(+), 2 deletions(-)
diff --git a/public/index.html b/public/index.html
index 0c70130..ca4605b 100644
--- a/public/index.html
+++ b/public/index.html
@@ -283,6 +283,25 @@ footer { padding:64px 32px 32px; border-top:1px solid var(--line); margin-top:32
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible {
outline: 2px solid var(--accent); outline-offset: 2px;
}
+
+/* ── Grid / List view ── */
+html.bwp-list .grid { display:block; }
+html.bwp-list .card { display:flex; flex-direction:row; align-items:stretch; aspect-ratio:auto; margin-bottom:8px; }
+html.bwp-list .card > a:first-child { flex:0 0 clamp(80px,16vw,160px); }
+html.bwp-list .card img { width:clamp(80px,16vw,160px); height:100%; min-height:80px; object-fit:cover; }
+html.bwp-list .card .overlay { position:static; transform:none; opacity:1; background:none; flex:1; display:flex; flex-direction:column; justify-content:center; padding:10px 14px; }
+html.bwp-list .card .pat, html.bwp-list .card .ven { color:var(--paper); }
+html.bwp-list .card:hover { transform:none; }
+
+/* ── Per-field hide rules (html.hf-<field>) ── */
+html.hf-image .card img { display:none; }
+html.hf-title [data-f="title"] { display:none; }
+html.hf-sample [data-f="sample"] { display:none; }
+
+/* ── Fields popover labels ── */
+#bwpFpop label { display:flex; align-items:center; gap:10px; padding:7px 14px; font-size:10px; letter-spacing:.14em; text-transform:uppercase; color:var(--paper); cursor:pointer; white-space:nowrap; font-family:inherit; font-weight:600; }
+#bwpFpop label:hover { background:var(--line); }
+#bwpFpop input[type=checkbox] { accent-color:var(--accent); width:13px; height:13px; cursor:pointer; }
</style>
<!-- Meta Pixel — INERT until set-fb-pixel.sh is run (does NOT load fbevents.js or hit Meta until flipped) -->
<script>
@@ -487,6 +506,16 @@ a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible
<span>Density</span>
<input id="densitySlider" type="range" min="2" max="8" value="5">
</div>
+ <!-- Grid/List view toggle -->
+ <div class="ctl" role="group" aria-label="View mode" style="gap:0;border:1px solid var(--line);padding:0;overflow:hidden;">
+ <button id="bwpVGrid" style="padding:7px 12px;background:var(--accent);color:var(--bg);border:0;font-size:10px;letter-spacing:.18em;text-transform:uppercase;cursor:pointer;font-family:inherit;font-weight:700;" title="Grid view">Grid</button>
+ <button id="bwpVList" style="padding:7px 12px;background:transparent;color:var(--muted);border:0;border-left:1px solid var(--line);font-size:10px;letter-spacing:.18em;text-transform:uppercase;cursor:pointer;font-family:inherit;font-weight:700;" title="List view">List</button>
+ </div>
+ <!-- Fields ▾ menu -->
+ <div class="bwp-fieldmenu" style="position:relative;">
+ <button id="bwpFieldsBtn" style="padding:8px 12px;border:1px solid var(--line);background:transparent;font-size:10px;letter-spacing:.18em;text-transform:uppercase;color:var(--muted);cursor:pointer;font-weight:700;font-family:inherit;" aria-haspopup="true" aria-expanded="false">Fields ▾</button>
+ <div id="bwpFpop" hidden style="position:absolute;top:calc(100% + 8px);right:0;background:var(--bg-soft);border:1px solid var(--line);box-shadow:0 14px 34px rgba(0,0,0,.14);padding:6px 4px;z-index:40;min-width:180px;" role="menu"></div>
+ </div>
</div>
<div class="stat-line" id="statLine">Loading…</div>
<div class="grid" id="grid"></div>
@@ -585,9 +614,9 @@ a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible
<img loading="lazy" src="${img}" alt="${title.replace(/"/g,'"')}">
</a>
<div class="overlay">
- <div class="pat">${title.replace(/</g,'<')}</div>
+ <div class="pat" data-f="title">${title.replace(/</g,'<')}</div>
<div class="actions">
- <a class="sample-btn" href="${sampleUrl}" target="_blank" rel="noopener noreferrer">Request Sample</a>
+ <a class="sample-btn" data-f="sample" href="${sampleUrl}" target="_blank" rel="noopener noreferrer">Request Sample</a>
</div>
</div>
</article>`;
@@ -613,6 +642,59 @@ a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible
if (window.innerHeight + window.scrollY >= document.body.offsetHeight - 600) fetchPage();
});
fetchPage();
+
+ // ── Grid/List view toggle ─────────────────────────────────────────────────
+ const BWP_FIELDS = [
+ ['image', 'Image', true],
+ ['title', 'Title', true],
+ ['sample', 'Sample', true],
+ ];
+ function bwpLoadFields(){
+ const def = {}; BWP_FIELDS.forEach(([k,,d]) => def[k] = d);
+ try { return Object.assign(def, JSON.parse(localStorage.getItem('bwp_fields') || '{}')); } catch(e){ return def; }
+ }
+ const bwpFieldState = bwpLoadFields();
+
+ function bwpApplyView(){
+ const v = localStorage.getItem('bwp_view') || 'grid';
+ document.documentElement.classList.toggle('bwp-list', v === 'list');
+ const gBtn = document.getElementById('bwpVGrid'), lBtn = document.getElementById('bwpVList');
+ if(gBtn){ gBtn.style.background = v==='grid'?'var(--accent)':'transparent'; gBtn.style.color = v==='grid'?'var(--bg)':'var(--muted)'; }
+ if(lBtn){ lBtn.style.background = v==='list'?'var(--accent)':'transparent'; lBtn.style.color = v==='list'?'var(--bg)':'var(--muted)'; }
+ }
+ const bwpVG = document.getElementById('bwpVGrid'), bwpVL = document.getElementById('bwpVList');
+ if(bwpVG) bwpVG.addEventListener('click', () => { localStorage.setItem('bwp_view','grid'); bwpApplyView(); });
+ if(bwpVL) bwpVL.addEventListener('click', () => { localStorage.setItem('bwp_view','list'); bwpApplyView(); });
+ bwpApplyView();
+
+ // ── Fields ▾ menu ─────────────────────────────────────────────────────────
+ function bwpApplyFields(){
+ BWP_FIELDS.forEach(([k]) => document.documentElement.classList.toggle('hf-' + k, !bwpFieldState[k]));
+ }
+ function bwpBuildFieldMenu(){
+ const pop = document.getElementById('bwpFpop');
+ if(!pop) return;
+ pop.innerHTML = BWP_FIELDS.map(([k, label]) =>
+ `<label><input type="checkbox" data-field="${k}"${bwpFieldState[k] ? ' checked' : ''}> ${label}</label>`).join('');
+ pop.querySelectorAll('input').forEach(cb => cb.addEventListener('change', () => {
+ bwpFieldState[cb.dataset.field] = cb.checked;
+ localStorage.setItem('bwp_fields', JSON.stringify(bwpFieldState));
+ bwpApplyFields();
+ }));
+ }
+ const bwpFBtn = document.getElementById('bwpFieldsBtn'), bwpFpop = document.getElementById('bwpFpop');
+ if(bwpFBtn && bwpFpop){
+ bwpFBtn.addEventListener('click', e => {
+ e.stopPropagation();
+ const open = bwpFpop.hidden; bwpFpop.hidden = !open;
+ bwpFBtn.setAttribute('aria-expanded', String(open));
+ });
+ document.addEventListener('click', e => {
+ if(!bwpFpop.hidden && !e.target.closest('.bwp-fieldmenu')){ bwpFpop.hidden = true; bwpFBtn.setAttribute('aria-expanded','false'); }
+ });
+ }
+ bwpBuildFieldMenu();
+ bwpApplyFields();
})();
</script>
← 56e178d fix: take infinite-scroll .loading indicator out of flow (ki
·
back to Bestwallpaperplace
·
auto-data-snapshot: 2026-08-22T11:19:22 (1 data files) — dat e6f60ca →