1/** 2 * Figures block â count each number up from 0 when it scrolls into view. 3 * 4 * SEO / progressive enhancement: the real, final number is always in the HTML. 5 * We only touch it here â and only when the element enters the viewport, so bots, 6 * no-JS users and reduced-motion users always read the correct value, never "0". 7 */ 8(function () { 9 'use strict'; 10 11 var counters = document.querySelectorAll('.js-figure-count'); 12 if (!counters.length) return; 13 14 var reduceMotion = window.matchMedia && window.matchMedia('(prefers-reduced-motion: reduce)').matches; 15 if (reduceMotion || !('IntersectionObserver' in window) || !window.requestAnimationFrame) { 16 return; // leave the final numbers untouched 17 } 18 19 var DURATION = 1600; 20 21 function animate(el) { 22 var raw = el.getAttribute('data-value') || el.textContent; 23 var parts = raw.match(/^(\D*)(\d+(?:[.,]\d+)*)(.*)$/); 24 if (!parts) return; // no number to animate â leave as is 25 26 var prefix = parts[1]; 27 var numStr = parts[2]; 28 var suffix = parts[3]; 29 var grouped = numStr.indexOf(',') > -1; 30 var dotIndex = numStr.lastIndexOf('.'); 31 var decimals = (!grouped && dotIndex > -1) ? numStr.length - dotIndex - 1 : 0; 32 var target = parseFloat(numStr.replace(/,/g, '')); 33 if (isNaN(target)) return; 34 35 function format(n) { 36 var body = grouped ? Math.round(n).toLocaleString('en-US') : n.toFixed(decimals); 37 return prefix + body + suffix; 38 } 39 40 var startTime = null; 41 function tick(now) { 42 if (startTime === null) startTime = now; 43 var progress = Math.min((now - startTime) / DURATION, 1); 44 var eased = 1 - Math.pow(1 - progress, 3); // easeOutCubic 45 if (progress < 1) { 46 el.textContent = format(target * eased); 47 window.requestAnimationFrame(tick); 48 } else { 49 el.textContent = raw; // guarantee the exact final value 50 } 51 } 52 window.requestAnimationFrame(tick); 53 } 54 55 var observer = new IntersectionObserver(function (entries) { 56 entries.forEach(function (entry) { 57 if (!entry.isIntersecting) return; 58 observer.unobserve(entry.target); 59 animate(entry.target); 60 }); 61 }, { threshold: 0.35 }); 62 63 counters.forEach(function (el) { observer.observe(el); }); 64})();
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.