[object Object]

← back to Rentv Sheet Enrich

rentv :9797 legend: Cody fixes — empty-rename guard, mark heuristic guesses, don't nuke mid-edit

46c2c4d9f01ef808f5f8870550d87be83138d5e0 · 2026-08-13 18:42:30 -0700 · Steve Abrams

- onblur only saves a NON-empty name (empty no longer permanently overrides CNAMED/heuristic)
- provName getter ignores an empty stored name
- non-grounded (heuristic) names render dim-italic + a grey '?' so a guess is never shown as fact
- renderLegend() skips rebuild while a name is being edited (no mid-edit data loss on tab switch)

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

Files touched

Diff

commit 46c2c4d9f01ef808f5f8870550d87be83138d5e0
Author: Steve Abrams <steve@designerwallcoverings.com>
Date:   Thu Aug 13 18:42:30 2026 -0700

    rentv :9797 legend: Cody fixes — empty-rename guard, mark heuristic guesses, don't nuke mid-edit
    
    - onblur only saves a NON-empty name (empty no longer permanently overrides CNAMED/heuristic)
    - provName getter ignores an empty stored name
    - non-grounded (heuristic) names render dim-italic + a grey '?' so a guess is never shown as fact
    - renderLegend() skips rebuild while a name is being edited (no mid-edit data loss on tab switch)
    
    Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
 public_live/index.html | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/public_live/index.html b/public_live/index.html
index 0b58a55..4bc958a 100644
--- a/public_live/index.html
+++ b/public_live/index.html
@@ -99,6 +99,8 @@
   .legendpanel .lgsw{width:16px;height:16px;border-radius:4px;border:1px solid rgba(128,128,128,.4);flex:0 0 auto}
   .legendpanel .lgname{flex:1;outline:none;border-radius:4px;padding:1px 4px;min-width:80px}
   .legendpanel .lgname:focus{box-shadow:inset 0 0 0 2px var(--accent)}
+  .legendpanel .lgname.lgguess{opacity:.72;font-style:italic}
+  .legendpanel .lgq{color:var(--dim);font-weight:700;font-size:11px;flex:0 0 auto}
   .legendpanel .lghex{color:var(--dim);font-variant-numeric:tabular-nums;font-size:10.5px}
   .legendpanel .lgn{color:var(--dim);font-variant-numeric:tabular-nums;min-width:46px;text-align:right}
   td.enriched{box-shadow:inset 3px 0 0 #7bc043;background:rgba(123,192,67,.09)}
@@ -545,7 +547,8 @@ function txtOn(color){ const m=color.match(/^#([0-9a-f]{6})$/i); if(!m)return '#
   const n=parseInt(m[1],16), r=n>>16, g=(n>>8)&255, b=n&255; return (0.299*r+0.587*g+0.114*b)>150?'#111':'#fff'; }
 // ---- color key / legend (exact sheet colors -> provisional, editable meanings; no sheet write) ----
 const CNAMED={'#cfe2f3':'Contacted','#0000ff':'Contacted','#3d85c6':'Contacted','#4a86e8':'Contacted','#00ffff':'Contacted ❓','#00ff00':'Has email','#ff00ff':'Needs email / Outreach pending','#ffff00':'Prospect / Follow-up ❓'};
-function provName(hex){ const o=LS.get('cname.'+hex,null); if(o!=null)return o;   // user rename wins (saved locally)
+function nameSure(hex){ const o=LS.get('cname.'+hex,null); return (o!=null&&o!=='')||!!CNAMED[hex]; }   // grounded (user-set or known) vs heuristic guess
+function provName(hex){ const o=LS.get('cname.'+hex,null); if(o!=null&&o!=='')return o;   // user rename wins (saved locally; empty never overrides)
   if(CNAMED[hex])return CNAMED[hex];
   const m=hex.match(/^#([0-9a-f]{2})([0-9a-f]{2})([0-9a-f]{2})$/i); if(!m)return '';
   const r=parseInt(m[1],16),g=parseInt(m[2],16),b=parseInt(m[3],16),mx=Math.max(r,g,b),mn=Math.min(r,g,b),d=mx-mn;
@@ -560,12 +563,13 @@ function provName(hex){ const o=LS.get('cname.'+hex,null); if(o!=null)return o;
   return 'Needs email / Outreach pending';                         // magenta/pink
 }
 function colorTally(){ const t={}; for(const hx of Object.values(COLORS))t[hx]=(t[hx]||0)+1; return Object.entries(t).sort((a,b)=>b[1]-a[1]); }
-function renderLegend(){ let p=$('#legendpanel'); if(!p){p=document.createElement('div');p.id='legendpanel';p.className='legendpanel';document.body.appendChild(p);}
+function renderLegend(){ let p=$('#legendpanel'); if(p&&document.activeElement&&p.contains(document.activeElement))return;   // don't nuke a name mid-edit
+  if(!p){p=document.createElement('div');p.id='legendpanel';p.className='legendpanel';document.body.appendChild(p);}
   const items=colorTally();
   if(!items.length){ p.innerHTML='<div class="lghead">Color key — this tab</div><div class="lgempty">No color-coded cells on this tab.</div>'; return; }
-  p.innerHTML='<div class="lghead">Color key — this tab<span class="lgnote">Exact sheet colors + provisional meaning. Click a name to rename (saved locally). ❓ = awaiting Steve.</span></div>'
-    +items.map(([hx,n])=>`<div class="lgrow"><span class="lgsw" style="background:${hx}"></span><span class="lgname" contenteditable="true" data-hx="${hx}" title="Click to rename">${esc(provName(hx))}</span><span class="lghex">${hx}</span><span class="lgn">${n.toLocaleString()}</span></div>`).join('');
-  p.querySelectorAll('.lgname').forEach(el=>{ el.onblur=()=>LS.set('cname.'+el.dataset.hx, el.textContent.trim());
+  p.innerHTML='<div class="lghead">Color key — this tab<span class="lgnote">Exact sheet colors + provisional meaning. Click a name to rename (saved locally). ❓ / grey “?” = unverified guess — rename to confirm.</span></div>'
+    +items.map(([hx,n])=>{const sure=nameSure(hx);return `<div class="lgrow"><span class="lgsw" style="background:${hx}"></span><span class="lgname${sure?'':' lgguess'}" contenteditable="true" data-hx="${hx}" title="${sure?'Click to rename':'Heuristic guess — click to rename'}">${esc(provName(hx))}</span>${sure?'':'<span class="lgq" title="unverified guess">?</span>'}<span class="lghex">${hx}</span><span class="lgn">${n.toLocaleString()}</span></div>`;}).join('');
+  p.querySelectorAll('.lgname').forEach(el=>{ el.onblur=()=>{ const v=el.textContent.trim(); if(v)LS.set('cname.'+el.dataset.hx, v); };
     el.onkeydown=e=>{ if(e.key==='Enter'){e.preventDefault();el.blur();} }; });
 }
 function toggleLegend(){ let p=$('#legendpanel'); const open=p&&p.style.display==='block';

← aba95a9 rentv :9797: add in-viewer Color Key legend panel (🎨 Colors  ·  back to Rentv Sheet Enrich  ·  rentv :9797 legend: close (✕/Esc/click-outside) + per-row ↺ 21e6af5 →