https://www.gsscloud.com/templates/vital2022/js/modules/nav-produc…?b63ae3952263319d4e7755155824cb94
1document.addEventListener('DOMContentLoaded', () => { 2 // ç£è½ç¯åæ¯ .nav__containerï¼ä¸æ¯ .nav__listï¼.nav__loginï¼ç«å³ç»å ¥/æå¡é¸å®é¢æ¿ï¼ 3 // è· burger å¹³è¡æ¾å¨ .nav__list å¤é¢ï¼click äºä»¶ä¸æ bubble å° .nav__list ä¸ï¼ 4 // å ©è å ±åçç¶å±¤ .nav__container æè½åææ¶µèå°ã 5 const navContainer = document.querySelector('.nav__container'); 6 if (!navContainer) return; 7 8 // è® _rwd.scss 輸åºç --bp-laptop-mï¼è· SCSS ç rwd(laptop_M) å ±ç¨åä¸åæ·é»ä¾æº 9 const bpLaptopM = 10 getComputedStyle(document.documentElement).getPropertyValue('--bp-laptop-m').trim() || '1024px'; 11 const mqMobile = window.matchMedia(`(max-width: ${bpLaptopM})`); 12 const mqReducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)'); 13 14 // éå® .push-view-host.panel-openï¼è¤å鏿å¨ï¼ï¼ä¸è¦æ¥è£¸ç .panel-openââ 15 // burger ç .nav.panel-open æ¯å¦ä¸åç¨ç«çæ ï¼æ··å¨ä¸èµ·æ¸ æèª¤é burger drawerã 16 const nav = document.querySelector('.nav'); 17 18 // inert è·ãmobile æ·é»å § + host æ¯å¦ panel-openã忥ï¼ä¸åªå¨ click æåæââ 19 // é é¢åè¼å ¥æå¾ desktop resize é² mobile æé½éæ²é»éæ±è¥¿ï¼drawer è¦è¦ºä¸å·²æ¶å 20 // å»å¾æ²è¢«è¨é inertï¼è¦ _user-menu.scss ç說æï¼ã 21 const syncLoginDrawerInert = () => { 22 document.querySelectorAll('.push-view-host').forEach((host) => { 23 const drawer = host.querySelector(':scope > .nav__login__drawer'); 24 if (!drawer) return; 25 drawer.toggleAttribute('inert', mqMobile.matches && !host.classList.contains('panel-open')); 26 }); 27 }; 28 syncLoginDrawerInert(); 29 30 // ééæé ææ¸ æ .nav__login__drawer ç inertï¼å ¶ä» host æ²æéåå層ï¼no-opï¼ 31 const closeAllPanels = () => { 32 document.querySelectorAll('.push-view-host.panel-open').forEach((el) => { 33 el.classList.remove('panel-open'); 34 el.querySelector(':scope > .nav__login__drawer')?.setAttribute('inert', ''); 35 }); 36 }; 37 38 const navList = document.querySelector('.nav__list'); 39 const openPanel = (panelEl) => { 40 closeAllPanels(); 41 // .nav__login è· burger drawer æ¯å¹³è¡çå ©åç¨ç« overlayï¼éå®ä¹å妿 drawer 42 // ééèï¼åç¨ burger èªå·±ç click handler éæï¼ä¸éè¤å¯«ä¸ä»½æ¸ çéè¼¯ï¼ 43 if (navList && !navList.contains(panelEl) && nav && nav.classList.contains('panel-open')) { 44 document.querySelector('.burger')?.click(); 45 } 46 panelEl.classList.add('panel-open'); 47 panelEl.querySelector(':scope > .nav__login__drawer')?.removeAttribute('inert'); 48 }; 49 50 // åæ product-dropdown tab ç active çæ ï¼desktop / mobile å ±ç¨ï¼ 51 const activateTab = (tabEl) => { 52 const root = tabEl.closest('.product-dropdown'); 53 if (!root) return; 54 const alias = tabEl.dataset.tag; 55 const prevHeight = root.offsetHeight; 56 57 root 58 .querySelectorAll('.product-dropdown__tab') 59 .forEach((t) => t.classList.toggle('is-active', t === tabEl)); 60 root 61 .querySelectorAll('.npd-panel') 62 .forEach((p) => p.classList.toggle('is-active', p.dataset.panel === alias)); 63 64 // Desktop å tab æåé«åº¦é渡åç« 65 if (!mqMobile.matches && !mqReducedMotion.matches) { 66 const newHeight = root.offsetHeight; 67 if (prevHeight !== newHeight) { 68 root.animate([{ height: `${prevHeight}px` }, { height: `${newHeight}px` }], { 69 duration: 300, 70 easing: 'ease', 71 fill: 'none', 72 }); 73 } 74 } 75 }; 76 77 navContainer.addEventListener('click', (e) => { 78 // å ±ç¨è¿åï¼ä»»ä½æ æ³é½çæï¼desktop ä¹å 許 â éç¶ desktop .nav__back çä¸è¦ï¼ 79 if (e.target.closest('.nav__back')) { 80 closeAllPanels(); 81 return; 82 } 83 84 // .nav__login èªå·±ç â éééï¼è· .nav__back åéï¼ä¸å ±ç¨ãè¿åãèªæï¼ 85 if (e.target.closest('.nav__login__close')) { 86 closeAllPanels(); 87 return; 88 } 89 90 // product-dropdown tabï¼desktop ç´å tabï¼mobile éè¦èµ° push-view æµç¨ 91 const tab = e.target.closest('.product-dropdown__tab'); 92 if (tab) { 93 activateTab(tab); 94 if (mqMobile.matches) {
95 openPanel(tab.closest('.push-view-host')); 96 } 97 return; 98 } 99 100 // Mobile-onlyï¼é»å¨ .push-view-host å §ãä½ä¸å¨ãhost èªå·±çãpanel å §æè§¸ç¼ openPanel 101 // ï¼panel å §çé£çµè¦ç §å¸¸å°èªï¼ãç¨ host.contains(panel) èéãæ .push-view-panel ç¥å ãï¼ 102 // å çº .menu-main æå¤å±¤ <ul> ä¹å¸¶éå classï¼å°å®èªå·±ç L1 <li> æ¯ç¥å 䏿¯åå«ï¼ 103 // 夿·æ³æèª¤å¤ãåæè¦èª .push-view-panel--dropdownï¼.nav__login ç mobile 颿¿åªæ 104 // éå classï¼æ²æ .push-view-panelï¼ï¼ä¸èªç話é»é¢æ¿å §éé£çµååæå誤觸ç¼ä¸æ¬¡ã 105 if (!mqMobile.matches) return; 106 const host = e.target.closest('.push-view-host'); 107 if (!host) return; 108 const panel = e.target.closest('.push-view-panel, .push-view-panel--dropdown'); 109 if (panel && host.contains(panel)) return; 110 openPanel(host); 111 }); 112 113 // <li role="tab"> éåçäºåå ç´ ï¼ç覽å¨ä¸æèªåæ Enter/Space è½æ click 114 navContainer.addEventListener('keydown', (e) => { 115 if (e.key !== 'Enter' && e.key !== ' ') return; 116 const tab = e.target.closest('.product-dropdown__tab'); 117 if (!tab) return; 118 e.preventDefault(); 119 activateTab(tab); 120 if (mqMobile.matches) { 121 openPanel(tab.closest('.push-view-host')); 122 } 123 }); 124 125 // .product-dropdown æ¯ç¨ç«æ¨¡çµãDOM ä½ç½®å¨è§¸ç¼å¨ä¹åï¼èªç¶ Tab é åºæ¥ä¸ä¸ï¼éæåå°ï¼ 126 // é²é¢æ¿ï¼é¢æ¿å°¾åºå»ï¼Shift+Tab å觸ç¼å¨ââå°äºã颿¿å°¾åºå»ãæè¢«ç¬¬ä¸é»å°å颿¿åºä¸å» 127 navContainer.addEventListener('keydown', (e) => { 128 if (e.key !== 'Tab' || mqMobile.matches) return; 129 130 const trigger = document.querySelector('.nav-header.nav-product'); 131 const dropdown = document.querySelector('.product-dropdown'); 132 if (!trigger || !dropdown) return; 133 134 if (e.target === trigger && !e.shiftKey) { 135 const focusable = dropdown.querySelectorAll('a[href], [tabindex]'); 136 e.preventDefault();
137 focusable[0]?.focus(); 138 return; 139 } 140 141 if (!dropdown.contains(e.target)) return; 142 const focusable = [...dropdown.querySelectorAll('a[href], [tabindex]')].filter( 143 (el) => el.tabIndex !== -1 && el.offsetParent !== null, 144 ); 145 146 if (!e.shiftKey && e.target === focusable[focusable.length - 1]) { 147 // æ²æä¸ä¸åé ç®å¯ä»¥æ¥ææï¼ä¾å¦ trigger 被移å°ä¸»é¸å®æå¾ä¸é ï¼å°±ä¸ preventDefaultï¼ 148 // è®ç覽å¨èµ°åç Tab è¡çºï¼é¿å ç¦é»è¢«æä½å»ç¡èå¯å» 149 const next = trigger 150 .closest('.nav-item') 151 ?.nextElementSibling?.querySelector(':scope > a, :scope > .nav-header'); 152 if (next) { 153 e.preventDefault(); 154 next.focus(); 155 } 156 } else if (e.shiftKey && e.target === focusable[0]) { 157 e.preventDefault(); 158 trigger.focus(); 159 } 160 }); 161 162 // .navï¼burger drawerï¼ç panel-open/inert ç± global.js èªå·±ç®¡ï¼ä¸æ¸é裡ï¼.nav 䏿¯ push-view-hostï¼ 163 mqMobile.addEventListener('change', (e) => { 164 if (!e.matches) closeAllPanels(); 165 syncLoginDrawerInert(); 166 }); 167});
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.