← back to Rentv Sheet Enrich Refine
Live console: Website/LinkedIn/phone cells are now WHOLE-CELL clickable (leading icon never clipped) — opens popup / dials; text cells stay editable
4ff3c021a195b30f6d5a95c23565b29f4def39df · 2026-08-13 16:06:19 -0700 · Steve Abrams
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
Diff
commit 4ff3c021a195b30f6d5a95c23565b29f4def39df
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Aug 13 16:06:19 2026 -0700
Live console: Website/LinkedIn/phone cells are now WHOLE-CELL clickable (leading icon never clipped) — opens popup / dials; text cells stay editable
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
public_live/index.html | 37 +++++++++++++++++++++++++++++++------
1 file changed, 31 insertions(+), 6 deletions(-)
diff --git a/public_live/index.html b/public_live/index.html
index 574914c..2d03cd8 100644
--- a/public_live/index.html
+++ b/public_live/index.html
@@ -82,6 +82,15 @@
a.iconbtn svg,a.callbtn svg{width:1.05em;height:1.05em;display:block}
a.callbtn{color:#16a34a} a.iconbtn.web{color:var(--accent)} a.iconbtn.li{color:#0a66c2}
.linkval{color:inherit}
+ /* whole-cell clickable links: icon on the LEFT (never clipped), entire cell opens popup / dials */
+ td.linkcell,td.callcell{cursor:pointer}
+ td.linkcell .cicon,td.callcell .cicon{display:inline-flex;vertical-align:middle;margin-right:5px}
+ td.linkcell .cicon svg,td.callcell .cicon svg{width:1.05em;height:1.05em;display:block}
+ td.linkcell.web .cicon,td.linkcell.web .linkval{color:var(--accent)}
+ td.linkcell.li .cicon,td.linkcell.li .linkval{color:#4aa3ff}
+ td.callcell .cicon{color:#16a34a}
+ td.linkcell:hover,td.callcell:hover{background:#12283a}
+ td.linkcell:hover .linkval,td.callcell:hover .linkval{text-decoration:underline}
/* FIELD LOOKUP: click a field in the left rail -> its full value list opens here in the main area */
.lkhead{display:flex;align-items:center;gap:10px;padding:8px 10px;position:sticky;top:0;background:var(--panel2);border-bottom:1px solid var(--line);z-index:6}
.lkhead b{font-size:14px;color:var(--accent)} .lksub{color:var(--dim);font-size:12px}
@@ -419,7 +428,7 @@ function tableHTML(rows){
if(GROUP!==''){ const gv=g(r,+GROUP)||'(blank)'; if(gv!==lastG){ lastG=gv; h+=`<tr class="grouphdr"><td colspan="${cols.length+1}">${esc(gv)}</td></tr>`; } }
h+=`<tr><td><button class="rowbtn" data-r="${ri}">✍</button></td>`;
for(const c of cols){ const gr=GREENSET.has(ri+','+c.i), isN=c.i===ROLE.name, val=g(r,c.i);
- h+=`<td data-r="${ri}" data-c="${c.i}" contenteditable="true" title="${esc(val)}" class="${[isN?'namecell':'',gr?'enriched':''].filter(Boolean).join(' ')}">${cellRender(val)}</td>`; }
+ h+=cellTD(ri,c.i,val,isN,gr); }
h+='</tr>';
}
return h+'</tbody></table>';
@@ -442,6 +451,22 @@ function iconLink(url,kind){
const svg=kind==='li'?ICON.li:ICON.web, label=kind==='li'?'Open LinkedIn profile':'Open website';
return `<a class="iconbtn ${kind}" href="${esc(url)}" target="_blank" rel="noopener" contenteditable="false" title="${label}">${svg}</a>`;
}
+// digits of a cell whose WHOLE value is one phone number (anchored, so a phone inside Notes prose is ignored)
+function telDigits(v){ v=String(v==null?'':v).trim();
+ if(!/^(\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}(\s*(x|ext\.?)\s*\d+)?$/i.test(v))return null;
+ const core=v.match(/(\+?1[-.\s]?)?\(?\d{3}\)?[-.\s]?\d{3}[-.\s]?\d{4}/)[0];
+ let d=core.replace(/\D/g,''); if(d.length===10)d='1'+d; return d; }
+// build one <td>. Website/LinkedIn/phone => whole cell is CLICKABLE (icon on the LEFT so it's never clipped,
+// entire cell opens a popup / dials). Everything else stays contenteditable + expand-on-click.
+function cellTD(ri,ci,val,isN,gr){
+ const cls=[isN?'namecell':'',gr?'enriched':''].filter(Boolean).join(' ');
+ const s=String(val==null?'':val), u=hrefOf(s);
+ if(u){ const li=/linkedin\.com/i.test(u), disp=s.replace(/^https?:\/\/(www\.)?/i,'').replace(/\/+$/,'');
+ return `<td data-r="${ri}" data-c="${ci}" contenteditable="false" data-href="${esc(u)}" title="Open ${esc(u)}" class="linkcell ${li?'li':'web'} ${cls}"><span class="cicon">${li?ICON.li:ICON.web}</span><span class="linkval">${esc(disp)}</span></td>`; }
+ const d=telDigits(s);
+ if(d){ return `<td data-r="${ri}" data-c="${ci}" contenteditable="false" data-tel="+${d}" title="Call ${esc(s)}" class="callcell ${cls}"><span class="cicon">${ICON.phone}</span><span class="linkval">${esc(s)}</span></td>`; }
+ return `<td data-r="${ri}" data-c="${ci}" contenteditable="true" title="${esc(s)}" class="${cls}">${esc(s)}</td>`;
+}
function cellRender(v){v=String(v==null?'':v);const u=hrefOf(v);
if(u){ const li=/linkedin\.com/i.test(u); // value stays plain text; icon opens the link
const disp=v.replace(/^https?:\/\/(www\.)?/i,'').replace(/\/+$/,'');
@@ -463,11 +488,11 @@ function wireGrid(){
// (per-render) #grid element and open the link in a POPUP WINDOW. tel: links proceed as normal.
const gridEl=$('#grid');
if(gridEl){
- gridEl.addEventListener('mousedown',e=>{ if(e.target.closest('a.iconbtn,a.callbtn'))e.stopPropagation(); });
gridEl.addEventListener('click',e=>{
- const a=e.target.closest('a.iconbtn'); if(!a)return; // callbtn (tel:) falls through to default
- e.preventDefault(); e.stopPropagation();
- window.open(a.getAttribute('href'),'linkpop','popup=yes,noopener,width=1100,height=850,left=140,top=90');
+ const lc=e.target.closest('td.linkcell'); // Website / LinkedIn -> popup window
+ if(lc){ e.preventDefault(); window.open(lc.dataset.href,'linkpop','popup=yes,noopener,width=1100,height=850,left=140,top=90'); return; }
+ const cc=e.target.closest('td.callcell'); // phone -> dial
+ if(cc){ location.href='tel:'+cc.dataset.tel; return; }
});
}
$$('.card').forEach(c=>c.onclick=()=>openDraft(+c.dataset.r));
@@ -510,7 +535,7 @@ function wireGrid(){
document.querySelectorAll('#grid tbody tr').forEach(tr=>{const t=tr.children[idx+1]?.textContent||'';if(t.length>max)max=t.length;});
const w=Math.min(600,Math.max(70,Math.round(max*7.1)+26));col.style.width=w+'px';COLW[ci]=w;LS.set('colw.'+curKey(),COLW);
}));
- $$('td[contenteditable]').forEach(td=>{td.addEventListener('focus',()=>{editing=true;td._o=td.textContent});td.addEventListener('blur',()=>saveCell(td));td.addEventListener('keydown',e=>{if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();td.blur()}})});
+ $$('td[contenteditable="true"]').forEach(td=>{td.addEventListener('focus',()=>{editing=true;td._o=td.textContent});td.addEventListener('blur',()=>saveCell(td));td.addEventListener('keydown',e=>{if(e.key==='Enter'&&!e.shiftKey){e.preventDefault();td.blur()}})});
}
function postWrite(r,c,value){return fetch('/api/write',{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify({gid:GID,row0:r,col0:c,value})}).then(x=>x.json())}
async function saveCell(td){ editing=false; const v=td.textContent.trim(); if(v===String(td._o||'').trim())return;
← 1bff2a8 Live console: click a field in the left rail to open its ful
·
back to Rentv Sheet Enrich Refine
·
Live console: theme-aware interaction colors (no more black- c5739ce →