1/* motion.js â çé¢å¨æç»ä¸èæ¬ 2 åºæ¯ Aï¼äºçº§æé®å å®¹åæ¢å ¥åºï¼å§æçå¬ï¼ä¸æ¹å页å èé»è¾ï¼ 3 åºæ¯ Bï¼Abstract æé£ç´ grid æå å±å¼ï¼æ¥ç®¡ research 页æ§é»è¾ï¼ 4 åºæ¯ Dï¼æ»å¨å ¥åºï¼IntersectionObserverï¼é¦å±å ç´ è·³è¿ï¼ */ 5(function () { 6 'use strict'; 7 8 var reduceMotion = window.matchMedia && 9 window.matchMedia('(prefers-reduced-motion: reduce)').matches; 10 11 /* ---------- åºæ¯ Aï¼åæ¢å å®¹å ¥åº ---------- */ 12 function animateSection(targetId) { 13 var el = document.getElementById(targetId); 14 if (!el) return; 15 el.classList.remove('section-enter'); 16 void el.offsetWidth; /* å¼ºå¶ reflow 以éå¯å¨ç» */ 17 el.classList.add('section-enter'); 18 el.addEventListener('animationend', function handler() { 19 el.classList.remove('section-enter'); 20 el.removeEventListener('animationend', handler); 21 }); 22 } 23 24 /* ---------- åºæ¯ Bï¼æé£ç´ ---------- */ 25 /* åå§åï¼ææ¯ä¸ª panel çå 容å è¿ .acc-wrap > .acc-innerï¼ 26 grid-template-rows 0fr -> 1fr å®ç°é«åº¦èªéåºçæå å¨ç» */ 27 function prepareAccordions() { 28 var panels = document.querySelectorAll('div.panel'); 29 Array.prototype.forEach.call(panels, function (panel) { 30 if (panel.querySelector(':scope > .acc-wrap')) return; 31 var wrap = document.createElement('div'); 32 wrap.className = 'acc-wrap'; 33 var inner = document.createElement('div'); 34 inner.className = 'acc-inner'; 35 while (panel.firstChild) inner.appendChild(panel.firstChild); 36 wrap.appendChild(inner); 37 panel.appendChild(wrap); 38 if (panel.classList.contains('show')) wrap.classList.add('open'); 39 }); 40 } 41 42 function toggleAccordion(btn) { 43 var host = btn.parentElement; 44 if (!host) return; 45 var panel = host.nextElementSibling; 46 if (!panel || !panel.classList.contains('panel')) return; 47 var wrap = panel.querySelector(':scope > .acc-wrap'); 48 49 btn.classList.toggle('active'); 50 var willShow = !panel.classList.contains('show'); 51 52 if (willShow) { 53 panel.classList.add('show'); 54 if (wrap) { 55 /* å rAF ç¡®ä¿å 宿 display 忢ï¼åææ¾å±å¼è¿æ¸¡ */ 56 requestAnimationFrame(function () { 57 requestAnimationFrame(function () { wrap.classList.add('open'); }); 58 }); 59 } 60 } else if (wrap) { 61 wrap.classList.remove('open'); 62 var settled = false; 63 var finish = function () { 64 if (settled) return; 65 settled = true; 66 wrap.removeEventListener('transitionend', onEnd); 67 if (!wrap.classList.contains('open')) panel.classList.remove('show'); 68 }; 69 var onEnd = function (e) { 70 if (e.target === wrap && e.propertyName !== 'grid-template-rows') return; 71 finish(); 72 }; 73 wrap.addEventListener('transitionend', onEnd); 74 setTimeout(finish, 320); /* å åºï¼transitionend æªè§¦åæ¶æ¶èµ· */ 75 } else { 76 panel.classList.remove('show'); 77 } 78 } 79 80 /* ---------- åºæ¯ Dï¼æ»å¨å ¥åº ---------- */ 81 var REVEAL_SELECTOR = '.paper-item, .handout-card, .scheduled-updates, ' + 82 '.updates-list li, .lecture-card, .resource-list li, .event-list li, ' + 83 '.course-item, #ug > li, #grad > li'; 84 85 function setupReveal() { 86 if (reduceMotion || !('IntersectionObserver' in window)) return; 87 var vh = window.innerHeight || document.documentElement.clientHeight; 88 var candidates = document.querySelectorAll(REVEAL_SELECTOR); 89 var targets = []; 90 91 Array.prototype.forEach.call(candidates, function (el) { 92 var rect = el.getBoundingClientRect(); 93 var isHidden = rect.width === 0 && rect.height === 0; 94 /* é¦å±å¯è§å ç´ ä¸åæ»å¨å ¥åºï¼é¡µé¢å ¥åºå¨ç»å·²è¦çï¼ */ 95 if (!isHidden && rect.top < vh && rect.bottom > 0) return; 96 el.classList.add('reveal'); 97 targets.push(el); 98 }); 99 100 if (!targets.length) return; 101 var observer = new IntersectionObserver(function (entries) { 102 var batch = 0; 103 entries.forEach(function (entry) { 104 if (!entry.isIntersecting) return; 105 var el = entry.target; 106 observer.unobserve(el); 107 /* åæ¹å ç´ 50ms éè¿ï¼300ms å°é¡¶ */ 108 el.style.setProperty('--reveal-delay', 109 Math.min(batch * 50, 300) + 'ms'); 110 el.classList.add('is-visible'); 111 batch += 1; 112 }); 113 }, { threshold: 0.08, rootMargin: '0px 0px -5% 0px' }); 114
115 targets.forEach(function (el) { observer.observe(el); }); 116 } 117 118 /* ---------- äºä»¶å§æ ---------- */ 119 function onDocClick(e) { 120 var target = e.target; 121 if (!target || !target.closest) return; 122 123 var accBtn = target.closest('button.accordion'); 124 if (accBtn) { 125 toggleAccordion(accBtn); 126 return; 127 } 128 129 var toggle = target.closest('.pub-btn, .sub-link, .pub-subbtn'); 130 if (toggle && toggle.getAttribute('data-target') && !reduceMotion) { 131 /* å页å èèæ¬å è¡åæ¢ displayï¼æ¤å¤ä¸ºæ°åºåè¡¥å ¥åºå¨ç» */ 132 animateSection(toggle.getAttribute('data-target')); 133 } 134 } 135 136 function init() { 137 prepareAccordions(); 138 setupReveal(); 139 document.addEventListener('click', onDocClick); 140 } 141 142 if (document.readyState === 'loading') { 143 document.addEventListener('DOMContentLoaded', init); 144 } else { 145 init(); 146 } 147})();
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.