[object Object]

← back to Customdigitalmurals

sort + density persist to localStorage; hydrate before first grid load

48db47594ef54345c942a7b0f1a7c17ea9187464 · 2026-05-19 15:13:46 -0700 · Steve Abrams

Standing rule: every product grid must persist sort + density selections to
localStorage and rehydrate the saved value before the first grid load. The
storefront had the controls but neither persisted; refresh always reset to
A-Z + density 4. Wires LS_SORT='cdm-sort' + LS_DENSITY='cdm-density' (matches
the existing cdm-theme key style), validates saved values against the rendered
options before applying, and updates the slider DOM value pre-mount so the
first paint matches the user's last choice.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Files touched

Diff

commit 48db47594ef54345c942a7b0f1a7c17ea9187464
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Tue May 19 15:13:46 2026 -0700

    sort + density persist to localStorage; hydrate before first grid load
    
    Standing rule: every product grid must persist sort + density selections to
    localStorage and rehydrate the saved value before the first grid load. The
    storefront had the controls but neither persisted; refresh always reset to
    A-Z + density 4. Wires LS_SORT='cdm-sort' + LS_DENSITY='cdm-density' (matches
    the existing cdm-theme key style), validates saved values against the rendered
    options before applying, and updates the slider DOM value pre-mount so the
    first paint matches the user's last choice.
    
    Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---
 server.js | 36 ++++++++++++++++++++++++++++++------
 1 file changed, 30 insertions(+), 6 deletions(-)

diff --git a/server.js b/server.js
index ffd2742..82bb6da 100644
--- a/server.js
+++ b/server.js
@@ -366,13 +366,13 @@ ${headerHtml('home')}
     <option value="">All Studios</option>
   </select>
   <select id="sort">
-    <option value="az">A → Z</option>
-    <option value="za">Z → A</option>
+    <option value="az">Title A → Z</option>
+    <option value="za">Title Z → A</option>
     <option value="price_asc">Price: Low</option>
     <option value="price_desc">Price: High</option>
   </select>
   <span class="density-label">Density</span>
-  <input type="range" id="density" class="density-slider" min="2" max="6" value="4" step="1">
+  <input type="range" id="density" class="density-slider" min="2" max="6" value="4" step="1" aria-label="Grid density">
   <span class="count" id="count"></span>
 </div>
 <div class="grid-wrap">
@@ -392,10 +392,30 @@ ${footerHtml()}
 <script>
 var page=1, per=60, total=0, pages=0;
 var q='', vendor='', sort='az';
+var LS_SORT='cdm-sort', LS_DENSITY='cdm-density';
+
+// Hydrate saved sort + density BEFORE the first grid load.
+try {
+  var savedSort = localStorage.getItem(LS_SORT);
+  if (savedSort) {
+    var sel = document.getElementById('sort');
+    var has = Array.prototype.some.call(sel.options, function(o){ return o.value === savedSort; });
+    if (has) { sort = savedSort; sel.value = savedSort; }
+  }
+} catch(e){}
+
+var savedCols = 4;
+try {
+  var d = parseInt(localStorage.getItem(LS_DENSITY), 10);
+  if (d >= 2 && d <= 6) { savedCols = d; document.getElementById('density').value = String(d); }
+} catch(e){}
 
 function setCols(n){document.querySelector('.product-grid').style.setProperty('--cols',n);}
-document.getElementById('density').addEventListener('input',function(){setCols(+this.value);});
-setCols(4);
+document.getElementById('density').addEventListener('input',function(){
+  setCols(+this.value);
+  try { localStorage.setItem(LS_DENSITY, String(this.value)); } catch(e){}
+});
+setCols(savedCols);
 
 function load(){
   var url='/api/products?page='+page+'&per='+per+'&q='+encodeURIComponent(q)+'&vendor='+encodeURIComponent(vendor)+'&sort='+sort;
@@ -446,7 +466,11 @@ fetch('/api/vendors').then(r=>r.json()).then(list=>{
 
 document.getElementById('search').addEventListener('input',function(){q=this.value;page=1;load();});
 document.getElementById('vendor-filter').addEventListener('change',function(){vendor=this.value;page=1;load();});
-document.getElementById('sort').addEventListener('change',function(){sort=this.value;page=1;load();});
+document.getElementById('sort').addEventListener('change',function(){
+  sort=this.value;page=1;
+  try { localStorage.setItem(LS_SORT, sort); } catch(e){}
+  load();
+});
 
 load();
 </script>

← 917bb01 Phase 2: mobile-ready + tap-to-reveal  ·  back to Customdigitalmurals  ·  add noreferrer to every target=_blank external link 58420cb →