← back to Rentv
Split nav into TWO hamburgers: upper-left (Explore+Regions) + upper-right (Sections+Tools)
2837beede329f6f37b2d5302f497c6336f3a8b97 · 2026-08-06 10:22:18 -0700 · Steve Abrams
Steve: 'Split hamburger between upper right and left.' Both the map's own build AND the
sitewide masthead build now render two hamburgers flanking a centered logo:
• LEFT drawer (slides from left): Explore pages + Regions
• RIGHT drawer (slides from right): Sections (+ the map's filters/legend/Near me/Reset on /map)
Region/Section links split from the hidden strip (.rt-geo → left, .rt-cat → right).
Verified markets/blog/map: 2 hamburgers, logo centered, correct split, 0 errors.
TK-10284
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Files touched
M public/map.htmlM public/rentv-nav.js
Diff
commit 2837beede329f6f37b2d5302f497c6336f3a8b97
Author: Steve Abrams <steve@designerwallcoverings.com>
Date: Thu Aug 6 10:22:18 2026 -0700
Split nav into TWO hamburgers: upper-left (Explore+Regions) + upper-right (Sections+Tools)
Steve: 'Split hamburger between upper right and left.' Both the map's own build AND the
sitewide masthead build now render two hamburgers flanking a centered logo:
• LEFT drawer (slides from left): Explore pages + Regions
• RIGHT drawer (slides from right): Sections (+ the map's filters/legend/Near me/Reset on /map)
Region/Section links split from the hidden strip (.rt-geo → left, .rt-cat → right).
Verified markets/blog/map: 2 hamburgers, logo centered, correct split, 0 errors.
TK-10284
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
---
public/map.html | 103 ++++++++++++++++++++++++++++++----------------------
public/rentv-nav.js | 59 +++++++++++++++++++-----------
2 files changed, 97 insertions(+), 65 deletions(-)
diff --git a/public/map.html b/public/map.html
index 061d81f1..8197a5c9 100644
--- a/public/map.html
+++ b/public/map.html
@@ -81,17 +81,20 @@ aside .ah{padding:12px 16px;border-bottom:1px solid var(--line);font-size:12px;f
.stage{position:relative}.bar h1{font-size:15px}}
/* ── Hamburger + drawer: all the nav tabs collapse in here so the map gets the screen ── */
.rentvtabs{display:none!important} /* injected region/section strip → moved into the drawer */
-/* Minimal top bar: hamburger LEFT, wordmark, story count. Everything else lives in the drawer. */
-.mast{position:relative;display:flex;align-items:center;padding:12px 16px;min-height:52px}
+/* Minimal top bar: hamburger UPPER-LEFT + UPPER-RIGHT, wordmark centered. All nav/tools live
+ in the two drawers (left = Explore+Regions, right = Sections+Filters). */
+.mast{position:relative;display:flex;align-items:center;justify-content:center;padding:12px 56px;min-height:52px}
.mast .logo{position:absolute;left:50%;transform:translateX(-50%);font-size:26px;white-space:nowrap}
-.cntpill{margin-left:auto;font-size:12px;font-weight:700;color:var(--sub);white-space:nowrap}
-@media(max-width:520px){.cntpill{display:none}}
-.ham{position:absolute;left:14px;top:50%;transform:translateY(-50%);background:#fff;border:1.5px solid var(--line);border-radius:9px;font-size:17px;line-height:1;padding:8px 11px;cursor:pointer;color:var(--ink);z-index:5}
+.cntpill{font-size:12px;font-weight:700;color:var(--sub);white-space:nowrap}
+.ham{position:absolute;top:50%;transform:translateY(-50%);background:#fff;border:1.5px solid var(--line);border-radius:9px;font-size:17px;line-height:1;padding:8px 11px;cursor:pointer;color:var(--ink);z-index:5}
+.ham.hamL{left:14px}.ham.hamR{right:14px}
.ham:hover{border-color:var(--red);color:var(--red)}
.drawer{position:fixed;inset:0;z-index:4000;display:none}
.drawer.open{display:block}
.drawer .bd{position:absolute;inset:0;background:rgba(0,0,0,.45)}
-.drawer .pl{position:absolute;top:0;left:0;width:min(86vw,300px);height:100%;background:#fff;overflow:auto;padding:18px 16px 44px;box-shadow:10px 0 44px rgba(0,0,0,.32)}
+.drawer .pl{position:absolute;top:0;width:min(86vw,300px);height:100%;background:#fff;overflow:auto;padding:18px 16px 44px}
+.drawer.left .pl{left:0;box-shadow:10px 0 44px rgba(0,0,0,.32)}
+.drawer.right .pl{right:0;box-shadow:-10px 0 44px rgba(0,0,0,.32)}
.drawer .pl h3{font-family:'Playfair Display',serif;font-size:19px;margin:0 0 2px}
.drawer .x{position:absolute;top:12px;right:14px;font-size:24px;background:none;border:0;cursor:pointer;color:var(--sub);line-height:1}
.drawer .gt{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.08em;color:var(--sub);margin:16px 0 6px}
@@ -110,17 +113,37 @@ aside .ah{padding:12px 16px;border-bottom:1px solid var(--line);font-size:12px;f
@media(max-width:760px){.mast{padding:8px 12px 8px 54px}.mast .logo{font-size:22px}.util{display:none}}
</style></head><body>
<header class="mast">
- <button class="ham" id="ham" aria-label="Open menu" aria-expanded="false">☰</button>
+ <button class="ham hamL" id="hamL" aria-label="Explore & regions menu" aria-expanded="false">☰</button>
<a class="logo" href="/">REN<span>TV</span>.com<small>News Map</small></a>
- <span class="cntpill" id="cnt"></span>
+ <button class="ham hamR" id="hamR" aria-label="Sections & filters menu" aria-expanded="false">☰</button>
</header>
-<div class="drawer" id="drawer" data-own-nav aria-hidden="true">
- <div class="bd" id="drawerBd"></div>
+<!-- LEFT drawer: Explore + Regions -->
+<div class="drawer left" id="drawerL" data-own-nav aria-hidden="true">
+ <div class="bd" data-close="L"></div>
<div class="pl">
- <button class="x" id="drawerX" aria-label="Close menu">×</button>
- <h3>REN<span style="color:var(--red)">TV</span>.com</h3>
+ <button class="x" data-close="L" aria-label="Close menu">×</button>
+ <h3>Explore</h3>
+ <a href="/">Front page</a>
+ <a href="/map">🗺 News Map</a>
+ <a href="/markets">Markets</a>
+ <a href="/review">The REview</a>
+ <a href="/cre-talk">CRE Talk</a>
+ <a href="/conferences">Conferences</a>
+ <a href="/blog">Blog</a>
+ <a href="/about">About</a>
+ <a href="/advertise">Advertise</a>
+ <a href="/subscribe">Subscribe</a>
+ <div class="gt">Regions</div>
+ <div id="drawerRegions"></div>
+ </div>
+</div>
+<!-- RIGHT drawer: Sections + map tools/filters -->
+<div class="drawer right" id="drawerR" data-own-nav aria-hidden="true">
+ <div class="bd" data-close="R"></div>
+ <div class="pl">
+ <button class="x" data-close="R" aria-label="Close menu">×</button>
+ <h3>Filter the map <span class="cntpill" id="cnt"></span></h3>
<span class="legend"><span><span class="dot g"></span>Last 3 months</span><span><span class="dot r"></span>Older</span></span>
- <div class="gt">Map filters</div>
<label class="fl">Show
<select id="fresh">
<option value="all">All stories</option>
@@ -135,19 +158,8 @@ aside .ah{padding:12px 16px;border-bottom:1px solid var(--line);font-size:12px;f
<div class="yrs"><label class="fl" style="margin:0">From<select id="yfrom" title="From year"></select></label><label class="fl" style="margin:0">To<select id="yto" title="To year"></select></label></div>
<button class="btn" id="near">📍 Near me</button>
<button class="btn ghost" id="reset">Reset view</button>
- <div class="gt">Explore</div>
- <a href="/">Front page</a>
- <a href="/map">🗺 News Map</a>
- <a href="/markets">Markets</a>
- <a href="/review">The REview</a>
- <a href="/cre-talk">CRE Talk</a>
- <a href="/conferences">Conferences</a>
- <a href="/blog">Blog</a>
- <a href="/about">About</a>
- <a href="/advertise">Advertise</a>
- <a href="/subscribe">Subscribe</a>
- <div class="gt">Regions & Sections</div>
- <div id="drawerNav"></div>
+ <div class="gt">Sections</div>
+ <div id="drawerSections"></div>
</div>
</div>
<div class="stage">
@@ -164,22 +176,27 @@ aside .ah{padding:12px 16px;border-bottom:1px solid var(--line);font-size:12px;f
var esc=function(s){return (s||'').replace(/[&<>"]/g,function(c){return {'&':'&','<':'<','>':'>','"':'"'}[c];});};
var $=function(id){return document.getElementById(id);};
-// Hamburger drawer — houses ALL nav tabs (the injected region/section strip is hidden and
-// cloned in here) so the map keeps the screen.
-function openDrawer(){
- var host=$('drawerNav');
- if(!host.getAttribute('data-filled')){
- var t=document.querySelector('.rentvtabs');
- host.innerHTML = t ? '<div class="clone">'+t.innerHTML+'</div>' : '<div style="color:var(--sub);font-size:13px">Loading…</div>';
- if(t) host.setAttribute('data-filled','1'); // retry next open until the injected nav exists
- }
- var d=$('drawer'); d.classList.add('open'); d.setAttribute('aria-hidden','false'); $('ham').setAttribute('aria-expanded','true');
+// Two drawers: LEFT (Explore + Regions), RIGHT (Sections + map filters). The region/section
+// links come from the hidden injected .rentvtabs strip — .rt-geo → Regions, .rt-cat → Sections.
+function cloneRows(hostId, rowSel){
+ var host=$(hostId); if(!host || host.getAttribute('data-filled')) return;
+ var row=document.querySelector('.rentvtabs '+rowSel);
+ if(row){ host.innerHTML='<div class="clone">'+row.innerHTML+'</div>'; host.setAttribute('data-filled','1'); }
+}
+function openL(){ cloneRows('drawerRegions','.rt-geo'); var d=$('drawerL'); d.classList.add('open'); d.setAttribute('aria-hidden','false'); $('hamL').setAttribute('aria-expanded','true'); }
+function openR(){ cloneRows('drawerSections','.rt-cat'); var d=$('drawerR'); d.classList.add('open'); d.setAttribute('aria-hidden','false'); $('hamR').setAttribute('aria-expanded','true'); }
+function closeDrawer(which){
+ var d=$('drawer'+which); if(!d) return; d.classList.remove('open'); d.setAttribute('aria-hidden','true');
+ $('ham'+which).setAttribute('aria-expanded','false');
}
-function closeDrawer(){ var d=$('drawer'); d.classList.remove('open'); d.setAttribute('aria-hidden','true'); $('ham').setAttribute('aria-expanded','false'); }
-$('ham').onclick=openDrawer; $('drawerX').onclick=closeDrawer; $('drawerBd').onclick=closeDrawer;
-document.addEventListener('keydown',function(e){if(e.key==='Escape')closeDrawer();});
-// close after tapping a link inside the drawer
-$('drawer').addEventListener('click',function(e){ if(e.target.closest('a')) closeDrawer(); });
+function closeAll(){ closeDrawer('L'); closeDrawer('R'); }
+$('hamL').onclick=openL; $('hamR').onclick=openR;
+document.addEventListener('click',function(e){
+ var c=e.target.closest('[data-close]'); if(c){ closeDrawer(c.getAttribute('data-close')); return; }
+ // tap a link inside either drawer → close both
+ if(e.target.closest('.drawer a')) closeAll();
+});
+document.addEventListener('keydown',function(e){if(e.key==='Escape')closeAll();});
// "Last 3 months" is computed HERE, at load, so freshness is always relative to today.
var CUTOFF=(function(){var d=new Date();d.setMonth(d.getMonth()-3);return d;})();
@@ -323,14 +340,14 @@ map.on('moveend',function(){ if(!meLatLng) refreshList(); });
// controls
$('fresh').onchange=function(e){fFresh=e.target.value;buildMarkers();};
$('txn').onchange=function(e){fTxn=e.target.value;buildMarkers();};
-$('reset').onclick=function(){ closeDrawer(); meLatLng=null; if(meMarker){map.removeLayer(meMarker);meMarker=null;}
+$('reset').onclick=function(){ closeDrawer('R'); meLatLng=null; if(meMarker){map.removeLayer(meMarker);meMarker=null;}
fFresh='all';$('fresh').value='all'; fTxn='';$('txn').value='';
if($('yfrom').options.length){fYFrom=parseInt($('yfrom').options[$('yfrom').options.length-1].value,10);$('yfrom').value=fYFrom;
fYTo=parseInt($('yto').options[0].value,10);$('yto').value=fYTo;}
map.setView([37.5,-119],5); buildMarkers(); };
$('near').onclick=function(){
if(!navigator.geolocation){alert('Location isn’t available in this browser.');return;}
- closeDrawer();
+ closeDrawer('R');
$('near').textContent='📍 Locating…';
navigator.geolocation.getCurrentPosition(function(pos){
meLatLng=[pos.coords.latitude,pos.coords.longitude];
diff --git a/public/rentv-nav.js b/public/rentv-nav.js
index 76a85e06..db8a19e8 100644
--- a/public/rentv-nav.js
+++ b/public/rentv-nav.js
@@ -43,11 +43,14 @@
// the data source cloned into the hamburger drawer on masthead pages.
'.rentvtabs{display:none!important}',
// Injected hamburger + left drawer for masthead-chrome pages (header.mast with no drawer).
- '.rtnav-ham{position:absolute;left:14px;top:50%;transform:translateY(-50%);background:#fff;border:1.5px solid var(--line,#e4e7ea);border-radius:9px;font-size:17px;line-height:1;padding:7px 11px;cursor:pointer;color:#14171a;z-index:20}',
+ '.rtnav-ham{position:absolute;top:50%;transform:translateY(-50%);background:#fff;border:1.5px solid var(--line,#e4e7ea);border-radius:9px;font-size:17px;line-height:1;padding:7px 11px;cursor:pointer;color:#14171a;z-index:20}',
+ '.rtnav-ham.l{left:14px}.rtnav-ham.r{right:14px}',
'.rtnav-ham:hover{border-color:var(--red,#c8102e);color:var(--red,#c8102e)}',
'.rtnav-dr{position:fixed;inset:0;z-index:4000;display:none}.rtnav-dr.open{display:block}',
'.rtnav-bd{position:absolute;inset:0;background:rgba(0,0,0,.45)}',
- '.rtnav-pl{position:absolute;top:0;left:0;width:min(86vw,300px);height:100%;background:#fff;overflow:auto;padding:18px 16px 44px;box-shadow:10px 0 44px rgba(0,0,0,.32)}',
+ '.rtnav-pl{position:absolute;top:0;width:min(86vw,300px);height:100%;background:#fff;overflow:auto;padding:18px 16px 44px}',
+ '.rtnav-dr.left .rtnav-pl{left:0;box-shadow:10px 0 44px rgba(0,0,0,.32)}',
+ '.rtnav-dr.right .rtnav-pl{right:0;box-shadow:-10px 0 44px rgba(0,0,0,.32)}',
'.rtnav-pl h3{font-family:"Playfair Display",serif;font-size:19px;margin:0 0 6px}.rtnav-pl h3 span{color:var(--red,#c8102e)}',
'.rtnav-x{position:absolute;top:12px;right:14px;font-size:24px;background:none;border:0;cursor:pointer;color:#5b636b;line-height:1}',
'.rtnav-gt{font-size:10px;font-weight:800;text-transform:uppercase;letter-spacing:.08em;color:#9aa2ab;margin:16px 0 6px}',
@@ -150,33 +153,45 @@
if (document.querySelector('.drawer')) return; // has its own drawer (map / header.top) — skip
if (document.querySelector('.rtnav-ham')) return; // idempotent
mast.classList.add('rtnav-has');
- var ham = document.createElement('button');
- ham.className = 'rtnav-ham'; ham.setAttribute('aria-label', 'Open menu'); ham.type = 'button'; ham.innerHTML = '☰';
- mast.insertBefore(ham, mast.firstChild);
var strip = document.querySelector('.rentvtabs');
- var dr = document.createElement('div'); dr.className = 'rtnav-dr'; dr.setAttribute('aria-hidden', 'true');
- dr.innerHTML = '<div class="rtnav-bd"></div><div class="rtnav-pl">' +
- '<button class="rtnav-x" type="button" aria-label="Close">×</button>' +
- '<h3>REN<span>TV</span>.com</h3>' +
- '<div class="rtnav-gt">Explore</div>' +
+ var geo = strip ? (strip.querySelector('.rt-geo') || {}).innerHTML || '' : ''; // Regions row
+ var cat = strip ? (strip.querySelector('.rt-cat') || {}).innerHTML || '' : ''; // Sections row
+ function mkHam(side, label) {
+ var h = document.createElement('button'); h.type = 'button';
+ h.className = 'rtnav-ham ' + side; h.setAttribute('aria-label', label); h.innerHTML = '☰';
+ return h;
+ }
+ // LEFT hamburger + drawer → Explore + Regions
+ var hamL = mkHam('l', 'Explore & regions menu');
+ var drL = document.createElement('div'); drL.className = 'rtnav-dr left'; drL.setAttribute('aria-hidden', 'true');
+ drL.innerHTML = '<div class="rtnav-bd"></div><div class="rtnav-pl">' +
+ '<button class="rtnav-x" type="button" aria-label="Close">×</button><h3>Explore</h3>' +
'<a href="/">Front page</a><a href="/map">🗺 News Map</a><a href="/markets">Markets</a>' +
'<a href="/review">The REview</a><a href="/cre-talk">CRE Talk</a><a href="/conferences">Conferences</a>' +
'<a href="/blog">Blog</a><a href="/about">About</a><a href="/advertise">Advertise</a><a href="/subscribe">Subscribe</a>' +
- '<div class="rtnav-gt">Regions & Sections</div><div class="rtnav-clone">' + (strip ? strip.innerHTML : '') + '</div>' +
- '</div>';
- document.body.appendChild(dr);
- // Hide the page's OWN horizontal nav bar (its links live in this drawer now). It's the first
- // <nav> after the masthead; skip the injected (already-hidden) .rentvtabs strip.
+ '<div class="rtnav-gt">Regions</div><div class="rtnav-clone">' + geo + '</div></div>';
+ // RIGHT hamburger + drawer → Sections
+ var hamR = mkHam('r', 'Sections menu');
+ var drR = document.createElement('div'); drR.className = 'rtnav-dr right'; drR.setAttribute('aria-hidden', 'true');
+ drR.innerHTML = '<div class="rtnav-bd"></div><div class="rtnav-pl">' +
+ '<button class="rtnav-x" type="button" aria-label="Close">×</button><h3>Sections</h3>' +
+ '<div class="rtnav-clone">' + cat + '</div></div>';
+ mast.insertBefore(hamL, mast.firstChild);
+ mast.appendChild(hamR);
+ document.body.appendChild(drL); document.body.appendChild(drR);
+ // Hide the page's OWN horizontal nav bar — its links live in these drawers now.
var sib = mast.nextElementSibling;
while (sib && sib.tagName !== 'NAV') sib = sib.nextElementSibling;
if (sib && !sib.classList.contains('rentvtabs')) sib.style.display = 'none';
- var open = function () { dr.classList.add('open'); dr.setAttribute('aria-hidden', 'false'); };
- var close = function () { dr.classList.remove('open'); dr.setAttribute('aria-hidden', 'true'); };
- ham.onclick = open;
- dr.querySelector('.rtnav-x').onclick = close;
- dr.querySelector('.rtnav-bd').onclick = close;
- dr.addEventListener('click', function (e) { if (e.target.closest('a')) close(); });
- document.addEventListener('keydown', function (e) { if (e.key === 'Escape') close(); });
+ function wire(ham, dr) {
+ ham.onclick = function () { dr.classList.add('open'); dr.setAttribute('aria-hidden', 'false'); };
+ var close = function () { dr.classList.remove('open'); dr.setAttribute('aria-hidden', 'true'); };
+ dr.querySelector('.rtnav-x').onclick = close;
+ dr.querySelector('.rtnav-bd').onclick = close;
+ dr.addEventListener('click', function (e) { if (e.target.closest('a')) close(); });
+ document.addEventListener('keydown', function (e) { if (e.key === 'Escape') close(); });
+ }
+ wire(hamL, drL); wire(hamR, drR);
}
// ---- 3) Refresh the wordmark into the 2026 liquid-glass RENTV logo (faithful to rentv.com) ----
← ba9f632d logo: make it genuinely LIQUID — animated specular sweep + f
·
back to Rentv
·
auto-data-snapshot: 2026-08-06T10:21:57 (6 data files) — dat f4d659e3 →