1/** 2 * Top-nav header interactions. 3 * Loaded immediately from _header_topnav.php (not deferred via Assets). 4 */ 5(function () { 6 'use strict'; 7 8 // Footer accordion (onclick in _footer_optimized_redesign.php). Defined here 9 // because top-nav pages skip header_redesign.js, which previously owned this. 10 // Prefer jQuery slide when available; vanilla fallback for deferred Assets. 11 window.footerMobileLinks = function (element) { 12 if (!element) return; 13 if (window.jQuery) { 14 var $el = window.jQuery(element); 15 var $content = $el.next('.footer-menu'); 16 if ($content.is(':visible')) { 17 $content.slideUp(); 18 $el.removeClass('active'); 19 } else { 20 $content.slideDown(); 21 $el.addClass('active'); 22 } 23 return; 24 } 25 var content = element.nextElementSibling; 26 if (!content || !content.classList.contains('footer-menu')) return; 27 if (element.classList.contains('active')) { 28 content.style.display = 'none'; 29 element.classList.remove('active'); 30 } else { 31 content.style.display = 'block'; 32 element.classList.add('active'); 33 } 34 }; 35 36 // Chat is clicked before the idle Intercom loader runs, so Intercom() is missing. 37 window.openSupportChat = function (event) { 38 if (event && event.preventDefault) event.preventDefault(); 39 40 window.intercomSettings = window.intercomSettings || { app_id: 'ld9mkn53' }; 41 42 if (typeof window.Intercom !== 'function') { 43 var queued = function () { queued.c(arguments); }; 44 queued.q = []; 45 queued.c = function (args) { queued.q.push(args); }; 46 window.Intercom = queued; 47 } 48 49 if (!document.querySelector('script[src*="widget.intercom.io/widget/ld9mkn53"]')) { 50 var script = document.createElement('script'); 51 script.type = 'text/javascript'; 52 script.async = true; 53 script.src = 'https://widget.intercom.io/widget/ld9mkn53'; 54 document.head.appendChild(script); 55 } 56 57 window.Intercom('show'); 58 }; 59 60 if (window.__tnHeaderInit) return; 61 window.__tnHeaderInit = true; 62 63 function ready(fn) { 64 if (document.readyState === 'loading') { 65 document.addEventListener('DOMContentLoaded', fn); 66 } else { 67 fn(); 68 } 69 } 70 71 // Account menus (dropdown + drawer). The header HTML is cached at the 72 // Cloudflare edge and shared by all visitors, so login state can't be 73 // rendered server-side. Guess from the jwt_token cookie for a fast first 74 // paint, then confirm with /controllers/sessions.php (uncached), which also 75 // issues a missing jwt. A stale jwt (session expired) is cleared here: the 76 // endpoint's own clear omits path=/ and so misses the root cookie. 77 ready(function () { 78 var authEls = Array.prototype.slice.call(document.querySelectorAll('[data-tn-auth]')); 79 if (!authEls.length) return; 80 81 function applyAuth(loggedIn) { 82 authEls.forEach(function (el) { 83 if ((el.getAttribute('data-tn-auth') === 'in') === loggedIn) { 84 el.style.removeProperty('display'); 85 } else { 86 el.style.setProperty('display', 'none', 'important'); 87 } 88 }); 89 } 90 91 var jwtMatch = document.cookie.match(/(?:^|;\s*)jwt_token=([^;]*)/); 92 var jwt = jwtMatch ? decodeURIComponent(jwtMatch[1]) : ''; 93 applyAuth(jwt !== '' && jwt !== 'undefined'); 94 95 if (!window.fetch) return; 96 fetch('/controllers/sessions.php', { credentials: 'same-origin', cache: 'no-store' }) 97 .then(function (res) { return res.json(); }) 98 .then(function (data) { 99 if (!data || !data.success) return; 100 if (!data.token && jwt) { 101 document.cookie = 'jwt_token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT'; 102 } 103 applyAuth(!!data.token); 104 }) 105 .catch(function () {}); 106 }); 107 108 ready(function () { 109 var header = document.getElementById('tnHeader'); 110 if (!header) return; 111 112 document.body.classList.add('has-tn-header'); 113 114 var items = Array.prototype.slice.call(header.querySelectorAll('[data-tn-menu]')); 115 var panels = Array.prototype.slice.call(header.querySelectorAll('[data-tn-panel]')); 116 var dropdowns = Array.prototype.slice.call(header.querySelectorAll('.tn-header__dropdown')); 117 var closeTimer = null; 118 var spacer = document.getElementById('tnHeaderSpacer'); 119 var SCROLL_THRESHOLD = 80; 120 121 var drawer = document.getElementById('tnDrawer'); 122 var backdrop = document.getElementById('tnDrawerBackdrop'); 123 var openBtns = Array.prototype.slice.call(document.querySelectorAll('[data-tn-menu-open]')); 124 var closeBtn = document.getElementById('tnMenuClose'); 125 var mobileSearchToggle = document.getElementById('tnMobileSearchToggle'); 126 // Premium marketplace pages ship their own sticky search bar â don't pin 127 // the site header on scroll (it would overlap that UI). 128 var hasMarketplaceStickySearch = !!document.getElementById('sticky-search-bar') 129 && !!document.getElementById('search-container'); 130 var currentPath = window.location.pathname || ''; 131 var isRegisterPath = /^\/register(?:\/|$)/.test(currentPath); 132 var isHandRegDealsPath = /^\/hand-reg-deals(?:\/|$)/.test(currentPath);
133 var isTrademarkFilingPath = /^\/trademark-filing(?:\/|$)/.test(currentPath); 134 var isNamePath = /^\/name(?:\/|$)/.test(currentPath); 135 var isDomainAppraisalPath = /^\/domain-appraisal(?:\/|$)/.test(currentPath); 136 var isSellingSettingsPath = /^\/marketplace\/settings\/selling(?:\/|$)/.test(currentPath); 137 var isRegisterTldPath = /^\/register\/tld(?:\/|$)/.test(currentPath); 138 var shouldHideHeaderOnScroll = (isRegisterPath && !isRegisterTldPath) || isHandRegDealsPath; 139 if (hasMarketplaceStickySearch) { 140 document.body.classList.add('has-marketplace-sticky-search'); 141 } 142 if (shouldHideHeaderOnScroll) { 143 document.body.classList.add('has-register-scroll-hide'); 144 } 145 146 function setMenuOpenExpanded(expanded) { 147 openBtns.forEach(function (btn) { 148 btn.setAttribute('aria-expanded', expanded ? 'true' : 'false'); 149 }); 150 } 151 152 function closeAllMenus() { 153 items.forEach(function (item) { 154 item.classList.remove('is-open'); 155 var btn = item.querySelector('.tn-header__nav-btn'); 156 if (btn) btn.setAttribute('aria-expanded', 'false'); 157 }); 158 panels.forEach(function (panel) { 159 panel.classList.remove('is-open'); 160 }); 161 } 162 163 function openMenu(key) { 164 items.forEach(function (item) { 165 var isActive = item.getAttribute('data-tn-menu') === key; 166 item.classList.toggle('is-open', isActive); 167 var btn = item.querySelector('.tn-header__nav-btn'); 168 if (btn) btn.setAttribute('aria-expanded', isActive ? 'true' : 'false'); 169 }); 170 panels.forEach(function (panel) { 171 panel.classList.toggle('is-open', panel.getAttribute('data-tn-panel') === key); 172 }); 173 } 174 175 function closeAllDropdowns() { 176 dropdowns.forEach(function (dd) { 177 dd.classList.remove('is-open'); 178 var toggle = dd.querySelector('.tn-header__dropdown-toggle'); 179 if (toggle) toggle.setAttribute('aria-expanded', 'false'); 180 }); 181 } 182 183 function closeMobileSearch() { 184 header.classList.remove('is-mobile-search-open'); 185 if (mobileSearchToggle) mobileSearchToggle.setAttribute('aria-expanded', 'false'); 186 } 187 188 function openDrawer(e) { 189 if (e) { 190 e.preventDefault(); 191 e.stopPropagation(); 192 } 193 if (!drawer || !backdrop) return; 194 closeAllMenus(); 195 closeAllDropdowns(); 196 closeMobileSearch(); 197 drawer.hidden = false; 198 backdrop.hidden = false; 199 void drawer.offsetWidth; 200 drawer.classList.add('is-open'); 201 backdrop.classList.add('is-open'); 202 drawer.setAttribute('aria-hidden', 'false'); 203 setMenuOpenExpanded(true); 204 document.body.classList.add('tn-header-open'); 205 } 206 207 function closeDrawer() { 208 if (!drawer || !backdrop) return; 209 drawer.classList.remove('is-open'); 210 backdrop.classList.remove('is-open'); 211 drawer.setAttribute('aria-hidden', 'true'); 212 setMenuOpenExpanded(false); 213 document.body.classList.remove('tn-header-open'); 214 setTimeout(function () { 215 if (!drawer.classList.contains('is-open')) { 216 drawer.hidden = true; 217 backdrop.hidden = true; 218 } 219 }, 250); 220 } 221 222 window.tnHeaderOpenDrawer = openDrawer; 223 window.tnHeaderCloseDrawer = closeDrawer; 224 225 document.addEventListener('click', function (e) { 226 if (e.target.closest('.sticky-bar-hamburger')) { 227 e.preventDefault(); 228 e.stopPropagation(); 229 openDrawer(e); 230 } 231 }); 232 233 items.forEach(function (item) { 234 var key = item.getAttribute('data-tn-menu'); 235 item.addEventListener('mouseenter', function () { 236 clearTimeout(closeTimer); 237 closeAllDropdowns(); 238 openMenu(key); 239 }); 240 item.addEventListener('mouseleave', function () { 241 closeTimer = setTimeout(closeAllMenus, 160); 242 }); 243 var btn = item.querySelector('.tn-header__nav-btn'); 244 if (btn) { 245 btn.addEventListener('click', function (e) { 246 e.preventDefault(); 247 e.stopPropagation(); 248 closeAllDropdowns(); 249 if (item.classList.contains('is-open')) { 250 closeAllMenus(); 251 } else { 252 openMenu(key); 253 } 254 }); 255 } 256 }); 257
258 panels.forEach(function (panel) { 259 panel.addEventListener('mouseenter', function () { 260 clearTimeout(closeTimer); 261 }); 262 panel.addEventListener('mouseleave', function () { 263 closeTimer = setTimeout(closeAllMenus, 160); 264 }); 265 }); 266 267 dropdowns.forEach(function (dd) { 268 var toggle = dd.querySelector('.tn-header__dropdown-toggle'); 269 if (!toggle) return; 270 toggle.addEventListener('click', function (e) { 271 e.preventDefault(); 272 e.stopPropagation(); 273 var willOpen = !dd.classList.contains('is-open'); 274 closeAllDropdowns(); 275 closeAllMenus(); 276 if (willOpen) { 277 dd.classList.add('is-open'); 278 toggle.setAttribute('aria-expanded', 'true'); 279 } 280 }); 281 }); 282 283 document.addEventListener('keydown', function (e) { 284 if (e.key === 'Escape') { 285 closeAllMenus(); 286 closeAllDropdowns(); 287 closeDrawer(); 288 closeMobileSearch(); 289 } 290 }); 291 292 document.addEventListener('click', function (e) { 293 if (!header.contains(e.target)) { 294 closeAllMenus(); 295 closeAllDropdowns(); 296 closeMobileSearch(); 297 } 298 }); 299 300 function onScroll() { 301 var scrolled = window.scrollY > SCROLL_THRESHOLD; 302 303 // Keep the top-of-page header (no sticky/fixed) on these landers. 304 if (isTrademarkFilingPath || isNamePath || isDomainAppraisalPath || isSellingSettingsPath || isRegisterTldPath) { 305 header.classList.remove('is-scrolled', 'is-scroll-hidden'); 306 if (spacer) spacer.classList.remove('is-active'); 307 document.body.classList.remove('tn-header-fixed'); 308 return; 309 } 310 311 if (hasMarketplaceStickySearch || shouldHideHeaderOnScroll) { 312 header.classList.toggle('is-scroll-hidden', scrolled); 313 header.classList.remove('is-scrolled'); 314 if (spacer) spacer.classList.remove('is-active'); 315 document.body.classList.remove('tn-header-fixed'); 316 } else { 317 header.classList.remove('is-scroll-hidden'); 318 header.classList.toggle('is-scrolled', scrolled); 319 if (spacer) spacer.classList.toggle('is-active', scrolled); 320 document.body.classList.toggle('tn-header-fixed', scrolled); 321 } 322 323 if (scrolled) { 324 closeAllMenus(); 325 if (hasMarketplaceStickySearch || shouldHideHeaderOnScroll) closeMobileSearch(); 326 } 327 } 328 329 window.addEventListener('scroll', onScroll, { passive: true }); 330 onScroll(); 331 332 openBtns.forEach(function (btn) { 333 btn.addEventListener('click', openDrawer); 334 }); 335 if (closeBtn) closeBtn.addEventListener('click', function (e) { 336 e.preventDefault(); 337 e.stopPropagation(); 338 closeDrawer(); 339 }); 340 if (backdrop) backdrop.addEventListener('click', closeDrawer); 341 342 if (mobileSearchToggle) { 343 mobileSearchToggle.addEventListener('click', function (e) { 344 e.preventDefault(); 345 e.stopPropagation(); 346 closeAllMenus(); 347 closeAllDropdowns(); 348 var willOpen = !header.classList.contains('is-mobile-search-open'); 349 header.classList.toggle('is-mobile-search-open', willOpen); 350 mobileSearchToggle.setAttribute('aria-expanded', willOpen ? 'true' : 'false'); 351 if (willOpen) { 352 var searchInput = document.getElementById('tnHeaderSearchInput'); 353 if (searchInput) { 354 setTimeout(function () { searchInput.focus(); }, 50); 355 } 356 } 357 }); 358 } 359 360 var form = document.getElementById('tnHeaderSearchForm'); 361 var input = document.getElementById('tnHeaderSearchInput'); 362 if (form && input) { 363 form.addEventListener('submit', function (e) { 364 e.preventDefault(); 365 var q = (input.value || '').trim(); 366 if (!q) { 367 input.focus(); 368 return; 369 } 370 371 window.location.href = '/premium-domains-for-sale/q/' + encodeURIComponent(q); 372 }); 373 } 374 375 var sticky = document.getElementById('stickySearchBar'); 376 if (sticky) sticky.style.display = 'none'; 377 }); 378})();
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.