PageSourceSearch

https://fancy-rolypoly-84ee13.netlify.app/shared/island-nav.js

js fancy-rolypoly-84ee13.netlify.app collected 2026-10-03 10:43:33 UTC 23,229 bytes, 338 lines download raw bytes

1// Island Nav — shared across all pages
2(function() {
3  // Skip if already exists (homepage has it inline)
4  if (document.getElementById('islandNav')) return;
5
6  // Need CSS variables for island nav sizing
7  var varsStyle = document.createElement('style');
8  varsStyle.textContent = ':root{--scale:1;--island-width:calc(380px * var(--scale));--island-height:calc(72px * var(--scale));--search-width:calc(300px * var(--scale));--search-height:calc(60px * var(--scale));--ham-size:calc(60px * var(--scale));--mega-width:min(980px,94vw);--mega-height:min(680px,88vh);--sidebar-width:240px;--ease-smooth:cubic-bezier(0.4,0,0.2,1);--ease:cubic-bezier(0.16,1,0.3,1)}';
9  document.head.appendChild(varsStyle);
10
11  // Inject nav overlay
12  var overlay = document.createElement('div');
13  overlay.className = 'nav-overlay';
14  overlay.id = 'navOverlay';
15  document.body.appendChild(overlay);
16
17  // Inject island nav HTML
18  var wrapper = document.createElement('div');
19  wrapper.innerHTML = `  <nav class="island-nav" id="islandNav">
20    <div class="island-closed">
21      <button class="island-ham" id="islandHam">
22        <div class="island-ham-lines">
23          <div class="island-ham-line"></div>
24          <div class="island-ham-line"></div>
25          <div class="island-ham-line"></div>
26        </div>
27      </button>
28      <button class="island-search" id="islandSearchBtn">
29        <span class="island-search-text">Search</span>
30        <svg class="island-search-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 4L12 4L12 12"/><path d="M12 4L4 12"/></svg>
31      </button>
32    </div>
33    
34    <div class="mega-content" id="megaContent">
35      <div class="mega-main">
36        <button class="mega-search-back" id="megaSearchBack" onclick="exitSearchMode()">
37          <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="15 18 9 12 15 6"/></svg>
38          Back to menu
39        </button>
40        <div class="mega-left">
41          <a class='mega-logo-nav' href='/'>
42            <img src="assets/energy_analytics_logomark_2.svg" alt="NCEA">
43          </a>
44          <nav class="mega-nav">
45            <a class='mega-nav-link is-active' data-panel='experts' href='advisory-board.html'>
46              Experts
47              <svg class="mega-nav-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
48            </a>
49            <a href="research-library.html" class="mega-nav-link" data-panel="research">
50              Research
51              <svg class="mega-nav-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
52            </a>
53            <a href="events.html" class="mega-nav-link" data-panel="events">
54              Events
55              <svg class="mega-nav-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
56            </a>
57            <a href="topics.html" class="mega-nav-link" data-panel="topics">
58              Topics
59              <svg class="mega-nav-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
60            </a>
61            <a href="about.html" class="mega-nav-link" data-panel="about">
62              About
63              <svg class="mega-nav-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
64            </a>
65            <a href="contact.html" class="mega-nav-link" data-panel="contact">
66              Contact
67              <svg class="mega-nav-arrow" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="5" y1="12" x2="19" y2="12"/><polyline points="12 5 19 12 12 19"/></svg>
68            </a>
69          </nav>
70          <div class="mega-socials">
71            <a href="#" class="mega-social">LinkedIn</a>
72            <a href="#" class="mega-social">Twitter</a>
73          </div>
74          <div class="mega-left-bottom">
75            <button class="mega-left-line" id="megaClose"></button>
76          </div>
77        </div>
78        
79        <div class="mega-right">
80          <div class="mega-right-content">
81            <div class="mega-content-panel is-active" data-panel="experts">
82              <div class="scholars-grid-nav" id="scholarsGridNav">
83                <a href="scholar-detail.html?slug=mark-p-mills" class="scholar-nav-card" data-row="1">
84                  <img src="assets/mark_p_mills.jpg" alt="" class="scholar-nav-card-photo">
85                  <div class="scholar-nav-card-count">Executive Director</div>
86                  <div class="scholar-nav-card-bottom">
87                    <div class="scholar-nav-card-name">Mark P. Mills</div>
88                    <div class="scholar-nav-card-icon"><svg viewBox="0 0 12 12" fill="none"><path d="M3 3L9 3L9 9" stroke="currentColor" stroke-width="1.5"/><path d="M9 3L3 9" stroke="currentColor" stroke-width="1.5"/></svg></div>
89                  </div>
90                </a>
91                <a href="scholar-detail.html?slug=paul-tice" class="scholar-nav-card" data-row="1">
92                  <img src="assets/Paul_Tice_Headshot.jpg" alt="" class="scholar-nav-card-photo">
93                  <div class="scholar-nav-card-count">Senior Fellow</div>
94                  <div class="scholar-nav-card-bottom">
95                    <div class="scholar-nav-card-name">Paul H. Tice</div>
96                    <div class="scholar-nav-card-icon"><svg viewBox="0 0 12 12" fill="none"><path d="M3 3L9 3L9 9" stroke="currentColor" stroke-width="1.5"/><path d="M9 3L3 9" stroke="currentColor" stroke-width="1.5"/></svg></div>
97                  </div>
98                </a>
99                <a href="scholar-detail.html?slug=neil-atkinson" class="scholar-nav-card" data-row="2">
100                  <img src="assets/Neil_Atkinson_Headshot.jpg" alt="" class="scholar-nav-card-photo">
101                  <div class="scholar-nav-card-count">Visiting Fellow</div>
102                  <div class="scholar-nav-card-bottom">
103                    <div class="scholar-nav-card-name">Neil Atkinson</div>
104                    <div class="scholar-nav-card-icon"><svg viewBox="0 0 12 12" fill="none"><path d="M3 3L9 3L9 9" stroke="currentColor" stroke-width="1.5"/><path d="M9 3L3 9" stroke="currentColor" stroke-width="1.5"/></svg></div>
105                  </div>
106                </a>
107                <a href="scholar-detail.html?slug=lars-schernikau" class="scholar-nav-card" data-row="2">
108                  <img src="assets/Lars_Schernikau_Headshot.jpg" alt="" class="scholar-nav-card-photo">
109                  <div class="scholar-nav-card-count">Visiting Fellow</div>
110                  <div class="scholar-nav-card-bottom">
111                    <div class="scholar-nav-card-name">Lars Schernikau</div>
112                    <div class="scholar-nav-card-icon"><svg viewBox="0 0 12 12" fill="none"><path d="M3 3L9 3L9 9" stroke="currentColor" stroke-width="1.5"/><path d="M9 3L3 9" stroke="currentColor" stroke-width="1.5"/></svg></div>
113                  </div>
114                </a>
115                <a href="scholar-detail.html?slug=pat-mccormick" class="scholar-nav-card" data-row="3">
116                  <img src="assets/Pat_McCormick_Headshot.jpg" alt="" class="scholar-nav-card-photo">
117                  <div class="scholar-nav-card-count">Senior Fellow</div>
118                  <div class="scholar-nav-card-bottom">
119                    <div class="scholar-nav-card-name">Patrick McCormick</div>
120                    <div class="scholar-nav-card-icon"><svg viewBox="0 0 12 12" fill="none"><path d="M3 3L9 3L9 9" stroke="currentColor" stroke-width="1.5"/><path d="M9 3L3 9" stroke="currentColor" stroke-width="1.5"/></svg></div>
121                  </div>
122                </a>
123                <a href="advisory-board.html" class="scholar-nav-card" data-row="3">
124                  <div class="scholar-nav-card-count">30+ experts</div>
125                  <div class="scholar-nav-card-bottom">
126                    <div class="scholar-nav-card-name">View all experts →</div>
127                  </div>
128                </a>
129              </div>
130            </div>
131            <div class="mega-content-panel" data-panel="research">
132              <div class="panel-grid" id="researchPanelGrid">
133                <a class='panel-card' data-row='1' href='studies.html'><img src="assets/datacenter-corridor.jpg" class="panel-card-bg" alt=""><div class="panel-card-label">50+ studies</div><div class="panel-card-title">
133Studies<svg class="panel-card-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 4L12 4L12 12"/><path d="M12 4L4 12"/></svg></div></a>
134                <a class='panel-card' data-row='1' href='issue-briefs.html'><img src="assets/pumpjack-wheat-sunset.jpg" class="panel-card-bg" alt=""><div class="panel-card-label">80+ briefs</div><div class="panel-card-title">Issue Briefs<svg class="panel-card-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 4L12 4L12 12"/><path d="M12 4L4 12"/></svg></div></a>
135                <a class='panel-card' data-row='2' href='studies.html'><img src="assets/offshore-platform-sunset.jpg" class="panel-card-bg" alt=""><div class="panel-card-label">12 initiatives</div><div class="panel-card-title">Special Initiatives<svg class="panel-card-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 4L12 4L12 12"/><path d="M12 4L4 12"/></svg></div></a>
136                <a class='panel-card' data-row='2' href='energy-index.html'><img src="assets/openpit-mine-aerial.jpg" class="panel-card-bg" alt=""><div class="panel-card-label">Dashboard</div><div class="panel-card-title">
136Leading Energy Indicators<svg class="panel-card-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 4L12 4L12 12"/><path d="M12 4L4 12"/></svg></div></a>
137                <a class='panel-card' data-row='3' href='advisory-board.html'><img src="assets/excavator-bucket-golden.jpg" class="panel-card-bg" alt=""><div class="panel-card-label">30+ experts</div><div class="panel-card-title">Expert Directory<svg class="panel-card-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 4L12 4L12 12"/><path d="M12 4L4 12"/></svg></div></a>
138                <a class='panel-card' data-row='3' href='research-library.html'><div class="panel-card-label">Browse all</div><div class="panel-card-title">View all research →</div></a>
139              </div>
140            </div>
141            <div class="mega-content-panel" data-panel="topics">
142              <div class="panel-grid" id="topicsPanelGrid">
143                <a class='panel-card' data-row='1' href='research-library.html'><img src="assets/datacenter-servers.jpg" class="panel-card-bg" alt=""><div class="panel-card-label">Policy area</div><div class="panel-card-title">
143Electricity & Grid<svg class="panel-card-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 4L12 4L12 12"/><path d="M12 4L4 12"/></svg></div></a>
144                <a class='panel-card' data-row='1' href='research-library.html'><img src="assets/pumpjacks-silhouette.jpg" class="panel-card-bg" alt=""><div class="panel-card-label">Policy area</div><div class="panel-card-title">Energy Affordability<svg class="panel-card-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 4L12 4L12 12"/><path d="M12 4L4 12"/></svg></div></a>
145                <a class='panel-card' data-row='2' href='research-library.html'><img src="assets/manufacturing-pellets.jpg" class="panel-card-bg" alt=""><div class="panel-card-label">Policy area</div><div class="panel-card-title">Nuclear Energy<svg class="panel-card-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 4L12 4L12 12"/><path d="M12 4L4 12"/></svg></div></a>
146                <a class='panel-card' data-row='2' href='research-library.html'><img src="assets/solar-aerial.jpg" class="panel-card-bg" alt=""><div class="panel-card-label">Policy area</div><div class="panel-card-title">
146Renewables<svg class="panel-card-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 4L12 4L12 12"/><path d="M12 4L4 12"/></svg></div></a>
147                <a class='panel-card' data-row='3' href='research-library.html'><img src="assets/port-tankers-dusk.jpg" class="panel-card-bg" alt=""><div class="panel-card-label">Policy area</div><div class="panel-card-title">Energy Markets<svg class="panel-card-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 4L12 4L12 12"/><path d="M12 4L4 12"/></svg></div></a>
148                <a class='panel-card' data-row='3' href='research-library.html'><div class="panel-card-label">Browse all</div><div class="panel-card-title">View all topics →</div></a>
149              </div>
150            </div>
151            <div class="mega-content-panel" data-panel="events">
152              <div class="panel-grid" id="eventsPanelGrid">
153                <a class='panel-card' data-row='1' href='events.html'><img src="assets/drilling-ships.jpg" class="panel-card-bg" alt=""><div class="panel-card-label">Upcoming</div><div class="panel-card-title">
153Webinars<svg class="panel-card-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 4L12 4L12 12"/><path d="M12 4L4 12"/></svg></div></a>
154                <a class='panel-card' data-row='1' href='events.html'><img src="assets/quarry-excavator.jpg" class="panel-card-bg" alt=""><div class="panel-card-label">In the field</div><div class="panel-card-title">Conferences<svg class="panel-card-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 4L12 4L12 12"/><path d="M12 4L4 12"/></svg></div></a>
155                <a class='panel-card' data-row='2' href='events.html'><img src="assets/mining-aerial-abstract.jpg" class="panel-card-bg" alt=""><div class="panel-card-label">Media</div><div class="panel-card-title">Podcasts<svg class="panel-card-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 4L12 4L12 12"/><path d="M12 4L4 12"/></svg></div></a>
156                <a class='panel-card' data-row='2' href='events.html'><img src="assets/offshore-rig-aerial.jpg" class="panel-card-bg" alt=""><div class="panel-card-label">Government</div><div class="panel-card-title">
156Testimony<svg class="panel-card-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 4L12 4L12 12"/><path d="M12 4L4 12"/></svg></div></a>
157                <a class='panel-card' data-row='3' href='events.html'><img src="assets/limestone-quarry.jpg" class="panel-card-bg" alt=""><div class="panel-card-label">Watch</div><div class="panel-card-title">Video Rewinds<svg class="panel-card-arrow" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M4 4L12 4L12 12"/><path d="M12 4L4 12"/></svg></div></a>
158                <a class='panel-card' data-row='3' href='events.html'><div class="panel-card-label">Browse all</div><div class="panel-card-title">View all events →</div></a>
159              </div>
160            </div>
161            <div class="mega-content-panel" data-panel="about">
162              <div class="about-panel">
163                <img src="assets/energy_analytics_logomark_2.svg" alt="NCEA" class="about-logo-large">
164                <p class="about-text">Independent research and analysis for informed energy policy decisions. Serving policymakers, industry leaders, and the public.</p>
165                <div class="about-stats-nav">
166                  <div class="about-stat"><div class="about-stat-num">15+</div><div class="about-stat-label">Years of<br>Research</div></div>
167                  <div class="about-stat"><div class="about-stat-num">200+</div><div class="about-stat-label">Published<br>Studies</div></div>
168                  <div class="about-stat"><div class="about-stat-num">30+</div><div class="about-stat-label">Expert<br>Experts</div></div>
169                </div>
170              </div>
171            </div>
172            <div class="mega-content-panel" data-panel="contact">
173              <div class="contact-panel">
174                <h2 class="contact-title-nav">Get in Touch</h2>
175                <div class="contact-links-nav">
176                  <a href="tel:+12025551234" class="contact-link-nav">+1 (202) 555-1234</a>
177                  <a href="mailto:[email protected]" class="contact-link-nav">[email protected]</a>
178                </div>
179                <p class="contact-address-nav">Washington, DC</p>
180              </div>
181            </div>
182            <div class="mega-content-panel" data-panel="search">
183              <div class="mega-search-panel">
184                <div class="mega-search-header">
185                  <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" class="mega-search-icon"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>
186                  <h3 class="mega-search-title">Search NCEA</h3>
187                  <p class="mega-search-subtitle">Find research, events, media, and scholars</p>
188                </div>
189                <div class="mega-search-input-wrap">
190                  <input type="text" class="mega-search-input" id="megaSearchInput" placeholder="Search by title, scholar, outlet, topic..." autocomplete="off">
191                  <button class="mega-search-submit" id="megaSearchSubmit">
192                    <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>
193                  </button>
194                </div>
195                <div class="mega-search-suggestions">
196                  <span class="mega-search-tag" data-query="Mark Mills">Mark Mills</span>
197                  <span class="mega-search-tag" data-query="grid reliability">Grid reliability</span>
198                  <span class="mega-search-tag" data-query="nuclear">Nuclear</span>
199                  <span class="mega-search-tag" data-query="podcast">Podcasts</span>
200                  <span class="mega-search-tag" data-query="testimony">Testimony</span>
201                  <span class="mega-search-tag" data-query="CNBC">Media appearances</span>
202                </div>
203                <div class="mega-search-results" id="megaSearchResults"></div>
204              </div>
205            </div>
206          </div>
207          
208          <div class="mega-search-bar" id="megaSearchBar">
209            <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" class="mega-search-bar-icon"><circle cx="11" cy="11" r="8"/><path d="M21 21l-4.35-4.35"/></svg>
210            <span class="mega-search-bar-text">Search NCEA...</span>
211            <span class="mega-search-bar-key">⌘K</span>
212          </div>
213        </div>
214      </div>
215    </div>
216  </nav>`;
217  var nav = wrapper.firstElementChild;
218  document.body.appendChild(nav);
219
220  // ---- ISLAND NAV LOGIC ----
221  var islandNav = document.getElementById('islandNav');
222  var islandHam = document.getElementById('islandHam');
223  var megaContent = document.getElementById('megaContent');
224  var megaClose = document.getElementById('megaClose');
225  var navOverlayEl = document.getElementById('navOverlay');
226  var navLinks = document.querySelectorAll('.mega-nav-link');
227  var contentPanels = document.querySelectorAll('.mega-content-panel');
228
229  if (!islandNav || !islandHam) return;
230
231  var isOpen = false;
232  var currentPanel = 'experts';
233  var openedAt = 0;
234
235  function openIsland() {
236    isOpen = true;
237    openedAt = Date.now();
238    // Restore visibility in case footer observer hid it
239    islandNav.style.opacity = '';
240    islandNav.style.pointerEvents = '';
241    islandNav.classList.add('is-open');
242    if (navOverlayEl) { navOverlayEl.classList.add('is-visible'); }
243    document.body.style.overflow = 'hidden';
244    // Fade in mega content (CSS default is opacity:0)
245    var mc = document.getElementById('megaContent');
246    if (mc) { setTimeout(function() { mc.style.transition = 'opacity 0.35s ease'; mc.style.opacity = '1'; }, 50); }
247  }
248
249  function closeIsland() {
250    if (!isOpen) return;
251    if (Date.now() - openedAt < 400) return; // prevent immediate close
252    isOpen = false;
253    var mc = document.getElementById('megaContent');
254    if (mc) { mc.style.opacity = '0'; }
255    setTimeout(function() {
256      islandNav.classList.remove('is-open');
257      if (navOverlayEl) { navOverlayEl.classList.remove('is-visible'); }
258      document.body.style.overflow = '';
259    }, 200);
260  }
261
262  function switchPanel(name) {
263    currentPanel = name;
264    navLinks.forEach(function(l) { l.classList.toggle('is-active', l.dataset.panel === name); });
265    contentPanels.forEach(function(p) { p.classList.toggle('is-active', p.dataset.panel === name); });
266  }
267
268  var hamBusy = false;
269  islandHam.addEventListener('click', function(e) {
270    e.preventDefault();
271    e.stopPropagation();
272    e.stopImmediatePropagation();
273    if (hamBusy) return;
274    hamBusy = true;
275    if (isOpen) {
276      closeIsland();
277    } else {
278      openIsland();
279    }
280    setTimeout(function() { hamBusy = false; }, 600);
281  });
282
283  if (megaClose) {
284    megaClose.addEventListener('click', function(e) { e.stopPropagation(); closeIsland(); });
285  }
286
287  navLinks.forEach(function(link) {
288    link.addEventListener('mouseenter', function() {
289      switchPanel(link.dataset.panel);
290    });
291    link.addEventListener('click', function(e) {
292      if (isOpen) {
293        // If clicking the active panel link, navigate
294        // Otherwise just switch panels
295        if (link.dataset.panel === currentPanel) {
296          closeIsland();
297        } else {
298          e.preventDefault();
299          switchPanel(link.dataset.panel);
300        }
301      }
302    });
303  });
304
305  if (navOverlayEl) {
306    navOverlayEl.addEventListener('click', closeIsland);
307  }
308
309  document.addEventListener('keydown', function(e) {
310    if (e.key === 'Escape' && isOpen) closeIsland();
311  });
312
313  // Island search button
314  var islandSearchBtn = document.getElementById('islandSearchBtn');
315  if (islandSearchBtn) {
316    islandSearchBtn.addEventListener('click', function() {
317      if (typeof window.openSearchModal === 'function') {
318        window.openSearchModal();
319      }
320    });
321  }
322})();
323
324// Hide island nav when footer is visible (direct style, no classes)
325(function() {
326  var island = document.getElementById('islandNav');
327  var footer = document.querySelector('footer, .footer');
328  if (!island || !footer) return;
329  var observer = new IntersectionObserver(function(entries) {
330    // Only hide if island nav is NOT open
331    if (island.classList.contains('is-open')) return;
332    var visible = entries[0].isIntersecting;
333    island.style.opacity = visible ? '0' : '';
334    island.style.pointerEvents = visible ? 'none' : '';
335  }, { threshold: 0.05 });
336  observer.observe(footer);
337})();
338

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.