1// Grove site polish: scroll-reveal engine (quiet fades, per Grove motion rules) 2(function(){ 3 document.documentElement.classList.add('rv-enabled'); 4 function init(){ 5 if (!('IntersectionObserver' in window)) { 6 document.querySelectorAll('[data-reveal]').forEach(function(e){ e.classList.add('rv-in'); }); 7 return; 8 } 9 var io = new IntersectionObserver(function(entries){ 10 entries.forEach(function(en){ 11 if (!en.isIntersecting) return; 12 var el = en.target; 13 var delay = el.getAttribute('data-reveal-delay'); 14 if (delay == null && el.parentNode) { 15 var sibs = Array.prototype.filter.call(el.parentNode.children, function(c){ return c.hasAttribute && c.hasAttribute('data-reveal'); }); 16 var idx = sibs.indexOf(el); 17 delay = idx > 0 ? Math.min(idx * 90, 450) + 'ms' : '0ms'; 18 } 19 el.style.transitionDelay = delay || '0ms'; 20 el.classList.add('rv-in'); 21 io.unobserve(el); 22 }); 23 }, { threshold: 0.1, rootMargin: '0px 0px -50px 0px' }); 24 var seen = new WeakSet(); 25 function scan(){ 26 document.querySelectorAll('[data-reveal]').forEach(function(el){ 27 if (seen.has(el)) return; 28 seen.add(el); 29 io.observe(el); 30 }); 31 } 32 // An element the viewport has already passed will never intersect again, so the 33 // observer alone would leave it faded out for good. That happens on any load that 34 // jumps straight down the page â a #faq deep link, a restored scroll position â 35 // so sweep everything above the viewport in without animating it. 36 function sweepPassed(){ 37 document.querySelectorAll('[data-reveal]:not(.rv-in)').forEach(function(el){ 38 if (el.getBoundingClientRect().bottom <= 0) { 39 el.style.transitionDelay = '0ms'; 40 el.classList.add('rv-in'); 41 io.unobserve(el); 42 } 43 }); 44 } 45 var queued = false; 46 function queueSweep(){ 47 if (queued) return; 48 queued = true; 49 requestAnimationFrame(function(){ queued = false; sweepPassed(); }); 50 } 51 scan(); 52 queueSweep(); 53 new MutationObserver(function(){ scan(); queueSweep(); }).observe(document.body, { childList: true, subtree: true }); 54 addEventListener('scroll', queueSweep, { passive: true }); 55 addEventListener('hashchange', queueSweep); 56 addEventListener('load', queueSweep); 57 } 58 if (document.readyState === 'loading') document.addEventListener('DOMContentLoaded', init); else init(); 59})();
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.