[object Object]

← back to La Socrata Ingester

viewer: make filters+sort shareable in the URL (deep-link/bookmark any filtered view)

1d08e306779a91f65bb409073d0358a8c140ebaf · 2026-08-12 07:49:00 -0700 · Steve Abrams

- syncURL() mirrors filters + sort + view + color into the URL on every render (history.replaceState, no history spam)
- boot IIFE now restores era/work_type/building_type/status/cd/zip/q/min_value/since + sort/dir from the URL (previously only view+color)
- verified: applying facets writes ?work_type=Bldg-New&cd=5&sort=...; cold-loading that URL restores active facets, filtered count (9,224), sort, and rows

Files touched

Diff

commit 1d08e306779a91f65bb409073d0358a8c140ebaf
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Wed Aug 12 07:49:00 2026 -0700

    viewer: make filters+sort shareable in the URL (deep-link/bookmark any filtered view)
    
    - syncURL() mirrors filters + sort + view + color into the URL on every render (history.replaceState, no history spam)
    - boot IIFE now restores era/work_type/building_type/status/cd/zip/q/min_value/since + sort/dir from the URL (previously only view+color)
    - verified: applying facets writes ?work_type=Bldg-New&cd=5&sort=...; cold-loading that URL restores active facets, filtered count (9,224), sort, and rows
---
 viewer/public/index.html | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)

diff --git a/viewer/public/index.html b/viewer/public/index.html
index b6fe636..57f6751 100644
--- a/viewer/public/index.html
+++ b/viewer/public/index.html
@@ -341,7 +341,17 @@ function renderMap(){
   setTimeout(()=>map.invalidateSize(),50);
 }
 
+function syncURL(){ // mirror filters+sort+view+color into the URL so any view is shareable/bookmarkable
+  const p=new URLSearchParams();
+  for(const [k,v] of Object.entries(state.filters)) if(v) p.set(k,v);
+  if(state.sort&&state.sort.col){ p.set('sort',state.sort.col); p.set('dir',state.sort.dir); }
+  if(state.view&&state.view!=='list') p.set('view',state.view);
+  if(state.colorBy&&state.colorBy!=='lead_score') p.set('color',state.colorBy);
+  const s=p.toString();
+  try{ history.replaceState(null,'', s?('?'+s):location.pathname); }catch(e){}
+}
 function render(){
+  syncURL();
   $('#listview').classList.toggle('hidden', state.view!=='list');
   $('#gridview').classList.toggle('hidden', state.view!=='grid');
   $('#mapview').classList.toggle('hidden', state.view!=='map');
@@ -387,9 +397,12 @@ function escapeHtml(s){return String(s).replace(/[&<>"]/g,c=>({'&':'&amp;','<':'
 function escapeAttr(s){return escapeHtml(s).replace(/'/g,'&#39;')}
 
 (function(){
-  const u=new URLSearchParams(location.search); // ?view=map&color=project_value shareable deep-links
+  const u=new URLSearchParams(location.search); // shareable deep-links: filters + sort + view + color
   if(u.get('view')) state.view=u.get('view');
   if(u.get('color')) state.colorBy=u.get('color');
+  ['q','era','work_type','building_type','status','cd','zip','min_value','since'].forEach(k=>{ if(u.get(k)) state.filters[k]=u.get(k); });
+  if(u.get('sort')) state.sort={col:u.get('sort'), dir:u.get('dir')==='asc'?'asc':'desc'};
+  if(state.filters.q) $('#q').value=state.filters.q;
   const d=LS.get('density','34'); document.documentElement.style.setProperty('--rowh',d+'px');
   document.documentElement.style.setProperty('--cols',Math.max(2,Math.round((72-d)/8))); $('#density').value=d;
   $('#colorby').value=state.colorBy;

← d115714 yoloforever c7 FIX (Cody): honest digest — verified-only hea  ·  back to La Socrata Ingester  ·  yoloforever c8: consolidated platform status brief (scripts/ e1a34c1 →